Whamcloud - gitweb
- merge with 1_5,some fixes.
authoryury <yury>
Sun, 20 Aug 2006 13:13:22 +0000 (13:13 +0000)
committeryury <yury>
Sun, 20 Aug 2006 13:13:22 +0000 (13:13 +0000)
419 files changed:
ldiskfs/kernel_patches/patches/ext3-check-jbd-errors-2.6.5.patch [new file with mode: 0644]
ldiskfs/kernel_patches/patches/ext3-check-jbd-errors-2.6.9.patch [new file with mode: 0644]
ldiskfs/kernel_patches/patches/ext3-ea-in-inode-2.6-rhel4.patch
ldiskfs/kernel_patches/patches/ext3-ea-in-inode-2.6-suse.patch
ldiskfs/kernel_patches/patches/ext3-extents-2.6.12.patch
ldiskfs/kernel_patches/patches/ext3-extents-2.6.15.patch [new file with mode: 0644]
ldiskfs/kernel_patches/patches/ext3-extents-2.6.18-vanilla.patch [new file with mode: 0644]
ldiskfs/kernel_patches/patches/ext3-extents-2.6.5.patch
ldiskfs/kernel_patches/patches/ext3-extents-2.6.9-rhel4.patch
ldiskfs/kernel_patches/patches/ext3-filterdata-2.6.15.patch [new file with mode: 0644]
ldiskfs/kernel_patches/patches/ext3-lookup-dotdot-2.6.9.patch [new file with mode: 0644]
ldiskfs/kernel_patches/patches/ext3-mballoc2-2.6-fc5.patch [new file with mode: 0644]
ldiskfs/kernel_patches/patches/ext3-mballoc2-2.6-suse.patch
ldiskfs/kernel_patches/patches/ext3-mballoc2-2.6.12.patch
ldiskfs/kernel_patches/patches/ext3-mballoc2-2.6.18-vanilla.patch [new file with mode: 0644]
ldiskfs/kernel_patches/patches/ext3-mballoc2-2.6.9-rhel4.patch
ldiskfs/kernel_patches/patches/ext3-sector_t-overflow-2.6.12.patch [new file with mode: 0644]
ldiskfs/kernel_patches/patches/ext3-sector_t-overflow-2.6.5-suse.patch [new file with mode: 0644]
ldiskfs/kernel_patches/patches/ext3-sector_t-overflow-2.6.9-rhel4.patch [new file with mode: 0644]
ldiskfs/kernel_patches/patches/ext3-wantedi-2.6-rhel4.patch
ldiskfs/kernel_patches/patches/ext3-wantedi-2.6-suse.patch
ldiskfs/kernel_patches/patches/iopen-2.6-fc5.patch [new file with mode: 0644]
ldiskfs/kernel_patches/series/ldiskfs-2.6-fc3.series [new file with mode: 0644]
ldiskfs/kernel_patches/series/ldiskfs-2.6-fc5.series [new file with mode: 0644]
ldiskfs/kernel_patches/series/ldiskfs-2.6-rhel4.series
ldiskfs/kernel_patches/series/ldiskfs-2.6-suse.series
ldiskfs/kernel_patches/series/ldiskfs-2.6.12-vanilla.series
ldiskfs/kernel_patches/series/ldiskfs-2.6.18-vanilla.series [new file with mode: 0644]
lustre/ChangeLog
lustre/autoMakefile.am
lustre/autoconf/lustre-core.m4
lustre/contrib/.cvsignore [new file with mode: 0644]
lustre/contrib/Makefile.am [new file with mode: 0644]
lustre/contrib/README [new file with mode: 0644]
lustre/contrib/mpich-1.2.6-lustre.patch [new file with mode: 0644]
lustre/doc/Makefile.am
lustre/doc/lconf.8
lustre/doc/lctl.8
lustre/doc/lfs.1
lustre/doc/lfs.lyx
lustre/doc/llverdev.txt [new file with mode: 0644]
lustre/doc/llverfs.txt [new file with mode: 0644]
lustre/doc/lmc.1
lustre/doc/lmc.lyx
lustre/doc/lustre.7 [new file with mode: 0644]
lustre/doc/mkfs.lustre.8 [new file with mode: 0644]
lustre/doc/mount.lustre.8 [new file with mode: 0644]
lustre/doc/tunefs.lustre.8 [new file with mode: 0644]
lustre/fid/fid_handler.c
lustre/fid/fid_internal.h
lustre/fid/fid_request.c
lustre/fld/fld_cache.c
lustre/fld/fld_handler.c
lustre/fld/fld_internal.h
lustre/fld/fld_request.c
lustre/include/Makefile.am
lustre/include/liblustre.h
lustre/include/linux/Makefile.am
lustre/include/linux/lustre_acl.h
lustre/include/linux/lustre_compat25.h
lustre/include/linux/lustre_dlm.h
lustre/include/linux/lustre_fsfilt.h
lustre/include/linux/lustre_intent.h [new file with mode: 0644]
lustre/include/linux/lustre_lite.h
lustre/include/linux/lustre_mds.h
lustre/include/linux/lustre_patchless_compat.h [new file with mode: 0644]
lustre/include/linux/lustre_types.h
lustre/include/linux/lustre_user.h
lustre/include/linux/lvfs_linux.h
lustre/include/lprocfs_status.h
lustre/include/lustre/liblustreapi.h
lustre/include/lustre/lustre_idl.h
lustre/include/lustre/lustre_user.h
lustre/include/lustre_cfg.h
lustre/include/lustre_disk.h
lustre/include/lustre_dlm.h
lustre/include/lustre_export.h
lustre/include/lustre_import.h
lustre/include/lustre_lib.h
lustre/include/lustre_lite.h
lustre/include/lustre_mdc.h
lustre/include/lustre_mds.h
lustre/include/lustre_net.h
lustre/include/lustre_param.h
lustre/include/lustre_req_layout.h
lustre/include/obd.h
lustre/include/obd_class.h
lustre/include/obd_ost.h
lustre/include/obd_support.h
lustre/kernel_patches/kernel_configs/kernel-2.4.21-rhel-2.4-i686-smp.config
lustre/kernel_patches/kernel_configs/kernel-2.4.21-rhel-2.4-i686.config
lustre/kernel_patches/kernel_configs/kernel-2.4.21-rhel-2.4-ia64-smp.config
lustre/kernel_patches/kernel_configs/kernel-2.4.21-rhel-2.4-ia64.config
lustre/kernel_patches/kernel_configs/kernel-2.4.21-rhel-2.4-x86_64-smp.config
lustre/kernel_patches/kernel_configs/kernel-2.4.21-rhel-2.4-x86_64.config
lustre/kernel_patches/kernel_configs/kernel-2.4.21-suse-2.4.21-2-x86_64.config
lustre/kernel_patches/kernel_configs/kernel-2.6.15-2.6-fc5-i686-smp.config [new file with mode: 0644]
lustre/kernel_patches/kernel_configs/kernel-2.6.15-2.6-fc5-i686.config [new file with mode: 0644]
lustre/kernel_patches/kernel_configs/kernel-2.6.15-fc5-i686.config [new file with mode: 0644]
lustre/kernel_patches/kernel_configs/kernel-2.6.16-2.6-patchless-i686-smp.config [new file with mode: 0644]
lustre/kernel_patches/kernel_configs/kernel-2.6.16-2.6-patchless-i686.config [new file with mode: 0644]
lustre/kernel_patches/kernel_configs/kernel-2.6.16-2.6-patchless-ia64-smp.config [new file with mode: 0644]
lustre/kernel_patches/kernel_configs/kernel-2.6.16-2.6-patchless-ia64.config [new file with mode: 0644]
lustre/kernel_patches/kernel_configs/kernel-2.6.16-2.6-patchless-x86_64-smp.config [new file with mode: 0644]
lustre/kernel_patches/kernel_configs/kernel-2.6.16-2.6-patchless-x86_64.config [new file with mode: 0644]
lustre/kernel_patches/kernel_configs/kernel-2.6.9-2.6-rhel4-i686-smp.config
lustre/kernel_patches/kernel_configs/kernel-2.6.9-2.6-rhel4-i686.config
lustre/kernel_patches/kernel_configs/kernel-2.6.9-2.6-rhel4-ia64-smp.config
lustre/kernel_patches/kernel_configs/kernel-2.6.9-2.6-rhel4-ia64.config
lustre/kernel_patches/kernel_configs/kernel-2.6.9-2.6-rhel4-x86_64-smp.config
lustre/kernel_patches/kernel_configs/kernel-2.6.9-2.6-rhel4-x86_64.config
lustre/kernel_patches/patches/compile-fixes-2.4.21-rhel.patch
lustre/kernel_patches/patches/dev_read_only-2.6-fc5.patch [new file with mode: 0644]
lustre/kernel_patches/patches/dev_read_only-2.6.18-vanilla.patch [new file with mode: 0644]
lustre/kernel_patches/patches/export-2.6-fc5.patch [new file with mode: 0644]
lustre/kernel_patches/patches/export-2.6.18-vanilla.patch [new file with mode: 0644]
lustre/kernel_patches/patches/export-show_task-2.6-fc5.patch [new file with mode: 0644]
lustre/kernel_patches/patches/export-show_task-2.6.18-vanilla.patch [new file with mode: 0644]
lustre/kernel_patches/patches/export-truncate-2.6.18-vanilla.patch [new file with mode: 0644]
lustre/kernel_patches/patches/export_symbol_numa-2.6-fc5.patch [new file with mode: 0644]
lustre/kernel_patches/patches/export_symbols-2.6.18-vanilla.patch [new file with mode: 0644]
lustre/kernel_patches/patches/ext3-check-jbd-errors-2.6.5.patch [new file with mode: 0644]
lustre/kernel_patches/patches/ext3-check-jbd-errors-2.6.9.patch [new file with mode: 0644]
lustre/kernel_patches/patches/ext3-ea-in-inode-2.4.20.patch
lustre/kernel_patches/patches/ext3-ea-in-inode-2.4.21-chaos.patch
lustre/kernel_patches/patches/ext3-ea-in-inode-2.4.21-suse2.patch
lustre/kernel_patches/patches/ext3-ea-in-inode-2.4.22-rh.patch
lustre/kernel_patches/patches/ext3-ea-in-inode-2.4.29.patch
lustre/kernel_patches/patches/ext3-ea-in-inode-2.6-rhel4.patch
lustre/kernel_patches/patches/ext3-ea-in-inode-2.6-suse.patch
lustre/kernel_patches/patches/ext3-extents-2.4.21-chaos.patch
lustre/kernel_patches/patches/ext3-extents-2.4.21-suse2.patch
lustre/kernel_patches/patches/ext3-extents-2.4.24.patch
lustre/kernel_patches/patches/ext3-extents-2.4.29.patch
lustre/kernel_patches/patches/ext3-extents-2.6.12.patch
lustre/kernel_patches/patches/ext3-extents-2.6.15.patch [new file with mode: 0644]
lustre/kernel_patches/patches/ext3-extents-2.6.18-vanilla.patch [new file with mode: 0644]
lustre/kernel_patches/patches/ext3-extents-2.6.5.patch
lustre/kernel_patches/patches/ext3-extents-2.6.9-rhel4.patch
lustre/kernel_patches/patches/ext3-external-journal-2.6.9.patch [new file with mode: 0644]
lustre/kernel_patches/patches/ext3-filterdata-2.6.15.patch [new file with mode: 0644]
lustre/kernel_patches/patches/ext3-hash-selection.patch
lustre/kernel_patches/patches/ext3-lookup-dotdot-2.4.20.patch [new file with mode: 0644]
lustre/kernel_patches/patches/ext3-lookup-dotdot-2.6.9.patch [new file with mode: 0644]
lustre/kernel_patches/patches/ext3-mballoc2-2.6-fc5.patch [new file with mode: 0644]
lustre/kernel_patches/patches/ext3-mballoc2-2.6-suse.patch
lustre/kernel_patches/patches/ext3-mballoc2-2.6.12.patch
lustre/kernel_patches/patches/ext3-mballoc2-2.6.18-vanilla.patch [new file with mode: 0644]
lustre/kernel_patches/patches/ext3-mballoc2-2.6.9-rhel4.patch
lustre/kernel_patches/patches/ext3-multi-mount-protection-2.6-fc5.patch [new file with mode: 0644]
lustre/kernel_patches/patches/ext3-multi-mount-protection-2.6.18-vanilla.patch [new file with mode: 0644]
lustre/kernel_patches/patches/ext3-sector_t-overflow-2.4.patch [new file with mode: 0644]
lustre/kernel_patches/patches/ext3-sector_t-overflow-2.6.12.patch [new file with mode: 0644]
lustre/kernel_patches/patches/ext3-sector_t-overflow-2.6.5-suse.patch [new file with mode: 0644]
lustre/kernel_patches/patches/ext3-sector_t-overflow-2.6.9-rhel4.patch [new file with mode: 0644]
lustre/kernel_patches/patches/ext3-wantedi-2.6-rhel4.patch
lustre/kernel_patches/patches/ext3-wantedi-2.6-suse.patch
lustre/kernel_patches/patches/ext3-wantedi-2.6.15.patch [new file with mode: 0644]
lustre/kernel_patches/patches/ext3-wantedi-misc-2.6.18-vanilla.patch [new file with mode: 0644]
lustre/kernel_patches/patches/iopen-2.6-fc5.patch [new file with mode: 0644]
lustre/kernel_patches/patches/iopen-misc-2.6.18-vanilla.patch [new file with mode: 0644]
lustre/kernel_patches/patches/jbd-jcberr-2.6.18-vanilla.patch [new file with mode: 0644]
lustre/kernel_patches/patches/llnl-frame-pointer-walk-2.4.21-rhel.patch
lustre/kernel_patches/patches/llnl-frame-pointer-walk-fix-2.4.21-rhel.patch
lustre/kernel_patches/patches/nfs-cifs-intent-2.6-fc5.patch [new file with mode: 0644]
lustre/kernel_patches/patches/nfs-cifs-intent-2.6.18-vanilla.patch [new file with mode: 0644]
lustre/kernel_patches/patches/raid5-configurable-cachesize.patch [new file with mode: 0644]
lustre/kernel_patches/patches/raid5-large-io.patch [new file with mode: 0644]
lustre/kernel_patches/patches/raid5-merge-ios.patch [new file with mode: 0644]
lustre/kernel_patches/patches/raid5-optimize-memcpy.patch [new file with mode: 0644]
lustre/kernel_patches/patches/raid5-serialize-ovelapping-reqs.patch [new file with mode: 0644]
lustre/kernel_patches/patches/raid5-stats.patch [new file with mode: 0644]
lustre/kernel_patches/patches/raid5-stripe-by-stripe-handling.patch [new file with mode: 0644]
lustre/kernel_patches/patches/small_scatterlist-2.4.21-rhel.patch
lustre/kernel_patches/patches/tcp-zero-copy-2.6-fc5.patch [new file with mode: 0644]
lustre/kernel_patches/patches/tcp-zero-copy-2.6-sles10.patch [new file with mode: 0644]
lustre/kernel_patches/patches/tcp-zero-copy-2.6.18-vanilla.patch [new file with mode: 0644]
lustre/kernel_patches/patches/vfs_intent-2.4.21-rhel.patch
lustre/kernel_patches/patches/vfs_intent-2.6-fc5-fix.patch [new file with mode: 0644]
lustre/kernel_patches/patches/vfs_intent-2.6-fc5.patch [new file with mode: 0644]
lustre/kernel_patches/patches/vfs_intent-2.6-sles10.patch [new file with mode: 0644]
lustre/kernel_patches/patches/vfs_intent-2.6.18-vanilla.patch [new file with mode: 0644]
lustre/kernel_patches/patches/vfs_nointent-2.6-fc5.patch [new file with mode: 0644]
lustre/kernel_patches/patches/vfs_nointent-2.6-sles10.patch [new file with mode: 0644]
lustre/kernel_patches/patches/vfs_nointent-2.6.18-vanilla.patch [new file with mode: 0644]
lustre/kernel_patches/patches/vfs_races-2.6.18-vanilla.patch [new file with mode: 0644]
lustre/kernel_patches/series/2.6-fc5.series [new file with mode: 0644]
lustre/kernel_patches/series/2.6-rhel4-titech.series [new file with mode: 0644]
lustre/kernel_patches/series/2.6-rhel4.series
lustre/kernel_patches/series/2.6-sles10.series [new file with mode: 0644]
lustre/kernel_patches/series/2.6.18-vanilla.series [new file with mode: 0644]
lustre/kernel_patches/series/hp-pnnl-2.4.20
lustre/kernel_patches/series/ldiskfs-2.6-fc3.series [new file with mode: 0644]
lustre/kernel_patches/series/ldiskfs-2.6-fc5.series [new file with mode: 0644]
lustre/kernel_patches/series/ldiskfs-2.6-rhel4.series
lustre/kernel_patches/series/ldiskfs-2.6-suse.series
lustre/kernel_patches/series/ldiskfs-2.6.12-vanilla.series
lustre/kernel_patches/series/ldiskfs-2.6.18-vanilla.series [new file with mode: 0644]
lustre/kernel_patches/series/rhel-2.4.21
lustre/kernel_patches/series/suse-2.4.21-cray
lustre/kernel_patches/series/suse-2.4.21-jvn [deleted file]
lustre/kernel_patches/series/vanilla-2.4.24
lustre/kernel_patches/series/vanilla-2.4.29
lustre/kernel_patches/series/vanilla-2.4.29-uml
lustre/kernel_patches/targets/2.6-fc5.target.in [new file with mode: 0644]
lustre/kernel_patches/targets/2.6-patchless.target.in [new file with mode: 0644]
lustre/kernel_patches/targets/2.6-rhel4.target.in
lustre/kernel_patches/targets/2.6-suse.target.in
lustre/kernel_patches/targets/rhel-2.4.target.in
lustre/kernel_patches/which_patch
lustre/ldiskfs/lustre_quota_fmt.c
lustre/ldlm/l_lock.c
lustre/ldlm/ldlm_extent.c
lustre/ldlm/ldlm_flock.c
lustre/ldlm/ldlm_inodebits.c
lustre/ldlm/ldlm_internal.h
lustre/ldlm/ldlm_lib.c
lustre/ldlm/ldlm_lock.c
lustre/ldlm/ldlm_lockd.c
lustre/ldlm/ldlm_plain.c
lustre/ldlm/ldlm_request.c
lustre/ldlm/ldlm_resource.c
lustre/liblustre/Makefile.am
lustre/liblustre/dir.c
lustre/liblustre/file.c
lustre/liblustre/genlib.sh
lustre/liblustre/llite_lib.c
lustre/liblustre/llite_lib.h
lustre/liblustre/namei.c
lustre/liblustre/rw.c
lustre/liblustre/super.c
lustre/liblustre/tests/Makefile.am
lustre/liblustre/tests/echo_test.c
lustre/liblustre/tests/sanity.c
lustre/llite/Makefile.in
lustre/llite/autoMakefile.am
lustre/llite/dcache.c
lustre/llite/dir.c
lustre/llite/file.c
lustre/llite/llite_internal.h
lustre/llite/llite_lib.c
lustre/llite/llite_mmap.c
lustre/llite/llite_nfs.c
lustre/llite/lproc_llite.c
lustre/llite/namei.c
lustre/llite/rw.c
lustre/llite/rw24.c
lustre/llite/rw26.c
lustre/llite/super.c
lustre/llite/super25.c
lustre/llite/symlink.c
lustre/llite/xattr.c
lustre/lmv/lmv_intent.c
lustre/lmv/lmv_obd.c
lustre/lov/lov_ea.c
lustre/lov/lov_internal.h
lustre/lov/lov_log.c
lustre/lov/lov_merge.c
lustre/lov/lov_obd.c
lustre/lov/lov_pack.c
lustre/lov/lov_qos.c
lustre/lov/lov_request.c
lustre/lov/lproc_lov.c
lustre/lvfs/fsfilt_ext3.c
lustre/lvfs/lvfs_linux.c
lustre/lvfs/upcall_cache.c
lustre/mdc/lproc_mdc.c
lustre/mdc/mdc_internal.h
lustre/mdc/mdc_lib.c
lustre/mdc/mdc_locks.c
lustre/mdc/mdc_reint.c
lustre/mdc/mdc_request.c
lustre/mdd/mdd_lov.c
lustre/mds/handler.c
lustre/mds/mds_fs.c
lustre/mds/mds_internal.h
lustre/mds/mds_join.c
lustre/mds/mds_lib.c
lustre/mds/mds_log.c
lustre/mds/mds_open.c
lustre/mds/mds_reint.c
lustre/mds/mds_unlink_open.c
lustre/mds/mds_xattr.c
lustre/mdt/mdt_fs.c
lustre/mdt/mdt_handler.c
lustre/mdt/mdt_lib.c
lustre/mdt/mdt_open.c
lustre/mdt/mdt_recovery.c
lustre/mdt/mdt_reint.c
lustre/mgc/autoMakefile.am
lustre/mgc/libmgc.c [new file with mode: 0644]
lustre/mgc/mgc_request.c
lustre/mgs/mgs_fs.c
lustre/mgs/mgs_handler.c
lustre/mgs/mgs_internal.h
lustre/mgs/mgs_llog.c
lustre/obdclass/class_obd.c
lustre/obdclass/debug.c
lustre/obdclass/genops.c
lustre/obdclass/linux/linux-module.c
lustre/obdclass/linux/linux-obdo.c
lustre/obdclass/llog_ioctl.c
lustre/obdclass/llog_lvfs.c
lustre/obdclass/llog_obd.c
lustre/obdclass/lprocfs_status.c
lustre/obdclass/lu_object.c
lustre/obdclass/obd_config.c
lustre/obdclass/obd_mount.c
lustre/obdecho/echo.c
lustre/obdecho/echo_client.c
lustre/obdfilter/filter.c
lustre/obdfilter/filter_internal.h
lustre/obdfilter/filter_io.c
lustre/obdfilter/filter_io_24.c
lustre/obdfilter/filter_io_26.c
lustre/obdfilter/filter_log.c
lustre/obdfilter/lproc_obdfilter.c
lustre/osc/lproc_osc.c
lustre/osc/osc_create.c
lustre/osc/osc_internal.h
lustre/osc/osc_request.c
lustre/ost/lproc_ost.c
lustre/ost/ost_handler.c
lustre/ptlrpc/Makefile.in
lustre/ptlrpc/autoMakefile.am
lustre/ptlrpc/client.c
lustre/ptlrpc/events.c
lustre/ptlrpc/import.c
lustre/ptlrpc/layout.c
lustre/ptlrpc/llog_client.c
lustre/ptlrpc/llog_net.c
lustre/ptlrpc/llog_server.c
lustre/ptlrpc/lproc_ptlrpc.c
lustre/ptlrpc/niobuf.c
lustre/ptlrpc/pack_generic.c
lustre/ptlrpc/pinger.c
lustre/ptlrpc/ptlrpc_internal.h
lustre/ptlrpc/ptlrpc_module.c
lustre/ptlrpc/ptlrpcd.c
lustre/ptlrpc/recov_thread.c
lustre/ptlrpc/recover.c
lustre/ptlrpc/service.c
lustre/ptlrpc/wirehdr.c [new file with mode: 0644]
lustre/ptlrpc/wiretest.c [new file with mode: 0644]
lustre/quota/quota_check.c
lustre/quota/quota_context.c
lustre/quota/quota_ctl.c
lustre/quota/quota_interface.c
lustre/tests/.cvsignore
lustre/tests/Makefile.am
lustre/tests/acceptance-small.sh
lustre/tests/cfg/insanity-local.sh
lustre/tests/cfg/local.sh
lustre/tests/cfg/lov.sh [new file with mode: 0644]
lustre/tests/conf-sanity.sh
lustre/tests/createdestroy.c
lustre/tests/insanity.sh
lustre/tests/lfscktest.sh [new file with mode: 0755]
lustre/tests/ll_dirstripe_verify.c
lustre/tests/llmount.sh
lustre/tests/llmountcleanup.sh
lustre/tests/llog-test.sh
lustre/tests/local.sh [deleted file]
lustre/tests/lov.sh [deleted file]
lustre/tests/mmap_sanity.c
lustre/tests/mountconf.sh [deleted file]
lustre/tests/qos.sh
lustre/tests/recovery-small.sh
lustre/tests/replay-dual.sh
lustre/tests/replay-ost-single.sh
lustre/tests/replay-single.sh
lustre/tests/rundbench
lustre/tests/runtests
lustre/tests/runvmstat
lustre/tests/sanity-quota.sh
lustre/tests/sanity.sh
lustre/tests/sanityN.sh
lustre/tests/small_write.c
lustre/tests/stat.c
lustre/tests/test-framework.sh
lustre/tests/uml.sh [deleted file]
lustre/tests/utime.c
lustre/tests/writemany.c
lustre/utils/.cvsignore
lustre/utils/Makefile.am
lustre/utils/cluster_scripts/1uml.csv [deleted file]
lustre/utils/cluster_scripts/cluster_config.sh [deleted file]
lustre/utils/cluster_scripts/gen_clumanager_config.sh [deleted file]
lustre/utils/cluster_scripts/gen_hb_config.sh [deleted file]
lustre/utils/cluster_scripts/module_config.sh [deleted file]
lustre/utils/cluster_scripts/verify_cluster_net.sh [deleted file]
lustre/utils/cluster_scripts/verify_serviceIP.sh [deleted file]
lustre/utils/lactive [deleted file]
lustre/utils/lconf
lustre/utils/lfind [deleted file]
lustre/utils/lfs.c
lustre/utils/liblustreapi.c
lustre/utils/llmount.c [deleted file]
lustre/utils/llobdstat.pl
lustre/utils/llog_reader.c
lustre/utils/llstat.pl
lustre/utils/llverdev.c [new file with mode: 0644]
lustre/utils/llverfs.c [new file with mode: 0644]
lustre/utils/lmc
lustre/utils/lr_reader.c [new file with mode: 0644]
lustre/utils/lstripe [deleted file]
lustre/utils/lustre_cfg.c
lustre/utils/mkfs_lustre.c
lustre/utils/module_cleanup.sh [new file with mode: 0755]
lustre/utils/module_setup.sh
lustre/utils/mount_lustre.c
lustre/utils/obd.c
lustre/utils/obdio.c
lustre/utils/obdiolib.c
lustre/utils/obdiolib.h
lustre/utils/req-layout.c
lustre/utils/wirecheck.c
lustre/utils/wirehdr.c
lustre/utils/wiretest.c

diff --git a/ldiskfs/kernel_patches/patches/ext3-check-jbd-errors-2.6.5.patch b/ldiskfs/kernel_patches/patches/ext3-check-jbd-errors-2.6.5.patch
new file mode 100644 (file)
index 0000000..dca4676
--- /dev/null
@@ -0,0 +1,101 @@
+Index: linux-2.6.5-7.201/fs/ext3/super.c
+===================================================================
+--- linux-2.6.5-7.201.orig/fs/ext3/super.c     2006-06-20 19:40:44.000000000 +0400
++++ linux-2.6.5-7.201/fs/ext3/super.c  2006-06-20 19:42:08.000000000 +0400
+@@ -39,7 +39,7 @@
+ static int ext3_load_journal(struct super_block *, struct ext3_super_block *);
+ static int ext3_create_journal(struct super_block *, struct ext3_super_block *,
+                              int);
+-static void ext3_commit_super (struct super_block * sb,
++void ext3_commit_super (struct super_block * sb,
+                              struct ext3_super_block * es,
+                              int sync);
+ static void ext3_mark_recovery_complete(struct super_block * sb,
+@@ -1781,7 +1781,7 @@ static int ext3_create_journal(struct su
+       return 0;
+ }
+-static void ext3_commit_super (struct super_block * sb,
++void ext3_commit_super (struct super_block * sb,
+                              struct ext3_super_block * es,
+                              int sync)
+ {
+Index: linux-2.6.5-7.201/fs/ext3/namei.c
+===================================================================
+--- linux-2.6.5-7.201.orig/fs/ext3/namei.c     2006-06-20 19:40:44.000000000 +0400
++++ linux-2.6.5-7.201/fs/ext3/namei.c  2006-06-20 19:42:08.000000000 +0400
+@@ -1598,7 +1598,7 @@ static int ext3_delete_entry (handle_t *
+                             struct buffer_head * bh)
+ {
+       struct ext3_dir_entry_2 * de, * pde;
+-      int i;
++      int i, err;
+       i = 0;
+       pde = NULL;
+@@ -1608,7 +1608,9 @@ static int ext3_delete_entry (handle_t *
+                       return -EIO;
+               if (de == de_del)  {
+                       BUFFER_TRACE(bh, "get_write_access");
+-                      ext3_journal_get_write_access(handle, bh);
++                      err = ext3_journal_get_write_access(handle, bh);
++                      if (err)
++                              return err;
+                       if (pde)
+                               pde->rec_len =
+                                       cpu_to_le16(le16_to_cpu(pde->rec_len) +
+Index: linux-2.6.5-7.201/fs/ext3/xattr.c
+===================================================================
+--- linux-2.6.5-7.201.orig/fs/ext3/xattr.c     2006-06-20 19:40:44.000000000 +0400
++++ linux-2.6.5-7.201/fs/ext3/xattr.c  2006-06-20 19:42:30.000000000 +0400
+@@ -107,7 +107,7 @@ ext3_xattr_register(int name_index, stru
+ {
+       int error = -EINVAL;
+-      if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) {
++      if (name_index > 0 && name_index < EXT3_XATTR_INDEX_MAX) {
+               write_lock(&ext3_handler_lock);
+               if (!ext3_xattr_handlers[name_index-1]) {
+                       ext3_xattr_handlers[name_index-1] = handler;
+Index: linux-2.6.5-7.201/fs/ext3/inode.c
+===================================================================
+--- linux-2.6.5-7.201.orig/fs/ext3/inode.c     2006-06-20 19:40:44.000000000 +0400
++++ linux-2.6.5-7.201/fs/ext3/inode.c  2006-06-20 19:42:08.000000000 +0400
+@@ -1517,9 +1517,14 @@ out_stop:
+                       if (end > inode->i_size) {
+                               ei->i_disksize = end;
+                               i_size_write(inode, end);
+-                              err = ext3_mark_inode_dirty(handle, inode);
+-                              if (!ret) 
+-                                      ret = err;
++                              /*
++                               * We're going to return a positive `ret'
++                               * here due to non-zero-length I/O, so there's
++                               * no way of reporting error returns from
++                               * ext3_mark_inode_dirty() to userspace.  So
++                               * ignore it.
++                               */
++                              ext3_mark_inode_dirty(handle, inode);
+                       }
+               }
+               err = ext3_journal_stop(handle);
+@@ -1811,8 +1816,18 @@ ext3_clear_blocks(handle_t *handle, stru
+               ext3_mark_inode_dirty(handle, inode);
+               ext3_journal_test_restart(handle, inode);
+               if (bh) {
++                      int err;
+                       BUFFER_TRACE(bh, "retaking write access");
+-                      ext3_journal_get_write_access(handle, bh);
++                      err = ext3_journal_get_write_access(handle, bh);
++                      if (err) {
++                              struct super_block *sb = inode->i_sb;
++                              struct ext3_super_block *es = EXT3_SB(sb)->s_es;
++                              printk (KERN_CRIT"EXT3-fs: can't continue truncate\n");
++                              EXT3_SB(sb)->s_mount_state |= EXT3_ERROR_FS;
++                              es->s_state |= cpu_to_le16(EXT3_ERROR_FS);
++                              ext3_commit_super(sb, es, 1);
++                              return;
++                      }
+               }
+       }
diff --git a/ldiskfs/kernel_patches/patches/ext3-check-jbd-errors-2.6.9.patch b/ldiskfs/kernel_patches/patches/ext3-check-jbd-errors-2.6.9.patch
new file mode 100644 (file)
index 0000000..df3d2ea
--- /dev/null
@@ -0,0 +1,101 @@
+Index: linux-2.6.9-full/fs/ext3/super.c
+===================================================================
+--- linux-2.6.9-full.orig/fs/ext3/super.c      2006-06-02 23:37:51.000000000 +0400
++++ linux-2.6.9-full/fs/ext3/super.c   2006-06-02 23:56:29.000000000 +0400
+@@ -43,7 +43,7 @@ static int ext3_load_journal(struct supe
+                            unsigned long journal_devnum);
+ static int ext3_create_journal(struct super_block *, struct ext3_super_block *,
+                              int);
+-static void ext3_commit_super (struct super_block * sb,
++void ext3_commit_super (struct super_block * sb,
+                              struct ext3_super_block * es,
+                              int sync);
+ static void ext3_mark_recovery_complete(struct super_block * sb,
+@@ -1991,7 +1991,7 @@ static int ext3_create_journal(struct su
+       return 0;
+ }
+-static void ext3_commit_super (struct super_block * sb,
++void ext3_commit_super (struct super_block * sb,
+                              struct ext3_super_block * es,
+                              int sync)
+ {
+Index: linux-2.6.9-full/fs/ext3/namei.c
+===================================================================
+--- linux-2.6.9-full.orig/fs/ext3/namei.c      2006-06-02 23:37:49.000000000 +0400
++++ linux-2.6.9-full/fs/ext3/namei.c   2006-06-02 23:43:31.000000000 +0400
+@@ -1599,7 +1599,7 @@ static int ext3_delete_entry (handle_t *
+                             struct buffer_head * bh)
+ {
+       struct ext3_dir_entry_2 * de, * pde;
+-      int i;
++      int i, err;
+       i = 0;
+       pde = NULL;
+@@ -1609,7 +1609,9 @@ static int ext3_delete_entry (handle_t *
+                       return -EIO;
+               if (de == de_del)  {
+                       BUFFER_TRACE(bh, "get_write_access");
+-                      ext3_journal_get_write_access(handle, bh);
++                      err = ext3_journal_get_write_access(handle, bh);
++                      if (err)
++                              return err;
+                       if (pde)
+                               pde->rec_len =
+                                       cpu_to_le16(le16_to_cpu(pde->rec_len) +
+Index: linux-2.6.9-full/fs/ext3/xattr.c
+===================================================================
+--- linux-2.6.9-full.orig/fs/ext3/xattr.c      2006-06-01 14:58:48.000000000 +0400
++++ linux-2.6.9-full/fs/ext3/xattr.c   2006-06-03 00:02:00.000000000 +0400
+@@ -132,7 +132,7 @@ ext3_xattr_handler(int name_index)
+ {
+       struct xattr_handler *handler = NULL;
+-      if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX)
++      if (name_index > 0 && name_index < EXT3_XATTR_INDEX_MAX)
+               handler = ext3_xattr_handler_map[name_index];
+       return handler;
+ }
+Index: linux-2.6.9-full/fs/ext3/inode.c
+===================================================================
+--- linux-2.6.9-full.orig/fs/ext3/inode.c      2006-06-02 23:37:38.000000000 +0400
++++ linux-2.6.9-full/fs/ext3/inode.c   2006-06-03 00:27:41.000000000 +0400
+@@ -1513,9 +1513,14 @@ out_stop:
+                       if (end > inode->i_size) {
+                               ei->i_disksize = end;
+                               i_size_write(inode, end);
+-                              err = ext3_mark_inode_dirty(handle, inode);
+-                              if (!ret) 
+-                                      ret = err;
++                              /*
++                               * We're going to return a positive `ret'
++                               * here due to non-zero-length I/O, so there's
++                               * no way of reporting error returns from
++                               * ext3_mark_inode_dirty() to userspace.  So
++                               * ignore it.
++                               */
++                              ext3_mark_inode_dirty(handle, inode);
+                       }
+               }
+               err = ext3_journal_stop(handle);
+@@ -1807,8 +1812,18 @@ ext3_clear_blocks(handle_t *handle, stru
+               ext3_mark_inode_dirty(handle, inode);
+               ext3_journal_test_restart(handle, inode);
+               if (bh) {
++                      int err;
+                       BUFFER_TRACE(bh, "retaking write access");
+-                      ext3_journal_get_write_access(handle, bh);
++                      err = ext3_journal_get_write_access(handle, bh);
++                      if (err) {
++                              struct super_block *sb = inode->i_sb;
++                              struct ext3_super_block *es = EXT3_SB(sb)->s_es;
++                              printk (KERN_CRIT"EXT3-fs: can't continue truncate\n");
++                              EXT3_SB(sb)->s_mount_state |= EXT3_ERROR_FS;
++                              es->s_state |= cpu_to_le16(EXT3_ERROR_FS);
++                              ext3_commit_super(sb, es, 1);
++                              return;
++                      }
+               }
+       }
index 3f5687b..89cc1b5 100644 (file)
@@ -2,15 +2,13 @@ Index: linux-stage/fs/ext3/ialloc.c
 ===================================================================
 --- linux-stage.orig/fs/ext3/ialloc.c  2005-10-04 16:53:24.000000000 -0600
 +++ linux-stage/fs/ext3/ialloc.c       2005-10-04 17:07:25.000000000 -0600
-@@ -629,6 +629,11 @@
+@@ -629,6 +629,9 @@
        spin_unlock(&sbi->s_next_gen_lock);
  
        ei->i_state = EXT3_STATE_NEW;
-+      if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) {
-+              ei->i_extra_isize = sizeof(__u16)       /* i_extra_isize */
-+                              + sizeof(__u16);        /* i_pad1 */
-+      } else
-+              ei->i_extra_isize = 0;
++      ei->i_extra_isize =
++              (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) ?
++              sizeof(struct ext3_inode) - EXT3_GOOD_OLD_INODE_SIZE : 0;
  
        ret = inode;
        if(DQUOT_ALLOC_INODE(inode)) {
index 19f153d..72c25a4 100644 (file)
@@ -3,15 +3,13 @@ Index: linux-2.6.0/fs/ext3/ialloc.c
 ===================================================================
 --- linux-2.6.0.orig/fs/ext3/ialloc.c  2004-01-14 18:54:11.000000000 +0300
 +++ linux-2.6.0/fs/ext3/ialloc.c       2004-01-14 18:54:12.000000000 +0300
-@@ -627,6 +627,11 @@
+@@ -627,6 +627,9 @@
        inode->i_generation = EXT3_SB(sb)->s_next_generation++;
  
        ei->i_state = EXT3_STATE_NEW;
-+      if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) {
-+              ei->i_extra_isize = sizeof(__u16)       /* i_extra_isize */
-+                              + sizeof(__u16);        /* i_pad1 */
-+      } else
-+              ei->i_extra_isize = 0;
++      ei->i_extra_isize =
++              (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) ?
++              sizeof(struct ext3_inode) - EXT3_GOOD_OLD_INODE_SIZE : 0;
  
        ret = inode;
        if(DQUOT_ALLOC_INODE(inode)) {
index b6439e6..f421f88 100644 (file)
@@ -2,7 +2,7 @@ Index: linux-2.6.12-rc6/fs/ext3/extents.c
 ===================================================================
 --- linux-2.6.12-rc6.orig/fs/ext3/extents.c    2005-06-14 16:31:25.756503133 +0200
 +++ linux-2.6.12-rc6/fs/ext3/extents.c 2005-06-14 16:31:25.836581257 +0200
-@@ -0,0 +1,2353 @@
+@@ -0,0 +1,2359 @@
 +/*
 + * Copyright(c) 2003, 2004, 2005, Cluster File Systems, Inc, info@clusterfs.com
 + * Written by Alex Tomas <alex@clusterfs.com>
@@ -178,7 +178,7 @@ Index: linux-2.6.12-rc6/fs/ext3/extents.c
 +{
 +      struct ext3_extent_header *neh = EXT_ROOT_HDR(tree);
 +      neh->eh_generation = ((EXT_FLAGS(neh) & ~EXT_FLAGS_CLR_UNKNOWN) << 24) |
-+                           (EXT_GENERATION(neh) + 1);
++                           (EXT_HDR_GEN(neh) + 1);
 +}
 +
 +static inline int ext3_ext_space_block(struct ext3_extents_tree *tree)
@@ -560,6 +560,7 @@ Index: linux-2.6.12-rc6/fs/ext3/extents.c
 +
 +      ix->ei_block = logical;
 +      ix->ei_leaf = ptr;
++      ix->ei_leaf_hi = ix->ei_unused = 0;
 +      curp->p_hdr->eh_entries++;
 +
 +      EXT_ASSERT(curp->p_hdr->eh_entries <= curp->p_hdr->eh_max);
@@ -722,6 +723,7 @@ Index: linux-2.6.12-rc6/fs/ext3/extents.c
 +              fidx = EXT_FIRST_INDEX(neh);
 +              fidx->ei_block = border;
 +              fidx->ei_leaf = oldblock;
++              fidx->ei_leaf_hi = fidx->ei_unused = 0;
 +
 +              ext_debug(tree, "int.index at %d (block %lu): %lu -> %lu\n",
 +                        i, newblock, border, oldblock);
@@ -855,6 +857,7 @@ Index: linux-2.6.12-rc6/fs/ext3/extents.c
 +      /* FIXME: it works, but actually path[0] can be index */
 +      curp->p_idx->ei_block = EXT_FIRST_EXTENT(path[0].p_hdr)->ee_block;
 +      curp->p_idx->ei_leaf = newblock;
++      curp->p_idx->ei_leaf_hi = curp->p_idx->ei_unused = 0;
 +
 +      neh = EXT_ROOT_HDR(tree);
 +      fidx = EXT_FIRST_INDEX(neh);
@@ -1403,6 +1406,7 @@ Index: linux-2.6.12-rc6/fs/ext3/extents.c
 +      if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) {
 +              ex->ee_block = cex->ec_block;
 +              ex->ee_start = cex->ec_start;
++              ex->ee_start_hi = 0;
 +              ex->ee_len = cex->ec_len;
 +              ext_debug(tree, "%lu cached by %lu:%lu:%lu\n",
 +                        (unsigned long) block,
@@ -1624,7 +1628,7 @@ Index: linux-2.6.12-rc6/fs/ext3/extents.c
 +
 +              if (num == 0) {
 +                      /* this extent is removed entirely mark slot unused */
-+                      ex->ee_start = 0;
++                      ex->ee_start = ex->ee_start_hi = 0;
 +                      eh->eh_entries--;
 +                      fu = ex;
 +              }
@@ -1646,7 +1650,7 @@ Index: linux-2.6.12-rc6/fs/ext3/extents.c
 +              while (lu < le) {
 +                      if (lu->ee_start) {
 +                              *fu = *lu;
-+                              lu->ee_start = 0;
++                              lu->ee_start = lu->ee_start_hi = 0;
 +                              fu++;
 +                      }
 +                      lu++;
@@ -2001,6 +2005,7 @@ Index: linux-2.6.12-rc6/fs/ext3/extents.c
 +              /* allocate new block for the extent */
 +              goal = ext3_ext_find_goal(inode, path, ex->ee_block);
 +              ex->ee_start = ext3_new_block(handle, inode, goal, err);
++              ex->ee_start_hi = 0;
 +              if (ex->ee_start == 0) {
 +                      /* error occured: restore old extent */
 +                      ex->ee_start = newblock;
@@ -2116,6 +2121,7 @@ Index: linux-2.6.12-rc6/fs/ext3/extents.c
 +      /* try to insert new extent into found leaf and return */
 +      newex.ee_block = iblock;
 +      newex.ee_start = newblock;
++      newex.ee_start_hi = 0;
 +      newex.ee_len = 1;
 +      err = ext3_ext_insert_extent(handle, &tree, path, &newex);
 +      if (err)
@@ -2523,26 +2529,30 @@ Index: linux-2.6.12-rc6/fs/ext3/super.c
        Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0,
        Opt_ignore, Opt_barrier, Opt_err, Opt_resize,
        Opt_iopen, Opt_noiopen, Opt_iopen_nopriv,
-+      Opt_extents, Opt_extdebug,
++      Opt_extents, Opt_noextents, Opt_extdebug,
  };
  
  static match_table_t tokens = {
-@@ -644,6 +647,8 @@
+@@ -644,6 +647,9 @@
        {Opt_iopen, "iopen"},
        {Opt_noiopen, "noiopen"},
        {Opt_iopen_nopriv, "iopen_nopriv"},
 +      {Opt_extents, "extents"},
++      {Opt_noextents, "noextents"},
 +      {Opt_extdebug, "extdebug"},
        {Opt_barrier, "barrier=%u"},
        {Opt_err, NULL},
        {Opt_resize, "resize"},
-@@ -953,6 +958,12 @@
+@@ -953,6 +958,15 @@
                case Opt_nobh:
                        set_opt(sbi->s_mount_opt, NOBH);
                        break;
 +              case Opt_extents:
 +                      set_opt (sbi->s_mount_opt, EXTENTS);
 +                      break;
++              case Opt_noextents:
++                      clear_opt (sbi->s_mount_opt, EXTENTS);
++                      break;
 +              case Opt_extdebug:
 +                      set_opt (sbi->s_mount_opt, EXTDEBUG);
 +                      break;
@@ -2621,11 +2631,13 @@ Index: linux-2.6.12-rc6/include/linux/ext3_fs.h
  #define EXT3_FEATURE_RO_COMPAT_SUPP   (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
                                         EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \
                                         EXT3_FEATURE_RO_COMPAT_BTREE_DIR)
-@@ -759,6 +767,7 @@
+@@ -759,6 +767,9 @@
  
  
  /* inode.c */
-+extern int ext3_block_truncate_page(handle_t *, struct page *, struct address_space *, loff_t);
++extern int ext3_block_truncate_page(handle_t *, struct page *,
++                                  struct address_space *, loff_t);
++extern int ext3_writepage_trans_blocks(struct inode *inode);
  extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int);
  extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
  extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
@@ -2849,14 +2861,14 @@ Index: linux-2.6.12-rc6/include/linux/ext3_extents.h
 +      (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_max - 1)
 +#define EXT_MAX_INDEX(__hdr__) \
 +      (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_max - 1)
-+#define EXT_GENERATION(__hdr__) ((__hdr__)->eh_generation & 0x00ffffff)
++#define EXT_HDR_GEN(__hdr__)  ((__hdr__)->eh_generation & 0x00ffffff)
 +#define EXT_FLAGS(__hdr__)    ((__hdr__)->eh_generation >> 24)
 +#define EXT_FLAGS_CLR_UNKNOWN 0x7     /* Flags cleared on modification */
 +
 +#define EXT_BLOCK_HDR(__bh__)         ((struct ext3_extent_header *)(__bh__)->b_data)
 +#define EXT_ROOT_HDR(__tree__)        ((struct ext3_extent_header *)(__tree__)->root)
 +#define EXT_DEPTH(__tree__)   (EXT_ROOT_HDR(__tree__)->eh_depth)
-+
++#define EXT_GENERATION(__tree__) EXT_HDR_GEN(EXT_ROOT_HDR(__tree__))
 +
 +#define EXT_ASSERT(__x__) if (!(__x__)) BUG();
 +
diff --git a/ldiskfs/kernel_patches/patches/ext3-extents-2.6.15.patch b/ldiskfs/kernel_patches/patches/ext3-extents-2.6.15.patch
new file mode 100644 (file)
index 0000000..3e18d55
--- /dev/null
@@ -0,0 +1,2933 @@
+Index: linux-2.6.16.21-0.8/fs/ext3/extents.c
+===================================================================
+--- /dev/null
++++ linux-2.6.16.21-0.8/fs/ext3/extents.c
+@@ -0,0 +1,2347 @@
++/*
++ * Copyright(c) 2003, 2004, 2005, Cluster File Systems, Inc, info@clusterfs.com
++ * Written by Alex Tomas <alex@clusterfs.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public Licens
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-
++ */
++
++/*
++ * Extents support for EXT3
++ *
++ * TODO:
++ *   - ext3_ext_walk_space() sould not use ext3_ext_find_extent()
++ *   - ext3_ext_calc_credits() could take 'mergable' into account
++ *   - ext3*_error() should be used in some situations
++ *   - find_goal() [to be tested and improved]
++ *   - smart tree reduction
++ *   - arch-independence
++ *     common on-disk format for big/little-endian arch
++ */
++
++#include <linux/module.h>
++#include <linux/fs.h>
++#include <linux/time.h>
++#include <linux/ext3_jbd.h>
++#include <linux/jbd.h>
++#include <linux/smp_lock.h>
++#include <linux/highuid.h>
++#include <linux/pagemap.h>
++#include <linux/quotaops.h>
++#include <linux/string.h>
++#include <linux/slab.h>
++#include <linux/ext3_extents.h>
++#include <asm/uaccess.h>
++
++
++static inline int ext3_ext_check_header(struct ext3_extent_header *eh)
++{
++      if (eh->eh_magic != EXT3_EXT_MAGIC) {
++              printk(KERN_ERR "EXT3-fs: invalid magic = 0x%x\n",
++                     (unsigned)eh->eh_magic);
++              return -EIO;
++      }
++      if (eh->eh_max == 0) {
++              printk(KERN_ERR "EXT3-fs: invalid eh_max = %u\n",
++                     (unsigned)eh->eh_max);
++              return -EIO;
++      }
++      if (eh->eh_entries > eh->eh_max) {
++              printk(KERN_ERR "EXT3-fs: invalid eh_entries = %u\n",
++                     (unsigned)eh->eh_entries);
++              return -EIO;
++      }
++      return 0;
++}
++
++static handle_t *ext3_ext_journal_restart(handle_t *handle, int needed)
++{
++      int err;
++
++      if (handle->h_buffer_credits > needed)
++              return handle;
++      if (!ext3_journal_extend(handle, needed))
++              return handle;
++      err = ext3_journal_restart(handle, needed);
++      
++      return handle;
++}
++
++static int inline
++ext3_ext_get_access_for_root(handle_t *h, struct ext3_extents_tree *tree)
++{
++      if (tree->ops->get_write_access)
++              return tree->ops->get_write_access(h,tree->buffer);
++      else
++              return 0;
++}
++
++static int inline
++ext3_ext_mark_root_dirty(handle_t *h, struct ext3_extents_tree *tree)
++{
++      if (tree->ops->mark_buffer_dirty)
++              return tree->ops->mark_buffer_dirty(h,tree->buffer);
++      else
++              return 0;
++}
++
++/*
++ * could return:
++ *  - EROFS
++ *  - ENOMEM
++ */
++static int ext3_ext_get_access(handle_t *handle,
++                             struct ext3_extents_tree *tree,
++                             struct ext3_ext_path *path)
++{
++      int err;
++
++      if (path->p_bh) {
++              /* path points to block */
++              err = ext3_journal_get_write_access(handle, path->p_bh);
++      } else {
++              /* path points to leaf/index in inode body */
++              err = ext3_ext_get_access_for_root(handle, tree);
++      }
++      return err;
++}
++
++/*
++ * could return:
++ *  - EROFS
++ *  - ENOMEM
++ *  - EIO
++ */
++static int ext3_ext_dirty(handle_t *handle, struct ext3_extents_tree *tree,
++                        struct ext3_ext_path *path)
++{
++      int err;
++      if (path->p_bh) {
++              /* path points to block */
++              err =ext3_journal_dirty_metadata(handle, path->p_bh);
++      } else {
++              /* path points to leaf/index in inode body */
++              err = ext3_ext_mark_root_dirty(handle, tree);
++      }
++      return err;
++}
++
++static int inline
++ext3_ext_new_block(handle_t *handle, struct ext3_extents_tree *tree,
++                 struct ext3_ext_path *path, struct ext3_extent *ex,
++                 int *err)
++{
++      int goal, depth, newblock;
++      struct inode *inode;
++
++      EXT_ASSERT(tree);
++      if (tree->ops->new_block)
++              return tree->ops->new_block(handle, tree, path, ex, err);
++
++      inode = tree->inode;
++      depth = EXT_DEPTH(tree);
++      if (path && depth > 0) {
++              goal = path[depth-1].p_block;
++      } else {
++              struct ext3_inode_info *ei = EXT3_I(inode);
++              unsigned long bg_start;
++              unsigned long colour;
++
++              bg_start = (ei->i_block_group *
++                          EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
++                      le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block);
++              colour = (current->pid % 16) *
++                      (EXT3_BLOCKS_PER_GROUP(inode->i_sb) / 16);
++              goal = bg_start + colour;
++      }
++
++      newblock = ext3_new_block(handle, inode, goal, err);
++      return newblock;
++}
++
++static inline void ext3_ext_tree_changed(struct ext3_extents_tree *tree)
++{
++      struct ext3_extent_header *neh;
++      neh = EXT_ROOT_HDR(tree);
++      neh->eh_generation++;
++}
++
++static inline int ext3_ext_space_block(struct ext3_extents_tree *tree)
++{
++      int size;
++
++      size = (tree->inode->i_sb->s_blocksize -
++              sizeof(struct ext3_extent_header)) /
++                              sizeof(struct ext3_extent);
++#ifdef AGRESSIVE_TEST
++      size = 6;
++#endif
++      return size;
++}
++
++static inline int ext3_ext_space_block_idx(struct ext3_extents_tree *tree)
++{
++      int size;
++
++      size = (tree->inode->i_sb->s_blocksize -
++              sizeof(struct ext3_extent_header)) /
++                              sizeof(struct ext3_extent_idx);
++#ifdef AGRESSIVE_TEST
++      size = 5;
++#endif
++      return size;
++}
++
++static inline int ext3_ext_space_root(struct ext3_extents_tree *tree)
++{
++      int size;
++
++      size = (tree->buffer_len - sizeof(struct ext3_extent_header)) /
++                      sizeof(struct ext3_extent);
++#ifdef AGRESSIVE_TEST
++      size = 3;
++#endif
++      return size;
++}
++
++static inline int ext3_ext_space_root_idx(struct ext3_extents_tree *tree)
++{
++      int size;
++
++      size = (tree->buffer_len - sizeof(struct ext3_extent_header)) /
++                      sizeof(struct ext3_extent_idx);
++#ifdef AGRESSIVE_TEST
++      size = 4;
++#endif
++      return size;
++}
++
++static void ext3_ext_show_path(struct ext3_extents_tree *tree,
++                             struct ext3_ext_path *path)
++{
++#ifdef EXT_DEBUG
++      int k, l = path->p_depth;
++
++      ext_debug(tree, "path:");
++      for (k = 0; k <= l; k++, path++) {
++              if (path->p_idx) {
++                      ext_debug(tree, "  %d->%d", path->p_idx->ei_block,
++                                path->p_idx->ei_leaf);
++              } else if (path->p_ext) {
++                      ext_debug(tree, "  %d:%d:%d",
++                                path->p_ext->ee_block,
++                                path->p_ext->ee_len,
++                                path->p_ext->ee_start);
++              } else
++                      ext_debug(tree, "  []");
++      }
++      ext_debug(tree, "\n");
++#endif
++}
++
++static void ext3_ext_show_leaf(struct ext3_extents_tree *tree,
++                             struct ext3_ext_path *path)
++{
++#ifdef EXT_DEBUG
++      int depth = EXT_DEPTH(tree);
++      struct ext3_extent_header *eh;
++      struct ext3_extent *ex;
++      int i;
++
++      if (!path)
++              return;
++
++      eh = path[depth].p_hdr;
++      ex = EXT_FIRST_EXTENT(eh);
++
++      for (i = 0; i < eh->eh_entries; i++, ex++) {
++              ext_debug(tree, "%d:%d:%d ",
++                        ex->ee_block, ex->ee_len, ex->ee_start);
++      }
++      ext_debug(tree, "\n");
++#endif
++}
++
++static void ext3_ext_drop_refs(struct ext3_ext_path *path)
++{
++      int depth = path->p_depth;
++      int i;
++
++      for (i = 0; i <= depth; i++, path++) {
++              if (path->p_bh) {
++                      brelse(path->p_bh);
++                      path->p_bh = NULL;
++              }
++      }
++}
++
++/*
++ * binary search for closest index by given block
++ */
++static inline void
++ext3_ext_binsearch_idx(struct ext3_extents_tree *tree,
++                     struct ext3_ext_path *path, int block)
++{
++      struct ext3_extent_header *eh = path->p_hdr;
++      struct ext3_extent_idx *ix;
++      int l = 0, k, r;
++
++      EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
++      EXT_ASSERT(eh->eh_entries <= eh->eh_max);
++      EXT_ASSERT(eh->eh_entries > 0);
++
++      ext_debug(tree, "binsearch for %d(idx):  ", block);
++
++      path->p_idx = ix = EXT_FIRST_INDEX(eh);
++
++      r = k = eh->eh_entries;
++      while (k > 1) {
++              k = (r - l) / 2;
++              if (block < ix[l + k].ei_block)
++                      r -= k;
++              else
++                      l += k;
++              ext_debug(tree, "%d:%d:%d ", k, l, r);
++      }
++
++      ix += l;
++      path->p_idx = ix;
++      ext_debug(tree," -> %d->%d ",path->p_idx->ei_block,path->p_idx->ei_leaf);
++
++      while (l++ < r) {
++              if (block < ix->ei_block) 
++                      break;
++              path->p_idx = ix++;
++      }
++      ext_debug(tree, "  -> %d->%d\n", path->p_idx->ei_block,
++                path->p_idx->ei_leaf);
++
++#ifdef CHECK_BINSEARCH 
++      {
++              struct ext3_extent_idx *chix;
++
++              chix = ix = EXT_FIRST_INDEX(eh);
++              for (k = 0; k < eh->eh_entries; k++, ix++) {
++                      if (k != 0 && ix->ei_block <= ix[-1].ei_block) {
++                              printk("k=%d, ix=0x%p, first=0x%p\n", k,
++                                     ix, EXT_FIRST_INDEX(eh));
++                              printk("%u <= %u\n",
++                                     ix->ei_block,ix[-1].ei_block);
++                      }
++                      EXT_ASSERT(k == 0 || ix->ei_block > ix[-1].ei_block);
++                      if (block < ix->ei_block) 
++                              break;
++                      chix = ix;
++              }
++              EXT_ASSERT(chix == path->p_idx);
++      }
++#endif
++}
++
++/*
++ * binary search for closest extent by given block
++ */
++static inline void
++ext3_ext_binsearch(struct ext3_extents_tree *tree,
++                 struct ext3_ext_path *path, int block)
++{
++      struct ext3_extent_header *eh = path->p_hdr;
++      struct ext3_extent *ex;
++      int l = 0, k, r;
++
++      EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
++      EXT_ASSERT(eh->eh_entries <= eh->eh_max);
++
++      if (eh->eh_entries == 0) {
++              /*
++               * this leaf is empty yet:
++               *  we get such a leaf in split/add case
++               */
++              return;
++      }
++      
++      ext_debug(tree, "binsearch for %d:  ", block);
++
++      path->p_ext = ex = EXT_FIRST_EXTENT(eh);
++
++      r = k = eh->eh_entries;
++      while (k > 1) {
++              k = (r - l) / 2;
++              if (block < ex[l + k].ee_block)
++                      r -= k;
++              else
++                      l += k;
++              ext_debug(tree, "%d:%d:%d ", k, l, r);
++      }
++
++      ex += l;
++      path->p_ext = ex;
++      ext_debug(tree, "  -> %d:%d:%d ", path->p_ext->ee_block,
++                path->p_ext->ee_start, path->p_ext->ee_len);
++
++      while (l++ < r) {
++              if (block < ex->ee_block) 
++                      break;
++              path->p_ext = ex++;
++      }
++      ext_debug(tree, "  -> %d:%d:%d\n", path->p_ext->ee_block,
++                path->p_ext->ee_start, path->p_ext->ee_len);
++
++#ifdef CHECK_BINSEARCH 
++      {
++              struct ext3_extent *chex;
++
++              chex = ex = EXT_FIRST_EXTENT(eh);
++              for (k = 0; k < eh->eh_entries; k++, ex++) {
++                      EXT_ASSERT(k == 0 || ex->ee_block > ex[-1].ee_block);
++                      if (block < ex->ee_block) 
++                              break;
++                      chex = ex;
++              }
++              EXT_ASSERT(chex == path->p_ext);
++      }
++#endif
++}
++
++int ext3_extent_tree_init(handle_t *handle, struct ext3_extents_tree *tree)
++{
++      struct ext3_extent_header *eh;
++
++      BUG_ON(tree->buffer_len == 0);
++      ext3_ext_get_access_for_root(handle, tree);
++      eh = EXT_ROOT_HDR(tree);
++      eh->eh_depth = 0;
++      eh->eh_entries = 0;
++      eh->eh_magic = EXT3_EXT_MAGIC;
++      eh->eh_max = ext3_ext_space_root(tree);
++      ext3_ext_mark_root_dirty(handle, tree);
++      ext3_ext_invalidate_cache(tree);
++      return 0;
++}
++
++struct ext3_ext_path *
++ext3_ext_find_extent(struct ext3_extents_tree *tree, int block,
++                   struct ext3_ext_path *path)
++{
++      struct ext3_extent_header *eh;
++      struct buffer_head *bh;
++      int depth, i, ppos = 0;
++
++      EXT_ASSERT(tree);
++      EXT_ASSERT(tree->inode);
++      EXT_ASSERT(tree->root);
++
++      eh = EXT_ROOT_HDR(tree);
++      EXT_ASSERT(eh);
++      if (ext3_ext_check_header(eh))
++              goto err;
++
++      i = depth = EXT_DEPTH(tree);
++      EXT_ASSERT(eh->eh_max);
++      EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
++      
++      /* account possible depth increase */
++      if (!path) {
++              path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 2),
++                             GFP_NOFS);
++              if (!path)
++                      return ERR_PTR(-ENOMEM);
++      }
++      memset(path, 0, sizeof(struct ext3_ext_path) * (depth + 1));
++      path[0].p_hdr = eh;
++
++      /* walk through the tree */
++      while (i) {
++              ext_debug(tree, "depth %d: num %d, max %d\n",
++                        ppos, eh->eh_entries, eh->eh_max);
++              ext3_ext_binsearch_idx(tree, path + ppos, block);
++              path[ppos].p_block = path[ppos].p_idx->ei_leaf;
++              path[ppos].p_depth = i;
++              path[ppos].p_ext = NULL;
++
++              bh = sb_bread(tree->inode->i_sb, path[ppos].p_block);
++              if (!bh)
++                      goto err;
++
++              eh = EXT_BLOCK_HDR(bh);
++              ppos++;
++              EXT_ASSERT(ppos <= depth);
++              path[ppos].p_bh = bh;
++              path[ppos].p_hdr = eh;
++              i--;
++
++              if (ext3_ext_check_header(eh))
++                      goto err;
++      }
++
++      path[ppos].p_depth = i;
++      path[ppos].p_hdr = eh;
++      path[ppos].p_ext = NULL;
++      path[ppos].p_idx = NULL;
++
++      if (ext3_ext_check_header(eh))
++              goto err;
++
++      /* find extent */
++      ext3_ext_binsearch(tree, path + ppos, block);
++
++      ext3_ext_show_path(tree, path);
++
++      return path;
++
++err:
++      printk(KERN_ERR "EXT3-fs: header is corrupted!\n");
++      ext3_ext_drop_refs(path);
++      kfree(path);
++      return ERR_PTR(-EIO);
++}
++
++/*
++ * insert new index [logical;ptr] into the block at cupr
++ * it check where to insert: before curp or after curp
++ */
++static int ext3_ext_insert_index(handle_t *handle,
++                               struct ext3_extents_tree *tree,
++                               struct ext3_ext_path *curp,
++                               int logical, int ptr)
++{
++      struct ext3_extent_idx *ix;
++      int len, err;
++
++      if ((err = ext3_ext_get_access(handle, tree, curp)))
++              return err;
++
++      EXT_ASSERT(logical != curp->p_idx->ei_block);
++      len = EXT_MAX_INDEX(curp->p_hdr) - curp->p_idx;
++      if (logical > curp->p_idx->ei_block) {
++              /* insert after */
++              if (curp->p_idx != EXT_LAST_INDEX(curp->p_hdr)) {
++                      len = (len - 1) * sizeof(struct ext3_extent_idx);
++                      len = len < 0 ? 0 : len;
++                      ext_debug(tree, "insert new index %d after: %d. "
++                                "move %d from 0x%p to 0x%p\n",
++                                logical, ptr, len,
++                                (curp->p_idx + 1), (curp->p_idx + 2));
++                      memmove(curp->p_idx + 2, curp->p_idx + 1, len);
++              }
++              ix = curp->p_idx + 1;
++      } else {
++              /* insert before */
++              len = len * sizeof(struct ext3_extent_idx);
++              len = len < 0 ? 0 : len;
++              ext_debug(tree, "insert new index %d before: %d. "
++                        "move %d from 0x%p to 0x%p\n",
++                        logical, ptr, len,
++                        curp->p_idx, (curp->p_idx + 1));
++              memmove(curp->p_idx + 1, curp->p_idx, len);
++              ix = curp->p_idx;
++      }
++
++      ix->ei_block = logical;
++      ix->ei_leaf = ptr;
++      curp->p_hdr->eh_entries++;
++
++      EXT_ASSERT(curp->p_hdr->eh_entries <= curp->p_hdr->eh_max);
++      EXT_ASSERT(ix <= EXT_LAST_INDEX(curp->p_hdr));
++
++      err = ext3_ext_dirty(handle, tree, curp);
++      ext3_std_error(tree->inode->i_sb, err);
++
++      return err;
++}
++
++/*
++ * routine inserts new subtree into the path, using free index entry
++ * at depth 'at:
++ *  - allocates all needed blocks (new leaf and all intermediate index blocks)
++ *  - makes decision where to split
++ *  - moves remaining extens and index entries (right to the split point)
++ *    into the newly allocated blocks
++ *  - initialize subtree
++ */
++static int ext3_ext_split(handle_t *handle, struct ext3_extents_tree *tree,
++                        struct ext3_ext_path *path,
++                        struct ext3_extent *newext, int at)
++{
++      struct buffer_head *bh = NULL;
++      int depth = EXT_DEPTH(tree);
++      struct ext3_extent_header *neh;
++      struct ext3_extent_idx *fidx;
++      struct ext3_extent *ex;
++      int i = at, k, m, a;
++      unsigned long newblock, oldblock, border;
++      int *ablocks = NULL; /* array of allocated blocks */
++      int err = 0;
++
++      /* make decision: where to split? */
++      /* FIXME: now desicion is simplest: at current extent */
++
++      /* if current leaf will be splitted, then we should use 
++       * border from split point */
++      EXT_ASSERT(path[depth].p_ext <= EXT_MAX_EXTENT(path[depth].p_hdr));
++      if (path[depth].p_ext != EXT_MAX_EXTENT(path[depth].p_hdr)) {
++              border = path[depth].p_ext[1].ee_block;
++              ext_debug(tree, "leaf will be splitted."
++                        " next leaf starts at %d\n",
++                        (int)border);
++      } else {
++              border = newext->ee_block;
++              ext_debug(tree, "leaf will be added."
++                        " next leaf starts at %d\n",
++                        (int)border);
++      }
++
++      /* 
++       * if error occurs, then we break processing
++       * and turn filesystem read-only. so, index won't
++       * be inserted and tree will be in consistent
++       * state. next mount will repair buffers too
++       */
++
++      /*
++       * get array to track all allocated blocks
++       * we need this to handle errors and free blocks
++       * upon them
++       */
++      ablocks = kmalloc(sizeof(unsigned long) * depth, GFP_NOFS);
++      if (!ablocks)
++              return -ENOMEM;
++      memset(ablocks, 0, sizeof(unsigned long) * depth);
++
++      /* allocate all needed blocks */
++      ext_debug(tree, "allocate %d blocks for indexes/leaf\n", depth - at);
++      for (a = 0; a < depth - at; a++) {
++              newblock = ext3_ext_new_block(handle, tree, path, newext, &err);
++              if (newblock == 0)
++                      goto cleanup;
++              ablocks[a] = newblock;
++      }
++
++      /* initialize new leaf */
++      newblock = ablocks[--a];
++      EXT_ASSERT(newblock);
++      bh = sb_getblk(tree->inode->i_sb, newblock);
++      if (!bh) {
++              err = -EIO;
++              goto cleanup;
++      }
++      lock_buffer(bh);
++
++      if ((err = ext3_journal_get_create_access(handle, bh)))
++              goto cleanup;
++
++      neh = EXT_BLOCK_HDR(bh);
++      neh->eh_entries = 0;
++      neh->eh_max = ext3_ext_space_block(tree);
++      neh->eh_magic = EXT3_EXT_MAGIC;
++      neh->eh_depth = 0;
++      ex = EXT_FIRST_EXTENT(neh);
++
++      /* move remain of path[depth] to the new leaf */
++      EXT_ASSERT(path[depth].p_hdr->eh_entries == path[depth].p_hdr->eh_max);
++      /* start copy from next extent */
++      /* TODO: we could do it by single memmove */
++      m = 0;
++      path[depth].p_ext++;
++      while (path[depth].p_ext <=
++                      EXT_MAX_EXTENT(path[depth].p_hdr)) {
++              ext_debug(tree, "move %d:%d:%d in new leaf %lu\n",
++                        path[depth].p_ext->ee_block,
++                        path[depth].p_ext->ee_start,
++                        path[depth].p_ext->ee_len,
++                        newblock);
++              memmove(ex++, path[depth].p_ext++, sizeof(struct ext3_extent));
++              neh->eh_entries++;
++              m++;
++      }
++      set_buffer_uptodate(bh);
++      unlock_buffer(bh);
++
++      if ((err = ext3_journal_dirty_metadata(handle, bh)))
++              goto cleanup;   
++      brelse(bh);
++      bh = NULL;
++
++      /* correct old leaf */
++      if (m) {
++              if ((err = ext3_ext_get_access(handle, tree, path + depth)))
++                      goto cleanup;
++              path[depth].p_hdr->eh_entries -= m;
++              if ((err = ext3_ext_dirty(handle, tree, path + depth)))
++                      goto cleanup;
++              
++      }
++
++      /* create intermediate indexes */
++      k = depth - at - 1;
++      EXT_ASSERT(k >= 0);
++      if (k)
++              ext_debug(tree, "create %d intermediate indices\n", k);
++      /* insert new index into current index block */
++      /* current depth stored in i var */
++      i = depth - 1;
++      while (k--) {
++              oldblock = newblock;
++              newblock = ablocks[--a];
++              bh = sb_getblk(tree->inode->i_sb, newblock);
++              if (!bh) {
++                      err = -EIO;
++                      goto cleanup;
++              }
++              lock_buffer(bh);
++
++              if ((err = ext3_journal_get_create_access(handle, bh)))
++                      goto cleanup;
++
++              neh = EXT_BLOCK_HDR(bh);
++              neh->eh_entries = 1;
++              neh->eh_magic = EXT3_EXT_MAGIC;
++              neh->eh_max = ext3_ext_space_block_idx(tree);
++              neh->eh_depth = depth - i; 
++              fidx = EXT_FIRST_INDEX(neh);
++              fidx->ei_block = border;
++              fidx->ei_leaf = oldblock;
++
++              ext_debug(tree, "int.index at %d (block %lu): %lu -> %lu\n",
++                        i, newblock, border, oldblock);
++              /* copy indexes */
++              m = 0;
++              path[i].p_idx++;
++
++              ext_debug(tree, "cur 0x%p, last 0x%p\n", path[i].p_idx,
++                        EXT_MAX_INDEX(path[i].p_hdr));
++              EXT_ASSERT(EXT_MAX_INDEX(path[i].p_hdr) ==
++                         EXT_LAST_INDEX(path[i].p_hdr));
++              while (path[i].p_idx <= EXT_MAX_INDEX(path[i].p_hdr)) {
++                      ext_debug(tree, "%d: move %d:%d in new index %lu\n",
++                                i, path[i].p_idx->ei_block,
++                                path[i].p_idx->ei_leaf, newblock);
++                      memmove(++fidx, path[i].p_idx++,
++                              sizeof(struct ext3_extent_idx));
++                      neh->eh_entries++;
++                      EXT_ASSERT(neh->eh_entries <= neh->eh_max);
++                      m++;
++              }
++              set_buffer_uptodate(bh);
++              unlock_buffer(bh);
++
++              if ((err = ext3_journal_dirty_metadata(handle, bh)))
++                      goto cleanup;
++              brelse(bh);
++              bh = NULL;
++
++              /* correct old index */
++              if (m) {
++                      err = ext3_ext_get_access(handle, tree, path + i);
++                      if (err)
++                              goto cleanup;
++                      path[i].p_hdr->eh_entries -= m;
++                      err = ext3_ext_dirty(handle, tree, path + i);
++                      if (err)
++                              goto cleanup;
++              }
++
++              i--;
++      }
++
++      /* insert new index */
++      if (!err)
++              err = ext3_ext_insert_index(handle, tree, path + at,
++                                          border, newblock);
++
++cleanup:
++      if (bh) {
++              if (buffer_locked(bh))
++                      unlock_buffer(bh);
++              brelse(bh);
++      }
++
++      if (err) {
++              /* free all allocated blocks in error case */
++              for (i = 0; i < depth; i++) {
++                      if (!ablocks[i])
++                              continue;
++                      ext3_free_blocks(handle, tree->inode, ablocks[i], 1);
++              }
++      }
++      kfree(ablocks);
++
++      return err;
++}
++
++/*
++ * routine implements tree growing procedure:
++ *  - allocates new block
++ *  - moves top-level data (index block or leaf) into the new block
++ *  - initialize new top-level, creating index that points to the
++ *    just created block
++ */
++static int ext3_ext_grow_indepth(handle_t *handle,
++                               struct ext3_extents_tree *tree,
++                               struct ext3_ext_path *path,
++                               struct ext3_extent *newext)
++{
++      struct ext3_ext_path *curp = path;
++      struct ext3_extent_header *neh;
++      struct ext3_extent_idx *fidx;
++      struct buffer_head *bh;
++      unsigned long newblock;
++      int err = 0;
++
++      newblock = ext3_ext_new_block(handle, tree, path, newext, &err);
++      if (newblock == 0)
++              return err;
++
++      bh = sb_getblk(tree->inode->i_sb, newblock);
++      if (!bh) {
++              err = -EIO;
++              ext3_std_error(tree->inode->i_sb, err);
++              return err;
++      }
++      lock_buffer(bh);
++
++      if ((err = ext3_journal_get_create_access(handle, bh))) {
++              unlock_buffer(bh);
++              goto out;       
++      }
++
++      /* move top-level index/leaf into new block */
++      memmove(bh->b_data, curp->p_hdr, tree->buffer_len);
++
++      /* set size of new block */
++      neh = EXT_BLOCK_HDR(bh);
++      /* old root could have indexes or leaves
++       * so calculate eh_max right way */
++      if (EXT_DEPTH(tree))
++              neh->eh_max = ext3_ext_space_block_idx(tree);
++      else
++              neh->eh_max = ext3_ext_space_block(tree);
++      neh->eh_magic = EXT3_EXT_MAGIC;
++      set_buffer_uptodate(bh);
++      unlock_buffer(bh);
++
++      if ((err = ext3_journal_dirty_metadata(handle, bh)))
++              goto out;
++
++      /* create index in new top-level index: num,max,pointer */
++      if ((err = ext3_ext_get_access(handle, tree, curp)))
++              goto out;
++
++      curp->p_hdr->eh_magic = EXT3_EXT_MAGIC;
++      curp->p_hdr->eh_max = ext3_ext_space_root_idx(tree);
++      curp->p_hdr->eh_entries = 1;
++      curp->p_idx = EXT_FIRST_INDEX(curp->p_hdr);
++      /* FIXME: it works, but actually path[0] can be index */
++      curp->p_idx->ei_block = EXT_FIRST_EXTENT(path[0].p_hdr)->ee_block;
++      curp->p_idx->ei_leaf = newblock;
++
++      neh = EXT_ROOT_HDR(tree);
++      fidx = EXT_FIRST_INDEX(neh);
++      ext_debug(tree, "new root: num %d(%d), lblock %d, ptr %d\n",
++                neh->eh_entries, neh->eh_max, fidx->ei_block, fidx->ei_leaf); 
++
++      neh->eh_depth = path->p_depth + 1;
++      err = ext3_ext_dirty(handle, tree, curp);
++out:
++      brelse(bh);
++
++      return err;
++}
++
++/*
++ * routine finds empty index and adds new leaf. if no free index found
++ * then it requests in-depth growing
++ */
++static int ext3_ext_create_new_leaf(handle_t *handle,
++                                  struct ext3_extents_tree *tree,
++                                  struct ext3_ext_path *path,
++                                  struct ext3_extent *newext)
++{
++      struct ext3_ext_path *curp;
++      int depth, i, err = 0;
++
++repeat:
++      i = depth = EXT_DEPTH(tree);
++      
++      /* walk up to the tree and look for free index entry */
++      curp = path + depth;
++      while (i > 0 && !EXT_HAS_FREE_INDEX(curp)) {
++              i--;
++              curp--;
++      }
++
++      /* we use already allocated block for index block
++       * so, subsequent data blocks should be contigoues */
++      if (EXT_HAS_FREE_INDEX(curp)) {
++              /* if we found index with free entry, then use that
++               * entry: create all needed subtree and add new leaf */
++              err = ext3_ext_split(handle, tree, path, newext, i);
++
++              /* refill path */
++              ext3_ext_drop_refs(path);
++              path = ext3_ext_find_extent(tree, newext->ee_block, path);
++              if (IS_ERR(path))
++                      err = PTR_ERR(path);
++      } else {
++              /* tree is full, time to grow in depth */
++              err = ext3_ext_grow_indepth(handle, tree, path, newext);
++
++              /* refill path */
++              ext3_ext_drop_refs(path);
++              path = ext3_ext_find_extent(tree, newext->ee_block, path);
++              if (IS_ERR(path))
++                      err = PTR_ERR(path);
++
++              /*
++               * only first (depth 0 -> 1) produces free space
++               * in all other cases we have to split growed tree
++               */
++              depth = EXT_DEPTH(tree);
++              if (path[depth].p_hdr->eh_entries == path[depth].p_hdr->eh_max) {
++                      /* now we need split */
++                      goto repeat;
++              }
++      }
++
++      if (err)
++              return err;
++
++      return 0;
++}
++
++/*
++ * returns allocated block in subsequent extent or EXT_MAX_BLOCK
++ * NOTE: it consider block number from index entry as
++ * allocated block. thus, index entries have to be consistent
++ * with leafs
++ */
++static unsigned long
++ext3_ext_next_allocated_block(struct ext3_ext_path *path)
++{
++      int depth;
++
++      EXT_ASSERT(path != NULL);
++      depth = path->p_depth;
++
++      if (depth == 0 && path->p_ext == NULL)
++              return EXT_MAX_BLOCK;
++
++      /* FIXME: what if index isn't full ?! */
++      while (depth >= 0) {
++              if (depth == path->p_depth) {
++                      /* leaf */
++                      if (path[depth].p_ext !=
++                          EXT_LAST_EXTENT(path[depth].p_hdr))
++                              return path[depth].p_ext[1].ee_block;
++              } else {
++                      /* index */
++                      if (path[depth].p_idx !=
++                          EXT_LAST_INDEX(path[depth].p_hdr))
++                              return path[depth].p_idx[1].ei_block;
++              }
++              depth--;        
++      }
++
++      return EXT_MAX_BLOCK;
++}
++
++/*
++ * returns first allocated block from next leaf or EXT_MAX_BLOCK
++ */
++static unsigned ext3_ext_next_leaf_block(struct ext3_extents_tree *tree,
++                                       struct ext3_ext_path *path)
++{
++      int depth;
++
++      EXT_ASSERT(path != NULL);
++      depth = path->p_depth;
++
++      /* zero-tree has no leaf blocks at all */
++      if (depth == 0)
++              return EXT_MAX_BLOCK;
++
++      /* go to index block */
++      depth--;
++      
++      while (depth >= 0) {
++              if (path[depth].p_idx !=
++                  EXT_LAST_INDEX(path[depth].p_hdr))
++                      return path[depth].p_idx[1].ei_block;
++              depth--;        
++      }
++
++      return EXT_MAX_BLOCK;
++}
++
++/*
++ * if leaf gets modified and modified extent is first in the leaf
++ * then we have to correct all indexes above
++ * TODO: do we need to correct tree in all cases?
++ */
++int ext3_ext_correct_indexes(handle_t *handle, struct ext3_extents_tree *tree,
++                           struct ext3_ext_path *path)
++{
++      struct ext3_extent_header *eh;
++      int depth = EXT_DEPTH(tree);    
++      struct ext3_extent *ex;
++      unsigned long border;
++      int k, err = 0;
++      
++      eh = path[depth].p_hdr;
++      ex = path[depth].p_ext;
++      EXT_ASSERT(ex);
++      EXT_ASSERT(eh);
++      
++      if (depth == 0) {
++              /* there is no tree at all */
++              return 0;
++      }
++      
++      if (ex != EXT_FIRST_EXTENT(eh)) {
++              /* we correct tree if first leaf got modified only */
++              return 0;
++      }
++      
++      /*
++       * TODO: we need correction if border is smaller then current one
++       */
++      k = depth - 1;
++      border = path[depth].p_ext->ee_block;
++      if ((err = ext3_ext_get_access(handle, tree, path + k)))
++              return err;
++      path[k].p_idx->ei_block = border;
++      if ((err = ext3_ext_dirty(handle, tree, path + k)))
++              return err;
++
++      while (k--) {
++              /* change all left-side indexes */
++              if (path[k+1].p_idx != EXT_FIRST_INDEX(path[k+1].p_hdr))
++                      break;
++              if ((err = ext3_ext_get_access(handle, tree, path + k)))
++                      break;
++              path[k].p_idx->ei_block = border;
++              if ((err = ext3_ext_dirty(handle, tree, path + k)))
++                      break;
++      }
++
++      return err;
++}
++
++static int inline
++ext3_can_extents_be_merged(struct ext3_extents_tree *tree,
++                         struct ext3_extent *ex1,
++                         struct ext3_extent *ex2)
++{
++      if (ex1->ee_block + ex1->ee_len != ex2->ee_block)
++              return 0;
++
++#ifdef AGRESSIVE_TEST
++      if (ex1->ee_len >= 4)
++              return 0;
++#endif
++
++      if (!tree->ops->mergable)
++              return 1;
++
++      return tree->ops->mergable(ex1, ex2);
++}
++
++/*
++ * this routine tries to merge requsted extent into the existing
++ * extent or inserts requested extent as new one into the tree,
++ * creating new leaf in no-space case
++ */
++int ext3_ext_insert_extent(handle_t *handle, struct ext3_extents_tree *tree,
++                         struct ext3_ext_path *path,
++                         struct ext3_extent *newext)
++{
++      struct ext3_extent_header * eh;
++      struct ext3_extent *ex, *fex;
++      struct ext3_extent *nearex; /* nearest extent */
++      struct ext3_ext_path *npath = NULL;
++      int depth, len, err, next;
++
++      EXT_ASSERT(newext->ee_len > 0);
++      depth = EXT_DEPTH(tree);
++      ex = path[depth].p_ext;
++      EXT_ASSERT(path[depth].p_hdr);
++
++      /* try to insert block into found extent and return */
++      if (ex && ext3_can_extents_be_merged(tree, ex, newext)) {
++              ext_debug(tree, "append %d block to %d:%d (from %d)\n",
++                        newext->ee_len, ex->ee_block, ex->ee_len,
++                        ex->ee_start);
++              if ((err = ext3_ext_get_access(handle, tree, path + depth)))
++                      return err;
++              ex->ee_len += newext->ee_len;
++              eh = path[depth].p_hdr;
++              nearex = ex;
++              goto merge;
++      }
++
++repeat:
++      depth = EXT_DEPTH(tree);
++      eh = path[depth].p_hdr;
++      if (eh->eh_entries < eh->eh_max)
++              goto has_space;
++
++      /* probably next leaf has space for us? */
++      fex = EXT_LAST_EXTENT(eh);
++      next = ext3_ext_next_leaf_block(tree, path);
++      if (newext->ee_block > fex->ee_block && next != EXT_MAX_BLOCK) {
++              ext_debug(tree, "next leaf block - %d\n", next);
++              EXT_ASSERT(!npath);
++              npath = ext3_ext_find_extent(tree, next, NULL);
++              if (IS_ERR(npath))
++                      return PTR_ERR(npath);
++              EXT_ASSERT(npath->p_depth == path->p_depth);
++              eh = npath[depth].p_hdr;
++              if (eh->eh_entries < eh->eh_max) {
++                      ext_debug(tree, "next leaf isnt full(%d)\n",
++                                eh->eh_entries);
++                      path = npath;
++                      goto repeat;
++              }
++              ext_debug(tree, "next leaf hasno free space(%d,%d)\n",
++                        eh->eh_entries, eh->eh_max);
++      }
++
++      /*
++       * there is no free space in found leaf
++       * we're gonna add new leaf in the tree
++       */
++      err = ext3_ext_create_new_leaf(handle, tree, path, newext);
++      if (err)
++              goto cleanup;
++      depth = EXT_DEPTH(tree);
++      eh = path[depth].p_hdr;
++
++has_space:
++      nearex = path[depth].p_ext;
++
++      if ((err = ext3_ext_get_access(handle, tree, path + depth)))
++              goto cleanup;
++
++      if (!nearex) {
++              /* there is no extent in this leaf, create first one */
++              ext_debug(tree, "first extent in the leaf: %d:%d:%d\n",
++                        newext->ee_block, newext->ee_start,
++                        newext->ee_len);
++              path[depth].p_ext = EXT_FIRST_EXTENT(eh);
++      } else if (newext->ee_block > nearex->ee_block) {
++              EXT_ASSERT(newext->ee_block != nearex->ee_block);
++              if (nearex != EXT_LAST_EXTENT(eh)) {
++                      len = EXT_MAX_EXTENT(eh) - nearex;
++                      len = (len - 1) * sizeof(struct ext3_extent);
++                      len = len < 0 ? 0 : len;
++                      ext_debug(tree, "insert %d:%d:%d after: nearest 0x%p, "
++                                "move %d from 0x%p to 0x%p\n",
++                                newext->ee_block, newext->ee_start,
++                                newext->ee_len,
++                                nearex, len, nearex + 1, nearex + 2);
++                      memmove(nearex + 2, nearex + 1, len);
++              }
++              path[depth].p_ext = nearex + 1;
++      } else {
++              EXT_ASSERT(newext->ee_block != nearex->ee_block);
++              len = (EXT_MAX_EXTENT(eh) - nearex) * sizeof(struct ext3_extent);
++              len = len < 0 ? 0 : len;
++              ext_debug(tree, "insert %d:%d:%d before: nearest 0x%p, "
++                        "move %d from 0x%p to 0x%p\n",
++                        newext->ee_block, newext->ee_start, newext->ee_len,
++                        nearex, len, nearex + 1, nearex + 2);
++              memmove(nearex + 1, nearex, len);
++              path[depth].p_ext = nearex;
++      }
++
++      eh->eh_entries++;
++      nearex = path[depth].p_ext;
++      nearex->ee_block = newext->ee_block;
++      nearex->ee_start = newext->ee_start;
++      nearex->ee_len = newext->ee_len;
++      /* FIXME: support for large fs */
++      nearex->ee_start_hi = 0;
++
++merge:
++      /* try to merge extents to the right */
++      while (nearex < EXT_LAST_EXTENT(eh)) {
++              if (!ext3_can_extents_be_merged(tree, nearex, nearex + 1))
++                      break;
++              /* merge with next extent! */
++              nearex->ee_len += nearex[1].ee_len;
++              if (nearex + 1 < EXT_LAST_EXTENT(eh)) {
++                      len = (EXT_LAST_EXTENT(eh) - nearex - 1) *
++                              sizeof(struct ext3_extent);
++                      memmove(nearex + 1, nearex + 2, len);
++              }
++              eh->eh_entries--;
++              EXT_ASSERT(eh->eh_entries > 0);
++      }
++
++      /* try to merge extents to the left */
++
++      /* time to correct all indexes above */
++      err = ext3_ext_correct_indexes(handle, tree, path);
++      if (err)
++              goto cleanup;
++
++      err = ext3_ext_dirty(handle, tree, path + depth);
++
++cleanup:
++      if (npath) {
++              ext3_ext_drop_refs(npath);
++              kfree(npath);
++      }
++      ext3_ext_tree_changed(tree);
++      ext3_ext_invalidate_cache(tree);
++      return err;
++}
++
++int ext3_ext_walk_space(struct ext3_extents_tree *tree, unsigned long block,
++                      unsigned long num, ext_prepare_callback func)
++{
++      struct ext3_ext_path *path = NULL;
++      struct ext3_ext_cache cbex;
++      struct ext3_extent *ex;
++      unsigned long next, start = 0, end = 0;
++      unsigned long last = block + num;
++      int depth, exists, err = 0;
++
++      EXT_ASSERT(tree);
++      EXT_ASSERT(func);
++      EXT_ASSERT(tree->inode);
++      EXT_ASSERT(tree->root);
++
++      while (block < last && block != EXT_MAX_BLOCK) {
++              num = last - block;
++              /* find extent for this block */
++              path = ext3_ext_find_extent(tree, block, path);
++              if (IS_ERR(path)) {
++                      err = PTR_ERR(path);
++                      path = NULL;
++                      break;
++              }
++
++              depth = EXT_DEPTH(tree);
++              EXT_ASSERT(path[depth].p_hdr);
++              ex = path[depth].p_ext;
++              next = ext3_ext_next_allocated_block(path);
++
++              exists = 0;
++              if (!ex) {
++                      /* there is no extent yet, so try to allocate
++                       * all requested space */
++                      start = block;
++                      end = block + num;
++              } else if (ex->ee_block > block) {
++                      /* need to allocate space before found extent */
++                      start = block;
++                      end = ex->ee_block;
++                      if (block + num < end)
++                              end = block + num;
++              } else if (block >= ex->ee_block + ex->ee_len) {
++                      /* need to allocate space after found extent */
++                      start = block;
++                      end = block + num;
++                      if (end >= next)
++                              end = next;
++              } else if (block >= ex->ee_block) {
++                      /* 
++                       * some part of requested space is covered
++                       * by found extent
++                       */
++                      start = block;
++                      end = ex->ee_block + ex->ee_len;
++                      if (block + num < end)
++                              end = block + num;
++                      exists = 1;
++              } else {
++                      BUG();
++              }
++              EXT_ASSERT(end > start);
++
++              if (!exists) {
++                      cbex.ec_block = start;
++                      cbex.ec_len = end - start;
++                      cbex.ec_start = 0;
++                      cbex.ec_type = EXT3_EXT_CACHE_GAP;
++              } else {
++                      cbex.ec_block = ex->ee_block;
++                      cbex.ec_len = ex->ee_len;
++                      cbex.ec_start = ex->ee_start;
++                      cbex.ec_type = EXT3_EXT_CACHE_EXTENT;
++              }
++
++              EXT_ASSERT(cbex.ec_len > 0);
++              EXT_ASSERT(path[depth].p_hdr);
++              err = func(tree, path, &cbex);
++              ext3_ext_drop_refs(path);
++
++              if (err < 0)
++                      break;
++              if (err == EXT_REPEAT)
++                      continue;
++              else if (err == EXT_BREAK) {
++                      err = 0;
++                      break;
++              }
++
++              if (EXT_DEPTH(tree) != depth) {
++                      /* depth was changed. we have to realloc path */
++                      kfree(path);
++                      path = NULL;
++              }
++
++              block = cbex.ec_block + cbex.ec_len;
++      }
++
++      if (path) {
++              ext3_ext_drop_refs(path);
++              kfree(path);
++      }
++
++      return err;
++}
++
++static inline void
++ext3_ext_put_in_cache(struct ext3_extents_tree *tree, __u32 block,
++                    __u32 len, __u32 start, int type)
++{
++      EXT_ASSERT(len > 0);
++      if (tree->cex) {
++              tree->cex->ec_type = type;
++              tree->cex->ec_block = block;
++              tree->cex->ec_len = len;
++              tree->cex->ec_start = start;
++      }
++}
++
++/*
++ * this routine calculate boundaries of the gap requested block fits into
++ * and cache this gap
++ */
++static inline void
++ext3_ext_put_gap_in_cache(struct ext3_extents_tree *tree,
++                        struct ext3_ext_path *path,
++                        unsigned long block)
++{
++      int depth = EXT_DEPTH(tree);
++      unsigned long lblock, len;
++      struct ext3_extent *ex;
++
++      if (!tree->cex)
++              return;
++
++      ex = path[depth].p_ext;
++      if (ex == NULL) {
++              /* there is no extent yet, so gap is [0;-] */
++              lblock = 0;
++              len = EXT_MAX_BLOCK;
++              ext_debug(tree, "cache gap(whole file):");
++      } else if (block < ex->ee_block) {
++              lblock = block;
++              len = ex->ee_block - block;
++              ext_debug(tree, "cache gap(before): %lu [%lu:%lu]",
++                        (unsigned long) block,
++                        (unsigned long) ex->ee_block,
++                        (unsigned long) ex->ee_len);
++      } else if (block >= ex->ee_block + ex->ee_len) {
++              lblock = ex->ee_block + ex->ee_len;
++              len = ext3_ext_next_allocated_block(path);
++              ext_debug(tree, "cache gap(after): [%lu:%lu] %lu",
++                        (unsigned long) ex->ee_block,
++                        (unsigned long) ex->ee_len,
++                        (unsigned long) block);
++              EXT_ASSERT(len > lblock);
++              len = len - lblock;
++      } else {
++              lblock = len = 0;
++              BUG();
++      }
++
++      ext_debug(tree, " -> %lu:%lu\n", (unsigned long) lblock, len);
++      ext3_ext_put_in_cache(tree, lblock, len, 0, EXT3_EXT_CACHE_GAP);
++}
++
++static inline int
++ext3_ext_in_cache(struct ext3_extents_tree *tree, unsigned long block,
++                struct ext3_extent *ex)
++{
++      struct ext3_ext_cache *cex = tree->cex;
++
++      /* is there cache storage at all? */
++      if (!cex)
++              return EXT3_EXT_CACHE_NO;
++
++      /* has cache valid data? */
++      if (cex->ec_type == EXT3_EXT_CACHE_NO)
++              return EXT3_EXT_CACHE_NO;
++
++      EXT_ASSERT(cex->ec_type == EXT3_EXT_CACHE_GAP ||
++                 cex->ec_type == EXT3_EXT_CACHE_EXTENT);
++      if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) {
++              ex->ee_block = cex->ec_block;
++              ex->ee_start = cex->ec_start;
++              ex->ee_len = cex->ec_len;
++              ext_debug(tree, "%lu cached by %lu:%lu:%lu\n",
++                        (unsigned long) block,
++                        (unsigned long) ex->ee_block,
++                        (unsigned long) ex->ee_len,
++                        (unsigned long) ex->ee_start);
++              return cex->ec_type;
++      }
++
++      /* not in cache */
++      return EXT3_EXT_CACHE_NO;
++}
++
++/*
++ * routine removes index from the index block
++ * it's used in truncate case only. thus all requests are for
++ * last index in the block only
++ */
++int ext3_ext_rm_idx(handle_t *handle, struct ext3_extents_tree *tree,
++                  struct ext3_ext_path *path)
++{
++      struct buffer_head *bh;
++      int err;
++      
++      /* free index block */
++      path--;
++      EXT_ASSERT(path->p_hdr->eh_entries);
++      if ((err = ext3_ext_get_access(handle, tree, path)))
++              return err;
++      path->p_hdr->eh_entries--;
++      if ((err = ext3_ext_dirty(handle, tree, path)))
++              return err;
++      ext_debug(tree, "index is empty, remove it, free block %d\n",
++                path->p_idx->ei_leaf);
++      bh = sb_find_get_block(tree->inode->i_sb, path->p_idx->ei_leaf);
++      ext3_forget(handle, 1, tree->inode, bh, path->p_idx->ei_leaf);
++      ext3_free_blocks(handle, tree->inode, path->p_idx->ei_leaf, 1);
++      return err;
++}
++
++int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *tree,
++                                   struct ext3_ext_path *path)
++{
++      int depth = EXT_DEPTH(tree);
++      int needed;
++
++      if (path) {
++              /* probably there is space in leaf? */
++              if (path[depth].p_hdr->eh_entries < path[depth].p_hdr->eh_max)
++                      return 1;
++      }
++      
++      /*
++       * the worste case we're expecting is creation of the
++       * new root (growing in depth) with index splitting
++       * for splitting we have to consider depth + 1 because
++       * previous growing could increase it
++       */
++      depth = depth + 1;
++
++      /* 
++       * growing in depth:
++       * block allocation + new root + old root
++       */
++      needed = EXT3_ALLOC_NEEDED + 2;
++
++      /* index split. we may need:
++       *   allocate intermediate indexes and new leaf
++       *   change two blocks at each level, but root
++       *   modify root block (inode)
++       */
++      needed += (depth * EXT3_ALLOC_NEEDED) + (2 * depth) + 1;
++
++      return needed;
++}
++
++static int
++ext3_ext_split_for_rm(handle_t *handle, struct ext3_extents_tree *tree,
++                    struct ext3_ext_path *path, unsigned long start,
++                    unsigned long end)
++{
++      struct ext3_extent *ex, tex;
++      struct ext3_ext_path *npath;
++      int depth, creds, err;
++
++      depth = EXT_DEPTH(tree);
++      ex = path[depth].p_ext;
++      EXT_ASSERT(ex);
++      EXT_ASSERT(end < ex->ee_block + ex->ee_len - 1);
++      EXT_ASSERT(ex->ee_block < start);
++
++      /* calculate tail extent */
++      tex.ee_block = end + 1;
++      EXT_ASSERT(tex.ee_block < ex->ee_block + ex->ee_len);
++      tex.ee_len = ex->ee_block + ex->ee_len - tex.ee_block;
++
++      creds = ext3_ext_calc_credits_for_insert(tree, path);
++      handle = ext3_ext_journal_restart(handle, creds);
++      if (IS_ERR(handle))
++              return PTR_ERR(handle);
++      
++      /* calculate head extent. use primary extent */
++      err = ext3_ext_get_access(handle, tree, path + depth);
++      if (err)
++              return err;
++      ex->ee_len = start - ex->ee_block;
++      err = ext3_ext_dirty(handle, tree, path + depth);
++      if (err)
++              return err;
++
++      /* FIXME: some callback to free underlying resource
++       * and correct ee_start? */
++      ext_debug(tree, "split extent: head %u:%u, tail %u:%u\n",
++                ex->ee_block, ex->ee_len, tex.ee_block, tex.ee_len);
++
++      npath = ext3_ext_find_extent(tree, ex->ee_block, NULL);
++      if (IS_ERR(npath))
++              return PTR_ERR(npath);
++      depth = EXT_DEPTH(tree);
++      EXT_ASSERT(npath[depth].p_ext->ee_block == ex->ee_block);
++      EXT_ASSERT(npath[depth].p_ext->ee_len == ex->ee_len);
++
++      err = ext3_ext_insert_extent(handle, tree, npath, &tex);
++      ext3_ext_drop_refs(npath);
++      kfree(npath);
++
++      return err;
++}
++
++static int
++ext3_ext_rm_leaf(handle_t *handle, struct ext3_extents_tree *tree,
++               struct ext3_ext_path *path, unsigned long start,
++               unsigned long end)
++{
++      struct ext3_extent *ex, *fu = NULL, *lu, *le;
++      int err = 0, correct_index = 0;
++      int depth = EXT_DEPTH(tree), credits;
++      struct ext3_extent_header *eh;
++      unsigned a, b, block, num;
++
++      ext_debug(tree, "remove [%lu:%lu] in leaf\n", start, end);
++      if (!path[depth].p_hdr)
++              path[depth].p_hdr = EXT_BLOCK_HDR(path[depth].p_bh);
++      eh = path[depth].p_hdr;
++      EXT_ASSERT(eh);
++      EXT_ASSERT(eh->eh_entries <= eh->eh_max);
++      EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
++      
++      /* find where to start removing */
++      le = ex = EXT_LAST_EXTENT(eh);
++      while (ex != EXT_FIRST_EXTENT(eh)) {
++              if (ex->ee_block <= end)
++                      break;
++              ex--;
++      }
++
++      if (start > ex->ee_block && end < ex->ee_block + ex->ee_len - 1) {
++              /* removal of internal part of the extent requested
++               * tail and head must be placed in different extent
++               * so, we have to insert one more extent */
++              path[depth].p_ext = ex;
++              return ext3_ext_split_for_rm(handle, tree, path, start, end);
++      }
++      
++      lu = ex;
++      while (ex >= EXT_FIRST_EXTENT(eh) && ex->ee_block + ex->ee_len > start) {
++              ext_debug(tree, "remove ext %u:%u\n", ex->ee_block, ex->ee_len);
++              path[depth].p_ext = ex;
++      
++              a = ex->ee_block > start ? ex->ee_block : start;
++              b = ex->ee_block + ex->ee_len - 1 < end ?
++                      ex->ee_block + ex->ee_len - 1 : end;
++              
++              ext_debug(tree, "  border %u:%u\n", a, b);
++
++              if (a != ex->ee_block && b != ex->ee_block + ex->ee_len - 1) {
++                      block = 0;
++                      num = 0;
++                      BUG();
++              } else if (a != ex->ee_block) {
++                      /* remove tail of the extent */
++                      block = ex->ee_block;
++                      num = a - block;
++              } else if (b != ex->ee_block + ex->ee_len - 1) {
++                      /* remove head of the extent */
++                      block = a;
++                      num = b - a;
++              } else {
++                      /* remove whole extent: excelent! */
++                      block = ex->ee_block; 
++                      num = 0;
++                      EXT_ASSERT(a == ex->ee_block &&
++                                 b == ex->ee_block + ex->ee_len - 1);
++              }
++
++              if (ex == EXT_FIRST_EXTENT(eh))
++                      correct_index = 1;
++
++              credits = 1;
++              if (correct_index)
++                      credits += (EXT_DEPTH(tree) * EXT3_ALLOC_NEEDED) + 1;
++              if (tree->ops->remove_extent_credits)
++                      credits+=tree->ops->remove_extent_credits(tree,ex,a,b);
++              
++              handle = ext3_ext_journal_restart(handle, credits);
++              if (IS_ERR(handle)) {
++                      err = PTR_ERR(handle);
++                      goto out;
++              }
++
++              err = ext3_ext_get_access(handle, tree, path + depth);
++              if (err)
++                      goto out;
++
++              if (tree->ops->remove_extent)
++                      err = tree->ops->remove_extent(tree, ex, a, b);
++              if (err)
++                      goto out;
++
++              if (num == 0) {
++                      /* this extent is removed entirely mark slot unused */
++                      ex->ee_start = 0;
++                      eh->eh_entries--;
++                      fu = ex;
++              }
++
++              ex->ee_block = block;
++              ex->ee_len = num;
++
++              err = ext3_ext_dirty(handle, tree, path + depth);
++              if (err)
++                      goto out;
++
++              ext_debug(tree, "new extent: %u:%u:%u\n",
++                        ex->ee_block, ex->ee_len, ex->ee_start);
++              ex--;
++      }
++
++      if (fu) {
++              /* reuse unused slots */
++              while (lu < le) {
++                      if (lu->ee_start) {
++                              *fu = *lu;
++                              lu->ee_start = 0;
++                              fu++;
++                      }
++                      lu++;
++              }
++      }
++
++      if (correct_index && eh->eh_entries)
++              err = ext3_ext_correct_indexes(handle, tree, path);
++
++      /* if this leaf is free, then we should
++       * remove it from index block above */
++      if (err == 0 && eh->eh_entries == 0 && path[depth].p_bh != NULL)
++              err = ext3_ext_rm_idx(handle, tree, path + depth);
++
++out:
++      return err;
++}
++
++
++static struct ext3_extent_idx *
++ext3_ext_last_covered(struct ext3_extent_header *hdr, unsigned long block)
++{
++      struct ext3_extent_idx *ix;
++      
++      ix = EXT_LAST_INDEX(hdr);
++      while (ix != EXT_FIRST_INDEX(hdr)) {
++              if (ix->ei_block <= block)
++                      break;
++              ix--;
++      }
++      return ix;
++}
++
++/*
++ * returns 1 if current index have to be freed (even partial)
++ */
++static int inline
++ext3_ext_more_to_rm(struct ext3_ext_path *path)
++{
++      EXT_ASSERT(path->p_idx);
++
++      if (path->p_idx < EXT_FIRST_INDEX(path->p_hdr))
++              return 0;
++
++      /*
++       * if truncate on deeper level happened it it wasn't partial
++       * so we have to consider current index for truncation
++       */
++      if (path->p_hdr->eh_entries == path->p_block)
++              return 0;
++      return 1;
++}
++
++int ext3_ext_remove_space(struct ext3_extents_tree *tree,
++                        unsigned long start, unsigned long end)
++{
++      struct inode *inode = tree->inode;
++      struct super_block *sb = inode->i_sb;
++      int depth = EXT_DEPTH(tree);
++      struct ext3_ext_path *path;
++      handle_t *handle;
++      int i = 0, err = 0;
++
++      ext_debug(tree, "space to be removed: %lu:%lu\n", start, end);
++
++      /* probably first extent we're gonna free will be last in block */
++      handle = ext3_journal_start(inode, depth + 1);
++      if (IS_ERR(handle))
++              return PTR_ERR(handle);
++
++      ext3_ext_invalidate_cache(tree);
++
++      /*
++       * we start scanning from right side freeing all the blocks
++       * after i_size and walking into the deep
++       */
++      path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 1), GFP_KERNEL);
++      if (IS_ERR(path)) {
++              ext3_error(sb, __FUNCTION__, "Can't allocate path array");
++              ext3_journal_stop(handle);
++              return -ENOMEM;
++      }
++      memset(path, 0, sizeof(struct ext3_ext_path) * (depth + 1));
++      path[i].p_hdr = EXT_ROOT_HDR(tree);
++      
++      while (i >= 0 && err == 0) {
++              if (i == depth) {
++                      /* this is leaf block */
++                      err = ext3_ext_rm_leaf(handle, tree, path, start, end);
++                      /* root level have p_bh == NULL, brelse() eats this */
++                      brelse(path[i].p_bh);
++                      i--;
++                      continue;
++              }
++              
++              /* this is index block */
++              if (!path[i].p_hdr) {
++                      ext_debug(tree, "initialize header\n");
++                      path[i].p_hdr = EXT_BLOCK_HDR(path[i].p_bh);
++              }
++
++              EXT_ASSERT(path[i].p_hdr->eh_entries <= path[i].p_hdr->eh_max);
++              EXT_ASSERT(path[i].p_hdr->eh_magic == EXT3_EXT_MAGIC);
++              
++              if (!path[i].p_idx) {
++                      /* this level hasn't touched yet */
++                      path[i].p_idx =
++                              ext3_ext_last_covered(path[i].p_hdr, end);
++                      path[i].p_block = path[i].p_hdr->eh_entries + 1;
++                      ext_debug(tree, "init index ptr: hdr 0x%p, num %d\n",
++                                path[i].p_hdr, path[i].p_hdr->eh_entries);
++              } else {
++                      /* we've already was here, see at next index */
++                      path[i].p_idx--;
++              }
++
++              ext_debug(tree, "level %d - index, first 0x%p, cur 0x%p\n",
++                        i, EXT_FIRST_INDEX(path[i].p_hdr),
++                        path[i].p_idx);
++              if (ext3_ext_more_to_rm(path + i)) {
++                      /* go to the next level */
++                      ext_debug(tree, "move to level %d (block %d)\n",
++                                i + 1, path[i].p_idx->ei_leaf);
++                      memset(path + i + 1, 0, sizeof(*path));
++                      path[i+1].p_bh = sb_bread(sb, path[i].p_idx->ei_leaf);
++                      if (!path[i+1].p_bh) {
++                              /* should we reset i_size? */
++                              err = -EIO;
++                              break;
++                      }
++                      /* put actual number of indexes to know is this
++                       * number got changed at the next iteration */
++                      path[i].p_block = path[i].p_hdr->eh_entries;
++                      i++;
++              } else {
++                      /* we finish processing this index, go up */
++                      if (path[i].p_hdr->eh_entries == 0 && i > 0) {
++                              /* index is empty, remove it
++                               * handle must be already prepared by the
++                               * truncatei_leaf() */
++                              err = ext3_ext_rm_idx(handle, tree, path + i);
++                      }
++                      /* root level have p_bh == NULL, brelse() eats this */
++                      brelse(path[i].p_bh);
++                      i--;
++                      ext_debug(tree, "return to level %d\n", i);
++              }
++      }
++
++      /* TODO: flexible tree reduction should be here */
++      if (path->p_hdr->eh_entries == 0) {
++              /*
++               * truncate to zero freed all the tree
++               * so, we need to correct eh_depth
++               */
++              err = ext3_ext_get_access(handle, tree, path);
++              if (err == 0) {
++                      EXT_ROOT_HDR(tree)->eh_depth = 0;
++                      EXT_ROOT_HDR(tree)->eh_max = ext3_ext_space_root(tree);
++                      err = ext3_ext_dirty(handle, tree, path);
++              }
++      }
++      ext3_ext_tree_changed(tree);
++
++      kfree(path);
++      ext3_journal_stop(handle);
++
++      return err;
++}
++
++int ext3_ext_calc_metadata_amount(struct ext3_extents_tree *tree, int blocks)
++{
++      int lcap, icap, rcap, leafs, idxs, num;
++
++      rcap = ext3_ext_space_root(tree);
++      if (blocks <= rcap) {
++              /* all extents fit to the root */
++              return 0;
++      }
++
++      rcap = ext3_ext_space_root_idx(tree);
++      lcap = ext3_ext_space_block(tree);
++      icap = ext3_ext_space_block_idx(tree);
++
++      num = leafs = (blocks + lcap - 1) / lcap;
++      if (leafs <= rcap) {
++              /* all pointers to leafs fit to the root */
++              return leafs;
++      }
++
++      /* ok. we need separate index block(s) to link all leaf blocks */
++      idxs = (leafs + icap - 1) / icap;
++      do {
++              num += idxs;
++              idxs = (idxs + icap - 1) / icap;
++      } while (idxs > rcap);
++
++      return num;
++}
++
++/*
++ * called at mount time
++ */
++void ext3_ext_init(struct super_block *sb)
++{
++      /*
++       * possible initialization would be here
++       */
++
++      if (test_opt(sb, EXTENTS)) {
++              printk("EXT3-fs: file extents enabled");
++#ifdef AGRESSIVE_TEST
++              printk(", agressive tests");
++#endif
++#ifdef CHECK_BINSEARCH
++              printk(", check binsearch");
++#endif
++              printk("\n");
++      }
++}
++
++/*
++ * called at umount time
++ */
++void ext3_ext_release(struct super_block *sb)
++{
++}
++
++/************************************************************************
++ * VFS related routines
++ ************************************************************************/
++
++static int ext3_get_inode_write_access(handle_t *handle, void *buffer)
++{
++      /* we use in-core data, not bh */
++      return 0;
++}
++
++static int ext3_mark_buffer_dirty(handle_t *handle, void *buffer)
++{
++      struct inode *inode = buffer;
++      return ext3_mark_inode_dirty(handle, inode);
++}
++
++static int ext3_ext_mergable(struct ext3_extent *ex1,
++                           struct ext3_extent *ex2)
++{
++      /* FIXME: support for large fs */
++      if (ex1->ee_start + ex1->ee_len == ex2->ee_start)
++              return 1;
++      return 0;
++}
++
++static int
++ext3_remove_blocks_credits(struct ext3_extents_tree *tree,
++                         struct ext3_extent *ex,
++                         unsigned long from, unsigned long to)
++{
++      int needed;
++      
++      /* at present, extent can't cross block group */;
++      needed = 4; /* bitmap + group desc + sb + inode */
++
++#ifdef CONFIG_QUOTA
++      needed += 2 * EXT3_SINGLEDATA_TRANS_BLOCKS;
++#endif
++      return needed;
++}
++
++static int
++ext3_remove_blocks(struct ext3_extents_tree *tree,
++                 struct ext3_extent *ex,
++                 unsigned long from, unsigned long to)
++{
++      int needed = ext3_remove_blocks_credits(tree, ex, from, to);
++      handle_t *handle = ext3_journal_start(tree->inode, needed);
++      struct buffer_head *bh;
++      int i;
++
++      if (IS_ERR(handle))
++              return PTR_ERR(handle);
++      if (from >= ex->ee_block && to == ex->ee_block + ex->ee_len - 1) {
++              /* tail removal */
++              unsigned long num, start;
++              num = ex->ee_block + ex->ee_len - from;
++              start = ex->ee_start + ex->ee_len - num;
++              ext_debug(tree, "free last %lu blocks starting %lu\n",
++                        num, start);
++              for (i = 0; i < num; i++) {
++                      bh = sb_find_get_block(tree->inode->i_sb, start + i);
++                      ext3_forget(handle, 0, tree->inode, bh, start + i);
++              }
++              ext3_free_blocks(handle, tree->inode, start, num);
++      } else if (from == ex->ee_block && to <= ex->ee_block + ex->ee_len - 1) {
++              printk("strange request: removal %lu-%lu from %u:%u\n",
++                     from, to, ex->ee_block, ex->ee_len);
++      } else {
++              printk("strange request: removal(2) %lu-%lu from %u:%u\n",
++                     from, to, ex->ee_block, ex->ee_len);
++      }
++      ext3_journal_stop(handle);
++      return 0;
++}
++
++static int ext3_ext_find_goal(struct inode *inode,
++                            struct ext3_ext_path *path, unsigned long block)
++{
++      struct ext3_inode_info *ei = EXT3_I(inode);
++      unsigned long bg_start;
++      unsigned long colour;
++      int depth;
++      
++      if (path) {
++              struct ext3_extent *ex;
++              depth = path->p_depth;
++              
++              /* try to predict block placement */
++              if ((ex = path[depth].p_ext))
++                      return ex->ee_start + (block - ex->ee_block);
++
++              /* it looks index is empty
++               * try to find starting from index itself */
++              if (path[depth].p_bh)
++                      return path[depth].p_bh->b_blocknr;
++      }
++
++      /* OK. use inode's group */
++      bg_start = (ei->i_block_group * EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
++              le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block);
++      colour = (current->pid % 16) *
++                      (EXT3_BLOCKS_PER_GROUP(inode->i_sb) / 16);
++      return bg_start + colour + block;
++}
++
++static int ext3_new_block_cb(handle_t *handle, struct ext3_extents_tree *tree,
++                           struct ext3_ext_path *path,
++                           struct ext3_extent *ex, int *err)
++{
++      struct inode *inode = tree->inode;
++      int newblock, goal;
++      
++      EXT_ASSERT(path);
++      EXT_ASSERT(ex);
++      EXT_ASSERT(ex->ee_start);
++      EXT_ASSERT(ex->ee_len);
++      
++      /* reuse block from the extent to order data/metadata */
++      newblock = ex->ee_start++;
++      ex->ee_len--;
++      if (ex->ee_len == 0) {
++              ex->ee_len = 1;
++              /* allocate new block for the extent */
++              goal = ext3_ext_find_goal(inode, path, ex->ee_block);
++              ex->ee_start = ext3_new_block(handle, inode, goal, err);
++              if (ex->ee_start == 0) {
++                      /* error occured: restore old extent */
++                      ex->ee_start = newblock;
++                      return 0;
++              }
++      }
++      return newblock;
++}
++
++static struct ext3_extents_helpers ext3_blockmap_helpers = {
++      .get_write_access       = ext3_get_inode_write_access,
++      .mark_buffer_dirty      = ext3_mark_buffer_dirty,
++      .mergable               = ext3_ext_mergable,
++      .new_block              = ext3_new_block_cb,
++      .remove_extent          = ext3_remove_blocks,
++      .remove_extent_credits  = ext3_remove_blocks_credits,
++};
++
++void ext3_init_tree_desc(struct ext3_extents_tree *tree,
++                       struct inode *inode)
++{
++      tree->inode = inode;
++      tree->root = (void *) EXT3_I(inode)->i_data;
++      tree->buffer = (void *) inode;
++      tree->buffer_len = sizeof(EXT3_I(inode)->i_data);
++      tree->cex = (struct ext3_ext_cache *) &EXT3_I(inode)->i_cached_extent;
++      tree->ops = &ext3_blockmap_helpers;
++}
++
++int ext3_ext_get_block(handle_t *handle, struct inode *inode,
++                     long iblock, struct buffer_head *bh_result,
++                     int create, int extend_disksize)
++{
++      struct ext3_ext_path *path = NULL;
++      struct ext3_extent newex;
++      struct ext3_extent *ex;
++      int goal, newblock, err = 0, depth;
++      struct ext3_extents_tree tree;
++
++      clear_buffer_new(bh_result);
++      ext3_init_tree_desc(&tree, inode);
++      ext_debug(&tree, "block %d requested for inode %u\n",
++                (int) iblock, (unsigned) inode->i_ino);
++      down(&EXT3_I(inode)->truncate_sem);
++
++      /* check in cache */
++      if ((goal = ext3_ext_in_cache(&tree, iblock, &newex))) {
++              if (goal == EXT3_EXT_CACHE_GAP) {
++                      if (!create) {
++                              /* block isn't allocated yet and
++                               * user don't want to allocate it */
++                              goto out2;
++                      }
++                      /* we should allocate requested block */
++              } else if (goal == EXT3_EXT_CACHE_EXTENT) {
++                      /* block is already allocated */
++                      newblock = iblock - newex.ee_block + newex.ee_start;
++                      goto out;
++              } else {
++                      EXT_ASSERT(0);
++              }
++      }
++
++      /* find extent for this block */
++      path = ext3_ext_find_extent(&tree, iblock, NULL);
++      if (IS_ERR(path)) {
++              err = PTR_ERR(path);
++              path = NULL;
++              goto out2;
++      }
++
++      depth = EXT_DEPTH(&tree);
++
++      /*
++       * consistent leaf must not be empty
++       * this situations is possible, though, _during_ tree modification
++       * this is why assert can't be put in ext3_ext_find_extent()
++       */
++      EXT_ASSERT(path[depth].p_ext != NULL || depth == 0);
++
++      if ((ex = path[depth].p_ext)) {
++              /* if found exent covers block, simple return it */
++              if (iblock >= ex->ee_block && iblock < ex->ee_block + ex->ee_len) {
++                      newblock = iblock - ex->ee_block + ex->ee_start;
++                      ext_debug(&tree, "%d fit into %d:%d -> %d\n",
++                                (int) iblock, ex->ee_block, ex->ee_len,
++                                newblock);
++                      ext3_ext_put_in_cache(&tree, ex->ee_block,
++                                            ex->ee_len, ex->ee_start,
++                                            EXT3_EXT_CACHE_EXTENT);
++                      goto out;
++              }
++      }
++
++      /*
++       * requested block isn't allocated yet
++       * we couldn't try to create block if create flag is zero 
++       */
++      if (!create) {
++              /* put just found gap into cache to speedup subsequest reqs */
++              ext3_ext_put_gap_in_cache(&tree, path, iblock);
++              goto out2;
++      }
++
++      /* allocate new block */
++      goal = ext3_ext_find_goal(inode, path, iblock);
++      newblock = ext3_new_block(handle, inode, goal, &err);
++      if (!newblock)
++              goto out2;
++      ext_debug(&tree, "allocate new block: goal %d, found %d\n",
++                goal, newblock);
++
++      /* try to insert new extent into found leaf and return */
++      newex.ee_block = iblock;
++      newex.ee_start = newblock;
++      newex.ee_len = 1;
++      err = ext3_ext_insert_extent(handle, &tree, path, &newex);
++      if (err)
++              goto out2;
++      
++      if (extend_disksize && inode->i_size > EXT3_I(inode)->i_disksize)
++              EXT3_I(inode)->i_disksize = inode->i_size;
++
++      /* previous routine could use block we allocated */
++      newblock = newex.ee_start;
++      set_buffer_new(bh_result);
++
++      ext3_ext_put_in_cache(&tree, newex.ee_block, newex.ee_len,
++                            newex.ee_start, EXT3_EXT_CACHE_EXTENT);
++out:
++      ext3_ext_show_leaf(&tree, path);
++      map_bh(bh_result, inode->i_sb, newblock);
++out2:
++      if (path) {
++              ext3_ext_drop_refs(path);
++              kfree(path);
++      }
++      up(&EXT3_I(inode)->truncate_sem);
++
++      return err;     
++}
++
++void ext3_ext_truncate(struct inode * inode, struct page *page)
++{
++      struct address_space *mapping = inode->i_mapping;
++      struct super_block *sb = inode->i_sb;
++      struct ext3_extents_tree tree;
++      unsigned long last_block;
++      handle_t *handle;
++      int err = 0;
++
++      ext3_init_tree_desc(&tree, inode);
++
++      /*
++       * probably first extent we're gonna free will be last in block
++       */
++      err = ext3_writepage_trans_blocks(inode) + 3;
++      handle = ext3_journal_start(inode, err);
++      if (IS_ERR(handle)) {
++              if (page) {
++                      clear_highpage(page);
++                      flush_dcache_page(page);
++                      unlock_page(page);
++                      page_cache_release(page);
++              }
++              return;
++      }
++
++      if (page)
++              ext3_block_truncate_page(handle, page, mapping, inode->i_size);
++
++      down(&EXT3_I(inode)->truncate_sem);
++      ext3_ext_invalidate_cache(&tree);
++
++      /* 
++       * TODO: optimization is possible here
++       * probably we need not scaning at all,
++       * because page truncation is enough
++       */
++      if (ext3_orphan_add(handle, inode))
++              goto out_stop;
++
++      /* we have to know where to truncate from in crash case */
++      EXT3_I(inode)->i_disksize = inode->i_size;
++      ext3_mark_inode_dirty(handle, inode);
++
++      last_block = (inode->i_size + sb->s_blocksize - 1) >>
++                      EXT3_BLOCK_SIZE_BITS(sb);
++      err = ext3_ext_remove_space(&tree, last_block, EXT_MAX_BLOCK);
++      
++      /* In a multi-transaction truncate, we only make the final
++       * transaction synchronous */
++      if (IS_SYNC(inode))
++              handle->h_sync = 1;
++
++out_stop:
++      /*
++       * If this was a simple ftruncate(), and the file will remain alive
++       * then we need to clear up the orphan record which we created above.
++       * However, if this was a real unlink then we were called by
++       * ext3_delete_inode(), and we allow that function to clean up the
++       * orphan info for us.
++       */
++      if (inode->i_nlink)
++              ext3_orphan_del(handle, inode);
++
++      up(&EXT3_I(inode)->truncate_sem);
++      ext3_journal_stop(handle);
++}
++
++/*
++ * this routine calculate max number of blocks we could modify
++ * in order to allocate new block for an inode
++ */
++int ext3_ext_writepage_trans_blocks(struct inode *inode, int num)
++{
++      struct ext3_extents_tree tree;
++      int needed;
++      
++      ext3_init_tree_desc(&tree, inode);
++      
++      needed = ext3_ext_calc_credits_for_insert(&tree, NULL);
++
++      /* caller want to allocate num blocks */
++      needed *= num;
++      
++#ifdef CONFIG_QUOTA
++      /* 
++       * FIXME: real calculation should be here
++       * it depends on blockmap format of qouta file
++       */
++      needed += 2 * EXT3_SINGLEDATA_TRANS_BLOCKS;
++#endif
++
++      return needed;
++}
++
++void ext3_extents_initialize_blockmap(handle_t *handle, struct inode *inode)
++{
++      struct ext3_extents_tree tree;
++
++      ext3_init_tree_desc(&tree, inode);
++      ext3_extent_tree_init(handle, &tree);
++}
++
++int ext3_ext_calc_blockmap_metadata(struct inode *inode, int blocks)
++{
++      struct ext3_extents_tree tree;
++
++      ext3_init_tree_desc(&tree, inode);
++      return ext3_ext_calc_metadata_amount(&tree, blocks);
++}
++      
++static int
++ext3_ext_store_extent_cb(struct ext3_extents_tree *tree,
++                       struct ext3_ext_path *path,
++                       struct ext3_ext_cache *newex)
++{
++      struct ext3_extent_buf *buf = (struct ext3_extent_buf *) tree->private;
++
++      if (newex->ec_type != EXT3_EXT_CACHE_EXTENT)
++              return EXT_CONTINUE;
++
++      if (buf->err < 0)
++              return EXT_BREAK;
++      if (buf->cur - buf->buffer + sizeof(*newex) > buf->buflen)
++              return EXT_BREAK;
++
++      if (!copy_to_user(buf->cur, newex, sizeof(*newex))) {
++              buf->err++;
++              buf->cur += sizeof(*newex);
++      } else {
++              buf->err = -EFAULT;
++              return EXT_BREAK;
++      }
++      return EXT_CONTINUE;
++}
++
++static int
++ext3_ext_collect_stats_cb(struct ext3_extents_tree *tree,
++                        struct ext3_ext_path *path,
++                        struct ext3_ext_cache *ex)
++{
++      struct ext3_extent_tree_stats *buf =
++              (struct ext3_extent_tree_stats *) tree->private;
++      int depth;
++
++      if (ex->ec_type != EXT3_EXT_CACHE_EXTENT)
++              return EXT_CONTINUE;
++
++      depth = EXT_DEPTH(tree);
++      buf->extents_num++;
++      if (path[depth].p_ext == EXT_FIRST_EXTENT(path[depth].p_hdr))
++              buf->leaf_num++;
++      return EXT_CONTINUE;
++}
++
++int ext3_ext_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
++                 unsigned long arg)
++{
++      int err = 0;
++
++      if (!(EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL))
++              return -EINVAL;
++
++      if (cmd == EXT3_IOC_GET_EXTENTS) {
++              struct ext3_extent_buf buf;
++              struct ext3_extents_tree tree;
++
++              if (copy_from_user(&buf, (void *) arg, sizeof(buf)))
++                      return -EFAULT;
++
++              ext3_init_tree_desc(&tree, inode);
++              buf.cur = buf.buffer;
++              buf.err = 0;
++              tree.private = &buf;
++              down(&EXT3_I(inode)->truncate_sem);
++              err = ext3_ext_walk_space(&tree, buf.start, EXT_MAX_BLOCK,
++                                        ext3_ext_store_extent_cb);
++              up(&EXT3_I(inode)->truncate_sem);
++              if (err == 0)
++                      err = buf.err;
++      } else if (cmd == EXT3_IOC_GET_TREE_STATS) {
++              struct ext3_extent_tree_stats buf;
++              struct ext3_extents_tree tree;
++
++              ext3_init_tree_desc(&tree, inode);
++              down(&EXT3_I(inode)->truncate_sem);
++              buf.depth = EXT_DEPTH(&tree);
++              buf.extents_num = 0;
++              buf.leaf_num = 0;
++              tree.private = &buf;
++              err = ext3_ext_walk_space(&tree, 0, EXT_MAX_BLOCK,
++                                        ext3_ext_collect_stats_cb);
++              up(&EXT3_I(inode)->truncate_sem);
++              if (!err)
++                      err = copy_to_user((void *) arg, &buf, sizeof(buf));
++      } else if (cmd == EXT3_IOC_GET_TREE_DEPTH) {
++              struct ext3_extents_tree tree;
++              ext3_init_tree_desc(&tree, inode);
++              down(&EXT3_I(inode)->truncate_sem);
++              err = EXT_DEPTH(&tree);
++              up(&EXT3_I(inode)->truncate_sem);
++      }
++
++      return err;
++}
++
++EXPORT_SYMBOL(ext3_init_tree_desc);
++EXPORT_SYMBOL(ext3_mark_inode_dirty);
++EXPORT_SYMBOL(ext3_ext_invalidate_cache);
++EXPORT_SYMBOL(ext3_ext_insert_extent);
++EXPORT_SYMBOL(ext3_ext_walk_space);
++EXPORT_SYMBOL(ext3_ext_find_goal);
++EXPORT_SYMBOL(ext3_ext_calc_credits_for_insert);
+Index: linux-2.6.16.21-0.8/fs/ext3/ialloc.c
+===================================================================
+--- linux-2.6.16.21-0.8.orig/fs/ext3/ialloc.c
++++ linux-2.6.16.21-0.8/fs/ext3/ialloc.c
+@@ -598,7 +598,7 @@ got:
+       ei->i_dir_start_lookup = 0;
+       ei->i_disksize = 0;
+-      ei->i_flags = EXT3_I(dir)->i_flags & ~EXT3_INDEX_FL;
++      ei->i_flags = EXT3_I(dir)->i_flags & ~(EXT3_INDEX_FL|EXT3_EXTENTS_FL);
+       if (S_ISLNK(mode))
+               ei->i_flags &= ~(EXT3_IMMUTABLE_FL|EXT3_APPEND_FL);
+       /* dirsync only applies to directories */
+@@ -642,6 +642,18 @@ got:
+       if (err)
+               goto fail_free_drop;
++      if (test_opt(sb, EXTENTS) && S_ISREG(inode->i_mode)) {
++              EXT3_I(inode)->i_flags |= EXT3_EXTENTS_FL;
++              ext3_extents_initialize_blockmap(handle, inode);
++              if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_EXTENTS)) {
++                      err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
++                      if (err) goto fail;
++                      EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_EXTENTS);
++                      BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "call ext3_journal_dirty_metadata");
++                      err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
++              }
++      }
++
+       err = ext3_mark_inode_dirty(handle, inode);
+       if (err) {
+               ext3_std_error(sb, err);
+Index: linux-2.6.16.21-0.8/fs/ext3/inode.c
+===================================================================
+--- linux-2.6.16.21-0.8.orig/fs/ext3/inode.c
++++ linux-2.6.16.21-0.8/fs/ext3/inode.c
+@@ -40,7 +40,7 @@
+ #include "iopen.h"
+ #include "acl.h"
+-static int ext3_writepage_trans_blocks(struct inode *inode);
++int ext3_writepage_trans_blocks(struct inode *inode);
+ /*
+  * Test whether an inode is a fast symlink.
+@@ -788,6 +788,17 @@ out:
+       return err;
+ }
++static inline int
++ext3_get_block_wrap(handle_t *handle, struct inode *inode, long block,
++                  struct buffer_head *bh, int create, int extend_disksize)
++{
++      if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
++              return ext3_ext_get_block(handle, inode, block, bh, create,
++                                        extend_disksize);
++      return ext3_get_block_handle(handle, inode, block, bh, create,
++                                   extend_disksize);
++}
++
+ static int ext3_get_block(struct inode *inode, sector_t iblock,
+                       struct buffer_head *bh_result, int create)
+ {
+@@ -798,8 +809,8 @@ static int ext3_get_block(struct inode *
+               handle = ext3_journal_current_handle();
+               J_ASSERT(handle != 0);
+       }
+-      ret = ext3_get_block_handle(handle, inode, iblock,
+-                              bh_result, create, 1);
++      ret = ext3_get_block_wrap(handle, inode, iblock,
++                                bh_result, create, 1);
+       return ret;
+ }
+@@ -843,7 +854,7 @@ ext3_direct_io_get_blocks(struct inode *
+ get_block:
+       if (ret == 0)
+-              ret = ext3_get_block_handle(handle, inode, iblock,
++              ret = ext3_get_block_wrap(handle, inode, iblock,
+                                       bh_result, create, 0);
+       bh_result->b_size = (1 << inode->i_blkbits);
+       return ret;
+@@ -863,7 +874,7 @@ struct buffer_head *ext3_getblk(handle_t
+       dummy.b_state = 0;
+       dummy.b_blocknr = -1000;
+       buffer_trace_init(&dummy.b_history);
+-      *errp = ext3_get_block_handle(handle, inode, block, &dummy, create, 1);
++      *errp = ext3_get_block_wrap(handle, inode, block, &dummy, create, 1);
+       if (!*errp && buffer_mapped(&dummy)) {
+               struct buffer_head *bh;
+               bh = sb_getblk(inode->i_sb, dummy.b_blocknr);
+@@ -1606,7 +1617,7 @@ void ext3_set_aops(struct inode *inode)
+  * This required during truncate. We need to physically zero the tail end
+  * of that block so it doesn't yield old data if the file is later grown.
+  */
+-static int ext3_block_truncate_page(handle_t *handle, struct page *page,
++int ext3_block_truncate_page(handle_t *handle, struct page *page,
+               struct address_space *mapping, loff_t from)
+ {
+       unsigned long index = from >> PAGE_CACHE_SHIFT;
+@@ -2116,6 +2127,9 @@ void ext3_truncate(struct inode * inode)
+                       return;
+       }
++      if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
++              return ext3_ext_truncate(inode, page);
++
+       handle = start_transaction(inode);
+       if (IS_ERR(handle)) {
+               if (page) {
+@@ -2863,12 +2877,15 @@ err_out:
+  * block and work out the exact number of indirects which are touched.  Pah.
+  */
+-static int ext3_writepage_trans_blocks(struct inode *inode)
++int ext3_writepage_trans_blocks(struct inode *inode)
+ {
+       int bpp = ext3_journal_blocks_per_page(inode);
+       int indirects = (EXT3_NDIR_BLOCKS % bpp) ? 5 : 3;
+       int ret;
++      if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
++              return ext3_ext_writepage_trans_blocks(inode, bpp);
++
+       if (ext3_should_journal_data(inode))
+               ret = 3 * (bpp + indirects) + 2;
+       else
+Index: linux-2.6.16.21-0.8/fs/ext3/Makefile
+===================================================================
+--- linux-2.6.16.21-0.8.orig/fs/ext3/Makefile
++++ linux-2.6.16.21-0.8/fs/ext3/Makefile
+@@ -5,7 +5,8 @@
+ obj-$(CONFIG_EXT3_FS) += ext3.o
+ ext3-y        := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
+-         ioctl.o namei.o super.o symlink.o hash.o resize.o
++         ioctl.o namei.o super.o symlink.o hash.o resize.o \
++         extents.o
+ ext3-$(CONFIG_EXT3_FS_XATTR)   += xattr.o xattr_user.o xattr_trusted.o
+ ext3-$(CONFIG_EXT3_FS_POSIX_ACL) += acl.o
+Index: linux-2.6.16.21-0.8/fs/ext3/super.c
+===================================================================
+--- linux-2.6.16.21-0.8.orig/fs/ext3/super.c
++++ linux-2.6.16.21-0.8/fs/ext3/super.c
+@@ -392,6 +392,7 @@ static void ext3_put_super (struct super
+       struct ext3_super_block *es = sbi->s_es;
+       int i;
++      ext3_ext_release(sb);
+       ext3_xattr_put_super(sb);
+       journal_destroy(sbi->s_journal);
+       if (!(sb->s_flags & MS_RDONLY)) {
+@@ -456,6 +457,8 @@ static struct inode *ext3_alloc_inode(st
+ #endif
+       ei->i_block_alloc_info = NULL;
+       ei->vfs_inode.i_version = 1;
++      
++      memset(&ei->i_cached_extent, 0, sizeof(ei->i_cached_extent));
+       return &ei->vfs_inode;
+ }
+@@ -638,6 +641,7 @@ enum {
+       Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
+       Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
+       Opt_iopen, Opt_noiopen, Opt_iopen_nopriv,
++      Opt_extents, Opt_extdebug,
+       Opt_grpquota
+ };
+@@ -689,6 +693,8 @@ static match_table_t tokens = {
+       {Opt_iopen, "iopen"},
+       {Opt_noiopen, "noiopen"},
+       {Opt_iopen_nopriv, "iopen_nopriv"},
++      {Opt_extents, "extents"},
++      {Opt_extdebug, "extdebug"},
+       {Opt_barrier, "barrier=%u"},
+       {Opt_err, NULL},
+       {Opt_resize, "resize"},
+@@ -1030,6 +1036,12 @@ clear_qf_name:
+               case Opt_nobh:
+                       set_opt(sbi->s_mount_opt, NOBH);
+                       break;
++              case Opt_extents:
++                      set_opt (sbi->s_mount_opt, EXTENTS);
++                      break;
++              case Opt_extdebug:
++                      set_opt (sbi->s_mount_opt, EXTDEBUG);
++                      break;
+               default:
+                       printk (KERN_ERR
+                               "EXT3-fs: Unrecognized mount option \"%s\" "
+@@ -1756,6 +1768,7 @@ static int ext3_fill_super (struct super
+       percpu_counter_mod(&sbi->s_dirs_counter,
+               ext3_count_dirs(sb));
++      ext3_ext_init(sb);
+       lock_kernel();
+       return 0;
+Index: linux-2.6.16.21-0.8/fs/ext3/ioctl.c
+===================================================================
+--- linux-2.6.16.21-0.8.orig/fs/ext3/ioctl.c
++++ linux-2.6.16.21-0.8/fs/ext3/ioctl.c
+@@ -125,6 +125,10 @@ flags_err:
+                       err = ext3_change_inode_journal_flag(inode, jflag);
+               return err;
+       }
++      case EXT3_IOC_GET_EXTENTS:
++      case EXT3_IOC_GET_TREE_STATS:
++      case EXT3_IOC_GET_TREE_DEPTH:
++              return ext3_ext_ioctl(inode, filp, cmd, arg);
+       case EXT3_IOC_GETVERSION:
+       case EXT3_IOC_GETVERSION_OLD:
+               return put_user(inode->i_generation, (int __user *) arg);
+Index: linux-2.6.16.21-0.8/include/linux/ext3_fs.h
+===================================================================
+--- linux-2.6.16.21-0.8.orig/include/linux/ext3_fs.h
++++ linux-2.6.16.21-0.8/include/linux/ext3_fs.h
+@@ -185,9 +185,10 @@ struct ext3_group_desc
+ #define EXT3_NOTAIL_FL                        0x00008000 /* file tail should not be merged */
+ #define EXT3_DIRSYNC_FL                       0x00010000 /* dirsync behaviour (directories only) */
+ #define EXT3_TOPDIR_FL                        0x00020000 /* Top of directory hierarchies*/
++#define EXT3_EXTENTS_FL                       0x00080000 /* Inode uses extents */
+ #define EXT3_RESERVED_FL              0x80000000 /* reserved for ext3 lib */
+-#define EXT3_FL_USER_VISIBLE          0x0003DFFF /* User visible flags */
++#define EXT3_FL_USER_VISIBLE          0x000BDFFF /* User visible flags */
+ #define EXT3_FL_USER_MODIFIABLE               0x000380FF /* User modifiable flags */
+ /*
+@@ -237,6 +238,9 @@ struct ext3_new_group_data {
+ #endif
+ #define EXT3_IOC_GETRSVSZ             _IOR('f', 5, long)
+ #define EXT3_IOC_SETRSVSZ             _IOW('f', 6, long)
++#define EXT3_IOC_GET_EXTENTS          _IOR('f', 7, long)
++#define EXT3_IOC_GET_TREE_DEPTH               _IOR('f', 8, long)
++#define EXT3_IOC_GET_TREE_STATS               _IOR('f', 9, long)
+ /*
+  *  Mount options
+@@ -377,6 +381,8 @@ struct ext3_inode {
+ #define EXT3_MOUNT_GRPQUOTA           0x200000 /* "old" group quota */
+ #define EXT3_MOUNT_IOPEN              0x400000        /* Allow access via iopen */
+ #define EXT3_MOUNT_IOPEN_NOPRIV               0x800000/* Make iopen world-readable */
++#define EXT3_MOUNT_EXTENTS            0x1000000/* Extents support */
++#define EXT3_MOUNT_EXTDEBUG           0x2000000/* Extents debug */
+ /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
+ #ifndef clear_opt
+@@ -565,11 +571,13 @@ static inline struct ext3_inode_info *EX
+ #define EXT3_FEATURE_INCOMPAT_RECOVER         0x0004 /* Needs recovery */
+ #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV     0x0008 /* Journal device */
+ #define EXT3_FEATURE_INCOMPAT_META_BG         0x0010
++#define EXT3_FEATURE_INCOMPAT_EXTENTS         0x0040 /* extents support */
+ #define EXT3_FEATURE_COMPAT_SUPP      EXT2_FEATURE_COMPAT_EXT_ATTR
+ #define EXT3_FEATURE_INCOMPAT_SUPP    (EXT3_FEATURE_INCOMPAT_FILETYPE| \
+                                        EXT3_FEATURE_INCOMPAT_RECOVER| \
+-                                       EXT3_FEATURE_INCOMPAT_META_BG)
++                                       EXT3_FEATURE_INCOMPAT_META_BG| \
++                                       EXT3_FEATURE_INCOMPAT_EXTENTS)
+ #define EXT3_FEATURE_RO_COMPAT_SUPP   (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
+                                        EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \
+                                        EXT3_FEATURE_RO_COMPAT_BTREE_DIR)
+@@ -776,6 +784,7 @@ extern unsigned long ext3_count_free (st
+ /* inode.c */
++extern int ext3_block_truncate_page(handle_t *, struct page *, struct address_space *, loff_t);
+ extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int);
+ extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
+ extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
+@@ -792,6 +801,7 @@ extern int ext3_get_inode_loc(struct ino
+ extern void ext3_truncate (struct inode *);
+ extern void ext3_set_inode_flags(struct inode *);
+ extern void ext3_set_aops(struct inode *inode);
++extern int ext3_writepage_trans_blocks(struct inode *inode);
+ /* ioctl.c */
+ extern int ext3_ioctl (struct inode *, struct file *, unsigned int,
+@@ -845,6 +855,16 @@ extern struct inode_operations ext3_spec
+ extern struct inode_operations ext3_symlink_inode_operations;
+ extern struct inode_operations ext3_fast_symlink_inode_operations;
++/* extents.c */
++extern int ext3_ext_writepage_trans_blocks(struct inode *, int);
++extern int ext3_ext_get_block(handle_t *, struct inode *, long,
++                            struct buffer_head *, int, int);
++extern void ext3_ext_truncate(struct inode *, struct page *);
++extern void ext3_ext_init(struct super_block *);
++extern void ext3_ext_release(struct super_block *);
++extern void ext3_extents_initialize_blockmap(handle_t *, struct inode *);
++extern int ext3_ext_ioctl(struct inode *inode, struct file *filp,
++                        unsigned int cmd, unsigned long arg);
+ #endif        /* __KERNEL__ */
+Index: linux-2.6.16.21-0.8/include/linux/ext3_extents.h
+===================================================================
+--- /dev/null
++++ linux-2.6.16.21-0.8/include/linux/ext3_extents.h
+@@ -0,0 +1,264 @@
++/*
++ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com
++ * Written by Alex Tomas <alex@clusterfs.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public Licens
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-
++ */
++
++#ifndef _LINUX_EXT3_EXTENTS
++#define _LINUX_EXT3_EXTENTS
++
++/*
++ * with AGRESSIVE_TEST defined capacity of index/leaf blocks
++ * become very little, so index split, in-depth growing and
++ * other hard changes happens much more often
++ * this is for debug purposes only
++ */
++#define AGRESSIVE_TEST_
++
++/*
++ * if CHECK_BINSEARCH defined, then results of binary search
++ * will be checked by linear search
++ */
++#define CHECK_BINSEARCH_
++
++/*
++ * if EXT_DEBUG is defined you can use 'extdebug' mount option
++ * to get lots of info what's going on
++ */
++#define EXT_DEBUG_
++#ifdef EXT_DEBUG
++#define ext_debug(tree,fmt,a...)                      \
++do {                                                  \
++      if (test_opt((tree)->inode->i_sb, EXTDEBUG))    \
++              printk(fmt, ##a);                       \
++} while (0);
++#else
++#define ext_debug(tree,fmt,a...)
++#endif
++
++/*
++ * if EXT_STATS is defined then stats numbers are collected
++ * these number will be displayed at umount time
++ */
++#define EXT_STATS_
++
++
++#define EXT3_ALLOC_NEEDED     3       /* block bitmap + group desc. + sb */
++
++/*
++ * ext3_inode has i_block array (total 60 bytes)
++ * first 4 bytes are used to store:
++ *  - tree depth (0 mean there is no tree yet. all extents in the inode)
++ *  - number of alive extents in the inode
++ */
++
++/*
++ * this is extent on-disk structure
++ * it's used at the bottom of the tree
++ */
++struct ext3_extent {
++      __u32   ee_block;       /* first logical block extent covers */
++      __u16   ee_len;         /* number of blocks covered by extent */
++      __u16   ee_start_hi;    /* high 16 bits of physical block */
++      __u32   ee_start;       /* low 32 bigs of physical block */
++};
++
++/*
++ * this is index on-disk structure
++ * it's used at all the levels, but the bottom
++ */
++struct ext3_extent_idx {
++      __u32   ei_block;       /* index covers logical blocks from 'block' */
++      __u32   ei_leaf;        /* pointer to the physical block of the next *
++                               * level. leaf or next index could bet here */
++      __u16   ei_leaf_hi;     /* high 16 bits of physical block */
++      __u16   ei_unused;
++};
++
++/*
++ * each block (leaves and indexes), even inode-stored has header
++ */
++struct ext3_extent_header {   
++      __u16   eh_magic;       /* probably will support different formats */   
++      __u16   eh_entries;     /* number of valid entries */
++      __u16   eh_max;         /* capacity of store in entries */
++      __u16   eh_depth;       /* has tree real underlaying blocks? */
++      __u32   eh_generation;  /* generation of the tree */
++};
++
++#define EXT3_EXT_MAGIC                0xf30a
++
++/*
++ * array of ext3_ext_path contains path to some extent
++ * creation/lookup routines use it for traversal/splitting/etc
++ * truncate uses it to simulate recursive walking
++ */
++struct ext3_ext_path {
++      __u32                           p_block;
++      __u16                           p_depth;
++      struct ext3_extent              *p_ext;
++      struct ext3_extent_idx          *p_idx;
++      struct ext3_extent_header       *p_hdr;
++      struct buffer_head              *p_bh;
++};
++
++/*
++ * structure for external API
++ */
++
++/*
++ * storage for cached extent
++ */
++struct ext3_ext_cache {
++      __u32   ec_start;
++      __u32   ec_block;
++      __u32   ec_len;
++      __u32   ec_type;
++};
++
++#define EXT3_EXT_CACHE_NO     0
++#define EXT3_EXT_CACHE_GAP    1
++#define EXT3_EXT_CACHE_EXTENT 2
++
++/*
++ * ext3_extents_tree is used to pass initial information
++ * to top-level extents API
++ */
++struct ext3_extents_helpers;
++struct ext3_extents_tree {
++      struct inode *inode;    /* inode which tree belongs to */
++      void *root;             /* ptr to data top of tree resides at */
++      void *buffer;           /* will be passed as arg to ^^ routines */
++      int buffer_len;
++      void *private;
++      struct ext3_ext_cache *cex;/* last found extent */
++      struct ext3_extents_helpers *ops;
++};
++
++struct ext3_extents_helpers {
++      int (*get_write_access)(handle_t *h, void *buffer);
++      int (*mark_buffer_dirty)(handle_t *h, void *buffer);
++      int (*mergable)(struct ext3_extent *ex1, struct ext3_extent *ex2);
++      int (*remove_extent_credits)(struct ext3_extents_tree *,
++                                   struct ext3_extent *, unsigned long,
++                                   unsigned long);
++      int (*remove_extent)(struct ext3_extents_tree *,
++                           struct ext3_extent *, unsigned long,
++                           unsigned long);
++      int (*new_block)(handle_t *, struct ext3_extents_tree *,
++                       struct ext3_ext_path *, struct ext3_extent *,
++                       int *);
++};
++
++/*
++ * to be called by ext3_ext_walk_space()
++ * negative retcode - error
++ * positive retcode - signal for ext3_ext_walk_space(), see below
++ * callback must return valid extent (passed or newly created)
++ */
++typedef int (*ext_prepare_callback)(struct ext3_extents_tree *,
++                                  struct ext3_ext_path *,
++                                  struct ext3_ext_cache *);
++
++#define EXT_CONTINUE  0
++#define EXT_BREAK     1
++#define EXT_REPEAT    2
++
++
++#define EXT_MAX_BLOCK 0xffffffff
++
++
++#define EXT_FIRST_EXTENT(__hdr__) \
++      ((struct ext3_extent *) (((char *) (__hdr__)) +         \
++                               sizeof(struct ext3_extent_header)))
++#define EXT_FIRST_INDEX(__hdr__) \
++      ((struct ext3_extent_idx *) (((char *) (__hdr__)) +     \
++                                   sizeof(struct ext3_extent_header)))
++#define EXT_HAS_FREE_INDEX(__path__) \
++      ((__path__)->p_hdr->eh_entries < (__path__)->p_hdr->eh_max)
++#define EXT_LAST_EXTENT(__hdr__) \
++      (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_entries - 1)
++#define EXT_LAST_INDEX(__hdr__) \
++      (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_entries - 1)
++#define EXT_MAX_EXTENT(__hdr__) \
++      (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_max - 1)
++#define EXT_MAX_INDEX(__hdr__) \
++      (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_max - 1)
++
++#define EXT_ROOT_HDR(tree) \
++      ((struct ext3_extent_header *) (tree)->root)
++#define EXT_BLOCK_HDR(bh) \
++      ((struct ext3_extent_header *) (bh)->b_data)
++#define EXT_DEPTH(_t_)        \
++      (((struct ext3_extent_header *)((_t_)->root))->eh_depth)
++#define EXT_GENERATION(_t_)   \
++      (((struct ext3_extent_header *)((_t_)->root))->eh_generation)
++
++
++#define EXT_ASSERT(__x__) if (!(__x__)) BUG();
++
++#define EXT_CHECK_PATH(tree,path)                                     \
++{                                                                     \
++      int depth = EXT_DEPTH(tree);                                    \
++      BUG_ON((unsigned long) (path) < __PAGE_OFFSET);                 \
++      BUG_ON((unsigned long) (path)[depth].p_idx <                    \
++                      __PAGE_OFFSET && (path)[depth].p_idx != NULL);  \
++      BUG_ON((unsigned long) (path)[depth].p_ext <                    \
++                      __PAGE_OFFSET && (path)[depth].p_ext != NULL);  \
++      BUG_ON((unsigned long) (path)[depth].p_hdr < __PAGE_OFFSET);    \
++      BUG_ON((unsigned long) (path)[depth].p_bh < __PAGE_OFFSET       \
++                      && depth != 0);                                 \
++      BUG_ON((path)[0].p_depth != depth);                             \
++}
++
++
++/*
++ * this structure is used to gather extents from the tree via ioctl
++ */
++struct ext3_extent_buf {
++      unsigned long start;
++      int buflen;
++      void *buffer;
++      void *cur;
++      int err;
++};
++
++/*
++ * this structure is used to collect stats info about the tree
++ */
++struct ext3_extent_tree_stats {
++      int depth;
++      int extents_num;
++      int leaf_num;
++};
++
++extern void ext3_init_tree_desc(struct ext3_extents_tree *, struct inode *);
++extern int ext3_extent_tree_init(handle_t *, struct ext3_extents_tree *);
++extern int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *, struct ext3_ext_path *);
++extern int ext3_ext_insert_extent(handle_t *, struct ext3_extents_tree *, struct ext3_ext_path *, struct ext3_extent *);
++extern int ext3_ext_walk_space(struct ext3_extents_tree *, unsigned long, unsigned long, ext_prepare_callback);
++extern int ext3_ext_remove_space(struct ext3_extents_tree *, unsigned long, unsigned long);
++extern struct ext3_ext_path * ext3_ext_find_extent(struct ext3_extents_tree *, int, struct ext3_ext_path *);
++extern int ext3_ext_calc_blockmap_metadata(struct inode *, int);
++
++static inline void
++ext3_ext_invalidate_cache(struct ext3_extents_tree *tree)
++{
++      if (tree->cex)
++              tree->cex->ec_type = EXT3_EXT_CACHE_NO;
++}
++
++
++#endif /* _LINUX_EXT3_EXTENTS */
+Index: linux-2.6.16.21-0.8/include/linux/ext3_fs_i.h
+===================================================================
+--- linux-2.6.16.21-0.8.orig/include/linux/ext3_fs_i.h
++++ linux-2.6.16.21-0.8/include/linux/ext3_fs_i.h
+@@ -133,6 +133,8 @@ struct ext3_inode_info {
+        */
+       struct semaphore truncate_sem;
+       struct inode vfs_inode;
++
++      __u32 i_cached_extent[4];
+ };
+ #endif        /* _LINUX_EXT3_FS_I */
diff --git a/ldiskfs/kernel_patches/patches/ext3-extents-2.6.18-vanilla.patch b/ldiskfs/kernel_patches/patches/ext3-extents-2.6.18-vanilla.patch
new file mode 100644 (file)
index 0000000..e89e8e7
--- /dev/null
@@ -0,0 +1,2935 @@
+Index: linux-stage/fs/ext3/extents.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-stage/fs/ext3/extents.c      2006-07-16 14:10:21.000000000 +0800
+@@ -0,0 +1,2347 @@
++/*
++ * Copyright(c) 2003, 2004, 2005, Cluster File Systems, Inc, info@clusterfs.com
++ * Written by Alex Tomas <alex@clusterfs.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public Licens
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-
++ */
++
++/*
++ * Extents support for EXT3
++ *
++ * TODO:
++ *   - ext3_ext_walk_space() sould not use ext3_ext_find_extent()
++ *   - ext3_ext_calc_credits() could take 'mergable' into account
++ *   - ext3*_error() should be used in some situations
++ *   - find_goal() [to be tested and improved]
++ *   - smart tree reduction
++ *   - arch-independence
++ *     common on-disk format for big/little-endian arch
++ */
++
++#include <linux/module.h>
++#include <linux/fs.h>
++#include <linux/time.h>
++#include <linux/ext3_jbd.h>
++#include <linux/jbd.h>
++#include <linux/smp_lock.h>
++#include <linux/highuid.h>
++#include <linux/pagemap.h>
++#include <linux/quotaops.h>
++#include <linux/string.h>
++#include <linux/slab.h>
++#include <linux/ext3_extents.h>
++#include <asm/uaccess.h>
++
++
++static inline int ext3_ext_check_header(struct ext3_extent_header *eh)
++{
++      if (eh->eh_magic != EXT3_EXT_MAGIC) {
++              printk(KERN_ERR "EXT3-fs: invalid magic = 0x%x\n",
++                     (unsigned)eh->eh_magic);
++              return -EIO;
++      }
++      if (eh->eh_max == 0) {
++              printk(KERN_ERR "EXT3-fs: invalid eh_max = %u\n",
++                     (unsigned)eh->eh_max);
++              return -EIO;
++      }
++      if (eh->eh_entries > eh->eh_max) {
++              printk(KERN_ERR "EXT3-fs: invalid eh_entries = %u\n",
++                     (unsigned)eh->eh_entries);
++              return -EIO;
++      }
++      return 0;
++}
++
++static handle_t *ext3_ext_journal_restart(handle_t *handle, int needed)
++{
++      int err;
++
++      if (handle->h_buffer_credits > needed)
++              return handle;
++      if (!ext3_journal_extend(handle, needed))
++              return handle;
++      err = ext3_journal_restart(handle, needed);
++      
++      return handle;
++}
++
++static int inline
++ext3_ext_get_access_for_root(handle_t *h, struct ext3_extents_tree *tree)
++{
++      if (tree->ops->get_write_access)
++              return tree->ops->get_write_access(h,tree->buffer);
++      else
++              return 0;
++}
++
++static int inline
++ext3_ext_mark_root_dirty(handle_t *h, struct ext3_extents_tree *tree)
++{
++      if (tree->ops->mark_buffer_dirty)
++              return tree->ops->mark_buffer_dirty(h,tree->buffer);
++      else
++              return 0;
++}
++
++/*
++ * could return:
++ *  - EROFS
++ *  - ENOMEM
++ */
++static int ext3_ext_get_access(handle_t *handle,
++                             struct ext3_extents_tree *tree,
++                             struct ext3_ext_path *path)
++{
++      int err;
++
++      if (path->p_bh) {
++              /* path points to block */
++              err = ext3_journal_get_write_access(handle, path->p_bh);
++      } else {
++              /* path points to leaf/index in inode body */
++              err = ext3_ext_get_access_for_root(handle, tree);
++      }
++      return err;
++}
++
++/*
++ * could return:
++ *  - EROFS
++ *  - ENOMEM
++ *  - EIO
++ */
++static int ext3_ext_dirty(handle_t *handle, struct ext3_extents_tree *tree,
++                        struct ext3_ext_path *path)
++{
++      int err;
++      if (path->p_bh) {
++              /* path points to block */
++              err =ext3_journal_dirty_metadata(handle, path->p_bh);
++      } else {
++              /* path points to leaf/index in inode body */
++              err = ext3_ext_mark_root_dirty(handle, tree);
++      }
++      return err;
++}
++
++static int inline
++ext3_ext_new_block(handle_t *handle, struct ext3_extents_tree *tree,
++                 struct ext3_ext_path *path, struct ext3_extent *ex,
++                 int *err)
++{
++      int goal, depth, newblock;
++      struct inode *inode;
++
++      EXT_ASSERT(tree);
++      if (tree->ops->new_block)
++              return tree->ops->new_block(handle, tree, path, ex, err);
++
++      inode = tree->inode;
++      depth = EXT_DEPTH(tree);
++      if (path && depth > 0) {
++              goal = path[depth-1].p_block;
++      } else {
++              struct ext3_inode_info *ei = EXT3_I(inode);
++              unsigned long bg_start;
++              unsigned long colour;
++
++              bg_start = (ei->i_block_group *
++                          EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
++                      le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block);
++              colour = (current->pid % 16) *
++                      (EXT3_BLOCKS_PER_GROUP(inode->i_sb) / 16);
++              goal = bg_start + colour;
++      }
++
++      newblock = ext3_new_block(handle, inode, goal, err);
++      return newblock;
++}
++
++static inline void ext3_ext_tree_changed(struct ext3_extents_tree *tree)
++{
++      struct ext3_extent_header *neh;
++      neh = EXT_ROOT_HDR(tree);
++      neh->eh_generation++;
++}
++
++static inline int ext3_ext_space_block(struct ext3_extents_tree *tree)
++{
++      int size;
++
++      size = (tree->inode->i_sb->s_blocksize -
++              sizeof(struct ext3_extent_header)) /
++                              sizeof(struct ext3_extent);
++#ifdef AGRESSIVE_TEST
++      size = 6;
++#endif
++      return size;
++}
++
++static inline int ext3_ext_space_block_idx(struct ext3_extents_tree *tree)
++{
++      int size;
++
++      size = (tree->inode->i_sb->s_blocksize -
++              sizeof(struct ext3_extent_header)) /
++                              sizeof(struct ext3_extent_idx);
++#ifdef AGRESSIVE_TEST
++      size = 5;
++#endif
++      return size;
++}
++
++static inline int ext3_ext_space_root(struct ext3_extents_tree *tree)
++{
++      int size;
++
++      size = (tree->buffer_len - sizeof(struct ext3_extent_header)) /
++                      sizeof(struct ext3_extent);
++#ifdef AGRESSIVE_TEST
++      size = 3;
++#endif
++      return size;
++}
++
++static inline int ext3_ext_space_root_idx(struct ext3_extents_tree *tree)
++{
++      int size;
++
++      size = (tree->buffer_len - sizeof(struct ext3_extent_header)) /
++                      sizeof(struct ext3_extent_idx);
++#ifdef AGRESSIVE_TEST
++      size = 4;
++#endif
++      return size;
++}
++
++static void ext3_ext_show_path(struct ext3_extents_tree *tree,
++                             struct ext3_ext_path *path)
++{
++#ifdef EXT_DEBUG
++      int k, l = path->p_depth;
++
++      ext_debug(tree, "path:");
++      for (k = 0; k <= l; k++, path++) {
++              if (path->p_idx) {
++                      ext_debug(tree, "  %d->%d", path->p_idx->ei_block,
++                                path->p_idx->ei_leaf);
++              } else if (path->p_ext) {
++                      ext_debug(tree, "  %d:%d:%d",
++                                path->p_ext->ee_block,
++                                path->p_ext->ee_len,
++                                path->p_ext->ee_start);
++              } else
++                      ext_debug(tree, "  []");
++      }
++      ext_debug(tree, "\n");
++#endif
++}
++
++static void ext3_ext_show_leaf(struct ext3_extents_tree *tree,
++                             struct ext3_ext_path *path)
++{
++#ifdef EXT_DEBUG
++      int depth = EXT_DEPTH(tree);
++      struct ext3_extent_header *eh;
++      struct ext3_extent *ex;
++      int i;
++
++      if (!path)
++              return;
++
++      eh = path[depth].p_hdr;
++      ex = EXT_FIRST_EXTENT(eh);
++
++      for (i = 0; i < eh->eh_entries; i++, ex++) {
++              ext_debug(tree, "%d:%d:%d ",
++                        ex->ee_block, ex->ee_len, ex->ee_start);
++      }
++      ext_debug(tree, "\n");
++#endif
++}
++
++static void ext3_ext_drop_refs(struct ext3_ext_path *path)
++{
++      int depth = path->p_depth;
++      int i;
++
++      for (i = 0; i <= depth; i++, path++) {
++              if (path->p_bh) {
++                      brelse(path->p_bh);
++                      path->p_bh = NULL;
++              }
++      }
++}
++
++/*
++ * binary search for closest index by given block
++ */
++static inline void
++ext3_ext_binsearch_idx(struct ext3_extents_tree *tree,
++                     struct ext3_ext_path *path, int block)
++{
++      struct ext3_extent_header *eh = path->p_hdr;
++      struct ext3_extent_idx *ix;
++      int l = 0, k, r;
++
++      EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
++      EXT_ASSERT(eh->eh_entries <= eh->eh_max);
++      EXT_ASSERT(eh->eh_entries > 0);
++
++      ext_debug(tree, "binsearch for %d(idx):  ", block);
++
++      path->p_idx = ix = EXT_FIRST_INDEX(eh);
++
++      r = k = eh->eh_entries;
++      while (k > 1) {
++              k = (r - l) / 2;
++              if (block < ix[l + k].ei_block)
++                      r -= k;
++              else
++                      l += k;
++              ext_debug(tree, "%d:%d:%d ", k, l, r);
++      }
++
++      ix += l;
++      path->p_idx = ix;
++      ext_debug(tree," -> %d->%d ",path->p_idx->ei_block,path->p_idx->ei_leaf);
++
++      while (l++ < r) {
++              if (block < ix->ei_block) 
++                      break;
++              path->p_idx = ix++;
++      }
++      ext_debug(tree, "  -> %d->%d\n", path->p_idx->ei_block,
++                path->p_idx->ei_leaf);
++
++#ifdef CHECK_BINSEARCH 
++      {
++              struct ext3_extent_idx *chix;
++
++              chix = ix = EXT_FIRST_INDEX(eh);
++              for (k = 0; k < eh->eh_entries; k++, ix++) {
++                      if (k != 0 && ix->ei_block <= ix[-1].ei_block) {
++                              printk("k=%d, ix=0x%p, first=0x%p\n", k,
++                                     ix, EXT_FIRST_INDEX(eh));
++                              printk("%u <= %u\n",
++                                     ix->ei_block,ix[-1].ei_block);
++                      }
++                      EXT_ASSERT(k == 0 || ix->ei_block > ix[-1].ei_block);
++                      if (block < ix->ei_block) 
++                              break;
++                      chix = ix;
++              }
++              EXT_ASSERT(chix == path->p_idx);
++      }
++#endif
++}
++
++/*
++ * binary search for closest extent by given block
++ */
++static inline void
++ext3_ext_binsearch(struct ext3_extents_tree *tree,
++                 struct ext3_ext_path *path, int block)
++{
++      struct ext3_extent_header *eh = path->p_hdr;
++      struct ext3_extent *ex;
++      int l = 0, k, r;
++
++      EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
++      EXT_ASSERT(eh->eh_entries <= eh->eh_max);
++
++      if (eh->eh_entries == 0) {
++              /*
++               * this leaf is empty yet:
++               *  we get such a leaf in split/add case
++               */
++              return;
++      }
++      
++      ext_debug(tree, "binsearch for %d:  ", block);
++
++      path->p_ext = ex = EXT_FIRST_EXTENT(eh);
++
++      r = k = eh->eh_entries;
++      while (k > 1) {
++              k = (r - l) / 2;
++              if (block < ex[l + k].ee_block)
++                      r -= k;
++              else
++                      l += k;
++              ext_debug(tree, "%d:%d:%d ", k, l, r);
++      }
++
++      ex += l;
++      path->p_ext = ex;
++      ext_debug(tree, "  -> %d:%d:%d ", path->p_ext->ee_block,
++                path->p_ext->ee_start, path->p_ext->ee_len);
++
++      while (l++ < r) {
++              if (block < ex->ee_block) 
++                      break;
++              path->p_ext = ex++;
++      }
++      ext_debug(tree, "  -> %d:%d:%d\n", path->p_ext->ee_block,
++                path->p_ext->ee_start, path->p_ext->ee_len);
++
++#ifdef CHECK_BINSEARCH 
++      {
++              struct ext3_extent *chex;
++
++              chex = ex = EXT_FIRST_EXTENT(eh);
++              for (k = 0; k < eh->eh_entries; k++, ex++) {
++                      EXT_ASSERT(k == 0 || ex->ee_block > ex[-1].ee_block);
++                      if (block < ex->ee_block) 
++                              break;
++                      chex = ex;
++              }
++              EXT_ASSERT(chex == path->p_ext);
++      }
++#endif
++}
++
++int ext3_extent_tree_init(handle_t *handle, struct ext3_extents_tree *tree)
++{
++      struct ext3_extent_header *eh;
++
++      BUG_ON(tree->buffer_len == 0);
++      ext3_ext_get_access_for_root(handle, tree);
++      eh = EXT_ROOT_HDR(tree);
++      eh->eh_depth = 0;
++      eh->eh_entries = 0;
++      eh->eh_magic = EXT3_EXT_MAGIC;
++      eh->eh_max = ext3_ext_space_root(tree);
++      ext3_ext_mark_root_dirty(handle, tree);
++      ext3_ext_invalidate_cache(tree);
++      return 0;
++}
++
++struct ext3_ext_path *
++ext3_ext_find_extent(struct ext3_extents_tree *tree, int block,
++                   struct ext3_ext_path *path)
++{
++      struct ext3_extent_header *eh;
++      struct buffer_head *bh;
++      int depth, i, ppos = 0;
++
++      EXT_ASSERT(tree);
++      EXT_ASSERT(tree->inode);
++      EXT_ASSERT(tree->root);
++
++      eh = EXT_ROOT_HDR(tree);
++      EXT_ASSERT(eh);
++      if (ext3_ext_check_header(eh))
++              goto err;
++
++      i = depth = EXT_DEPTH(tree);
++      EXT_ASSERT(eh->eh_max);
++      EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
++      
++      /* account possible depth increase */
++      if (!path) {
++              path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 2),
++                             GFP_NOFS);
++              if (!path)
++                      return ERR_PTR(-ENOMEM);
++      }
++      memset(path, 0, sizeof(struct ext3_ext_path) * (depth + 1));
++      path[0].p_hdr = eh;
++
++      /* walk through the tree */
++      while (i) {
++              ext_debug(tree, "depth %d: num %d, max %d\n",
++                        ppos, eh->eh_entries, eh->eh_max);
++              ext3_ext_binsearch_idx(tree, path + ppos, block);
++              path[ppos].p_block = path[ppos].p_idx->ei_leaf;
++              path[ppos].p_depth = i;
++              path[ppos].p_ext = NULL;
++
++              bh = sb_bread(tree->inode->i_sb, path[ppos].p_block);
++              if (!bh)
++                      goto err;
++
++              eh = EXT_BLOCK_HDR(bh);
++              ppos++;
++              EXT_ASSERT(ppos <= depth);
++              path[ppos].p_bh = bh;
++              path[ppos].p_hdr = eh;
++              i--;
++
++              if (ext3_ext_check_header(eh))
++                      goto err;
++      }
++
++      path[ppos].p_depth = i;
++      path[ppos].p_hdr = eh;
++      path[ppos].p_ext = NULL;
++      path[ppos].p_idx = NULL;
++
++      if (ext3_ext_check_header(eh))
++              goto err;
++
++      /* find extent */
++      ext3_ext_binsearch(tree, path + ppos, block);
++
++      ext3_ext_show_path(tree, path);
++
++      return path;
++
++err:
++      printk(KERN_ERR "EXT3-fs: header is corrupted!\n");
++      ext3_ext_drop_refs(path);
++      kfree(path);
++      return ERR_PTR(-EIO);
++}
++
++/*
++ * insert new index [logical;ptr] into the block at cupr
++ * it check where to insert: before curp or after curp
++ */
++static int ext3_ext_insert_index(handle_t *handle,
++                               struct ext3_extents_tree *tree,
++                               struct ext3_ext_path *curp,
++                               int logical, int ptr)
++{
++      struct ext3_extent_idx *ix;
++      int len, err;
++
++      if ((err = ext3_ext_get_access(handle, tree, curp)))
++              return err;
++
++      EXT_ASSERT(logical != curp->p_idx->ei_block);
++      len = EXT_MAX_INDEX(curp->p_hdr) - curp->p_idx;
++      if (logical > curp->p_idx->ei_block) {
++              /* insert after */
++              if (curp->p_idx != EXT_LAST_INDEX(curp->p_hdr)) {
++                      len = (len - 1) * sizeof(struct ext3_extent_idx);
++                      len = len < 0 ? 0 : len;
++                      ext_debug(tree, "insert new index %d after: %d. "
++                                "move %d from 0x%p to 0x%p\n",
++                                logical, ptr, len,
++                                (curp->p_idx + 1), (curp->p_idx + 2));
++                      memmove(curp->p_idx + 2, curp->p_idx + 1, len);
++              }
++              ix = curp->p_idx + 1;
++      } else {
++              /* insert before */
++              len = len * sizeof(struct ext3_extent_idx);
++              len = len < 0 ? 0 : len;
++              ext_debug(tree, "insert new index %d before: %d. "
++                        "move %d from 0x%p to 0x%p\n",
++                        logical, ptr, len,
++                        curp->p_idx, (curp->p_idx + 1));
++              memmove(curp->p_idx + 1, curp->p_idx, len);
++              ix = curp->p_idx;
++      }
++
++      ix->ei_block = logical;
++      ix->ei_leaf = ptr;
++      curp->p_hdr->eh_entries++;
++
++      EXT_ASSERT(curp->p_hdr->eh_entries <= curp->p_hdr->eh_max);
++      EXT_ASSERT(ix <= EXT_LAST_INDEX(curp->p_hdr));
++
++      err = ext3_ext_dirty(handle, tree, curp);
++      ext3_std_error(tree->inode->i_sb, err);
++
++      return err;
++}
++
++/*
++ * routine inserts new subtree into the path, using free index entry
++ * at depth 'at:
++ *  - allocates all needed blocks (new leaf and all intermediate index blocks)
++ *  - makes decision where to split
++ *  - moves remaining extens and index entries (right to the split point)
++ *    into the newly allocated blocks
++ *  - initialize subtree
++ */
++static int ext3_ext_split(handle_t *handle, struct ext3_extents_tree *tree,
++                        struct ext3_ext_path *path,
++                        struct ext3_extent *newext, int at)
++{
++      struct buffer_head *bh = NULL;
++      int depth = EXT_DEPTH(tree);
++      struct ext3_extent_header *neh;
++      struct ext3_extent_idx *fidx;
++      struct ext3_extent *ex;
++      int i = at, k, m, a;
++      unsigned long newblock, oldblock, border;
++      int *ablocks = NULL; /* array of allocated blocks */
++      int err = 0;
++
++      /* make decision: where to split? */
++      /* FIXME: now desicion is simplest: at current extent */
++
++      /* if current leaf will be splitted, then we should use 
++       * border from split point */
++      EXT_ASSERT(path[depth].p_ext <= EXT_MAX_EXTENT(path[depth].p_hdr));
++      if (path[depth].p_ext != EXT_MAX_EXTENT(path[depth].p_hdr)) {
++              border = path[depth].p_ext[1].ee_block;
++              ext_debug(tree, "leaf will be splitted."
++                        " next leaf starts at %d\n",
++                        (int)border);
++      } else {
++              border = newext->ee_block;
++              ext_debug(tree, "leaf will be added."
++                        " next leaf starts at %d\n",
++                        (int)border);
++      }
++
++      /* 
++       * if error occurs, then we break processing
++       * and turn filesystem read-only. so, index won't
++       * be inserted and tree will be in consistent
++       * state. next mount will repair buffers too
++       */
++
++      /*
++       * get array to track all allocated blocks
++       * we need this to handle errors and free blocks
++       * upon them
++       */
++      ablocks = kmalloc(sizeof(unsigned long) * depth, GFP_NOFS);
++      if (!ablocks)
++              return -ENOMEM;
++      memset(ablocks, 0, sizeof(unsigned long) * depth);
++
++      /* allocate all needed blocks */
++      ext_debug(tree, "allocate %d blocks for indexes/leaf\n", depth - at);
++      for (a = 0; a < depth - at; a++) {
++              newblock = ext3_ext_new_block(handle, tree, path, newext, &err);
++              if (newblock == 0)
++                      goto cleanup;
++              ablocks[a] = newblock;
++      }
++
++      /* initialize new leaf */
++      newblock = ablocks[--a];
++      EXT_ASSERT(newblock);
++      bh = sb_getblk(tree->inode->i_sb, newblock);
++      if (!bh) {
++              err = -EIO;
++              goto cleanup;
++      }
++      lock_buffer(bh);
++
++      if ((err = ext3_journal_get_create_access(handle, bh)))
++              goto cleanup;
++
++      neh = EXT_BLOCK_HDR(bh);
++      neh->eh_entries = 0;
++      neh->eh_max = ext3_ext_space_block(tree);
++      neh->eh_magic = EXT3_EXT_MAGIC;
++      neh->eh_depth = 0;
++      ex = EXT_FIRST_EXTENT(neh);
++
++      /* move remain of path[depth] to the new leaf */
++      EXT_ASSERT(path[depth].p_hdr->eh_entries == path[depth].p_hdr->eh_max);
++      /* start copy from next extent */
++      /* TODO: we could do it by single memmove */
++      m = 0;
++      path[depth].p_ext++;
++      while (path[depth].p_ext <=
++                      EXT_MAX_EXTENT(path[depth].p_hdr)) {
++              ext_debug(tree, "move %d:%d:%d in new leaf %lu\n",
++                        path[depth].p_ext->ee_block,
++                        path[depth].p_ext->ee_start,
++                        path[depth].p_ext->ee_len,
++                        newblock);
++              memmove(ex++, path[depth].p_ext++, sizeof(struct ext3_extent));
++              neh->eh_entries++;
++              m++;
++      }
++      set_buffer_uptodate(bh);
++      unlock_buffer(bh);
++
++      if ((err = ext3_journal_dirty_metadata(handle, bh)))
++              goto cleanup;   
++      brelse(bh);
++      bh = NULL;
++
++      /* correct old leaf */
++      if (m) {
++              if ((err = ext3_ext_get_access(handle, tree, path + depth)))
++                      goto cleanup;
++              path[depth].p_hdr->eh_entries -= m;
++              if ((err = ext3_ext_dirty(handle, tree, path + depth)))
++                      goto cleanup;
++              
++      }
++
++      /* create intermediate indexes */
++      k = depth - at - 1;
++      EXT_ASSERT(k >= 0);
++      if (k)
++              ext_debug(tree, "create %d intermediate indices\n", k);
++      /* insert new index into current index block */
++      /* current depth stored in i var */
++      i = depth - 1;
++      while (k--) {
++              oldblock = newblock;
++              newblock = ablocks[--a];
++              bh = sb_getblk(tree->inode->i_sb, newblock);
++              if (!bh) {
++                      err = -EIO;
++                      goto cleanup;
++              }
++              lock_buffer(bh);
++
++              if ((err = ext3_journal_get_create_access(handle, bh)))
++                      goto cleanup;
++
++              neh = EXT_BLOCK_HDR(bh);
++              neh->eh_entries = 1;
++              neh->eh_magic = EXT3_EXT_MAGIC;
++              neh->eh_max = ext3_ext_space_block_idx(tree);
++              neh->eh_depth = depth - i; 
++              fidx = EXT_FIRST_INDEX(neh);
++              fidx->ei_block = border;
++              fidx->ei_leaf = oldblock;
++
++              ext_debug(tree, "int.index at %d (block %lu): %lu -> %lu\n",
++                        i, newblock, border, oldblock);
++              /* copy indexes */
++              m = 0;
++              path[i].p_idx++;
++
++              ext_debug(tree, "cur 0x%p, last 0x%p\n", path[i].p_idx,
++                        EXT_MAX_INDEX(path[i].p_hdr));
++              EXT_ASSERT(EXT_MAX_INDEX(path[i].p_hdr) ==
++                         EXT_LAST_INDEX(path[i].p_hdr));
++              while (path[i].p_idx <= EXT_MAX_INDEX(path[i].p_hdr)) {
++                      ext_debug(tree, "%d: move %d:%d in new index %lu\n",
++                                i, path[i].p_idx->ei_block,
++                                path[i].p_idx->ei_leaf, newblock);
++                      memmove(++fidx, path[i].p_idx++,
++                              sizeof(struct ext3_extent_idx));
++                      neh->eh_entries++;
++                      EXT_ASSERT(neh->eh_entries <= neh->eh_max);
++                      m++;
++              }
++              set_buffer_uptodate(bh);
++              unlock_buffer(bh);
++
++              if ((err = ext3_journal_dirty_metadata(handle, bh)))
++                      goto cleanup;
++              brelse(bh);
++              bh = NULL;
++
++              /* correct old index */
++              if (m) {
++                      err = ext3_ext_get_access(handle, tree, path + i);
++                      if (err)
++                              goto cleanup;
++                      path[i].p_hdr->eh_entries -= m;
++                      err = ext3_ext_dirty(handle, tree, path + i);
++                      if (err)
++                              goto cleanup;
++              }
++
++              i--;
++      }
++
++      /* insert new index */
++      if (!err)
++              err = ext3_ext_insert_index(handle, tree, path + at,
++                                          border, newblock);
++
++cleanup:
++      if (bh) {
++              if (buffer_locked(bh))
++                      unlock_buffer(bh);
++              brelse(bh);
++      }
++
++      if (err) {
++              /* free all allocated blocks in error case */
++              for (i = 0; i < depth; i++) {
++                      if (!ablocks[i])
++                              continue;
++                      ext3_free_blocks(handle, tree->inode, ablocks[i], 1);
++              }
++      }
++      kfree(ablocks);
++
++      return err;
++}
++
++/*
++ * routine implements tree growing procedure:
++ *  - allocates new block
++ *  - moves top-level data (index block or leaf) into the new block
++ *  - initialize new top-level, creating index that points to the
++ *    just created block
++ */
++static int ext3_ext_grow_indepth(handle_t *handle,
++                               struct ext3_extents_tree *tree,
++                               struct ext3_ext_path *path,
++                               struct ext3_extent *newext)
++{
++      struct ext3_ext_path *curp = path;
++      struct ext3_extent_header *neh;
++      struct ext3_extent_idx *fidx;
++      struct buffer_head *bh;
++      unsigned long newblock;
++      int err = 0;
++
++      newblock = ext3_ext_new_block(handle, tree, path, newext, &err);
++      if (newblock == 0)
++              return err;
++
++      bh = sb_getblk(tree->inode->i_sb, newblock);
++      if (!bh) {
++              err = -EIO;
++              ext3_std_error(tree->inode->i_sb, err);
++              return err;
++      }
++      lock_buffer(bh);
++
++      if ((err = ext3_journal_get_create_access(handle, bh))) {
++              unlock_buffer(bh);
++              goto out;       
++      }
++
++      /* move top-level index/leaf into new block */
++      memmove(bh->b_data, curp->p_hdr, tree->buffer_len);
++
++      /* set size of new block */
++      neh = EXT_BLOCK_HDR(bh);
++      /* old root could have indexes or leaves
++       * so calculate eh_max right way */
++      if (EXT_DEPTH(tree))
++              neh->eh_max = ext3_ext_space_block_idx(tree);
++      else
++              neh->eh_max = ext3_ext_space_block(tree);
++      neh->eh_magic = EXT3_EXT_MAGIC;
++      set_buffer_uptodate(bh);
++      unlock_buffer(bh);
++
++      if ((err = ext3_journal_dirty_metadata(handle, bh)))
++              goto out;
++
++      /* create index in new top-level index: num,max,pointer */
++      if ((err = ext3_ext_get_access(handle, tree, curp)))
++              goto out;
++
++      curp->p_hdr->eh_magic = EXT3_EXT_MAGIC;
++      curp->p_hdr->eh_max = ext3_ext_space_root_idx(tree);
++      curp->p_hdr->eh_entries = 1;
++      curp->p_idx = EXT_FIRST_INDEX(curp->p_hdr);
++      /* FIXME: it works, but actually path[0] can be index */
++      curp->p_idx->ei_block = EXT_FIRST_EXTENT(path[0].p_hdr)->ee_block;
++      curp->p_idx->ei_leaf = newblock;
++
++      neh = EXT_ROOT_HDR(tree);
++      fidx = EXT_FIRST_INDEX(neh);
++      ext_debug(tree, "new root: num %d(%d), lblock %d, ptr %d\n",
++                neh->eh_entries, neh->eh_max, fidx->ei_block, fidx->ei_leaf); 
++
++      neh->eh_depth = path->p_depth + 1;
++      err = ext3_ext_dirty(handle, tree, curp);
++out:
++      brelse(bh);
++
++      return err;
++}
++
++/*
++ * routine finds empty index and adds new leaf. if no free index found
++ * then it requests in-depth growing
++ */
++static int ext3_ext_create_new_leaf(handle_t *handle,
++                                  struct ext3_extents_tree *tree,
++                                  struct ext3_ext_path *path,
++                                  struct ext3_extent *newext)
++{
++      struct ext3_ext_path *curp;
++      int depth, i, err = 0;
++
++repeat:
++      i = depth = EXT_DEPTH(tree);
++      
++      /* walk up to the tree and look for free index entry */
++      curp = path + depth;
++      while (i > 0 && !EXT_HAS_FREE_INDEX(curp)) {
++              i--;
++              curp--;
++      }
++
++      /* we use already allocated block for index block
++       * so, subsequent data blocks should be contigoues */
++      if (EXT_HAS_FREE_INDEX(curp)) {
++              /* if we found index with free entry, then use that
++               * entry: create all needed subtree and add new leaf */
++              err = ext3_ext_split(handle, tree, path, newext, i);
++
++              /* refill path */
++              ext3_ext_drop_refs(path);
++              path = ext3_ext_find_extent(tree, newext->ee_block, path);
++              if (IS_ERR(path))
++                      err = PTR_ERR(path);
++      } else {
++              /* tree is full, time to grow in depth */
++              err = ext3_ext_grow_indepth(handle, tree, path, newext);
++
++              /* refill path */
++              ext3_ext_drop_refs(path);
++              path = ext3_ext_find_extent(tree, newext->ee_block, path);
++              if (IS_ERR(path))
++                      err = PTR_ERR(path);
++
++              /*
++               * only first (depth 0 -> 1) produces free space
++               * in all other cases we have to split growed tree
++               */
++              depth = EXT_DEPTH(tree);
++              if (path[depth].p_hdr->eh_entries == path[depth].p_hdr->eh_max) {
++                      /* now we need split */
++                      goto repeat;
++              }
++      }
++
++      if (err)
++              return err;
++
++      return 0;
++}
++
++/*
++ * returns allocated block in subsequent extent or EXT_MAX_BLOCK
++ * NOTE: it consider block number from index entry as
++ * allocated block. thus, index entries have to be consistent
++ * with leafs
++ */
++static unsigned long
++ext3_ext_next_allocated_block(struct ext3_ext_path *path)
++{
++      int depth;
++
++      EXT_ASSERT(path != NULL);
++      depth = path->p_depth;
++
++      if (depth == 0 && path->p_ext == NULL)
++              return EXT_MAX_BLOCK;
++
++      /* FIXME: what if index isn't full ?! */
++      while (depth >= 0) {
++              if (depth == path->p_depth) {
++                      /* leaf */
++                      if (path[depth].p_ext !=
++                          EXT_LAST_EXTENT(path[depth].p_hdr))
++                              return path[depth].p_ext[1].ee_block;
++              } else {
++                      /* index */
++                      if (path[depth].p_idx !=
++                          EXT_LAST_INDEX(path[depth].p_hdr))
++                              return path[depth].p_idx[1].ei_block;
++              }
++              depth--;        
++      }
++
++      return EXT_MAX_BLOCK;
++}
++
++/*
++ * returns first allocated block from next leaf or EXT_MAX_BLOCK
++ */
++static unsigned ext3_ext_next_leaf_block(struct ext3_extents_tree *tree,
++                                       struct ext3_ext_path *path)
++{
++      int depth;
++
++      EXT_ASSERT(path != NULL);
++      depth = path->p_depth;
++
++      /* zero-tree has no leaf blocks at all */
++      if (depth == 0)
++              return EXT_MAX_BLOCK;
++
++      /* go to index block */
++      depth--;
++      
++      while (depth >= 0) {
++              if (path[depth].p_idx !=
++                  EXT_LAST_INDEX(path[depth].p_hdr))
++                      return path[depth].p_idx[1].ei_block;
++              depth--;        
++      }
++
++      return EXT_MAX_BLOCK;
++}
++
++/*
++ * if leaf gets modified and modified extent is first in the leaf
++ * then we have to correct all indexes above
++ * TODO: do we need to correct tree in all cases?
++ */
++int ext3_ext_correct_indexes(handle_t *handle, struct ext3_extents_tree *tree,
++                           struct ext3_ext_path *path)
++{
++      struct ext3_extent_header *eh;
++      int depth = EXT_DEPTH(tree);    
++      struct ext3_extent *ex;
++      unsigned long border;
++      int k, err = 0;
++      
++      eh = path[depth].p_hdr;
++      ex = path[depth].p_ext;
++      EXT_ASSERT(ex);
++      EXT_ASSERT(eh);
++      
++      if (depth == 0) {
++              /* there is no tree at all */
++              return 0;
++      }
++      
++      if (ex != EXT_FIRST_EXTENT(eh)) {
++              /* we correct tree if first leaf got modified only */
++              return 0;
++      }
++      
++      /*
++       * TODO: we need correction if border is smaller then current one
++       */
++      k = depth - 1;
++      border = path[depth].p_ext->ee_block;
++      if ((err = ext3_ext_get_access(handle, tree, path + k)))
++              return err;
++      path[k].p_idx->ei_block = border;
++      if ((err = ext3_ext_dirty(handle, tree, path + k)))
++              return err;
++
++      while (k--) {
++              /* change all left-side indexes */
++              if (path[k+1].p_idx != EXT_FIRST_INDEX(path[k+1].p_hdr))
++                      break;
++              if ((err = ext3_ext_get_access(handle, tree, path + k)))
++                      break;
++              path[k].p_idx->ei_block = border;
++              if ((err = ext3_ext_dirty(handle, tree, path + k)))
++                      break;
++      }
++
++      return err;
++}
++
++static int inline
++ext3_can_extents_be_merged(struct ext3_extents_tree *tree,
++                         struct ext3_extent *ex1,
++                         struct ext3_extent *ex2)
++{
++      if (ex1->ee_block + ex1->ee_len != ex2->ee_block)
++              return 0;
++
++#ifdef AGRESSIVE_TEST
++      if (ex1->ee_len >= 4)
++              return 0;
++#endif
++
++      if (!tree->ops->mergable)
++              return 1;
++
++      return tree->ops->mergable(ex1, ex2);
++}
++
++/*
++ * this routine tries to merge requsted extent into the existing
++ * extent or inserts requested extent as new one into the tree,
++ * creating new leaf in no-space case
++ */
++int ext3_ext_insert_extent(handle_t *handle, struct ext3_extents_tree *tree,
++                         struct ext3_ext_path *path,
++                         struct ext3_extent *newext)
++{
++      struct ext3_extent_header * eh;
++      struct ext3_extent *ex, *fex;
++      struct ext3_extent *nearex; /* nearest extent */
++      struct ext3_ext_path *npath = NULL;
++      int depth, len, err, next;
++
++      EXT_ASSERT(newext->ee_len > 0);
++      depth = EXT_DEPTH(tree);
++      ex = path[depth].p_ext;
++      EXT_ASSERT(path[depth].p_hdr);
++
++      /* try to insert block into found extent and return */
++      if (ex && ext3_can_extents_be_merged(tree, ex, newext)) {
++              ext_debug(tree, "append %d block to %d:%d (from %d)\n",
++                        newext->ee_len, ex->ee_block, ex->ee_len,
++                        ex->ee_start);
++              if ((err = ext3_ext_get_access(handle, tree, path + depth)))
++                      return err;
++              ex->ee_len += newext->ee_len;
++              eh = path[depth].p_hdr;
++              nearex = ex;
++              goto merge;
++      }
++
++repeat:
++      depth = EXT_DEPTH(tree);
++      eh = path[depth].p_hdr;
++      if (eh->eh_entries < eh->eh_max)
++              goto has_space;
++
++      /* probably next leaf has space for us? */
++      fex = EXT_LAST_EXTENT(eh);
++      next = ext3_ext_next_leaf_block(tree, path);
++      if (newext->ee_block > fex->ee_block && next != EXT_MAX_BLOCK) {
++              ext_debug(tree, "next leaf block - %d\n", next);
++              EXT_ASSERT(!npath);
++              npath = ext3_ext_find_extent(tree, next, NULL);
++              if (IS_ERR(npath))
++                      return PTR_ERR(npath);
++              EXT_ASSERT(npath->p_depth == path->p_depth);
++              eh = npath[depth].p_hdr;
++              if (eh->eh_entries < eh->eh_max) {
++                      ext_debug(tree, "next leaf isnt full(%d)\n",
++                                eh->eh_entries);
++                      path = npath;
++                      goto repeat;
++              }
++              ext_debug(tree, "next leaf hasno free space(%d,%d)\n",
++                        eh->eh_entries, eh->eh_max);
++      }
++
++      /*
++       * there is no free space in found leaf
++       * we're gonna add new leaf in the tree
++       */
++      err = ext3_ext_create_new_leaf(handle, tree, path, newext);
++      if (err)
++              goto cleanup;
++      depth = EXT_DEPTH(tree);
++      eh = path[depth].p_hdr;
++
++has_space:
++      nearex = path[depth].p_ext;
++
++      if ((err = ext3_ext_get_access(handle, tree, path + depth)))
++              goto cleanup;
++
++      if (!nearex) {
++              /* there is no extent in this leaf, create first one */
++              ext_debug(tree, "first extent in the leaf: %d:%d:%d\n",
++                        newext->ee_block, newext->ee_start,
++                        newext->ee_len);
++              path[depth].p_ext = EXT_FIRST_EXTENT(eh);
++      } else if (newext->ee_block > nearex->ee_block) {
++              EXT_ASSERT(newext->ee_block != nearex->ee_block);
++              if (nearex != EXT_LAST_EXTENT(eh)) {
++                      len = EXT_MAX_EXTENT(eh) - nearex;
++                      len = (len - 1) * sizeof(struct ext3_extent);
++                      len = len < 0 ? 0 : len;
++                      ext_debug(tree, "insert %d:%d:%d after: nearest 0x%p, "
++                                "move %d from 0x%p to 0x%p\n",
++                                newext->ee_block, newext->ee_start,
++                                newext->ee_len,
++                                nearex, len, nearex + 1, nearex + 2);
++                      memmove(nearex + 2, nearex + 1, len);
++              }
++              path[depth].p_ext = nearex + 1;
++      } else {
++              EXT_ASSERT(newext->ee_block != nearex->ee_block);
++              len = (EXT_MAX_EXTENT(eh) - nearex) * sizeof(struct ext3_extent);
++              len = len < 0 ? 0 : len;
++              ext_debug(tree, "insert %d:%d:%d before: nearest 0x%p, "
++                        "move %d from 0x%p to 0x%p\n",
++                        newext->ee_block, newext->ee_start, newext->ee_len,
++                        nearex, len, nearex + 1, nearex + 2);
++              memmove(nearex + 1, nearex, len);
++              path[depth].p_ext = nearex;
++      }
++
++      eh->eh_entries++;
++      nearex = path[depth].p_ext;
++      nearex->ee_block = newext->ee_block;
++      nearex->ee_start = newext->ee_start;
++      nearex->ee_len = newext->ee_len;
++      /* FIXME: support for large fs */
++      nearex->ee_start_hi = 0;
++
++merge:
++      /* try to merge extents to the right */
++      while (nearex < EXT_LAST_EXTENT(eh)) {
++              if (!ext3_can_extents_be_merged(tree, nearex, nearex + 1))
++                      break;
++              /* merge with next extent! */
++              nearex->ee_len += nearex[1].ee_len;
++              if (nearex + 1 < EXT_LAST_EXTENT(eh)) {
++                      len = (EXT_LAST_EXTENT(eh) - nearex - 1) *
++                              sizeof(struct ext3_extent);
++                      memmove(nearex + 1, nearex + 2, len);
++              }
++              eh->eh_entries--;
++              EXT_ASSERT(eh->eh_entries > 0);
++      }
++
++      /* try to merge extents to the left */
++
++      /* time to correct all indexes above */
++      err = ext3_ext_correct_indexes(handle, tree, path);
++      if (err)
++              goto cleanup;
++
++      err = ext3_ext_dirty(handle, tree, path + depth);
++
++cleanup:
++      if (npath) {
++              ext3_ext_drop_refs(npath);
++              kfree(npath);
++      }
++      ext3_ext_tree_changed(tree);
++      ext3_ext_invalidate_cache(tree);
++      return err;
++}
++
++int ext3_ext_walk_space(struct ext3_extents_tree *tree, unsigned long block,
++                      unsigned long num, ext_prepare_callback func)
++{
++      struct ext3_ext_path *path = NULL;
++      struct ext3_ext_cache cbex;
++      struct ext3_extent *ex;
++      unsigned long next, start = 0, end = 0;
++      unsigned long last = block + num;
++      int depth, exists, err = 0;
++
++      EXT_ASSERT(tree);
++      EXT_ASSERT(func);
++      EXT_ASSERT(tree->inode);
++      EXT_ASSERT(tree->root);
++
++      while (block < last && block != EXT_MAX_BLOCK) {
++              num = last - block;
++              /* find extent for this block */
++              path = ext3_ext_find_extent(tree, block, path);
++              if (IS_ERR(path)) {
++                      err = PTR_ERR(path);
++                      path = NULL;
++                      break;
++              }
++
++              depth = EXT_DEPTH(tree);
++              EXT_ASSERT(path[depth].p_hdr);
++              ex = path[depth].p_ext;
++              next = ext3_ext_next_allocated_block(path);
++
++              exists = 0;
++              if (!ex) {
++                      /* there is no extent yet, so try to allocate
++                       * all requested space */
++                      start = block;
++                      end = block + num;
++              } else if (ex->ee_block > block) {
++                      /* need to allocate space before found extent */
++                      start = block;
++                      end = ex->ee_block;
++                      if (block + num < end)
++                              end = block + num;
++              } else if (block >= ex->ee_block + ex->ee_len) {
++                      /* need to allocate space after found extent */
++                      start = block;
++                      end = block + num;
++                      if (end >= next)
++                              end = next;
++              } else if (block >= ex->ee_block) {
++                      /* 
++                       * some part of requested space is covered
++                       * by found extent
++                       */
++                      start = block;
++                      end = ex->ee_block + ex->ee_len;
++                      if (block + num < end)
++                              end = block + num;
++                      exists = 1;
++              } else {
++                      BUG();
++              }
++              EXT_ASSERT(end > start);
++
++              if (!exists) {
++                      cbex.ec_block = start;
++                      cbex.ec_len = end - start;
++                      cbex.ec_start = 0;
++                      cbex.ec_type = EXT3_EXT_CACHE_GAP;
++              } else {
++                      cbex.ec_block = ex->ee_block;
++                      cbex.ec_len = ex->ee_len;
++                      cbex.ec_start = ex->ee_start;
++                      cbex.ec_type = EXT3_EXT_CACHE_EXTENT;
++              }
++
++              EXT_ASSERT(cbex.ec_len > 0);
++              EXT_ASSERT(path[depth].p_hdr);
++              err = func(tree, path, &cbex);
++              ext3_ext_drop_refs(path);
++
++              if (err < 0)
++                      break;
++              if (err == EXT_REPEAT)
++                      continue;
++              else if (err == EXT_BREAK) {
++                      err = 0;
++                      break;
++              }
++
++              if (EXT_DEPTH(tree) != depth) {
++                      /* depth was changed. we have to realloc path */
++                      kfree(path);
++                      path = NULL;
++              }
++
++              block = cbex.ec_block + cbex.ec_len;
++      }
++
++      if (path) {
++              ext3_ext_drop_refs(path);
++              kfree(path);
++      }
++
++      return err;
++}
++
++static inline void
++ext3_ext_put_in_cache(struct ext3_extents_tree *tree, __u32 block,
++                    __u32 len, __u32 start, int type)
++{
++      EXT_ASSERT(len > 0);
++      if (tree->cex) {
++              tree->cex->ec_type = type;
++              tree->cex->ec_block = block;
++              tree->cex->ec_len = len;
++              tree->cex->ec_start = start;
++      }
++}
++
++/*
++ * this routine calculate boundaries of the gap requested block fits into
++ * and cache this gap
++ */
++static inline void
++ext3_ext_put_gap_in_cache(struct ext3_extents_tree *tree,
++                        struct ext3_ext_path *path,
++                        unsigned long block)
++{
++      int depth = EXT_DEPTH(tree);
++      unsigned long lblock, len;
++      struct ext3_extent *ex;
++
++      if (!tree->cex)
++              return;
++
++      ex = path[depth].p_ext;
++      if (ex == NULL) {
++              /* there is no extent yet, so gap is [0;-] */
++              lblock = 0;
++              len = EXT_MAX_BLOCK;
++              ext_debug(tree, "cache gap(whole file):");
++      } else if (block < ex->ee_block) {
++              lblock = block;
++              len = ex->ee_block - block;
++              ext_debug(tree, "cache gap(before): %lu [%lu:%lu]",
++                        (unsigned long) block,
++                        (unsigned long) ex->ee_block,
++                        (unsigned long) ex->ee_len);
++      } else if (block >= ex->ee_block + ex->ee_len) {
++              lblock = ex->ee_block + ex->ee_len;
++              len = ext3_ext_next_allocated_block(path);
++              ext_debug(tree, "cache gap(after): [%lu:%lu] %lu",
++                        (unsigned long) ex->ee_block,
++                        (unsigned long) ex->ee_len,
++                        (unsigned long) block);
++              EXT_ASSERT(len > lblock);
++              len = len - lblock;
++      } else {
++              lblock = len = 0;
++              BUG();
++      }
++
++      ext_debug(tree, " -> %lu:%lu\n", (unsigned long) lblock, len);
++      ext3_ext_put_in_cache(tree, lblock, len, 0, EXT3_EXT_CACHE_GAP);
++}
++
++static inline int
++ext3_ext_in_cache(struct ext3_extents_tree *tree, unsigned long block,
++                struct ext3_extent *ex)
++{
++      struct ext3_ext_cache *cex = tree->cex;
++
++      /* is there cache storage at all? */
++      if (!cex)
++              return EXT3_EXT_CACHE_NO;
++
++      /* has cache valid data? */
++      if (cex->ec_type == EXT3_EXT_CACHE_NO)
++              return EXT3_EXT_CACHE_NO;
++
++      EXT_ASSERT(cex->ec_type == EXT3_EXT_CACHE_GAP ||
++                 cex->ec_type == EXT3_EXT_CACHE_EXTENT);
++      if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) {
++              ex->ee_block = cex->ec_block;
++              ex->ee_start = cex->ec_start;
++              ex->ee_len = cex->ec_len;
++              ext_debug(tree, "%lu cached by %lu:%lu:%lu\n",
++                        (unsigned long) block,
++                        (unsigned long) ex->ee_block,
++                        (unsigned long) ex->ee_len,
++                        (unsigned long) ex->ee_start);
++              return cex->ec_type;
++      }
++
++      /* not in cache */
++      return EXT3_EXT_CACHE_NO;
++}
++
++/*
++ * routine removes index from the index block
++ * it's used in truncate case only. thus all requests are for
++ * last index in the block only
++ */
++int ext3_ext_rm_idx(handle_t *handle, struct ext3_extents_tree *tree,
++                  struct ext3_ext_path *path)
++{
++      struct buffer_head *bh;
++      int err;
++      
++      /* free index block */
++      path--;
++      EXT_ASSERT(path->p_hdr->eh_entries);
++      if ((err = ext3_ext_get_access(handle, tree, path)))
++              return err;
++      path->p_hdr->eh_entries--;
++      if ((err = ext3_ext_dirty(handle, tree, path)))
++              return err;
++      ext_debug(tree, "index is empty, remove it, free block %d\n",
++                path->p_idx->ei_leaf);
++      bh = sb_find_get_block(tree->inode->i_sb, path->p_idx->ei_leaf);
++      ext3_forget(handle, 1, tree->inode, bh, path->p_idx->ei_leaf);
++      ext3_free_blocks(handle, tree->inode, path->p_idx->ei_leaf, 1);
++      return err;
++}
++
++int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *tree,
++                                   struct ext3_ext_path *path)
++{
++      int depth = EXT_DEPTH(tree);
++      int needed;
++
++      if (path) {
++              /* probably there is space in leaf? */
++              if (path[depth].p_hdr->eh_entries < path[depth].p_hdr->eh_max)
++                      return 1;
++      }
++      
++      /*
++       * the worste case we're expecting is creation of the
++       * new root (growing in depth) with index splitting
++       * for splitting we have to consider depth + 1 because
++       * previous growing could increase it
++       */
++      depth = depth + 1;
++
++      /* 
++       * growing in depth:
++       * block allocation + new root + old root
++       */
++      needed = EXT3_ALLOC_NEEDED + 2;
++
++      /* index split. we may need:
++       *   allocate intermediate indexes and new leaf
++       *   change two blocks at each level, but root
++       *   modify root block (inode)
++       */
++      needed += (depth * EXT3_ALLOC_NEEDED) + (2 * depth) + 1;
++
++      return needed;
++}
++
++static int
++ext3_ext_split_for_rm(handle_t *handle, struct ext3_extents_tree *tree,
++                    struct ext3_ext_path *path, unsigned long start,
++                    unsigned long end)
++{
++      struct ext3_extent *ex, tex;
++      struct ext3_ext_path *npath;
++      int depth, creds, err;
++
++      depth = EXT_DEPTH(tree);
++      ex = path[depth].p_ext;
++      EXT_ASSERT(ex);
++      EXT_ASSERT(end < ex->ee_block + ex->ee_len - 1);
++      EXT_ASSERT(ex->ee_block < start);
++
++      /* calculate tail extent */
++      tex.ee_block = end + 1;
++      EXT_ASSERT(tex.ee_block < ex->ee_block + ex->ee_len);
++      tex.ee_len = ex->ee_block + ex->ee_len - tex.ee_block;
++
++      creds = ext3_ext_calc_credits_for_insert(tree, path);
++      handle = ext3_ext_journal_restart(handle, creds);
++      if (IS_ERR(handle))
++              return PTR_ERR(handle);
++      
++      /* calculate head extent. use primary extent */
++      err = ext3_ext_get_access(handle, tree, path + depth);
++      if (err)
++              return err;
++      ex->ee_len = start - ex->ee_block;
++      err = ext3_ext_dirty(handle, tree, path + depth);
++      if (err)
++              return err;
++
++      /* FIXME: some callback to free underlying resource
++       * and correct ee_start? */
++      ext_debug(tree, "split extent: head %u:%u, tail %u:%u\n",
++                ex->ee_block, ex->ee_len, tex.ee_block, tex.ee_len);
++
++      npath = ext3_ext_find_extent(tree, ex->ee_block, NULL);
++      if (IS_ERR(npath))
++              return PTR_ERR(npath);
++      depth = EXT_DEPTH(tree);
++      EXT_ASSERT(npath[depth].p_ext->ee_block == ex->ee_block);
++      EXT_ASSERT(npath[depth].p_ext->ee_len == ex->ee_len);
++
++      err = ext3_ext_insert_extent(handle, tree, npath, &tex);
++      ext3_ext_drop_refs(npath);
++      kfree(npath);
++
++      return err;
++}
++
++static int
++ext3_ext_rm_leaf(handle_t *handle, struct ext3_extents_tree *tree,
++               struct ext3_ext_path *path, unsigned long start,
++               unsigned long end)
++{
++      struct ext3_extent *ex, *fu = NULL, *lu, *le;
++      int err = 0, correct_index = 0;
++      int depth = EXT_DEPTH(tree), credits;
++      struct ext3_extent_header *eh;
++      unsigned a, b, block, num;
++
++      ext_debug(tree, "remove [%lu:%lu] in leaf\n", start, end);
++      if (!path[depth].p_hdr)
++              path[depth].p_hdr = EXT_BLOCK_HDR(path[depth].p_bh);
++      eh = path[depth].p_hdr;
++      EXT_ASSERT(eh);
++      EXT_ASSERT(eh->eh_entries <= eh->eh_max);
++      EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
++      
++      /* find where to start removing */
++      le = ex = EXT_LAST_EXTENT(eh);
++      while (ex != EXT_FIRST_EXTENT(eh)) {
++              if (ex->ee_block <= end)
++                      break;
++              ex--;
++      }
++
++      if (start > ex->ee_block && end < ex->ee_block + ex->ee_len - 1) {
++              /* removal of internal part of the extent requested
++               * tail and head must be placed in different extent
++               * so, we have to insert one more extent */
++              path[depth].p_ext = ex;
++              return ext3_ext_split_for_rm(handle, tree, path, start, end);
++      }
++      
++      lu = ex;
++      while (ex >= EXT_FIRST_EXTENT(eh) && ex->ee_block + ex->ee_len > start) {
++              ext_debug(tree, "remove ext %u:%u\n", ex->ee_block, ex->ee_len);
++              path[depth].p_ext = ex;
++      
++              a = ex->ee_block > start ? ex->ee_block : start;
++              b = ex->ee_block + ex->ee_len - 1 < end ?
++                      ex->ee_block + ex->ee_len - 1 : end;
++              
++              ext_debug(tree, "  border %u:%u\n", a, b);
++
++              if (a != ex->ee_block && b != ex->ee_block + ex->ee_len - 1) {
++                      block = 0;
++                      num = 0;
++                      BUG();
++              } else if (a != ex->ee_block) {
++                      /* remove tail of the extent */
++                      block = ex->ee_block;
++                      num = a - block;
++              } else if (b != ex->ee_block + ex->ee_len - 1) {
++                      /* remove head of the extent */
++                      block = a;
++                      num = b - a;
++              } else {
++                      /* remove whole extent: excelent! */
++                      block = ex->ee_block; 
++                      num = 0;
++                      EXT_ASSERT(a == ex->ee_block &&
++                                 b == ex->ee_block + ex->ee_len - 1);
++              }
++
++              if (ex == EXT_FIRST_EXTENT(eh))
++                      correct_index = 1;
++
++              credits = 1;
++              if (correct_index)
++                      credits += (EXT_DEPTH(tree) * EXT3_ALLOC_NEEDED) + 1;
++              if (tree->ops->remove_extent_credits)
++                      credits+=tree->ops->remove_extent_credits(tree,ex,a,b);
++              
++              handle = ext3_ext_journal_restart(handle, credits);
++              if (IS_ERR(handle)) {
++                      err = PTR_ERR(handle);
++                      goto out;
++              }
++
++              err = ext3_ext_get_access(handle, tree, path + depth);
++              if (err)
++                      goto out;
++
++              if (tree->ops->remove_extent)
++                      err = tree->ops->remove_extent(tree, ex, a, b);
++              if (err)
++                      goto out;
++
++              if (num == 0) {
++                      /* this extent is removed entirely mark slot unused */
++                      ex->ee_start = 0;
++                      eh->eh_entries--;
++                      fu = ex;
++              }
++
++              ex->ee_block = block;
++              ex->ee_len = num;
++
++              err = ext3_ext_dirty(handle, tree, path + depth);
++              if (err)
++                      goto out;
++
++              ext_debug(tree, "new extent: %u:%u:%u\n",
++                        ex->ee_block, ex->ee_len, ex->ee_start);
++              ex--;
++      }
++
++      if (fu) {
++              /* reuse unused slots */
++              while (lu < le) {
++                      if (lu->ee_start) {
++                              *fu = *lu;
++                              lu->ee_start = 0;
++                              fu++;
++                      }
++                      lu++;
++              }
++      }
++
++      if (correct_index && eh->eh_entries)
++              err = ext3_ext_correct_indexes(handle, tree, path);
++
++      /* if this leaf is free, then we should
++       * remove it from index block above */
++      if (err == 0 && eh->eh_entries == 0 && path[depth].p_bh != NULL)
++              err = ext3_ext_rm_idx(handle, tree, path + depth);
++
++out:
++      return err;
++}
++
++
++static struct ext3_extent_idx *
++ext3_ext_last_covered(struct ext3_extent_header *hdr, unsigned long block)
++{
++      struct ext3_extent_idx *ix;
++      
++      ix = EXT_LAST_INDEX(hdr);
++      while (ix != EXT_FIRST_INDEX(hdr)) {
++              if (ix->ei_block <= block)
++                      break;
++              ix--;
++      }
++      return ix;
++}
++
++/*
++ * returns 1 if current index have to be freed (even partial)
++ */
++static int inline
++ext3_ext_more_to_rm(struct ext3_ext_path *path)
++{
++      EXT_ASSERT(path->p_idx);
++
++      if (path->p_idx < EXT_FIRST_INDEX(path->p_hdr))
++              return 0;
++
++      /*
++       * if truncate on deeper level happened it it wasn't partial
++       * so we have to consider current index for truncation
++       */
++      if (path->p_hdr->eh_entries == path->p_block)
++              return 0;
++      return 1;
++}
++
++int ext3_ext_remove_space(struct ext3_extents_tree *tree,
++                        unsigned long start, unsigned long end)
++{
++      struct inode *inode = tree->inode;
++      struct super_block *sb = inode->i_sb;
++      int depth = EXT_DEPTH(tree);
++      struct ext3_ext_path *path;
++      handle_t *handle;
++      int i = 0, err = 0;
++
++      ext_debug(tree, "space to be removed: %lu:%lu\n", start, end);
++
++      /* probably first extent we're gonna free will be last in block */
++      handle = ext3_journal_start(inode, depth + 1);
++      if (IS_ERR(handle))
++              return PTR_ERR(handle);
++
++      ext3_ext_invalidate_cache(tree);
++
++      /*
++       * we start scanning from right side freeing all the blocks
++       * after i_size and walking into the deep
++       */
++      path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 1), GFP_KERNEL);
++      if (IS_ERR(path)) {
++              ext3_error(sb, __FUNCTION__, "Can't allocate path array");
++              ext3_journal_stop(handle);
++              return -ENOMEM;
++      }
++      memset(path, 0, sizeof(struct ext3_ext_path) * (depth + 1));
++      path[i].p_hdr = EXT_ROOT_HDR(tree);
++      
++      while (i >= 0 && err == 0) {
++              if (i == depth) {
++                      /* this is leaf block */
++                      err = ext3_ext_rm_leaf(handle, tree, path, start, end);
++                      /* root level have p_bh == NULL, brelse() eats this */
++                      brelse(path[i].p_bh);
++                      i--;
++                      continue;
++              }
++              
++              /* this is index block */
++              if (!path[i].p_hdr) {
++                      ext_debug(tree, "initialize header\n");
++                      path[i].p_hdr = EXT_BLOCK_HDR(path[i].p_bh);
++              }
++
++              EXT_ASSERT(path[i].p_hdr->eh_entries <= path[i].p_hdr->eh_max);
++              EXT_ASSERT(path[i].p_hdr->eh_magic == EXT3_EXT_MAGIC);
++              
++              if (!path[i].p_idx) {
++                      /* this level hasn't touched yet */
++                      path[i].p_idx =
++                              ext3_ext_last_covered(path[i].p_hdr, end);
++                      path[i].p_block = path[i].p_hdr->eh_entries + 1;
++                      ext_debug(tree, "init index ptr: hdr 0x%p, num %d\n",
++                                path[i].p_hdr, path[i].p_hdr->eh_entries);
++              } else {
++                      /* we've already was here, see at next index */
++                      path[i].p_idx--;
++              }
++
++              ext_debug(tree, "level %d - index, first 0x%p, cur 0x%p\n",
++                        i, EXT_FIRST_INDEX(path[i].p_hdr),
++                        path[i].p_idx);
++              if (ext3_ext_more_to_rm(path + i)) {
++                      /* go to the next level */
++                      ext_debug(tree, "move to level %d (block %d)\n",
++                                i + 1, path[i].p_idx->ei_leaf);
++                      memset(path + i + 1, 0, sizeof(*path));
++                      path[i+1].p_bh = sb_bread(sb, path[i].p_idx->ei_leaf);
++                      if (!path[i+1].p_bh) {
++                              /* should we reset i_size? */
++                              err = -EIO;
++                              break;
++                      }
++                      /* put actual number of indexes to know is this
++                       * number got changed at the next iteration */
++                      path[i].p_block = path[i].p_hdr->eh_entries;
++                      i++;
++              } else {
++                      /* we finish processing this index, go up */
++                      if (path[i].p_hdr->eh_entries == 0 && i > 0) {
++                              /* index is empty, remove it
++                               * handle must be already prepared by the
++                               * truncatei_leaf() */
++                              err = ext3_ext_rm_idx(handle, tree, path + i);
++                      }
++                      /* root level have p_bh == NULL, brelse() eats this */
++                      brelse(path[i].p_bh);
++                      i--;
++                      ext_debug(tree, "return to level %d\n", i);
++              }
++      }
++
++      /* TODO: flexible tree reduction should be here */
++      if (path->p_hdr->eh_entries == 0) {
++              /*
++               * truncate to zero freed all the tree
++               * so, we need to correct eh_depth
++               */
++              err = ext3_ext_get_access(handle, tree, path);
++              if (err == 0) {
++                      EXT_ROOT_HDR(tree)->eh_depth = 0;
++                      EXT_ROOT_HDR(tree)->eh_max = ext3_ext_space_root(tree);
++                      err = ext3_ext_dirty(handle, tree, path);
++              }
++      }
++      ext3_ext_tree_changed(tree);
++
++      kfree(path);
++      ext3_journal_stop(handle);
++
++      return err;
++}
++
++int ext3_ext_calc_metadata_amount(struct ext3_extents_tree *tree, int blocks)
++{
++      int lcap, icap, rcap, leafs, idxs, num;
++
++      rcap = ext3_ext_space_root(tree);
++      if (blocks <= rcap) {
++              /* all extents fit to the root */
++              return 0;
++      }
++
++      rcap = ext3_ext_space_root_idx(tree);
++      lcap = ext3_ext_space_block(tree);
++      icap = ext3_ext_space_block_idx(tree);
++
++      num = leafs = (blocks + lcap - 1) / lcap;
++      if (leafs <= rcap) {
++              /* all pointers to leafs fit to the root */
++              return leafs;
++      }
++
++      /* ok. we need separate index block(s) to link all leaf blocks */
++      idxs = (leafs + icap - 1) / icap;
++      do {
++              num += idxs;
++              idxs = (idxs + icap - 1) / icap;
++      } while (idxs > rcap);
++
++      return num;
++}
++
++/*
++ * called at mount time
++ */
++void ext3_ext_init(struct super_block *sb)
++{
++      /*
++       * possible initialization would be here
++       */
++
++      if (test_opt(sb, EXTENTS)) {
++              printk("EXT3-fs: file extents enabled");
++#ifdef AGRESSIVE_TEST
++              printk(", agressive tests");
++#endif
++#ifdef CHECK_BINSEARCH
++              printk(", check binsearch");
++#endif
++              printk("\n");
++      }
++}
++
++/*
++ * called at umount time
++ */
++void ext3_ext_release(struct super_block *sb)
++{
++}
++
++/************************************************************************
++ * VFS related routines
++ ************************************************************************/
++
++static int ext3_get_inode_write_access(handle_t *handle, void *buffer)
++{
++      /* we use in-core data, not bh */
++      return 0;
++}
++
++static int ext3_mark_buffer_dirty(handle_t *handle, void *buffer)
++{
++      struct inode *inode = buffer;
++      return ext3_mark_inode_dirty(handle, inode);
++}
++
++static int ext3_ext_mergable(struct ext3_extent *ex1,
++                           struct ext3_extent *ex2)
++{
++      /* FIXME: support for large fs */
++      if (ex1->ee_start + ex1->ee_len == ex2->ee_start)
++              return 1;
++      return 0;
++}
++
++static int
++ext3_remove_blocks_credits(struct ext3_extents_tree *tree,
++                         struct ext3_extent *ex,
++                         unsigned long from, unsigned long to)
++{
++      int needed;
++      
++      /* at present, extent can't cross block group */;
++      needed = 4; /* bitmap + group desc + sb + inode */
++
++#ifdef CONFIG_QUOTA
++      needed += 2 * EXT3_SINGLEDATA_TRANS_BLOCKS;
++#endif
++      return needed;
++}
++
++static int
++ext3_remove_blocks(struct ext3_extents_tree *tree,
++                 struct ext3_extent *ex,
++                 unsigned long from, unsigned long to)
++{
++      int needed = ext3_remove_blocks_credits(tree, ex, from, to);
++      handle_t *handle = ext3_journal_start(tree->inode, needed);
++      struct buffer_head *bh;
++      int i;
++
++      if (IS_ERR(handle))
++              return PTR_ERR(handle);
++      if (from >= ex->ee_block && to == ex->ee_block + ex->ee_len - 1) {
++              /* tail removal */
++              unsigned long num, start;
++              num = ex->ee_block + ex->ee_len - from;
++              start = ex->ee_start + ex->ee_len - num;
++              ext_debug(tree, "free last %lu blocks starting %lu\n",
++                        num, start);
++              for (i = 0; i < num; i++) {
++                      bh = sb_find_get_block(tree->inode->i_sb, start + i);
++                      ext3_forget(handle, 0, tree->inode, bh, start + i);
++              }
++              ext3_free_blocks(handle, tree->inode, start, num);
++      } else if (from == ex->ee_block && to <= ex->ee_block + ex->ee_len - 1) {
++              printk("strange request: removal %lu-%lu from %u:%u\n",
++                     from, to, ex->ee_block, ex->ee_len);
++      } else {
++              printk("strange request: removal(2) %lu-%lu from %u:%u\n",
++                     from, to, ex->ee_block, ex->ee_len);
++      }
++      ext3_journal_stop(handle);
++      return 0;
++}
++
++static int ext3_ext_find_goal(struct inode *inode,
++                            struct ext3_ext_path *path, unsigned long block)
++{
++      struct ext3_inode_info *ei = EXT3_I(inode);
++      unsigned long bg_start;
++      unsigned long colour;
++      int depth;
++      
++      if (path) {
++              struct ext3_extent *ex;
++              depth = path->p_depth;
++              
++              /* try to predict block placement */
++              if ((ex = path[depth].p_ext))
++                      return ex->ee_start + (block - ex->ee_block);
++
++              /* it looks index is empty
++               * try to find starting from index itself */
++              if (path[depth].p_bh)
++                      return path[depth].p_bh->b_blocknr;
++      }
++
++      /* OK. use inode's group */
++      bg_start = (ei->i_block_group * EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
++              le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block);
++      colour = (current->pid % 16) *
++                      (EXT3_BLOCKS_PER_GROUP(inode->i_sb) / 16);
++      return bg_start + colour + block;
++}
++
++static int ext3_new_block_cb(handle_t *handle, struct ext3_extents_tree *tree,
++                           struct ext3_ext_path *path,
++                           struct ext3_extent *ex, int *err)
++{
++      struct inode *inode = tree->inode;
++      int newblock, goal;
++      
++      EXT_ASSERT(path);
++      EXT_ASSERT(ex);
++      EXT_ASSERT(ex->ee_start);
++      EXT_ASSERT(ex->ee_len);
++      
++      /* reuse block from the extent to order data/metadata */
++      newblock = ex->ee_start++;
++      ex->ee_len--;
++      if (ex->ee_len == 0) {
++              ex->ee_len = 1;
++              /* allocate new block for the extent */
++              goal = ext3_ext_find_goal(inode, path, ex->ee_block);
++              ex->ee_start = ext3_new_block(handle, inode, goal, err);
++              if (ex->ee_start == 0) {
++                      /* error occured: restore old extent */
++                      ex->ee_start = newblock;
++                      return 0;
++              }
++      }
++      return newblock;
++}
++
++static struct ext3_extents_helpers ext3_blockmap_helpers = {
++      .get_write_access       = ext3_get_inode_write_access,
++      .mark_buffer_dirty      = ext3_mark_buffer_dirty,
++      .mergable               = ext3_ext_mergable,
++      .new_block              = ext3_new_block_cb,
++      .remove_extent          = ext3_remove_blocks,
++      .remove_extent_credits  = ext3_remove_blocks_credits,
++};
++
++void ext3_init_tree_desc(struct ext3_extents_tree *tree,
++                       struct inode *inode)
++{
++      tree->inode = inode;
++      tree->root = (void *) EXT3_I(inode)->i_data;
++      tree->buffer = (void *) inode;
++      tree->buffer_len = sizeof(EXT3_I(inode)->i_data);
++      tree->cex = (struct ext3_ext_cache *) &EXT3_I(inode)->i_cached_extent;
++      tree->ops = &ext3_blockmap_helpers;
++}
++
++int ext3_ext_get_block(handle_t *handle, struct inode *inode,
++                     long iblock, struct buffer_head *bh_result,
++                     int create, int extend_disksize)
++{
++      struct ext3_ext_path *path = NULL;
++      struct ext3_extent newex;
++      struct ext3_extent *ex;
++      int goal, newblock, err = 0, depth;
++      struct ext3_extents_tree tree;
++
++      clear_buffer_new(bh_result);
++      ext3_init_tree_desc(&tree, inode);
++      ext_debug(&tree, "block %d requested for inode %u\n",
++                (int) iblock, (unsigned) inode->i_ino);
++      mutex_lock(&EXT3_I(inode)->truncate_mutex);
++
++      /* check in cache */
++      if ((goal = ext3_ext_in_cache(&tree, iblock, &newex))) {
++              if (goal == EXT3_EXT_CACHE_GAP) {
++                      if (!create) {
++                              /* block isn't allocated yet and
++                               * user don't want to allocate it */
++                              goto out2;
++                      }
++                      /* we should allocate requested block */
++              } else if (goal == EXT3_EXT_CACHE_EXTENT) {
++                      /* block is already allocated */
++                      newblock = iblock - newex.ee_block + newex.ee_start;
++                      goto out;
++              } else {
++                      EXT_ASSERT(0);
++              }
++      }
++
++      /* find extent for this block */
++      path = ext3_ext_find_extent(&tree, iblock, NULL);
++      if (IS_ERR(path)) {
++              err = PTR_ERR(path);
++              path = NULL;
++              goto out2;
++      }
++
++      depth = EXT_DEPTH(&tree);
++
++      /*
++       * consistent leaf must not be empty
++       * this situations is possible, though, _during_ tree modification
++       * this is why assert can't be put in ext3_ext_find_extent()
++       */
++      EXT_ASSERT(path[depth].p_ext != NULL || depth == 0);
++
++      if ((ex = path[depth].p_ext)) {
++              /* if found exent covers block, simple return it */
++              if (iblock >= ex->ee_block && iblock < ex->ee_block + ex->ee_len) {
++                      newblock = iblock - ex->ee_block + ex->ee_start;
++                      ext_debug(&tree, "%d fit into %d:%d -> %d\n",
++                                (int) iblock, ex->ee_block, ex->ee_len,
++                                newblock);
++                      ext3_ext_put_in_cache(&tree, ex->ee_block,
++                                            ex->ee_len, ex->ee_start,
++                                            EXT3_EXT_CACHE_EXTENT);
++                      goto out;
++              }
++      }
++
++      /*
++       * requested block isn't allocated yet
++       * we couldn't try to create block if create flag is zero 
++       */
++      if (!create) {
++              /* put just found gap into cache to speedup subsequest reqs */
++              ext3_ext_put_gap_in_cache(&tree, path, iblock);
++              goto out2;
++      }
++
++      /* allocate new block */
++      goal = ext3_ext_find_goal(inode, path, iblock);
++      newblock = ext3_new_block(handle, inode, goal, &err);
++      if (!newblock)
++              goto out2;
++      ext_debug(&tree, "allocate new block: goal %d, found %d\n",
++                goal, newblock);
++
++      /* try to insert new extent into found leaf and return */
++      newex.ee_block = iblock;
++      newex.ee_start = newblock;
++      newex.ee_len = 1;
++      err = ext3_ext_insert_extent(handle, &tree, path, &newex);
++      if (err)
++              goto out2;
++      
++      if (extend_disksize && inode->i_size > EXT3_I(inode)->i_disksize)
++              EXT3_I(inode)->i_disksize = inode->i_size;
++
++      /* previous routine could use block we allocated */
++      newblock = newex.ee_start;
++      set_buffer_new(bh_result);
++
++      ext3_ext_put_in_cache(&tree, newex.ee_block, newex.ee_len,
++                            newex.ee_start, EXT3_EXT_CACHE_EXTENT);
++out:
++      ext3_ext_show_leaf(&tree, path);
++      map_bh(bh_result, inode->i_sb, newblock);
++out2:
++      if (path) {
++              ext3_ext_drop_refs(path);
++              kfree(path);
++      }
++      mutex_unlock(&EXT3_I(inode)->truncate_mutex);
++
++      return err;     
++}
++
++void ext3_ext_truncate(struct inode * inode, struct page *page)
++{
++      struct address_space *mapping = inode->i_mapping;
++      struct super_block *sb = inode->i_sb;
++      struct ext3_extents_tree tree;
++      unsigned long last_block;
++      handle_t *handle;
++      int err = 0;
++
++      ext3_init_tree_desc(&tree, inode);
++
++      /*
++       * probably first extent we're gonna free will be last in block
++       */
++      err = ext3_writepage_trans_blocks(inode) + 3;
++      handle = ext3_journal_start(inode, err);
++      if (IS_ERR(handle)) {
++              if (page) {
++                      clear_highpage(page);
++                      flush_dcache_page(page);
++                      unlock_page(page);
++                      page_cache_release(page);
++              }
++              return;
++      }
++
++      if (page)
++              ext3_block_truncate_page(handle, page, mapping, inode->i_size);
++
++      mutex_lock(&EXT3_I(inode)->truncate_mutex);
++      ext3_ext_invalidate_cache(&tree);
++
++      /* 
++       * TODO: optimization is possible here
++       * probably we need not scaning at all,
++       * because page truncation is enough
++       */
++      if (ext3_orphan_add(handle, inode))
++              goto out_stop;
++
++      /* we have to know where to truncate from in crash case */
++      EXT3_I(inode)->i_disksize = inode->i_size;
++      ext3_mark_inode_dirty(handle, inode);
++
++      last_block = (inode->i_size + sb->s_blocksize - 1) >>
++                      EXT3_BLOCK_SIZE_BITS(sb);
++      err = ext3_ext_remove_space(&tree, last_block, EXT_MAX_BLOCK);
++      
++      /* In a multi-transaction truncate, we only make the final
++       * transaction synchronous */
++      if (IS_SYNC(inode))
++              handle->h_sync = 1;
++
++out_stop:
++      /*
++       * If this was a simple ftruncate(), and the file will remain alive
++       * then we need to clear up the orphan record which we created above.
++       * However, if this was a real unlink then we were called by
++       * ext3_delete_inode(), and we allow that function to clean up the
++       * orphan info for us.
++       */
++      if (inode->i_nlink)
++              ext3_orphan_del(handle, inode);
++
++      mutex_unlock(&EXT3_I(inode)->truncate_mutex);
++      ext3_journal_stop(handle);
++}
++
++/*
++ * this routine calculate max number of blocks we could modify
++ * in order to allocate new block for an inode
++ */
++int ext3_ext_writepage_trans_blocks(struct inode *inode, int num)
++{
++      struct ext3_extents_tree tree;
++      int needed;
++      
++      ext3_init_tree_desc(&tree, inode);
++      
++      needed = ext3_ext_calc_credits_for_insert(&tree, NULL);
++
++      /* caller want to allocate num blocks */
++      needed *= num;
++      
++#ifdef CONFIG_QUOTA
++      /* 
++       * FIXME: real calculation should be here
++       * it depends on blockmap format of qouta file
++       */
++      needed += 2 * EXT3_SINGLEDATA_TRANS_BLOCKS;
++#endif
++
++      return needed;
++}
++
++void ext3_extents_initialize_blockmap(handle_t *handle, struct inode *inode)
++{
++      struct ext3_extents_tree tree;
++
++      ext3_init_tree_desc(&tree, inode);
++      ext3_extent_tree_init(handle, &tree);
++}
++
++int ext3_ext_calc_blockmap_metadata(struct inode *inode, int blocks)
++{
++      struct ext3_extents_tree tree;
++
++      ext3_init_tree_desc(&tree, inode);
++      return ext3_ext_calc_metadata_amount(&tree, blocks);
++}
++      
++static int
++ext3_ext_store_extent_cb(struct ext3_extents_tree *tree,
++                       struct ext3_ext_path *path,
++                       struct ext3_ext_cache *newex)
++{
++      struct ext3_extent_buf *buf = (struct ext3_extent_buf *) tree->private;
++
++      if (newex->ec_type != EXT3_EXT_CACHE_EXTENT)
++              return EXT_CONTINUE;
++
++      if (buf->err < 0)
++              return EXT_BREAK;
++      if (buf->cur - buf->buffer + sizeof(*newex) > buf->buflen)
++              return EXT_BREAK;
++
++      if (!copy_to_user(buf->cur, newex, sizeof(*newex))) {
++              buf->err++;
++              buf->cur += sizeof(*newex);
++      } else {
++              buf->err = -EFAULT;
++              return EXT_BREAK;
++      }
++      return EXT_CONTINUE;
++}
++
++static int
++ext3_ext_collect_stats_cb(struct ext3_extents_tree *tree,
++                        struct ext3_ext_path *path,
++                        struct ext3_ext_cache *ex)
++{
++      struct ext3_extent_tree_stats *buf =
++              (struct ext3_extent_tree_stats *) tree->private;
++      int depth;
++
++      if (ex->ec_type != EXT3_EXT_CACHE_EXTENT)
++              return EXT_CONTINUE;
++
++      depth = EXT_DEPTH(tree);
++      buf->extents_num++;
++      if (path[depth].p_ext == EXT_FIRST_EXTENT(path[depth].p_hdr))
++              buf->leaf_num++;
++      return EXT_CONTINUE;
++}
++
++int ext3_ext_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
++                 unsigned long arg)
++{
++      int err = 0;
++
++      if (!(EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL))
++              return -EINVAL;
++
++      if (cmd == EXT3_IOC_GET_EXTENTS) {
++              struct ext3_extent_buf buf;
++              struct ext3_extents_tree tree;
++
++              if (copy_from_user(&buf, (void *) arg, sizeof(buf)))
++                      return -EFAULT;
++
++              ext3_init_tree_desc(&tree, inode);
++              buf.cur = buf.buffer;
++              buf.err = 0;
++              tree.private = &buf;
++              mutex_lock(&EXT3_I(inode)->truncate_mutex);
++              err = ext3_ext_walk_space(&tree, buf.start, EXT_MAX_BLOCK,
++                                        ext3_ext_store_extent_cb);
++              mutex_unlock(&EXT3_I(inode)->truncate_mutex);
++              if (err == 0)
++                      err = buf.err;
++      } else if (cmd == EXT3_IOC_GET_TREE_STATS) {
++              struct ext3_extent_tree_stats buf;
++              struct ext3_extents_tree tree;
++
++              ext3_init_tree_desc(&tree, inode);
++              mutex_lock(&EXT3_I(inode)->truncate_mutex);
++              buf.depth = EXT_DEPTH(&tree);
++              buf.extents_num = 0;
++              buf.leaf_num = 0;
++              tree.private = &buf;
++              err = ext3_ext_walk_space(&tree, 0, EXT_MAX_BLOCK,
++                                        ext3_ext_collect_stats_cb);
++              mutex_unlock(&EXT3_I(inode)->truncate_mutex);
++              if (!err)
++                      err = copy_to_user((void *) arg, &buf, sizeof(buf));
++      } else if (cmd == EXT3_IOC_GET_TREE_DEPTH) {
++              struct ext3_extents_tree tree;
++              ext3_init_tree_desc(&tree, inode);
++              mutex_lock(&EXT3_I(inode)->truncate_mutex);
++              err = EXT_DEPTH(&tree);
++              mutex_unlock(&EXT3_I(inode)->truncate_mutex);
++      }
++
++      return err;
++}
++
++EXPORT_SYMBOL(ext3_init_tree_desc);
++EXPORT_SYMBOL(ext3_mark_inode_dirty);
++EXPORT_SYMBOL(ext3_ext_invalidate_cache);
++EXPORT_SYMBOL(ext3_ext_insert_extent);
++EXPORT_SYMBOL(ext3_ext_walk_space);
++EXPORT_SYMBOL(ext3_ext_find_goal);
++EXPORT_SYMBOL(ext3_ext_calc_credits_for_insert);
+Index: linux-stage/fs/ext3/ialloc.c
+===================================================================
+--- linux-stage.orig/fs/ext3/ialloc.c  2006-07-16 13:55:31.000000000 +0800
++++ linux-stage/fs/ext3/ialloc.c       2006-07-16 14:10:20.000000000 +0800
+@@ -600,7 +600,7 @@ got:
+       ei->i_dir_start_lookup = 0;
+       ei->i_disksize = 0;
+-      ei->i_flags = EXT3_I(dir)->i_flags & ~EXT3_INDEX_FL;
++      ei->i_flags = EXT3_I(dir)->i_flags & ~(EXT3_INDEX_FL|EXT3_EXTENTS_FL);
+       if (S_ISLNK(mode))
+               ei->i_flags &= ~(EXT3_IMMUTABLE_FL|EXT3_APPEND_FL);
+       /* dirsync only applies to directories */
+@@ -644,6 +644,18 @@ got:
+       if (err)
+               goto fail_free_drop;
++      if (test_opt(sb, EXTENTS) && S_ISREG(inode->i_mode)) {
++              EXT3_I(inode)->i_flags |= EXT3_EXTENTS_FL;
++              ext3_extents_initialize_blockmap(handle, inode);
++              if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_EXTENTS)) {
++                      err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
++                      if (err) goto fail;
++                      EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_EXTENTS);
++                      BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "call ext3_journal_dirty_metadata");
++                      err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
++              }
++      }
++
+       err = ext3_mark_inode_dirty(handle, inode);
+       if (err) {
+               ext3_std_error(sb, err);
+Index: linux-stage/fs/ext3/inode.c
+===================================================================
+--- linux-stage.orig/fs/ext3/inode.c   2006-07-16 13:55:31.000000000 +0800
++++ linux-stage/fs/ext3/inode.c        2006-07-16 14:11:28.000000000 +0800
+@@ -40,7 +40,7 @@
+ #include "iopen.h"
+ #include "acl.h"
+-static int ext3_writepage_trans_blocks(struct inode *inode);
++int ext3_writepage_trans_blocks(struct inode *inode);
+ /*
+  * Test whether an inode is a fast symlink.
+@@ -944,6 +944,17 @@ out:
+ #define DIO_CREDITS (EXT3_RESERVE_TRANS_BLOCKS + 32)
++static inline int
++ext3_get_block_wrap(handle_t *handle, struct inode *inode, long block,
++                  struct buffer_head *bh, int create, int extend_disksize)
++{
++      if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
++              return ext3_ext_get_block(handle, inode, block, bh, create,
++                                        extend_disksize);
++      return ext3_get_blocks_handle(handle, inode, block, 1, bh, create,
++                                   extend_disksize);
++}
++
+ static int ext3_get_block(struct inode *inode, sector_t iblock,
+                       struct buffer_head *bh_result, int create)
+ {
+@@ -984,8 +995,8 @@ static int ext3_get_block(struct inode *
+ get_block:
+       if (ret == 0) {
+-              ret = ext3_get_blocks_handle(handle, inode, iblock,
+-                                      max_blocks, bh_result, create, 0);
++              ret = ext3_get_block_wrap(handle, inode, iblock,
++                                              bh_result, create, 0);
+               if (ret > 0) {
+                       bh_result->b_size = (ret << inode->i_blkbits);
+                       ret = 0;
+@@ -1008,7 +1019,7 @@ struct buffer_head *ext3_getblk(handle_t
+       dummy.b_state = 0;
+       dummy.b_blocknr = -1000;
+       buffer_trace_init(&dummy.b_history);
+-      err = ext3_get_blocks_handle(handle, inode, block, 1,
++      err = ext3_get_block_wrap(handle, inode, block,
+                                       &dummy, create, 1);
+       if (err == 1) {
+               err = 0;
+@@ -1756,7 +1767,7 @@ void ext3_set_aops(struct inode *inode)
+  * This required during truncate. We need to physically zero the tail end
+  * of that block so it doesn't yield old data if the file is later grown.
+  */
+-static int ext3_block_truncate_page(handle_t *handle, struct page *page,
++int ext3_block_truncate_page(handle_t *handle, struct page *page,
+               struct address_space *mapping, loff_t from)
+ {
+       ext3_fsblk_t index = from >> PAGE_CACHE_SHIFT;
+@@ -2260,6 +2271,9 @@ void ext3_truncate(struct inode *inode)
+                       return;
+       }
++      if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
++              return ext3_ext_truncate(inode, page);
++
+       handle = start_transaction(inode);
+       if (IS_ERR(handle)) {
+               if (page) {
+@@ -3004,12 +3018,15 @@ err_out:
+  * block and work out the exact number of indirects which are touched.  Pah.
+  */
+-static int ext3_writepage_trans_blocks(struct inode *inode)
++int ext3_writepage_trans_blocks(struct inode *inode)
+ {
+       int bpp = ext3_journal_blocks_per_page(inode);
+       int indirects = (EXT3_NDIR_BLOCKS % bpp) ? 5 : 3;
+       int ret;
++      if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
++              return ext3_ext_writepage_trans_blocks(inode, bpp);
++
+       if (ext3_should_journal_data(inode))
+               ret = 3 * (bpp + indirects) + 2;
+       else
+@@ -3277,7 +3294,7 @@ int ext3_prep_san_write(struct inode *in
+       /* alloc blocks one by one */
+       for (i = 0; i < nblocks; i++) {
+-              ret = ext3_get_block_handle(handle, inode, blocks[i],
++              ret = ext3_get_blocks_handle(handle, inode, blocks[i], 1,
+                                               &bh_tmp, 1, 1);
+               if (ret)
+                       break;
+@@ -3337,7 +3354,7 @@ int ext3_map_inode_page(struct inode *in
+                 if (blocks[i] != 0)
+                         continue;
+-                rc = ext3_get_block_handle(handle, inode, iblock, &dummy, 1, 1);
++                rc = ext3_get_blocks_handle(handle, inode, iblock, 1, &dummy, 1, 1);
+                 if (rc) {
+                         printk(KERN_INFO "ext3_map_inode_page: error reading "
+                                "block %ld\n", iblock);
+Index: linux-stage/fs/ext3/Makefile
+===================================================================
+--- linux-stage.orig/fs/ext3/Makefile  2006-07-16 13:55:31.000000000 +0800
++++ linux-stage/fs/ext3/Makefile       2006-07-16 14:10:21.000000000 +0800
+@@ -5,7 +5,8 @@
+ obj-$(CONFIG_EXT3_FS) += ext3.o
+ ext3-y        := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
+-         ioctl.o namei.o super.o symlink.o hash.o resize.o
++         ioctl.o namei.o super.o symlink.o hash.o resize.o \
++         extents.o
+ ext3-$(CONFIG_EXT3_FS_XATTR)   += xattr.o xattr_user.o xattr_trusted.o
+ ext3-$(CONFIG_EXT3_FS_POSIX_ACL) += acl.o
+Index: linux-stage/fs/ext3/super.c
+===================================================================
+--- linux-stage.orig/fs/ext3/super.c   2006-07-16 13:55:31.000000000 +0800
++++ linux-stage/fs/ext3/super.c        2006-07-16 14:10:21.000000000 +0800
+@@ -391,6 +391,7 @@ static void ext3_put_super (struct super
+       struct ext3_super_block *es = sbi->s_es;
+       int i;
++      ext3_ext_release(sb);
+       ext3_xattr_put_super(sb);
+       journal_destroy(sbi->s_journal);
+       if (!(sb->s_flags & MS_RDONLY)) {
+@@ -455,6 +456,8 @@ static struct inode *ext3_alloc_inode(st
+ #endif
+       ei->i_block_alloc_info = NULL;
+       ei->vfs_inode.i_version = 1;
++      
++      memset(&ei->i_cached_extent, 0, sizeof(ei->i_cached_extent));
+       return &ei->vfs_inode;
+ }
+@@ -638,6 +641,7 @@ enum {
+       Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
+       Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
+       Opt_iopen, Opt_noiopen, Opt_iopen_nopriv,
++      Opt_extents, Opt_extdebug,
+       Opt_grpquota
+ };
+@@ -690,6 +694,8 @@ static match_table_t tokens = {
+       {Opt_iopen, "iopen"},
+       {Opt_noiopen, "noiopen"},
+       {Opt_iopen_nopriv, "iopen_nopriv"},
++      {Opt_extents, "extents"},
++      {Opt_extdebug, "extdebug"},
+       {Opt_barrier, "barrier=%u"},
+       {Opt_err, NULL},
+       {Opt_resize, "resize"},
+@@ -1035,6 +1041,12 @@ clear_qf_name:
+               case Opt_bh:
+                       clear_opt(sbi->s_mount_opt, NOBH);
+                       break;
++              case Opt_extents:
++                      set_opt (sbi->s_mount_opt, EXTENTS);
++                      break;
++              case Opt_extdebug:
++                      set_opt (sbi->s_mount_opt, EXTDEBUG);
++                      break;
+               default:
+                       printk (KERN_ERR
+                               "EXT3-fs: Unrecognized mount option \"%s\" "
+@@ -1760,6 +1772,7 @@ static int ext3_fill_super (struct super
+               test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered":
+               "writeback");
++      ext3_ext_init(sb);
+       lock_kernel();
+       return 0;
+Index: linux-stage/fs/ext3/ioctl.c
+===================================================================
+--- linux-stage.orig/fs/ext3/ioctl.c   2006-07-16 13:55:31.000000000 +0800
++++ linux-stage/fs/ext3/ioctl.c        2006-07-16 13:55:31.000000000 +0800
+@@ -135,6 +135,10 @@ flags_err:
+               mutex_unlock(&inode->i_mutex);
+               return err;
+       }
++      case EXT3_IOC_GET_EXTENTS:
++      case EXT3_IOC_GET_TREE_STATS:
++      case EXT3_IOC_GET_TREE_DEPTH:
++              return ext3_ext_ioctl(inode, filp, cmd, arg);
+       case EXT3_IOC_GETVERSION:
+       case EXT3_IOC_GETVERSION_OLD:
+               return put_user(inode->i_generation, (int __user *) arg);
+Index: linux-stage/include/linux/ext3_fs.h
+===================================================================
+--- linux-stage.orig/include/linux/ext3_fs.h   2006-07-16 13:55:31.000000000 +0800
++++ linux-stage/include/linux/ext3_fs.h        2006-07-16 14:10:21.000000000 +0800
+@@ -181,9 +181,10 @@ struct ext3_group_desc
+ #define EXT3_NOTAIL_FL                        0x00008000 /* file tail should not be merged */
+ #define EXT3_DIRSYNC_FL                       0x00010000 /* dirsync behaviour (directories only) */
+ #define EXT3_TOPDIR_FL                        0x00020000 /* Top of directory hierarchies*/
++#define EXT3_EXTENTS_FL                       0x00080000 /* Inode uses extents */
+ #define EXT3_RESERVED_FL              0x80000000 /* reserved for ext3 lib */
+-#define EXT3_FL_USER_VISIBLE          0x0003DFFF /* User visible flags */
++#define EXT3_FL_USER_VISIBLE          0x000BDFFF /* User visible flags */
+ #define EXT3_FL_USER_MODIFIABLE               0x000380FF /* User modifiable flags */
+ /*
+@@ -233,6 +234,9 @@ struct ext3_new_group_data {
+ #endif
+ #define EXT3_IOC_GETRSVSZ             _IOR('f', 5, long)
+ #define EXT3_IOC_SETRSVSZ             _IOW('f', 6, long)
++#define EXT3_IOC_GET_EXTENTS          _IOR('f', 7, long)
++#define EXT3_IOC_GET_TREE_DEPTH               _IOR('f', 8, long)
++#define EXT3_IOC_GET_TREE_STATS               _IOR('f', 9, long)
+ /*
+  *  Mount options
+@@ -373,6 +377,8 @@ struct ext3_inode {
+ #define EXT3_MOUNT_GRPQUOTA           0x200000 /* "old" group quota */
+ #define EXT3_MOUNT_IOPEN              0x400000        /* Allow access via iopen */
+ #define EXT3_MOUNT_IOPEN_NOPRIV               0x800000/* Make iopen world-readable */
++#define EXT3_MOUNT_EXTENTS            0x1000000/* Extents support */
++#define EXT3_MOUNT_EXTDEBUG           0x2000000/* Extents debug */
+ /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
+ #ifndef clear_opt
+@@ -563,11 +569,13 @@ static inline struct ext3_inode_info *EX
+ #define EXT3_FEATURE_INCOMPAT_RECOVER         0x0004 /* Needs recovery */
+ #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV     0x0008 /* Journal device */
+ #define EXT3_FEATURE_INCOMPAT_META_BG         0x0010
++#define EXT3_FEATURE_INCOMPAT_EXTENTS         0x0040 /* extents support */
+ #define EXT3_FEATURE_COMPAT_SUPP      EXT2_FEATURE_COMPAT_EXT_ATTR
+ #define EXT3_FEATURE_INCOMPAT_SUPP    (EXT3_FEATURE_INCOMPAT_FILETYPE| \
+                                        EXT3_FEATURE_INCOMPAT_RECOVER| \
+-                                       EXT3_FEATURE_INCOMPAT_META_BG)
++                                       EXT3_FEATURE_INCOMPAT_META_BG| \
++                                       EXT3_FEATURE_INCOMPAT_EXTENTS)
+ #define EXT3_FEATURE_RO_COMPAT_SUPP   (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
+                                        EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \
+                                        EXT3_FEATURE_RO_COMPAT_BTREE_DIR)
+@@ -787,6 +795,8 @@ extern unsigned long ext3_count_free (st
+ /* inode.c */
++extern int ext3_block_truncate_page(handle_t *, struct page *,
++                                      struct address_space *, loff_t);
+ int ext3_forget(handle_t *handle, int is_metadata, struct inode *inode,
+               struct buffer_head *bh, ext3_fsblk_t blocknr);
+ struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
+@@ -860,6 +870,16 @@ extern struct inode_operations ext3_spec
+ extern struct inode_operations ext3_symlink_inode_operations;
+ extern struct inode_operations ext3_fast_symlink_inode_operations;
++/* extents.c */
++extern int ext3_ext_writepage_trans_blocks(struct inode *, int);
++extern int ext3_ext_get_block(handle_t *, struct inode *, long,
++                            struct buffer_head *, int, int);
++extern void ext3_ext_truncate(struct inode *, struct page *);
++extern void ext3_ext_init(struct super_block *);
++extern void ext3_ext_release(struct super_block *);
++extern void ext3_extents_initialize_blockmap(handle_t *, struct inode *);
++extern int ext3_ext_ioctl(struct inode *inode, struct file *filp,
++                        unsigned int cmd, unsigned long arg);
+ #endif        /* __KERNEL__ */
+Index: linux-stage/include/linux/ext3_extents.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-stage/include/linux/ext3_extents.h   2006-07-16 13:55:31.000000000 +0800
+@@ -0,0 +1,264 @@
++/*
++ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com
++ * Written by Alex Tomas <alex@clusterfs.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public Licens
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-
++ */
++
++#ifndef _LINUX_EXT3_EXTENTS
++#define _LINUX_EXT3_EXTENTS
++
++/*
++ * with AGRESSIVE_TEST defined capacity of index/leaf blocks
++ * become very little, so index split, in-depth growing and
++ * other hard changes happens much more often
++ * this is for debug purposes only
++ */
++#define AGRESSIVE_TEST_
++
++/*
++ * if CHECK_BINSEARCH defined, then results of binary search
++ * will be checked by linear search
++ */
++#define CHECK_BINSEARCH_
++
++/*
++ * if EXT_DEBUG is defined you can use 'extdebug' mount option
++ * to get lots of info what's going on
++ */
++#define EXT_DEBUG_
++#ifdef EXT_DEBUG
++#define ext_debug(tree,fmt,a...)                      \
++do {                                                  \
++      if (test_opt((tree)->inode->i_sb, EXTDEBUG))    \
++              printk(fmt, ##a);                       \
++} while (0);
++#else
++#define ext_debug(tree,fmt,a...)
++#endif
++
++/*
++ * if EXT_STATS is defined then stats numbers are collected
++ * these number will be displayed at umount time
++ */
++#define EXT_STATS_
++
++
++#define EXT3_ALLOC_NEEDED     3       /* block bitmap + group desc. + sb */
++
++/*
++ * ext3_inode has i_block array (total 60 bytes)
++ * first 4 bytes are used to store:
++ *  - tree depth (0 mean there is no tree yet. all extents in the inode)
++ *  - number of alive extents in the inode
++ */
++
++/*
++ * this is extent on-disk structure
++ * it's used at the bottom of the tree
++ */
++struct ext3_extent {
++      __u32   ee_block;       /* first logical block extent covers */
++      __u16   ee_len;         /* number of blocks covered by extent */
++      __u16   ee_start_hi;    /* high 16 bits of physical block */
++      __u32   ee_start;       /* low 32 bigs of physical block */
++};
++
++/*
++ * this is index on-disk structure
++ * it's used at all the levels, but the bottom
++ */
++struct ext3_extent_idx {
++      __u32   ei_block;       /* index covers logical blocks from 'block' */
++      __u32   ei_leaf;        /* pointer to the physical block of the next *
++                               * level. leaf or next index could bet here */
++      __u16   ei_leaf_hi;     /* high 16 bits of physical block */
++      __u16   ei_unused;
++};
++
++/*
++ * each block (leaves and indexes), even inode-stored has header
++ */
++struct ext3_extent_header {   
++      __u16   eh_magic;       /* probably will support different formats */   
++      __u16   eh_entries;     /* number of valid entries */
++      __u16   eh_max;         /* capacity of store in entries */
++      __u16   eh_depth;       /* has tree real underlaying blocks? */
++      __u32   eh_generation;  /* generation of the tree */
++};
++
++#define EXT3_EXT_MAGIC                0xf30a
++
++/*
++ * array of ext3_ext_path contains path to some extent
++ * creation/lookup routines use it for traversal/splitting/etc
++ * truncate uses it to simulate recursive walking
++ */
++struct ext3_ext_path {
++      __u32                           p_block;
++      __u16                           p_depth;
++      struct ext3_extent              *p_ext;
++      struct ext3_extent_idx          *p_idx;
++      struct ext3_extent_header       *p_hdr;
++      struct buffer_head              *p_bh;
++};
++
++/*
++ * structure for external API
++ */
++
++/*
++ * storage for cached extent
++ */
++struct ext3_ext_cache {
++      __u32   ec_start;
++      __u32   ec_block;
++      __u32   ec_len;
++      __u32   ec_type;
++};
++
++#define EXT3_EXT_CACHE_NO     0
++#define EXT3_EXT_CACHE_GAP    1
++#define EXT3_EXT_CACHE_EXTENT 2
++
++/*
++ * ext3_extents_tree is used to pass initial information
++ * to top-level extents API
++ */
++struct ext3_extents_helpers;
++struct ext3_extents_tree {
++      struct inode *inode;    /* inode which tree belongs to */
++      void *root;             /* ptr to data top of tree resides at */
++      void *buffer;           /* will be passed as arg to ^^ routines */
++      int buffer_len;
++      void *private;
++      struct ext3_ext_cache *cex;/* last found extent */
++      struct ext3_extents_helpers *ops;
++};
++
++struct ext3_extents_helpers {
++      int (*get_write_access)(handle_t *h, void *buffer);
++      int (*mark_buffer_dirty)(handle_t *h, void *buffer);
++      int (*mergable)(struct ext3_extent *ex1, struct ext3_extent *ex2);
++      int (*remove_extent_credits)(struct ext3_extents_tree *,
++                                   struct ext3_extent *, unsigned long,
++                                   unsigned long);
++      int (*remove_extent)(struct ext3_extents_tree *,
++                           struct ext3_extent *, unsigned long,
++                           unsigned long);
++      int (*new_block)(handle_t *, struct ext3_extents_tree *,
++                       struct ext3_ext_path *, struct ext3_extent *,
++                       int *);
++};
++
++/*
++ * to be called by ext3_ext_walk_space()
++ * negative retcode - error
++ * positive retcode - signal for ext3_ext_walk_space(), see below
++ * callback must return valid extent (passed or newly created)
++ */
++typedef int (*ext_prepare_callback)(struct ext3_extents_tree *,
++                                  struct ext3_ext_path *,
++                                  struct ext3_ext_cache *);
++
++#define EXT_CONTINUE  0
++#define EXT_BREAK     1
++#define EXT_REPEAT    2
++
++
++#define EXT_MAX_BLOCK 0xffffffff
++
++
++#define EXT_FIRST_EXTENT(__hdr__) \
++      ((struct ext3_extent *) (((char *) (__hdr__)) +         \
++                               sizeof(struct ext3_extent_header)))
++#define EXT_FIRST_INDEX(__hdr__) \
++      ((struct ext3_extent_idx *) (((char *) (__hdr__)) +     \
++                                   sizeof(struct ext3_extent_header)))
++#define EXT_HAS_FREE_INDEX(__path__) \
++      ((__path__)->p_hdr->eh_entries < (__path__)->p_hdr->eh_max)
++#define EXT_LAST_EXTENT(__hdr__) \
++      (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_entries - 1)
++#define EXT_LAST_INDEX(__hdr__) \
++      (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_entries - 1)
++#define EXT_MAX_EXTENT(__hdr__) \
++      (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_max - 1)
++#define EXT_MAX_INDEX(__hdr__) \
++      (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_max - 1)
++
++#define EXT_ROOT_HDR(tree) \
++      ((struct ext3_extent_header *) (tree)->root)
++#define EXT_BLOCK_HDR(bh) \
++      ((struct ext3_extent_header *) (bh)->b_data)
++#define EXT_DEPTH(_t_)        \
++      (((struct ext3_extent_header *)((_t_)->root))->eh_depth)
++#define EXT_GENERATION(_t_)   \
++      (((struct ext3_extent_header *)((_t_)->root))->eh_generation)
++
++
++#define EXT_ASSERT(__x__) if (!(__x__)) BUG();
++
++#define EXT_CHECK_PATH(tree,path)                                     \
++{                                                                     \
++      int depth = EXT_DEPTH(tree);                                    \
++      BUG_ON((unsigned long) (path) < __PAGE_OFFSET);                 \
++      BUG_ON((unsigned long) (path)[depth].p_idx <                    \
++                      __PAGE_OFFSET && (path)[depth].p_idx != NULL);  \
++      BUG_ON((unsigned long) (path)[depth].p_ext <                    \
++                      __PAGE_OFFSET && (path)[depth].p_ext != NULL);  \
++      BUG_ON((unsigned long) (path)[depth].p_hdr < __PAGE_OFFSET);    \
++      BUG_ON((unsigned long) (path)[depth].p_bh < __PAGE_OFFSET       \
++                      && depth != 0);                                 \
++      BUG_ON((path)[0].p_depth != depth);                             \
++}
++
++
++/*
++ * this structure is used to gather extents from the tree via ioctl
++ */
++struct ext3_extent_buf {
++      unsigned long start;
++      int buflen;
++      void *buffer;
++      void *cur;
++      int err;
++};
++
++/*
++ * this structure is used to collect stats info about the tree
++ */
++struct ext3_extent_tree_stats {
++      int depth;
++      int extents_num;
++      int leaf_num;
++};
++
++extern void ext3_init_tree_desc(struct ext3_extents_tree *, struct inode *);
++extern int ext3_extent_tree_init(handle_t *, struct ext3_extents_tree *);
++extern int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *, struct ext3_ext_path *);
++extern int ext3_ext_insert_extent(handle_t *, struct ext3_extents_tree *, struct ext3_ext_path *, struct ext3_extent *);
++extern int ext3_ext_walk_space(struct ext3_extents_tree *, unsigned long, unsigned long, ext_prepare_callback);
++extern int ext3_ext_remove_space(struct ext3_extents_tree *, unsigned long, unsigned long);
++extern struct ext3_ext_path * ext3_ext_find_extent(struct ext3_extents_tree *, int, struct ext3_ext_path *);
++extern int ext3_ext_calc_blockmap_metadata(struct inode *, int);
++
++static inline void
++ext3_ext_invalidate_cache(struct ext3_extents_tree *tree)
++{
++      if (tree->cex)
++              tree->cex->ec_type = EXT3_EXT_CACHE_NO;
++}
++
++
++#endif /* _LINUX_EXT3_EXTENTS */
+Index: linux-stage/include/linux/ext3_fs_i.h
+===================================================================
+--- linux-stage.orig/include/linux/ext3_fs_i.h 2006-07-16 13:55:30.000000000 +0800
++++ linux-stage/include/linux/ext3_fs_i.h      2006-07-16 14:10:20.000000000 +0800
+@@ -142,6 +142,8 @@ struct ext3_inode_info {
+        */
+       struct mutex truncate_mutex;
+       struct inode vfs_inode;
++
++      __u32 i_cached_extent[4];
+ };
+ #endif        /* _LINUX_EXT3_FS_I */
index 9e78214..b6c37c1 100644 (file)
@@ -3,7 +3,7 @@ Index: linux-2.6.5-sles9/fs/ext3/extents.c
 ===================================================================
 --- linux-2.6.5-sles9.orig/fs/ext3/extents.c   2005-02-17 22:07:57.023609040 +0300
 +++ linux-2.6.5-sles9/fs/ext3/extents.c        2005-02-23 01:02:37.396435640 +0300
-@@ -0,0 +1,2355 @@
+@@ -0,0 +1,2361 @@
 +/*
 + * Copyright(c) 2003, 2004, 2005, Cluster File Systems, Inc, info@clusterfs.com
 + * Written by Alex Tomas <alex@clusterfs.com>
@@ -179,7 +179,7 @@ Index: linux-2.6.5-sles9/fs/ext3/extents.c
 +{
 +      struct ext3_extent_header *neh = EXT_ROOT_HDR(tree);
 +      neh->eh_generation = ((EXT_FLAGS(neh) & ~EXT_FLAGS_CLR_UNKNOWN) << 24) |
-+                           (EXT_GENERATION(neh) + 1);
++                           (EXT_HDR_GEN(neh) + 1);
 +}
 +
 +static inline int ext3_ext_space_block(struct ext3_extents_tree *tree)
@@ -561,6 +561,7 @@ Index: linux-2.6.5-sles9/fs/ext3/extents.c
 +
 +      ix->ei_block = logical;
 +      ix->ei_leaf = ptr;
++      ix->ei_leaf_hi = ix->ei_unused = 0;
 +      curp->p_hdr->eh_entries++;
 +
 +      EXT_ASSERT(curp->p_hdr->eh_entries <= curp->p_hdr->eh_max);
@@ -723,6 +724,7 @@ Index: linux-2.6.5-sles9/fs/ext3/extents.c
 +              fidx = EXT_FIRST_INDEX(neh);
 +              fidx->ei_block = border;
 +              fidx->ei_leaf = oldblock;
++              fidx->ei_leaf_hi = fidx->ei_unused = 0;
 +
 +              ext_debug(tree, "int.index at %d (block %lu): %lu -> %lu\n",
 +                        i, newblock, border, oldblock);
@@ -856,6 +858,7 @@ Index: linux-2.6.5-sles9/fs/ext3/extents.c
 +      /* FIXME: it works, but actually path[0] can be index */
 +      curp->p_idx->ei_block = EXT_FIRST_EXTENT(path[0].p_hdr)->ee_block;
 +      curp->p_idx->ei_leaf = newblock;
++      curp->p_idx->ei_leaf_hi = curp->p_idx->ei_unused = 0;
 +
 +      neh = EXT_ROOT_HDR(tree);
 +      fidx = EXT_FIRST_INDEX(neh);
@@ -1404,6 +1407,7 @@ Index: linux-2.6.5-sles9/fs/ext3/extents.c
 +      if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) {
 +              ex->ee_block = cex->ec_block;
 +              ex->ee_start = cex->ec_start;
++              ex->ee_start_hi = 0;
 +              ex->ee_len = cex->ec_len;
 +              ext_debug(tree, "%lu cached by %lu:%lu:%lu\n",
 +                        (unsigned long) block,
@@ -1625,7 +1629,7 @@ Index: linux-2.6.5-sles9/fs/ext3/extents.c
 +
 +              if (num == 0) {
 +                      /* this extent is removed entirely mark slot unused */
-+                      ex->ee_start = 0;
++                      ex->ee_start = ex->ee_start_hi = 0;
 +                      eh->eh_entries--;
 +                      fu = ex;
 +              }
@@ -1647,7 +1651,7 @@ Index: linux-2.6.5-sles9/fs/ext3/extents.c
 +              while (lu < le) {
 +                      if (lu->ee_start) {
 +                              *fu = *lu;
-+                              lu->ee_start = 0;
++                              lu->ee_start = lu->ee_start_hi = 0;
 +                              fu++;
 +                      }
 +                      lu++;
@@ -2002,6 +2006,7 @@ Index: linux-2.6.5-sles9/fs/ext3/extents.c
 +              /* allocate new block for the extent */
 +              goal = ext3_ext_find_goal(inode, path, ex->ee_block);
 +              ex->ee_start = ext3_new_block(handle, inode, goal, err);
++              ex->ee_start_hi = 0;
 +              if (ex->ee_start == 0) {
 +                      /* error occured: restore old extent */
 +                      ex->ee_start = newblock;
@@ -2117,6 +2122,7 @@ Index: linux-2.6.5-sles9/fs/ext3/extents.c
 +      /* try to insert new extent into found leaf and return */
 +      newex.ee_block = iblock;
 +      newex.ee_start = newblock;
++      newex.ee_start_hi = 0;
 +      newex.ee_len = 1;
 +      err = ext3_ext_insert_extent(handle, &tree, path, &newex);
 +      if (err)
@@ -2512,26 +2518,30 @@ Index: linux-2.6.5-sles9/fs/ext3/super.c
        Opt_ignore, Opt_barrier,
        Opt_err,
        Opt_iopen, Opt_noiopen, Opt_iopen_nopriv,
-+      Opt_extents, Opt_extdebug,
++      Opt_extents, Opt_noextents, Opt_extdebug,
  };
  
  static match_table_t tokens = {
-@@ -582,6 +585,8 @@
+@@ -582,6 +585,9 @@
        {Opt_iopen, "iopen"},
        {Opt_noiopen, "noiopen"},
        {Opt_iopen_nopriv, "iopen_nopriv"},
 +      {Opt_extents, "extents"},
++      {Opt_noextents, "noextents"},
 +      {Opt_extdebug, "extdebug"},
        {Opt_barrier, "barrier=%u"},
        {Opt_err, NULL}
  };
-@@ -797,6 +802,12 @@
+@@ -797,6 +802,15 @@
                        break;
                case Opt_ignore:
                        break;
 +              case Opt_extents:
 +                      set_opt (sbi->s_mount_opt, EXTENTS);
 +                      break;
++              case Opt_noextents:
++                      clear_opt (sbi->s_mount_opt, EXTENTS);
++                      break;
 +              case Opt_extdebug:
 +                      set_opt (sbi->s_mount_opt, EXTDEBUG);
 +                      break;
@@ -2611,11 +2621,13 @@ Index: linux-2.6.5-sles9/include/linux/ext3_fs.h
  #define EXT3_FEATURE_RO_COMPAT_SUPP   (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
                                         EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \
                                         EXT3_FEATURE_RO_COMPAT_BTREE_DIR)
-@@ -729,6 +735,7 @@
+@@ -729,6 +735,9 @@
  
  
  /* inode.c */
-+extern int ext3_block_truncate_page(handle_t *, struct page *, struct address_space *, loff_t);
++extern int ext3_block_truncate_page(handle_t *, struct page *,
++                                  struct address_space *, loff_t);
++extern int ext3_writepage_trans_blocks(struct inode *inode);
  extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int);
  extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
  extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
@@ -2839,14 +2851,14 @@ Index: linux-2.6.5-sles9/include/linux/ext3_extents.h
 +      (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_max - 1)
 +#define EXT_MAX_INDEX(__hdr__) \
 +      (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_max - 1)
-+#define EXT_GENERATION(__hdr__) ((__hdr__)->eh_generation & 0x00ffffff)
++#define EXT_HDR_GEN(__hdr__)  ((__hdr__)->eh_generation & 0x00ffffff)
 +#define EXT_FLAGS(__hdr__)    ((__hdr__)->eh_generation >> 24)
 +#define EXT_FLAGS_CLR_UNKNOWN 0x7     /* Flags cleared on modification */
 +
 +#define EXT_BLOCK_HDR(__bh__)         ((struct ext3_extent_header *)(__bh__)->b_data)
 +#define EXT_ROOT_HDR(__tree__)        ((struct ext3_extent_header *)(__tree__)->root)
 +#define EXT_DEPTH(__tree__)   (EXT_ROOT_HDR(__tree__)->eh_depth)
-+
++#define EXT_GENERATION(__tree__) EXT_HDR_GEN(EXT_ROOT_HDR(__tree__))
 +
 +#define EXT_ASSERT(__x__) if (!(__x__)) BUG();
 +
index bd95c54..5b5558c 100644 (file)
@@ -2,7 +2,7 @@ Index: linux-stage/fs/ext3/extents.c
 ===================================================================
 --- linux-stage.orig/fs/ext3/extents.c 2005-02-25 15:33:48.890198160 +0200
 +++ linux-stage/fs/ext3/extents.c      2005-02-25 15:33:48.917194056 +0200
-@@ -0,0 +1,2353 @@
+@@ -0,0 +1,2359 @@
 +/*
 + * Copyright(c) 2003, 2004, 2005, Cluster File Systems, Inc, info@clusterfs.com
 + * Written by Alex Tomas <alex@clusterfs.com>
@@ -178,7 +178,7 @@ Index: linux-stage/fs/ext3/extents.c
 +{
 +      struct ext3_extent_header *neh = EXT_ROOT_HDR(tree);
 +      neh->eh_generation = ((EXT_FLAGS(neh) & ~EXT_FLAGS_CLR_UNKNOWN) << 24) |
-+                           (EXT_GENERATION(neh) + 1);
++                           (EXT_HDR_GEN(neh) + 1);
 +}
 +
 +static inline int ext3_ext_space_block(struct ext3_extents_tree *tree)
@@ -560,6 +560,7 @@ Index: linux-stage/fs/ext3/extents.c
 +
 +      ix->ei_block = logical;
 +      ix->ei_leaf = ptr;
++      ix->ei_leaf_hi = ix->ei_unused = 0;
 +      curp->p_hdr->eh_entries++;
 +
 +      EXT_ASSERT(curp->p_hdr->eh_entries <= curp->p_hdr->eh_max);
@@ -722,6 +723,7 @@ Index: linux-stage/fs/ext3/extents.c
 +              fidx = EXT_FIRST_INDEX(neh);
 +              fidx->ei_block = border;
 +              fidx->ei_leaf = oldblock;
++              fidx->ei_leaf_hi = fidx->ei_unused = 0;
 +
 +              ext_debug(tree, "int.index at %d (block %lu): %lu -> %lu\n",
 +                        i, newblock, border, oldblock);
@@ -855,6 +857,7 @@ Index: linux-stage/fs/ext3/extents.c
 +      /* FIXME: it works, but actually path[0] can be index */
 +      curp->p_idx->ei_block = EXT_FIRST_EXTENT(path[0].p_hdr)->ee_block;
 +      curp->p_idx->ei_leaf = newblock;
++      curp->p_idx->ei_leaf_hi = curp->p_idx->ei_unused = 0;
 +
 +      neh = EXT_ROOT_HDR(tree);
 +      fidx = EXT_FIRST_INDEX(neh);
@@ -1403,6 +1406,7 @@ Index: linux-stage/fs/ext3/extents.c
 +      if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) {
 +              ex->ee_block = cex->ec_block;
 +              ex->ee_start = cex->ec_start;
++              ex->ee_start_hi = 0;
 +              ex->ee_len = cex->ec_len;
 +              ext_debug(tree, "%lu cached by %lu:%lu:%lu\n",
 +                        (unsigned long) block,
@@ -1624,7 +1628,7 @@ Index: linux-stage/fs/ext3/extents.c
 +
 +              if (num == 0) {
 +                      /* this extent is removed entirely mark slot unused */
-+                      ex->ee_start = 0;
++                      ex->ee_start = ex->ee_start_hi = 0;
 +                      eh->eh_entries--;
 +                      fu = ex;
 +              }
@@ -1646,7 +1650,7 @@ Index: linux-stage/fs/ext3/extents.c
 +              while (lu < le) {
 +                      if (lu->ee_start) {
 +                              *fu = *lu;
-+                              lu->ee_start = 0;
++                              lu->ee_start = lu->ee_start_hi = 0;
 +                              fu++;
 +                      }
 +                      lu++;
@@ -2001,6 +2005,7 @@ Index: linux-stage/fs/ext3/extents.c
 +              /* allocate new block for the extent */
 +              goal = ext3_ext_find_goal(inode, path, ex->ee_block);
 +              ex->ee_start = ext3_new_block(handle, inode, goal, err);
++              ex->ee_start_hi = 0;
 +              if (ex->ee_start == 0) {
 +                      /* error occured: restore old extent */
 +                      ex->ee_start = newblock;
@@ -2116,6 +2121,7 @@ Index: linux-stage/fs/ext3/extents.c
 +      /* try to insert new extent into found leaf and return */
 +      newex.ee_block = iblock;
 +      newex.ee_start = newblock;
++      newex.ee_start_hi = 0;
 +      newex.ee_len = 1;
 +      err = ext3_ext_insert_extent(handle, &tree, path, &newex);
 +      if (err)
@@ -2507,26 +2513,30 @@ Index: linux-stage/fs/ext3/super.c
        Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0,
        Opt_ignore, Opt_barrier, Opt_err, Opt_resize,
        Opt_iopen, Opt_noiopen, Opt_iopen_nopriv,
-+      Opt_extents, Opt_extdebug,
++      Opt_extents, Opt_noextents, Opt_extdebug,
  };
  
  static match_table_t tokens = {
-@@ -639,6 +644,8 @@
+@@ -639,6 +644,9 @@
        {Opt_iopen, "iopen"},
        {Opt_noiopen, "noiopen"},
        {Opt_iopen_nopriv, "iopen_nopriv"},
 +      {Opt_extents, "extents"},
++      {Opt_noextents, "noextents"},
 +      {Opt_extdebug, "extdebug"},
        {Opt_barrier, "barrier=%u"},
        {Opt_err, NULL},
        {Opt_resize, "resize"},
-@@ -943,6 +950,12 @@
+@@ -943,6 +950,15 @@
                        match_int(&args[0], &option);
                        *n_blocks_count = option;
                        break;
 +              case Opt_extents:
 +                      set_opt (sbi->s_mount_opt, EXTENTS);
 +                      break;
++              case Opt_noextents:
++                      clear_opt (sbi->s_mount_opt, EXTENTS);
++                      break;
 +              case Opt_extdebug:
 +                      set_opt (sbi->s_mount_opt, EXTDEBUG);
 +                      break;
@@ -2606,11 +2616,13 @@ Index: linux-stage/include/linux/ext3_fs.h
  #define EXT3_FEATURE_RO_COMPAT_SUPP   (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
                                         EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \
                                         EXT3_FEATURE_RO_COMPAT_BTREE_DIR)
-@@ -756,6 +763,7 @@
+@@ -756,6 +763,9 @@
  
  
  /* inode.c */
-+extern int ext3_block_truncate_page(handle_t *, struct page *, struct address_space *, loff_t);
++extern int ext3_block_truncate_page(handle_t *, struct page *,
++                                  struct address_space *, loff_t);
++extern int ext3_writepage_trans_blocks(struct inode *inode);
  extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int);
  extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
  extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
@@ -2834,14 +2846,14 @@ Index: linux-stage/include/linux/ext3_extents.h
 +      (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_max - 1)
 +#define EXT_MAX_INDEX(__hdr__) \
 +      (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_max - 1)
-+#define EXT_GENERATION(__hdr__) ((__hdr__)->eh_generation & 0x00ffffff)
++#define EXT_HDR_GEN(__hdr__)  ((__hdr__)->eh_generation & 0x00ffffff)
 +#define EXT_FLAGS(__hdr__)    ((__hdr__)->eh_generation >> 24)
 +#define EXT_FLAGS_CLR_UNKNOWN 0x7     /* Flags cleared on modification */
 +
 +#define EXT_BLOCK_HDR(__bh__)         ((struct ext3_extent_header *)(__bh__)->b_data)
 +#define EXT_ROOT_HDR(__tree__)        ((struct ext3_extent_header *)(__tree__)->root)
 +#define EXT_DEPTH(__tree__)   (EXT_ROOT_HDR(__tree__)->eh_depth)
-+
++#define EXT_GENERATION(__tree__) EXT_HDR_GEN(EXT_ROOT_HDR(__tree__))
 +
 +#define EXT_ASSERT(__x__) if (!(__x__)) BUG();
 +
diff --git a/ldiskfs/kernel_patches/patches/ext3-filterdata-2.6.15.patch b/ldiskfs/kernel_patches/patches/ext3-filterdata-2.6.15.patch
new file mode 100644 (file)
index 0000000..e6d431f
--- /dev/null
@@ -0,0 +1,25 @@
+Index: linux-2.6.15/include/linux/ext3_fs_i.h
+===================================================================
+--- linux-2.6.15.orig/include/linux/ext3_fs_i.h        2006-02-24 15:41:30.000000000 +0300
++++ linux-2.6.15/include/linux/ext3_fs_i.h     2006-02-24 15:41:31.000000000 +0300
+@@ -135,6 +135,8 @@ struct ext3_inode_info {
+       struct inode vfs_inode;
+       __u32 i_cached_extent[4];
++
++      void *i_filterdata;
+ };
+ #endif        /* _LINUX_EXT3_FS_I */
+Index: linux-2.6.15/fs/ext3/super.c
+===================================================================
+--- linux-2.6.15.orig/fs/ext3/super.c  2006-02-24 15:41:30.000000000 +0300
++++ linux-2.6.15/fs/ext3/super.c       2006-02-24 15:42:02.000000000 +0300
+@@ -459,6 +459,7 @@ static struct inode *ext3_alloc_inode(st
+       ei->vfs_inode.i_version = 1;
+       
+       memset(&ei->i_cached_extent, 0, sizeof(ei->i_cached_extent));
++      ei->i_filterdata = NULL;
+       return &ei->vfs_inode;
+ }
diff --git a/ldiskfs/kernel_patches/patches/ext3-lookup-dotdot-2.6.9.patch b/ldiskfs/kernel_patches/patches/ext3-lookup-dotdot-2.6.9.patch
new file mode 100644 (file)
index 0000000..a05256b
--- /dev/null
@@ -0,0 +1,63 @@
+Index: linux-2.6.9-full/fs/ext3/iopen.c
+===================================================================
+--- linux-2.6.9-full.orig/fs/ext3/iopen.c      2006-04-25 08:51:11.000000000 +0400
++++ linux-2.6.9-full/fs/ext3/iopen.c   2006-05-06 01:21:11.000000000 +0400
+@@ -94,9 +94,12 @@ static struct dentry *iopen_lookup(struc
+               assert(!(alternate->d_flags & DCACHE_DISCONNECTED));
+       }
+-      if (!list_empty(&inode->i_dentry)) {
+-              alternate = list_entry(inode->i_dentry.next,
+-                                     struct dentry, d_alias);
++      list_for_each(lp, &inode->i_dentry) {
++              alternate = list_entry(lp, struct dentry, d_alias);
++              /* ignore dentries created for ".." to preserve
++               * proper dcache hierarchy -- bug 10458 */
++              if (alternate->d_flags & DCACHE_NFSFS_RENAMED)
++                      continue;
+               dget_locked(alternate);
+               spin_lock(&alternate->d_lock);
+               alternate->d_flags |= DCACHE_REFERENCED;
+Index: linux-2.6.9-full/fs/ext3/namei.c
+===================================================================
+--- linux-2.6.9-full.orig/fs/ext3/namei.c      2006-05-06 01:21:10.000000000 +0400
++++ linux-2.6.9-full/fs/ext3/namei.c   2006-05-06 01:29:30.000000000 +0400
+@@ -1003,6 +1003,38 @@ static struct dentry *ext3_lookup(struct
+                       return ERR_PTR(-EACCES);
+       }
++      /* ".." shouldn't go into dcache to preserve dcache hierarchy
++       * otherwise we'll get parent being a child of actual child.
++       * see bug 10458 for details -bzzz */
++      if (inode && (dentry->d_name.name[0] == '.' && (dentry->d_name.len == 1 ||
++              (dentry->d_name.len == 2 && dentry->d_name.name[1] == '.')))) {
++              struct dentry *tmp, *goal = NULL;
++              struct list_head *lp;
++
++              /* first, look for an existing dentry - any one is good */
++              spin_lock(&dcache_lock);
++              list_for_each(lp, &inode->i_dentry) {
++                      tmp = list_entry(lp, struct dentry, d_alias);
++                      goal = tmp;
++                      dget_locked(goal);
++                      break;
++              }
++              if (goal == NULL) {
++                      /* there is no alias, we need to make current dentry:
++                       *  a) inaccessible for __d_lookup()
++                       *  b) inaccessible for iopen */
++                      J_ASSERT(list_empty(&dentry->d_alias));
++                      dentry->d_flags |= DCACHE_NFSFS_RENAMED;
++                      /* this is d_instantiate() ... */
++                      list_add(&dentry->d_alias, &inode->i_dentry);
++                      dentry->d_inode = inode;
++              }
++              spin_unlock(&dcache_lock);
++              if (goal)
++                      iput(inode);
++              return goal;
++      }
++
+       return iopen_connect_dentry(dentry, inode, 1);
+ }
diff --git a/ldiskfs/kernel_patches/patches/ext3-mballoc2-2.6-fc5.patch b/ldiskfs/kernel_patches/patches/ext3-mballoc2-2.6-fc5.patch
new file mode 100644 (file)
index 0000000..325d080
--- /dev/null
@@ -0,0 +1,2779 @@
+Index: linux-2.6.16.i686/fs/ext3/inode.c
+===================================================================
+--- linux-2.6.16.i686.orig/fs/ext3/inode.c     2006-05-30 22:55:32.000000000 +0800
++++ linux-2.6.16.i686/fs/ext3/inode.c  2006-05-30 23:02:59.000000000 +0800
+@@ -568,7 +568,7 @@
+               ext3_journal_forget(handle, branch[i].bh);
+       }
+       for (i = 0; i < keys; i++)
+-              ext3_free_blocks(handle, inode, le32_to_cpu(branch[i].key), 1);
++              ext3_free_blocks(handle, inode, le32_to_cpu(branch[i].key), 1, 1);
+       return err;
+ }
+@@ -1862,7 +1862,7 @@
+               }
+       }
+-      ext3_free_blocks(handle, inode, block_to_free, count);
++      ext3_free_blocks(handle, inode, block_to_free, count, 1);
+ }
+ /**
+@@ -2035,7 +2035,7 @@
+                               ext3_journal_test_restart(handle, inode);
+                       }
+-                      ext3_free_blocks(handle, inode, nr, 1);
++                      ext3_free_blocks(handle, inode, nr, 1, 1);
+                       if (parent_bh) {
+                               /*
+Index: linux-2.6.16.i686/fs/ext3/mballoc.c
+===================================================================
+--- linux-2.6.16.i686.orig/fs/ext3/mballoc.c   2006-05-31 04:14:15.752410384 +0800
++++ linux-2.6.16.i686/fs/ext3/mballoc.c        2006-05-30 23:03:38.000000000 +0800
+@@ -0,0 +1,2434 @@
++/*
++ * Copyright (c) 2003-2005, Cluster File Systems, Inc, info@clusterfs.com
++ * Written by Alex Tomas <alex@clusterfs.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public Licens
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-
++ */
++
++
++/*
++ * mballoc.c contains the multiblocks allocation routines
++ */
++
++#include <linux/config.h>
++#include <linux/time.h>
++#include <linux/fs.h>
++#include <linux/namei.h>
++#include <linux/jbd.h>
++#include <linux/ext3_fs.h>
++#include <linux/ext3_jbd.h>
++#include <linux/quotaops.h>
++#include <linux/buffer_head.h>
++#include <linux/module.h>
++#include <linux/swap.h>
++#include <linux/proc_fs.h>
++#include <linux/pagemap.h>
++#include <linux/seq_file.h>
++
++/*
++ * TODO:
++ *   - bitmap read-ahead (proposed by Oleg Drokin aka green)
++ *   - track min/max extents in each group for better group selection
++ *   - mb_mark_used() may allocate chunk right after splitting buddy
++ *   - special flag to advice allocator to look for requested + N blocks
++ *     this may improve interaction between extents and mballoc
++ *   - tree of groups sorted by number of free blocks
++ *   - percpu reservation code (hotpath)
++ *   - error handling
++ */
++
++/*
++ * with AGRESSIVE_CHECK allocator runs consistency checks over
++ * structures. these checks slow things down a lot
++ */
++#define AGGRESSIVE_CHECK__
++
++/*
++ */
++#define MB_DEBUG__
++#ifdef MB_DEBUG
++#define mb_debug(fmt,a...)    printk(fmt, ##a)
++#else
++#define mb_debug(fmt,a...)
++#endif
++
++/*
++ * with EXT3_MB_HISTORY mballoc stores last N allocations in memory
++ * and you can monitor it in /proc/fs/ext3/<dev>/mb_history
++ */
++#define EXT3_MB_HISTORY
++
++/*
++ * How long mballoc can look for a best extent (in found extents)
++ */
++long ext3_mb_max_to_scan = 500;
++
++/*
++ * How long mballoc must look for a best extent
++ */
++long ext3_mb_min_to_scan = 30;
++
++/*
++ * with 'ext3_mb_stats' allocator will collect stats that will be
++ * shown at umount. The collecting costs though!
++ */
++
++long ext3_mb_stats = 1;
++
++#ifdef EXT3_BB_MAX_BLOCKS
++#undef EXT3_BB_MAX_BLOCKS
++#endif
++#define EXT3_BB_MAX_BLOCKS    30
++
++struct ext3_free_metadata {
++      unsigned short group;
++      unsigned short num;
++      unsigned short blocks[EXT3_BB_MAX_BLOCKS];
++      struct list_head list;
++};
++
++struct ext3_group_info {
++      unsigned long   bb_state;
++      unsigned long   bb_tid;
++      struct ext3_free_metadata *bb_md_cur;
++      unsigned short  bb_first_free;
++      unsigned short  bb_free;
++      unsigned short  bb_fragments;
++      unsigned short  bb_counters[];
++};
++
++
++#define EXT3_GROUP_INFO_NEED_INIT_BIT 0
++#define EXT3_GROUP_INFO_LOCKED_BIT    1
++
++#define EXT3_MB_GRP_NEED_INIT(grp)    \
++      (test_bit(EXT3_GROUP_INFO_NEED_INIT_BIT, &(grp)->bb_state))
++
++struct ext3_free_extent {
++      __u16 fe_start;
++      __u16 fe_len;
++      __u16 fe_group;
++};
++
++struct ext3_allocation_context {
++      struct super_block *ac_sb;
++
++      /* search goals */
++      struct ext3_free_extent ac_g_ex;
++      
++      /* the best found extent */
++      struct ext3_free_extent ac_b_ex;
++      
++      /* number of iterations done. we have to track to limit searching */
++      unsigned long ac_ex_scanned;
++      __u16 ac_groups_scanned;
++      __u16 ac_found;
++      __u16 ac_tail;
++      __u16 ac_buddy;
++      __u8 ac_status; 
++      __u8 ac_flags;          /* allocation hints */
++      __u8 ac_criteria;
++      __u8 ac_repeats;
++      __u8 ac_2order;         /* if request is to allocate 2^N blocks and
++                               * N > 0, the field stores N, otherwise 0 */
++};
++
++#define AC_STATUS_CONTINUE    1
++#define AC_STATUS_FOUND               2
++#define AC_STATUS_BREAK               3
++
++struct ext3_mb_history {
++      struct ext3_free_extent goal;   /* goal allocation */
++      struct ext3_free_extent result; /* result allocation */
++      __u16 found;    /* how many extents have been found */
++      __u16 groups;   /* how many groups have been scanned */
++      __u16 tail;     /* what tail broke some buddy */
++      __u16 buddy;    /* buddy the tail ^^^ broke */
++      __u8 cr;        /* which phase the result extent was found at */
++      __u8 merged;
++};
++
++struct ext3_buddy {
++      struct page *bd_buddy_page;
++      void *bd_buddy;
++      struct page *bd_bitmap_page;
++      void *bd_bitmap;
++      struct ext3_group_info *bd_info;
++      struct super_block *bd_sb;
++      __u16 bd_blkbits;
++      __u16 bd_group;
++};
++#define EXT3_MB_BITMAP(e3b)   ((e3b)->bd_bitmap)
++#define EXT3_MB_BUDDY(e3b)    ((e3b)->bd_buddy)
++
++#ifndef EXT3_MB_HISTORY
++#define ext3_mb_store_history(sb,ac)
++#else
++static void ext3_mb_store_history(struct super_block *,
++                              struct ext3_allocation_context *ac);
++#endif
++
++#define in_range(b, first, len)       ((b) >= (first) && (b) <= (first) + (len) - 1)
++
++static struct proc_dir_entry *proc_root_ext3;
++
++int ext3_create (struct inode *, struct dentry *, int, struct nameidata *);
++struct buffer_head * read_block_bitmap(struct super_block *, unsigned int);
++int ext3_new_block_old(handle_t *, struct inode *, unsigned long, int *);
++int ext3_mb_reserve_blocks(struct super_block *, int);
++void ext3_mb_release_blocks(struct super_block *, int);
++void ext3_mb_poll_new_transaction(struct super_block *, handle_t *);
++void ext3_mb_free_committed_blocks(struct super_block *);
++
++#if BITS_PER_LONG == 64
++#define mb_correct_addr_and_bit(bit,addr)             \
++{                                                     \
++      bit += ((unsigned long) addr & 7UL) << 3;       \
++      addr = (void *) ((unsigned long) addr & ~7UL);  \
++}
++#elif BITS_PER_LONG == 32
++#define mb_correct_addr_and_bit(bit,addr)             \
++{                                                     \
++      bit += ((unsigned long) addr & 3UL) << 3;       \
++      addr = (void *) ((unsigned long) addr & ~3UL);  \
++}
++#else
++#error "how many bits you are?!"
++#endif
++
++static inline int mb_test_bit(int bit, void *addr)
++{
++      mb_correct_addr_and_bit(bit,addr);
++      return ext2_test_bit(bit, addr);
++}
++
++static inline void mb_set_bit(int bit, void *addr)
++{
++      mb_correct_addr_and_bit(bit,addr);
++      ext2_set_bit(bit, addr);
++}
++
++static inline void mb_set_bit_atomic(int bit, void *addr)
++{
++      mb_correct_addr_and_bit(bit,addr);
++      ext2_set_bit_atomic(NULL, bit, addr);
++}
++
++static inline void mb_clear_bit(int bit, void *addr)
++{
++      mb_correct_addr_and_bit(bit,addr);
++      ext2_clear_bit(bit, addr);
++}
++
++static inline void mb_clear_bit_atomic(int bit, void *addr)
++{
++      mb_correct_addr_and_bit(bit,addr);
++      ext2_clear_bit_atomic(NULL, bit, addr);
++}
++
++static inline int mb_find_next_zero_bit(void *addr, int max, int start)
++{
++      int fix;
++#if BITS_PER_LONG == 64
++      fix = ((unsigned long) addr & 7UL) << 3;
++      addr = (void *) ((unsigned long) addr & ~7UL);
++#elif BITS_PER_LONG == 32
++      fix = ((unsigned long) addr & 3UL) << 3;
++      addr = (void *) ((unsigned long) addr & ~3UL);
++#else
++#error "how many bits you are?!"
++#endif
++      max += fix;
++      start += fix;
++      return ext2_find_next_zero_bit(addr, max, start) - fix;
++}
++
++static inline void *mb_find_buddy(struct ext3_buddy *e3b, int order, int *max)
++{
++      char *bb;
++
++      J_ASSERT(EXT3_MB_BITMAP(e3b) != EXT3_MB_BUDDY(e3b));
++      J_ASSERT(max != NULL);
++
++      if (order > e3b->bd_blkbits + 1) {
++              *max = 0;
++              return NULL;
++      }
++
++      /* at order 0 we see each particular block */
++      *max = 1 << (e3b->bd_blkbits + 3);
++      if (order == 0)
++              return EXT3_MB_BITMAP(e3b);
++
++      bb = EXT3_MB_BUDDY(e3b) + EXT3_SB(e3b->bd_sb)->s_mb_offsets[order];
++      *max = EXT3_SB(e3b->bd_sb)->s_mb_maxs[order];
++
++      return bb;
++}
++
++#ifdef AGGRESSIVE_CHECK
++
++static void mb_check_buddy(struct ext3_buddy *e3b)
++{
++      int order = e3b->bd_blkbits + 1;
++      int max, max2, i, j, k, count;
++      int fragments = 0, fstart;
++      void *buddy, *buddy2;
++
++      if (!test_opt(e3b->bd_sb, MBALLOC))
++              return;
++
++      {
++              static int mb_check_counter = 0;
++              if (mb_check_counter++ % 300 != 0)
++                      return;
++      }
++      
++      while (order > 1) {
++              buddy = mb_find_buddy(e3b, order, &max);
++              J_ASSERT(buddy);
++              buddy2 = mb_find_buddy(e3b, order - 1, &max2);
++              J_ASSERT(buddy2);
++              J_ASSERT(buddy != buddy2);
++              J_ASSERT(max * 2 == max2);
++
++              count = 0;
++              for (i = 0; i < max; i++) {
++
++                      if (mb_test_bit(i, buddy)) {
++                              /* only single bit in buddy2 may be 1 */
++                              if (!mb_test_bit(i << 1, buddy2))
++                                      J_ASSERT(mb_test_bit((i<<1)+1, buddy2));
++                              else if (!mb_test_bit((i << 1) + 1, buddy2))
++                                      J_ASSERT(mb_test_bit(i << 1, buddy2));
++                              continue;
++                      }
++
++                      /* both bits in buddy2 must be 0 */
++                      J_ASSERT(mb_test_bit(i << 1, buddy2));
++                      J_ASSERT(mb_test_bit((i << 1) + 1, buddy2));
++
++                      for (j = 0; j < (1 << order); j++) {
++                              k = (i * (1 << order)) + j;
++                              J_ASSERT(!mb_test_bit(k, EXT3_MB_BITMAP(e3b)));
++                      }
++                      count++;
++              }
++              J_ASSERT(e3b->bd_info->bb_counters[order] == count);
++              order--;
++      }
++
++      fstart = -1;
++      buddy = mb_find_buddy(e3b, 0, &max);
++      for (i = 0; i < max; i++) {
++              if (!mb_test_bit(i, buddy)) {
++                      J_ASSERT(i >= e3b->bd_info->bb_first_free);
++                      if (fstart == -1) {
++                              fragments++;
++                              fstart = i;
++                      }
++                      continue;
++              }
++              fstart = -1;
++              /* check used bits only */
++              for (j = 0; j < e3b->bd_blkbits + 1; j++) {
++                      buddy2 = mb_find_buddy(e3b, j, &max2);
++                      k = i >> j;
++                      J_ASSERT(k < max2);
++                      J_ASSERT(mb_test_bit(k, buddy2));
++              }
++      }
++      J_ASSERT(!EXT3_MB_GRP_NEED_INIT(e3b->bd_info));
++      J_ASSERT(e3b->bd_info->bb_fragments == fragments);
++}
++
++#else
++#define mb_check_buddy(e3b)
++#endif
++
++/* find most significant bit */
++static int inline fmsb(unsigned short word)
++{
++      int order;
++
++      if (word > 255) {
++              order = 7;
++              word >>= 8;
++      } else {
++              order = -1;
++      }
++
++      do {
++              order++;
++              word >>= 1;
++      } while (word != 0);
++
++      return order;
++}
++
++static void inline
++ext3_mb_mark_free_simple(struct super_block *sb, void *buddy, unsigned first,
++                              int len, struct ext3_group_info *grp)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      unsigned short min, max, chunk, border;
++
++      mb_debug("mark %u/%u free\n", first, len);
++      J_ASSERT(len < EXT3_BLOCKS_PER_GROUP(sb));
++
++      border = 2 << sb->s_blocksize_bits;
++
++      while (len > 0) {
++              /* find how many blocks can be covered since this position */
++              max = ffs(first | border) - 1;
++
++              /* find how many blocks of power 2 we need to mark */
++              min = fmsb(len);
++
++              mb_debug("  %u/%u -> max %u, min %u\n",
++                      first & ((2 << sb->s_blocksize_bits) - 1),
++                      len, max, min);
++
++              if (max < min)
++                      min = max;
++              chunk = 1 << min;
++
++              /* mark multiblock chunks only */
++              grp->bb_counters[min]++;
++              if (min > 0) {
++                      mb_debug("    set %u at %u \n", first >> min,
++                              sbi->s_mb_offsets[min]);
++                      mb_clear_bit(first >> min, buddy + sbi->s_mb_offsets[min]);
++              }
++
++              len -= chunk;
++              first += chunk;
++      }
++}
++
++static void
++ext3_mb_generate_buddy(struct super_block *sb, void *buddy, void *bitmap,
++                      struct ext3_group_info *grp)
++{
++      unsigned short max = EXT3_BLOCKS_PER_GROUP(sb);
++      unsigned short i = 0, first, len;
++      unsigned free = 0, fragments = 0;
++      unsigned long long period = get_cycles();
++
++      i = mb_find_next_zero_bit(bitmap, max, 0);
++      grp->bb_first_free = i;
++      while (i < max) {
++              fragments++;
++              first = i;
++              i = find_next_bit(bitmap, max, i);
++              len = i - first;
++              free += len;
++              if (len > 1) 
++                      ext3_mb_mark_free_simple(sb, buddy, first, len, grp);
++              else
++                      grp->bb_counters[0]++;
++              if (i < max)
++                      i = mb_find_next_zero_bit(bitmap, max, i);
++      }
++      grp->bb_fragments = fragments;
++
++      /* bb_state shouldn't being modified because all
++       * others waits for init completion on page lock */
++      clear_bit(EXT3_GROUP_INFO_NEED_INIT_BIT, &grp->bb_state);
++      if (free != grp->bb_free) {
++              printk("EXT3-fs: %u blocks in bitmap, %u in group descriptor\n",
++                      free, grp->bb_free);
++              grp->bb_free = free;
++      }
++
++      period = get_cycles() - period;
++      spin_lock(&EXT3_SB(sb)->s_bal_lock);
++      EXT3_SB(sb)->s_mb_buddies_generated++;
++      EXT3_SB(sb)->s_mb_generation_time += period;
++      spin_unlock(&EXT3_SB(sb)->s_bal_lock);
++}
++
++static int ext3_mb_init_cache(struct page *page)
++{
++      int blocksize, blocks_per_page, groups_per_page;
++      int err = 0, i, first_group, first_block;
++      struct super_block *sb;
++      struct buffer_head *bhs;
++      struct buffer_head **bh;
++      struct inode *inode;
++      char *data, *bitmap;
++
++      mb_debug("init page %lu\n", page->index);
++
++      inode = page->mapping->host;
++      sb = inode->i_sb;
++      blocksize = 1 << inode->i_blkbits;
++      blocks_per_page = PAGE_CACHE_SIZE / blocksize;
++      
++      groups_per_page = blocks_per_page >> 1;
++      if (groups_per_page == 0)
++              groups_per_page = 1;
++
++      /* allocate buffer_heads to read bitmaps */
++      if (groups_per_page > 1) {
++              err = -ENOMEM;
++              i = sizeof(struct buffer_head *) * groups_per_page;
++              bh = kmalloc(i, GFP_NOFS);
++              if (bh == NULL)
++                      goto out;
++              memset(bh, 0, i);
++      } else
++              bh = &bhs;
++      
++      first_group = page->index * blocks_per_page / 2;
++      
++      /* read all groups the page covers into the cache */
++      for (i = 0; i < groups_per_page; i++) {
++              struct ext3_group_desc * desc;
++
++              if (first_group + i >= EXT3_SB(sb)->s_groups_count)
++                      break;
++
++              err = -EIO;
++              desc = ext3_get_group_desc(sb, first_group + i, NULL);
++              if (desc == NULL)
++                      goto out;
++
++              err = -ENOMEM;
++              bh[i] = sb_getblk(sb, le32_to_cpu(desc->bg_block_bitmap));
++              if (bh[i] == NULL)
++                      goto out;
++
++              if (buffer_uptodate(bh[i]))
++                      continue;
++
++              lock_buffer(bh[i]);
++              if (buffer_uptodate(bh[i])) {
++                      unlock_buffer(bh[i]);
++                      continue;
++              }
++
++              get_bh(bh[i]);
++              bh[i]->b_end_io = end_buffer_read_sync;
++              submit_bh(READ, bh[i]);
++              mb_debug("read bitmap for group %u\n", first_group + i);
++      }
++
++      /* wait for I/O completion */
++      for (i = 0; i < groups_per_page && bh[i]; i++)
++              wait_on_buffer(bh[i]);
++
++      /* XXX: I/O error handling here */
++
++      first_block = page->index * blocks_per_page;
++      for (i = 0; i < blocks_per_page; i++) {
++              int group;
++
++              group = (first_block + i) >> 1;
++              if (group >= EXT3_SB(sb)->s_groups_count)
++                      break;
++
++              data = page_address(page) + (i * blocksize);
++              bitmap = bh[group - first_group]->b_data;
++
++              if ((first_block + i) & 1) {
++                      /* this is block of buddy */
++                      mb_debug("put buddy for group %u in page %lu/%x\n",
++                              group, page->index, i * blocksize);
++                      memset(data, 0xff, blocksize);
++                      EXT3_SB(sb)->s_group_info[group]->bb_fragments = 0;
++                      memset(EXT3_SB(sb)->s_group_info[group]->bb_counters, 0,
++                              sizeof(unsigned short)*(sb->s_blocksize_bits+2));
++                      ext3_mb_generate_buddy(sb, data, bitmap,
++                                              EXT3_SB(sb)->s_group_info[group]);
++              } else {
++                      /* this is block of bitmap */
++                      mb_debug("put bitmap for group %u in page %lu/%x\n",
++                              group, page->index, i * blocksize);
++                      memcpy(data, bitmap, blocksize);
++              }
++      }
++      SetPageUptodate(page);
++
++out:
++      for (i = 0; i < groups_per_page && bh[i]; i++)
++              brelse(bh[i]);
++      if (bh && bh != &bhs)
++              kfree(bh);
++      return err;
++}
++
++static int ext3_mb_load_buddy(struct super_block *sb, int group,
++              struct ext3_buddy *e3b)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      struct inode *inode = sbi->s_buddy_cache;
++      int blocks_per_page, block, pnum, poff;
++      struct page *page;
++
++      mb_debug("load group %u\n", group);
++
++      blocks_per_page = PAGE_CACHE_SIZE / sb->s_blocksize;
++
++      e3b->bd_blkbits = sb->s_blocksize_bits;
++      e3b->bd_info = sbi->s_group_info[group];
++      e3b->bd_sb = sb;
++      e3b->bd_group = group;
++      e3b->bd_buddy_page = NULL;
++      e3b->bd_bitmap_page = NULL;
++
++      block = group * 2;
++      pnum = block / blocks_per_page;
++      poff = block % blocks_per_page;
++
++      page = find_get_page(inode->i_mapping, pnum);
++      if (page == NULL || !PageUptodate(page)) {
++              if (page)
++                      page_cache_release(page);
++              page = find_or_create_page(inode->i_mapping, pnum, GFP_NOFS);
++              if (page) {
++                      if (!PageUptodate(page))
++                              ext3_mb_init_cache(page);
++                      unlock_page(page);
++              }
++      }
++      if (page == NULL || !PageUptodate(page))
++              goto err;
++      e3b->bd_bitmap_page = page;
++      e3b->bd_bitmap = page_address(page) + (poff * sb->s_blocksize);
++      mark_page_accessed(page);
++
++      block++;
++      pnum = block / blocks_per_page;
++      poff = block % blocks_per_page;
++
++      page = find_get_page(inode->i_mapping, pnum);
++      if (page == NULL || !PageUptodate(page)) {
++              if (page)
++                      page_cache_release(page);
++              page = find_or_create_page(inode->i_mapping, pnum, GFP_NOFS);
++              if (page) {
++                      if (!PageUptodate(page))
++                              ext3_mb_init_cache(page);
++                      unlock_page(page);
++              }
++      }
++      if (page == NULL || !PageUptodate(page))
++              goto err;
++      e3b->bd_buddy_page = page;
++      e3b->bd_buddy = page_address(page) + (poff * sb->s_blocksize);
++      mark_page_accessed(page);
++
++      J_ASSERT(e3b->bd_bitmap_page != NULL);
++      J_ASSERT(e3b->bd_buddy_page != NULL);
++
++      return 0;
++
++err:
++      if (e3b->bd_bitmap_page)
++              page_cache_release(e3b->bd_bitmap_page);
++      if (e3b->bd_buddy_page)
++              page_cache_release(e3b->bd_buddy_page);
++      e3b->bd_buddy = NULL;
++      e3b->bd_bitmap = NULL;
++      return -EIO;
++}
++
++static void ext3_mb_release_desc(struct ext3_buddy *e3b)
++{
++      if (e3b->bd_bitmap_page)
++              page_cache_release(e3b->bd_bitmap_page);
++      if (e3b->bd_buddy_page)
++              page_cache_release(e3b->bd_buddy_page);
++}
++
++
++static inline void
++ext3_lock_group(struct super_block *sb, int group)
++{
++      bit_spin_lock(EXT3_GROUP_INFO_LOCKED_BIT,
++                      &EXT3_SB(sb)->s_group_info[group]->bb_state);
++}
++
++static inline void
++ext3_unlock_group(struct super_block *sb, int group)
++{
++      bit_spin_unlock(EXT3_GROUP_INFO_LOCKED_BIT,
++                      &EXT3_SB(sb)->s_group_info[group]->bb_state);
++}
++
++static int mb_find_order_for_block(struct ext3_buddy *e3b, int block)
++{
++      int order = 1;
++      void *bb;
++
++      J_ASSERT(EXT3_MB_BITMAP(e3b) != EXT3_MB_BUDDY(e3b));
++      J_ASSERT(block < (1 << (e3b->bd_blkbits + 3)));
++
++      bb = EXT3_MB_BUDDY(e3b);
++      while (order <= e3b->bd_blkbits + 1) {
++              block = block >> 1;
++              if (!mb_test_bit(block, bb)) {
++                      /* this block is part of buddy of order 'order' */
++                      return order;
++              }
++              bb += 1 << (e3b->bd_blkbits - order);
++              order++;
++      }
++      return 0;
++}
++
++static inline void mb_clear_bits(void *bm, int cur, int len)
++{
++      __u32 *addr;
++
++      len = cur + len;
++      while (cur < len) {
++              if ((cur & 31) == 0 && (len - cur) >= 32) {
++                      /* fast path: clear whole word at once */
++                      addr = bm + (cur >> 3);
++                      *addr = 0;
++                      cur += 32;
++                      continue;
++              }
++              mb_clear_bit_atomic(cur, bm);
++              cur++;
++      }
++}
++
++static inline void mb_set_bits(void *bm, int cur, int len)
++{
++      __u32 *addr;
++
++      len = cur + len;
++      while (cur < len) {
++              if ((cur & 31) == 0 && (len - cur) >= 32) {
++                      /* fast path: clear whole word at once */
++                      addr = bm + (cur >> 3);
++                      *addr = 0xffffffff;
++                      cur += 32;
++                      continue;
++              }
++              mb_set_bit_atomic(cur, bm);
++              cur++;
++      }
++}
++
++static int mb_free_blocks(struct ext3_buddy *e3b, int first, int count)
++{
++      int block = 0, max = 0, order;
++      void *buddy, *buddy2;
++
++      mb_check_buddy(e3b);
++
++      e3b->bd_info->bb_free += count;
++      if (first < e3b->bd_info->bb_first_free)
++              e3b->bd_info->bb_first_free = first;
++
++      /* let's maintain fragments counter */
++      if (first != 0)
++              block = !mb_test_bit(first - 1, EXT3_MB_BITMAP(e3b));
++      if (first + count < EXT3_SB(e3b->bd_sb)->s_mb_maxs[0])
++              max = !mb_test_bit(first + count, EXT3_MB_BITMAP(e3b));
++      if (block && max)
++              e3b->bd_info->bb_fragments--;
++      else if (!block && !max)
++              e3b->bd_info->bb_fragments++;
++
++      /* let's maintain buddy itself */
++      while (count-- > 0) {
++              block = first++;
++              order = 0;
++
++              J_ASSERT(mb_test_bit(block, EXT3_MB_BITMAP(e3b)));
++              mb_clear_bit(block, EXT3_MB_BITMAP(e3b));
++              e3b->bd_info->bb_counters[order]++;
++
++              /* start of the buddy */
++              buddy = mb_find_buddy(e3b, order, &max);
++
++              do {
++                      block &= ~1UL;
++                      if (mb_test_bit(block, buddy) ||
++                                      mb_test_bit(block + 1, buddy))
++                              break;
++
++                      /* both the buddies are free, try to coalesce them */
++                      buddy2 = mb_find_buddy(e3b, order + 1, &max);
++
++                      if (!buddy2)
++                              break;
++
++                      if (order > 0) {
++                              /* for special purposes, we don't set
++                               * free bits in bitmap */
++                              mb_set_bit(block, buddy);
++                              mb_set_bit(block + 1, buddy);
++                      }
++                      e3b->bd_info->bb_counters[order]--;
++                      e3b->bd_info->bb_counters[order]--;
++
++                      block = block >> 1;
++                      order++;
++                      e3b->bd_info->bb_counters[order]++;
++
++                      mb_clear_bit(block, buddy2);
++                      buddy = buddy2;
++              } while (1);
++      }
++      mb_check_buddy(e3b);
++
++      return 0;
++}
++
++static int mb_find_extent(struct ext3_buddy *e3b, int order, int block,
++                              int needed, struct ext3_free_extent *ex)
++{
++      int next, max, ord;
++      void *buddy;
++
++      J_ASSERT(ex != NULL);
++
++      buddy = mb_find_buddy(e3b, order, &max);
++      J_ASSERT(buddy);
++      J_ASSERT(block < max);
++      if (mb_test_bit(block, buddy)) {
++              ex->fe_len = 0;
++              ex->fe_start = 0;
++              ex->fe_group = 0;
++              return 0;
++      }
++
++      if (likely(order == 0)) {
++              /* find actual order */
++              order = mb_find_order_for_block(e3b, block);
++              block = block >> order;
++      }
++
++      ex->fe_len = 1 << order;
++      ex->fe_start = block << order;
++      ex->fe_group = e3b->bd_group;
++
++      while (needed > ex->fe_len && (buddy = mb_find_buddy(e3b, order, &max))) {
++
++              if (block + 1 >= max)
++                      break;
++
++              next = (block + 1) * (1 << order);
++              if (mb_test_bit(next, EXT3_MB_BITMAP(e3b)))
++                      break;
++
++              ord = mb_find_order_for_block(e3b, next);
++
++              order = ord;
++              block = next >> order;
++              ex->fe_len += 1 << order;
++      }
++
++      J_ASSERT(ex->fe_start + ex->fe_len <= (1 << (e3b->bd_blkbits + 3)));
++      return ex->fe_len;
++}
++
++static int mb_mark_used(struct ext3_buddy *e3b, struct ext3_free_extent *ex)
++{
++      int ord, mlen = 0, max = 0, cur;
++      int start = ex->fe_start;
++      int len = ex->fe_len;
++      unsigned ret = 0;
++      int len0 = len;
++      void *buddy;
++
++      mb_check_buddy(e3b);
++
++      e3b->bd_info->bb_free -= len;
++      if (e3b->bd_info->bb_first_free == start)
++              e3b->bd_info->bb_first_free += len;
++
++      /* let's maintain fragments counter */
++      if (start != 0)
++              mlen = !mb_test_bit(start - 1, EXT3_MB_BITMAP(e3b));
++      if (start + len < EXT3_SB(e3b->bd_sb)->s_mb_maxs[0])
++              max = !mb_test_bit(start + len, EXT3_MB_BITMAP(e3b));
++      if (mlen && max)
++              e3b->bd_info->bb_fragments++;
++      else if (!mlen && !max)
++              e3b->bd_info->bb_fragments--;
++
++      /* let's maintain buddy itself */
++      while (len) {
++              ord = mb_find_order_for_block(e3b, start);
++
++              if (((start >> ord) << ord) == start && len >= (1 << ord)) {
++                      /* the whole chunk may be allocated at once! */
++                      mlen = 1 << ord;
++                      buddy = mb_find_buddy(e3b, ord, &max);
++                      J_ASSERT((start >> ord) < max);
++                      mb_set_bit(start >> ord, buddy);
++                      e3b->bd_info->bb_counters[ord]--;
++                      start += mlen;
++                      len -= mlen;
++                      J_ASSERT(len >= 0);
++                      continue;
++              }
++
++              /* store for history */
++              if (ret == 0)
++                      ret = len | (ord << 16);
++
++              /* we have to split large buddy */
++              J_ASSERT(ord > 0);
++              buddy = mb_find_buddy(e3b, ord, &max);
++              mb_set_bit(start >> ord, buddy);
++              e3b->bd_info->bb_counters[ord]--;
++
++              ord--;
++              cur = (start >> ord) & ~1U;
++              buddy = mb_find_buddy(e3b, ord, &max);
++              mb_clear_bit(cur, buddy);
++              mb_clear_bit(cur + 1, buddy);
++              e3b->bd_info->bb_counters[ord]++;
++              e3b->bd_info->bb_counters[ord]++;
++      }
++
++      /* now drop all the bits in bitmap */
++      mb_set_bits(EXT3_MB_BITMAP(e3b), ex->fe_start, len0);
++
++      mb_check_buddy(e3b);
++
++      return ret;
++}
++
++/*
++ * Must be called under group lock!
++ */
++static void ext3_mb_use_best_found(struct ext3_allocation_context *ac,
++                                      struct ext3_buddy *e3b)
++{
++      unsigned long ret;
++
++      ac->ac_b_ex.fe_len = min(ac->ac_b_ex.fe_len, ac->ac_g_ex.fe_len);
++      ret = mb_mark_used(e3b, &ac->ac_b_ex);
++
++      ac->ac_status = AC_STATUS_FOUND;
++      ac->ac_tail = ret & 0xffff;
++      ac->ac_buddy = ret >> 16;
++}
++
++/*
++ * The routine checks whether found extent is good enough. If it is,
++ * then the extent gets marked used and flag is set to the context
++ * to stop scanning. Otherwise, the extent is compared with the
++ * previous found extent and if new one is better, then it's stored
++ * in the context. Later, the best found extent will be used, if
++ * mballoc can't find good enough extent.
++ *
++ * FIXME: real allocation policy is to be designed yet!
++ */
++static void ext3_mb_measure_extent(struct ext3_allocation_context *ac,
++                                      struct ext3_free_extent *ex,
++                                      struct ext3_buddy *e3b)
++{
++      struct ext3_free_extent *bex = &ac->ac_b_ex;
++      struct ext3_free_extent *gex = &ac->ac_g_ex;
++
++      J_ASSERT(ex->fe_len > 0);
++      J_ASSERT(ex->fe_len < (1 << ac->ac_sb->s_blocksize_bits) * 8);
++      J_ASSERT(ex->fe_start < (1 << ac->ac_sb->s_blocksize_bits) * 8);
++
++      ac->ac_found++;
++
++      /*
++       * The special case - take what you catch first
++       */
++      if (unlikely(ac->ac_flags & EXT3_MB_HINT_FIRST)) {
++              *bex = *ex;
++              ext3_mb_use_best_found(ac, e3b);
++              return;
++      }
++
++      /*
++       * Let's check whether the chuck is good enough
++       */
++      if (ex->fe_len == gex->fe_len) {
++              *bex = *ex;
++              ext3_mb_use_best_found(ac, e3b);
++              return;
++      }
++
++      /*
++       * If this is first found extent, just store it in the context
++       */
++      if (bex->fe_len == 0) {
++              *bex = *ex;
++              return;
++      }
++
++      /*
++       * If new found extent is better, store it in the context
++       */
++      if (bex->fe_len < gex->fe_len) {
++              /* if the request isn't satisfied, any found extent
++               * larger than previous best one is better */
++              if (ex->fe_len > bex->fe_len)
++                      *bex = *ex;
++      } else if (ex->fe_len > gex->fe_len) {
++              /* if the request is satisfied, then we try to find
++               * an extent that still satisfy the request, but is
++               * smaller than previous one */
++              *bex = *ex;
++      }
++
++      /*
++       * Let's scan at least few extents and don't pick up a first one
++       */
++      if (bex->fe_len > gex->fe_len && ac->ac_found > ext3_mb_min_to_scan)
++              ac->ac_status = AC_STATUS_BREAK;
++
++      /*
++       * We don't want to scan for a whole year
++       */
++      if (ac->ac_found > ext3_mb_max_to_scan)
++              ac->ac_status = AC_STATUS_BREAK;
++}
++
++static int ext3_mb_try_best_found(struct ext3_allocation_context *ac,
++                                      struct ext3_buddy *e3b)
++{
++      struct ext3_free_extent ex = ac->ac_b_ex;
++      int group = ex.fe_group, max, err;
++
++      J_ASSERT(ex.fe_len > 0);
++      err = ext3_mb_load_buddy(ac->ac_sb, group, e3b);
++      if (err)
++              return err;
++
++      ext3_lock_group(ac->ac_sb, group);
++      max = mb_find_extent(e3b, 0, ex.fe_start, ex.fe_len, &ex);
++      
++      if (max > 0) {
++              ac->ac_b_ex = ex;
++              ext3_mb_use_best_found(ac, e3b);
++      }
++
++      ext3_unlock_group(ac->ac_sb, group);
++
++      ext3_mb_release_desc(e3b);
++
++      return 0;
++}
++
++static int ext3_mb_find_by_goal(struct ext3_allocation_context *ac,
++                              struct ext3_buddy *e3b)
++{
++      int group = ac->ac_g_ex.fe_group, max, err;
++      struct ext3_free_extent ex;
++
++      err = ext3_mb_load_buddy(ac->ac_sb, group, e3b);
++      if (err)
++              return err;
++
++      ext3_lock_group(ac->ac_sb, group);
++      max = mb_find_extent(e3b, 0, ac->ac_g_ex.fe_start,
++                              ac->ac_g_ex.fe_len, &ex);
++      
++      if (max > 0) {
++              J_ASSERT(ex.fe_len > 0);
++              J_ASSERT(ex.fe_group == ac->ac_g_ex.fe_group);
++              J_ASSERT(ex.fe_start == ac->ac_g_ex.fe_start);
++              ac->ac_found++;
++              ac->ac_b_ex = ex;
++              ext3_mb_use_best_found(ac, e3b);
++      }
++      ext3_unlock_group(ac->ac_sb, group);
++
++      ext3_mb_release_desc(e3b);
++
++      return 0;
++}
++
++/*
++ * The routine scans buddy structures (not bitmap!) from given order
++ * to max order and tries to find big enough chunk to satisfy the req
++ */
++static void ext3_mb_simple_scan_group(struct ext3_allocation_context *ac,
++                                      struct ext3_buddy *e3b)
++{
++      struct super_block *sb = ac->ac_sb;
++      struct ext3_group_info *grp = e3b->bd_info;
++      void *buddy;
++      int i, k, max;
++
++      J_ASSERT(ac->ac_2order > 0);
++      for (i = ac->ac_2order; i < sb->s_blocksize_bits + 1; i++) {
++              if (grp->bb_counters[i] == 0)
++                      continue;
++
++              buddy = mb_find_buddy(e3b, i, &max);
++              if (buddy == NULL) {
++                      printk(KERN_ALERT "looking for wrong order?\n");
++                      break;
++              }
++
++              k = mb_find_next_zero_bit(buddy, max, 0);
++              J_ASSERT(k < max);
++
++              ac->ac_found++;
++
++              ac->ac_b_ex.fe_len = 1 << i;
++              ac->ac_b_ex.fe_start = k << i;
++              ac->ac_b_ex.fe_group = e3b->bd_group;
++              
++              ext3_mb_use_best_found(ac, e3b);
++              J_ASSERT(ac->ac_b_ex.fe_len == ac->ac_g_ex.fe_len);
++
++              if (unlikely(ext3_mb_stats))
++                      atomic_inc(&EXT3_SB(sb)->s_bal_2orders);
++
++              break;
++      }
++}
++
++/*
++ * The routine scans the group and measures all found extents.
++ * In order to optimize scanning, caller must pass number of
++ * free blocks in the group, so the routine can know upper limit.
++ */
++static void ext3_mb_complex_scan_group(struct ext3_allocation_context *ac,
++                                      struct ext3_buddy *e3b)
++{
++      struct super_block *sb = ac->ac_sb;
++      void *bitmap = EXT3_MB_BITMAP(e3b);
++      struct ext3_free_extent ex;
++      int i, free;
++
++      free = e3b->bd_info->bb_free;
++      J_ASSERT(free > 0);
++
++      i = e3b->bd_info->bb_first_free;
++
++      while (free && ac->ac_status == AC_STATUS_CONTINUE) {
++              i = mb_find_next_zero_bit(bitmap, sb->s_blocksize * 8, i);
++              if (i >= sb->s_blocksize * 8) {
++                      J_ASSERT(free == 0);
++                      break;
++              }
++
++              mb_find_extent(e3b, 0, i, ac->ac_g_ex.fe_len, &ex);
++              J_ASSERT(ex.fe_len > 0);
++              J_ASSERT(free >= ex.fe_len);
++
++              ext3_mb_measure_extent(ac, &ex, e3b);
++
++              i += ex.fe_len;
++              free -= ex.fe_len;
++      }
++}
++
++static int ext3_mb_good_group(struct ext3_allocation_context *ac,
++                              int group, int cr)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(ac->ac_sb);
++      struct ext3_group_info *grp = sbi->s_group_info[group];
++      unsigned free, fragments, i, bits;
++
++      J_ASSERT(cr >= 0 && cr < 4);
++      J_ASSERT(!EXT3_MB_GRP_NEED_INIT(grp));
++
++      free = grp->bb_free;
++      fragments = grp->bb_fragments;
++      if (free == 0)
++              return 0;
++      if (fragments == 0)
++              return 0;
++
++      switch (cr) {
++              case 0:
++                      J_ASSERT(ac->ac_2order != 0);
++                      bits = ac->ac_sb->s_blocksize_bits + 1;
++                      for (i = ac->ac_2order; i < bits; i++)
++                              if (grp->bb_counters[i] > 0)
++                                      return 1;
++              case 1:
++                      if ((free / fragments) >= ac->ac_g_ex.fe_len)
++                              return 1;
++              case 2:
++                      if (free >= ac->ac_g_ex.fe_len)
++                              return 1;
++              case 3:
++                      return 1;
++              default:
++                      BUG();
++      }
++
++      return 0;
++}
++
++int ext3_mb_new_blocks(handle_t *handle, struct inode *inode,
++                     unsigned long goal, int *len, int flags, int *errp)
++{
++      struct buffer_head *bitmap_bh = NULL;
++      struct ext3_allocation_context ac;
++      int i, group, block, cr, err = 0;
++      struct ext3_group_desc *gdp;
++      struct ext3_super_block *es;
++      struct buffer_head *gdp_bh;
++      struct ext3_sb_info *sbi;
++      struct super_block *sb;
++      struct ext3_buddy e3b;
++
++      J_ASSERT(len != NULL);
++      J_ASSERT(*len > 0);
++
++      sb = inode->i_sb;
++      if (!sb) {
++              printk("ext3_mb_new_nblocks: nonexistent device");
++              return 0;
++      }
++
++      if (!test_opt(sb, MBALLOC)) {
++              static int ext3_mballoc_warning = 0;
++              if (ext3_mballoc_warning == 0) {
++                      printk(KERN_ERR "EXT3-fs: multiblock request with "
++                              "mballoc disabled!\n");
++                      ext3_mballoc_warning++;
++              }
++              *len = 1;
++              err = ext3_new_block_old(handle, inode, goal, errp);
++              return err;
++      }
++
++      ext3_mb_poll_new_transaction(sb, handle);
++
++      sbi = EXT3_SB(sb);
++      es = EXT3_SB(sb)->s_es;
++
++      /*
++       * We can't allocate > group size
++       */
++      if (*len >= EXT3_BLOCKS_PER_GROUP(sb) - 10)
++              *len = EXT3_BLOCKS_PER_GROUP(sb) - 10;
++
++      if (!(flags & EXT3_MB_HINT_RESERVED)) {
++              /* someone asks for non-reserved blocks */
++              BUG_ON(*len > 1);
++              err = ext3_mb_reserve_blocks(sb, 1);
++              if (err) {
++                      *errp = err;
++                      return 0;
++              }
++      }
++
++      /*
++       * Check quota for allocation of this blocks.
++       */
++      while (*len && DQUOT_ALLOC_BLOCK(inode, *len))
++              *len -= 1;
++      if (*len == 0) {
++              *errp = -EDQUOT;
++              block = 0;
++              goto out;
++      }
++
++      /* start searching from the goal */
++      if (goal < le32_to_cpu(es->s_first_data_block) ||
++          goal >= le32_to_cpu(es->s_blocks_count))
++              goal = le32_to_cpu(es->s_first_data_block);
++      group = (goal - le32_to_cpu(es->s_first_data_block)) /
++                      EXT3_BLOCKS_PER_GROUP(sb);
++      block = ((goal - le32_to_cpu(es->s_first_data_block)) %
++                      EXT3_BLOCKS_PER_GROUP(sb));
++
++      /* set up allocation goals */
++      ac.ac_b_ex.fe_group = 0;
++      ac.ac_b_ex.fe_start = 0;
++      ac.ac_b_ex.fe_len = 0;
++      ac.ac_status = AC_STATUS_CONTINUE;
++      ac.ac_groups_scanned = 0;
++      ac.ac_ex_scanned = 0;
++      ac.ac_found = 0;
++      ac.ac_sb = inode->i_sb;
++      ac.ac_g_ex.fe_group = group;
++      ac.ac_g_ex.fe_start = block;
++      ac.ac_g_ex.fe_len = *len;
++      ac.ac_flags = flags;
++      ac.ac_2order = 0;
++      ac.ac_criteria = 0;
++
++      /* probably, the request is for 2^8+ blocks (1/2/3/... MB) */
++      i = ffs(*len);
++      if (i >= 8) {
++              i--;
++              if ((*len & (~(1 << i))) == 0)
++                      ac.ac_2order = i;
++      }
++
++      /* Sometimes, caller may want to merge even small
++       * number of blocks to an existing extent */
++      if (ac.ac_flags & EXT3_MB_HINT_MERGE) {
++              err = ext3_mb_find_by_goal(&ac, &e3b);
++              if (err)
++                      goto out_err;
++              if (ac.ac_status == AC_STATUS_FOUND)
++                      goto found;
++      }
++
++      /* Let's just scan groups to find more-less suitable blocks */
++      cr = ac.ac_2order ? 0 : 1;
++repeat:
++      for (; cr < 4 && ac.ac_status == AC_STATUS_CONTINUE; cr++) {
++              ac.ac_criteria = cr;
++              for (i = 0; i < EXT3_SB(sb)->s_groups_count; group++, i++) {
++                      if (group == EXT3_SB(sb)->s_groups_count)
++                              group = 0;
++
++                      if (EXT3_MB_GRP_NEED_INIT(sbi->s_group_info[group])) {
++                              /* we need full data about the group
++                               * to make a good selection */
++                              err = ext3_mb_load_buddy(ac.ac_sb, group, &e3b);
++                              if (err)
++                                      goto out_err;
++                              ext3_mb_release_desc(&e3b);
++                      }
++                              
++                      /* check is group good for our criteries */
++                      if (!ext3_mb_good_group(&ac, group, cr))
++                              continue;
++
++                      err = ext3_mb_load_buddy(ac.ac_sb, group, &e3b);
++                      if (err)
++                              goto out_err;
++
++                      ext3_lock_group(sb, group);
++                      if (!ext3_mb_good_group(&ac, group, cr)) {
++                              /* someone did allocation from this group */
++                              ext3_unlock_group(sb, group);
++                              ext3_mb_release_desc(&e3b);
++                              continue;
++                      }
++
++                      ac.ac_groups_scanned++;
++                      if (cr == 0)
++                              ext3_mb_simple_scan_group(&ac, &e3b);
++                      else
++                              ext3_mb_complex_scan_group(&ac, &e3b);
++
++                      ext3_unlock_group(sb, group);
++
++                      ext3_mb_release_desc(&e3b);
++
++                      if (err)
++                              goto out_err;
++                      if (ac.ac_status != AC_STATUS_CONTINUE)
++                              break;
++              }
++      }
++
++      if (ac.ac_b_ex.fe_len > 0 && ac.ac_status != AC_STATUS_FOUND &&
++                      !(ac.ac_flags & EXT3_MB_HINT_FIRST)) {
++              /*
++               * We've been searching too long. Let's try to allocate
++               * the best chunk we've found so far
++               */
++
++              /*if (ac.ac_found > ext3_mb_max_to_scan)
++                      printk(KERN_ERR "EXT3-fs: too long searching at "
++                              "%u (%d/%d)\n", cr, ac.ac_b_ex.fe_len,
++                              ac.ac_g_ex.fe_len);*/
++              ext3_mb_try_best_found(&ac, &e3b);
++              if (ac.ac_status != AC_STATUS_FOUND) {
++                      /*
++                       * Someone more lucky has already allocated it.
++                       * The only thing we can do is just take first
++                       * found block(s)
++                       */
++                      printk(KERN_ERR "EXT3-fs: and someone won our chunk\n");
++                      ac.ac_b_ex.fe_group = 0;
++                      ac.ac_b_ex.fe_start = 0;
++                      ac.ac_b_ex.fe_len = 0;
++                      ac.ac_status = AC_STATUS_CONTINUE;
++                      ac.ac_flags |= EXT3_MB_HINT_FIRST;
++                      cr = 3;
++                      goto repeat;
++              }
++      }
++
++      if (ac.ac_status != AC_STATUS_FOUND) {
++              /*
++               * We aren't lucky definitely
++               */
++              DQUOT_FREE_BLOCK(inode, *len);
++              *errp = -ENOSPC;
++              block = 0;
++#if 1
++              printk(KERN_ERR "EXT3-fs: cant allocate: status %d, flags %d\n",
++                      ac.ac_status, ac.ac_flags);
++              printk(KERN_ERR "EXT3-fs: goal %d, best found %d/%d/%d, cr %d\n",
++                      ac.ac_g_ex.fe_len, ac.ac_b_ex.fe_group,
++                      ac.ac_b_ex.fe_start, ac.ac_b_ex.fe_len, cr);
++              printk(KERN_ERR "EXT3-fs: %lu block reserved, %d found\n",
++                      sbi->s_blocks_reserved, ac.ac_found);
++              printk("EXT3-fs: groups: ");
++              for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++)
++                      printk("%d: %d ", i,
++                              sbi->s_group_info[i]->bb_free);
++              printk("\n");
++#endif
++              goto out;
++      }
++
++found:
++      J_ASSERT(ac.ac_b_ex.fe_len > 0);
++
++      /* good news - free block(s) have been found. now it's time
++       * to mark block(s) in good old journaled bitmap */
++      block = ac.ac_b_ex.fe_group * EXT3_BLOCKS_PER_GROUP(sb)
++                      + ac.ac_b_ex.fe_start
++                      + le32_to_cpu(es->s_first_data_block);
++
++      /* we made a desicion, now mark found blocks in good old
++       * bitmap to be journaled */
++
++      ext3_debug("using block group %d(%d)\n",
++                      ac.ac_b_group.group, gdp->bg_free_blocks_count);
++
++      bitmap_bh = read_block_bitmap(sb, ac.ac_b_ex.fe_group);
++      if (!bitmap_bh) {
++              *errp = -EIO;
++              goto out_err;
++      }
++
++      err = ext3_journal_get_write_access(handle, bitmap_bh);
++      if (err) {
++              *errp = err;
++              goto out_err;
++      }
++
++      gdp = ext3_get_group_desc(sb, ac.ac_b_ex.fe_group, &gdp_bh);
++      if (!gdp) {
++              *errp = -EIO;
++              goto out_err;
++      }
++      
++      err = ext3_journal_get_write_access(handle, gdp_bh);
++      if (err)
++              goto out_err;
++
++      block = ac.ac_b_ex.fe_group * EXT3_BLOCKS_PER_GROUP(sb)
++                      + ac.ac_b_ex.fe_start
++                      + le32_to_cpu(es->s_first_data_block);
++
++      if (block == le32_to_cpu(gdp->bg_block_bitmap) ||
++          block == le32_to_cpu(gdp->bg_inode_bitmap) ||
++          in_range(block, le32_to_cpu(gdp->bg_inode_table),
++                    EXT3_SB(sb)->s_itb_per_group))
++              ext3_error(sb, "ext3_new_block",
++                          "Allocating block in system zone - "
++                          "block = %u", block);
++#ifdef AGGRESSIVE_CHECK
++      for (i = 0; i < ac.ac_b_ex.fe_len; i++)
++              J_ASSERT(!mb_test_bit(ac.ac_b_ex.fe_start + i, bitmap_bh->b_data));
++#endif
++      mb_set_bits(bitmap_bh->b_data, ac.ac_b_ex.fe_start, ac.ac_b_ex.fe_len);
++
++      spin_lock(sb_bgl_lock(sbi, ac.ac_b_ex.fe_group));
++      gdp->bg_free_blocks_count =
++                      cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count)
++                                      - ac.ac_b_ex.fe_len);
++      spin_unlock(sb_bgl_lock(sbi, ac.ac_b_ex.fe_group));
++      percpu_counter_mod(&sbi->s_freeblocks_counter, - ac.ac_b_ex.fe_len);
++
++      err = ext3_journal_dirty_metadata(handle, bitmap_bh);
++      if (err)
++              goto out_err;
++      err = ext3_journal_dirty_metadata(handle, gdp_bh);
++      if (err)
++              goto out_err;
++
++      sb->s_dirt = 1;
++      *errp = 0;
++      brelse(bitmap_bh);
++
++      /* drop non-allocated, but dquote'd blocks */
++      J_ASSERT(*len >= ac.ac_b_ex.fe_len);
++      DQUOT_FREE_BLOCK(inode, *len - ac.ac_b_ex.fe_len);
++
++      *len = ac.ac_b_ex.fe_len;
++      J_ASSERT(*len > 0);
++      J_ASSERT(block != 0);
++      goto out;
++
++out_err:
++      /* if we've already allocated something, roll it back */
++      if (ac.ac_status == AC_STATUS_FOUND) {
++              /* FIXME: free blocks here */
++      }
++
++      DQUOT_FREE_BLOCK(inode, *len);
++      brelse(bitmap_bh);
++      *errp = err;
++      block = 0;
++out:
++      if (!(flags & EXT3_MB_HINT_RESERVED)) {
++              /* block wasn't reserved before and we reserved it
++               * at the beginning of allocation. it doesn't matter
++               * whether we allocated anything or we failed: time
++               * to release reservation. NOTE: because I expect
++               * any multiblock request from delayed allocation
++               * path only, here is single block always */
++              ext3_mb_release_blocks(sb, 1);
++      }
++      
++      if (unlikely(ext3_mb_stats) && ac.ac_g_ex.fe_len > 1) {
++              atomic_inc(&sbi->s_bal_reqs);
++              atomic_add(*len, &sbi->s_bal_allocated);
++              if (*len >= ac.ac_g_ex.fe_len)
++                      atomic_inc(&sbi->s_bal_success);
++              atomic_add(ac.ac_found, &sbi->s_bal_ex_scanned);
++              if (ac.ac_g_ex.fe_start == ac.ac_b_ex.fe_start &&
++                              ac.ac_g_ex.fe_group == ac.ac_b_ex.fe_group)
++                      atomic_inc(&sbi->s_bal_goals);
++              if (ac.ac_found > ext3_mb_max_to_scan)
++                      atomic_inc(&sbi->s_bal_breaks);
++      }
++
++      ext3_mb_store_history(sb, &ac);
++
++      return block;
++}
++EXPORT_SYMBOL(ext3_mb_new_blocks);
++
++#ifdef EXT3_MB_HISTORY
++struct ext3_mb_proc_session {
++      struct ext3_mb_history *history;
++      struct super_block *sb;
++      int start;
++      int max;
++};
++
++static void *ext3_mb_history_skip_empty(struct ext3_mb_proc_session *s,
++                                      struct ext3_mb_history *hs,
++                                      int first)
++{
++      if (hs == s->history + s->max)
++              hs = s->history;
++      if (!first && hs == s->history + s->start)
++              return NULL;
++      while (hs->goal.fe_len == 0) {
++              hs++;
++              if (hs == s->history + s->max)
++                      hs = s->history;
++              if (hs == s->history + s->start)
++                      return NULL;
++      }
++      return hs;
++}
++
++static void *ext3_mb_seq_history_start(struct seq_file *seq, loff_t *pos)
++{
++      struct ext3_mb_proc_session *s = seq->private;
++      struct ext3_mb_history *hs;
++      int l = *pos;
++
++      if (l == 0)
++              return SEQ_START_TOKEN;
++      hs = ext3_mb_history_skip_empty(s, s->history + s->start, 1);
++      if (!hs)
++              return NULL;
++      while (--l && (hs = ext3_mb_history_skip_empty(s, ++hs, 0)) != NULL);
++      return hs;
++}
++
++static void *ext3_mb_seq_history_next(struct seq_file *seq, void *v, loff_t *pos)
++{
++      struct ext3_mb_proc_session *s = seq->private;
++      struct ext3_mb_history *hs = v;
++
++      ++*pos;
++      if (v == SEQ_START_TOKEN)
++              return ext3_mb_history_skip_empty(s, s->history + s->start, 1);
++      else
++              return ext3_mb_history_skip_empty(s, ++hs, 0);
++}
++
++static int ext3_mb_seq_history_show(struct seq_file *seq, void *v)
++{
++      struct ext3_mb_history *hs = v;
++      char buf[20], buf2[20];
++
++      if (v == SEQ_START_TOKEN) {
++              seq_printf(seq, "%-17s %-17s %-5s %-5s %-2s %-5s %-5s %-6s\n",
++                       "goal", "result", "found", "grps", "cr", "merge",
++                       "tail", "broken");
++              return 0;
++      }
++
++      sprintf(buf, "%u/%u/%u", hs->goal.fe_group,
++              hs->goal.fe_start, hs->goal.fe_len);
++      sprintf(buf2, "%u/%u/%u", hs->result.fe_group,
++              hs->result.fe_start, hs->result.fe_len);
++      seq_printf(seq, "%-17s %-17s %-5u %-5u %-2u %-5s %-5u %-6u\n", buf,
++                      buf2, hs->found, hs->groups, hs->cr, 
++                      hs->merged ? "M" : "", hs->tail,
++                      hs->buddy ? 1 << hs->buddy : 0);
++      return 0;
++}
++
++static void ext3_mb_seq_history_stop(struct seq_file *seq, void *v)
++{
++}
++
++static struct seq_operations ext3_mb_seq_history_ops = {
++      .start  = ext3_mb_seq_history_start,
++      .next   = ext3_mb_seq_history_next,
++      .stop   = ext3_mb_seq_history_stop,
++      .show   = ext3_mb_seq_history_show,
++};
++
++static int ext3_mb_seq_history_open(struct inode *inode, struct file *file)
++{
++      struct super_block *sb = PDE(inode)->data;
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      struct ext3_mb_proc_session *s;
++      int rc, size;
++
++      s = kmalloc(sizeof(*s), GFP_KERNEL);
++      if (s == NULL)
++              return -EIO;
++      size = sizeof(struct ext3_mb_history) * sbi->s_mb_history_max;
++      s->history = kmalloc(size, GFP_KERNEL);
++      if (s == NULL) {
++              kfree(s);
++              return -EIO;
++      }
++
++      spin_lock(&sbi->s_mb_history_lock);
++      memcpy(s->history, sbi->s_mb_history, size);
++      s->max = sbi->s_mb_history_max;
++      s->start = sbi->s_mb_history_cur % s->max;
++      spin_unlock(&sbi->s_mb_history_lock);
++      
++      rc = seq_open(file, &ext3_mb_seq_history_ops);
++      if (rc == 0) {
++              struct seq_file *m = (struct seq_file *)file->private_data;
++              m->private = s;
++      } else {
++              kfree(s->history);
++              kfree(s);
++      }
++      return rc;
++
++}
++
++static int ext3_mb_seq_history_release(struct inode *inode, struct file *file)
++{
++      struct seq_file *seq = (struct seq_file *)file->private_data;
++      struct ext3_mb_proc_session *s = seq->private;
++      kfree(s->history);
++      kfree(s);
++      return seq_release(inode, file);
++}
++
++static struct file_operations ext3_mb_seq_history_fops = {
++      .owner          = THIS_MODULE,
++      .open           = ext3_mb_seq_history_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = ext3_mb_seq_history_release,
++};
++
++static void ext3_mb_history_release(struct super_block *sb)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      char name[64];
++
++      snprintf(name, sizeof(name) - 1, "%s", bdevname(sb->s_bdev, name));
++      remove_proc_entry("mb_history", sbi->s_mb_proc);
++      remove_proc_entry(name, proc_root_ext3);
++
++      if (sbi->s_mb_history)
++              kfree(sbi->s_mb_history);
++}
++
++static void ext3_mb_history_init(struct super_block *sb)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      char name[64];
++      int i;
++
++      snprintf(name, sizeof(name) - 1, "%s", bdevname(sb->s_bdev, name));
++      sbi->s_mb_proc = proc_mkdir(name, proc_root_ext3);
++      if (sbi->s_mb_proc != NULL) {
++              struct proc_dir_entry *p;
++              p = create_proc_entry("mb_history", S_IRUGO, sbi->s_mb_proc);
++              if (p) {
++                      p->proc_fops = &ext3_mb_seq_history_fops;
++                      p->data = sb;
++              }
++      }
++
++      sbi->s_mb_history_max = 1000;
++      sbi->s_mb_history_cur = 0;
++      spin_lock_init(&sbi->s_mb_history_lock);
++      i = sbi->s_mb_history_max * sizeof(struct ext3_mb_history);
++      sbi->s_mb_history = kmalloc(i, GFP_KERNEL);
++      memset(sbi->s_mb_history, 0, i);
++      /* if we can't allocate history, then we simple won't use it */
++}
++
++static void
++ext3_mb_store_history(struct super_block *sb, struct ext3_allocation_context *ac)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      struct ext3_mb_history h;
++
++      if (likely(sbi->s_mb_history == NULL))
++              return;
++
++      h.goal = ac->ac_g_ex;
++      h.result = ac->ac_b_ex;
++      h.found = ac->ac_found;
++      h.cr = ac->ac_criteria;
++      h.groups = ac->ac_groups_scanned;
++      h.tail = ac->ac_tail;
++      h.buddy = ac->ac_buddy;
++      h.merged = 0;
++      if (ac->ac_g_ex.fe_start == ac->ac_b_ex.fe_start &&
++                      ac->ac_g_ex.fe_group == ac->ac_b_ex.fe_group)
++              h.merged = 1;
++
++      spin_lock(&sbi->s_mb_history_lock);
++      memcpy(sbi->s_mb_history + sbi->s_mb_history_cur, &h, sizeof(h));
++      if (++sbi->s_mb_history_cur >= sbi->s_mb_history_max)
++              sbi->s_mb_history_cur = 0;
++      spin_unlock(&sbi->s_mb_history_lock);
++}
++
++#else
++#define ext3_mb_history_release(sb)
++#define ext3_mb_history_init(sb)
++#endif
++
++int ext3_mb_init_backend(struct super_block *sb)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      int i, len;
++
++      len = sizeof(struct ext3_buddy_group_blocks *) * sbi->s_groups_count;
++      sbi->s_group_info = kmalloc(len, GFP_KERNEL);
++      if (sbi->s_group_info == NULL) {
++              printk(KERN_ERR "EXT3-fs: can't allocate mem for buddy\n");
++              return -ENOMEM;
++      }
++      memset(sbi->s_group_info, 0, len);
++
++      sbi->s_buddy_cache = new_inode(sb);
++      if (sbi->s_buddy_cache == NULL) {
++              printk(KERN_ERR "EXT3-fs: can't get new inode\n");
++              kfree(sbi->s_group_info);
++              return -ENOMEM;
++      }
++
++      /* 
++       * calculate needed size. if change bb_counters size,
++       * don't forget about ext3_mb_generate_buddy()
++       */
++      len = sizeof(struct ext3_group_info);
++      len += sizeof(unsigned short) * (sb->s_blocksize_bits + 2);
++      for (i = 0; i < sbi->s_groups_count; i++) {
++              struct ext3_group_desc * desc;
++
++              sbi->s_group_info[i] = kmalloc(len, GFP_KERNEL);
++              if (sbi->s_group_info[i] == NULL) {
++                      printk(KERN_ERR "EXT3-fs: cant allocate mem for buddy\n");
++                      goto err_out;
++              }
++              desc = ext3_get_group_desc(sb, i, NULL);
++              if (desc == NULL) {
++                      printk(KERN_ERR "EXT3-fs: cant read descriptor %u\n", i);
++                      goto err_out;
++              }
++              memset(sbi->s_group_info[i], 0, len);
++              set_bit(EXT3_GROUP_INFO_NEED_INIT_BIT,
++                      &sbi->s_group_info[i]->bb_state);
++              sbi->s_group_info[i]->bb_free =
++                      le16_to_cpu(desc->bg_free_blocks_count);
++      }
++
++      return 0;
++
++err_out:
++      while (--i >= 0)
++              kfree(sbi->s_group_info[i]);
++      iput(sbi->s_buddy_cache);
++
++      return -ENOMEM;
++}
++
++int ext3_mb_init(struct super_block *sb, int needs_recovery)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      struct inode *root = sb->s_root->d_inode;
++      unsigned i, offset, max;
++      struct dentry *dentry;
++
++      if (!test_opt(sb, MBALLOC))
++              return 0;
++
++      i = (sb->s_blocksize_bits + 2) * sizeof(unsigned short);
++
++      sbi->s_mb_offsets = kmalloc(i, GFP_KERNEL);
++      if (sbi->s_mb_offsets == NULL) {
++              clear_opt(sbi->s_mount_opt, MBALLOC);
++              return -ENOMEM;
++      }
++      sbi->s_mb_maxs = kmalloc(i, GFP_KERNEL);
++      if (sbi->s_mb_maxs == NULL) {
++              clear_opt(sbi->s_mount_opt, MBALLOC);
++              kfree(sbi->s_mb_maxs);
++              return -ENOMEM;
++      }
++
++       /* order 0 is regular bitmap */
++      sbi->s_mb_maxs[0] = sb->s_blocksize << 3;
++      sbi->s_mb_offsets[0] = 0;
++
++      i = 1;
++      offset = 0;
++      max = sb->s_blocksize << 2;
++      do {
++              sbi->s_mb_offsets[i] = offset;
++              sbi->s_mb_maxs[i] = max;
++              offset += 1 << (sb->s_blocksize_bits - i);
++              max = max >> 1;
++              i++;
++      } while (i <= sb->s_blocksize_bits + 1);
++      
++
++      /* init file for buddy data */
++      if ((i = ext3_mb_init_backend(sb))) {
++              clear_opt(sbi->s_mount_opt, MBALLOC);
++              kfree(sbi->s_mb_offsets);
++              kfree(sbi->s_mb_maxs);
++              return i;
++      }
++
++      spin_lock_init(&sbi->s_reserve_lock);
++      spin_lock_init(&sbi->s_md_lock);
++      INIT_LIST_HEAD(&sbi->s_active_transaction);
++      INIT_LIST_HEAD(&sbi->s_closed_transaction);
++      INIT_LIST_HEAD(&sbi->s_committed_transaction);
++      spin_lock_init(&sbi->s_bal_lock);
++
++      /* remove old on-disk buddy file */
++      mutex_lock(&root->i_mutex);
++      dentry = lookup_one_len(".buddy", sb->s_root, strlen(".buddy"));
++      if (dentry->d_inode != NULL) {
++              i = vfs_unlink(root, dentry);
++              if (i != 0)
++                      printk("EXT3-fs: can't remove .buddy file: %d\n", i);
++      }
++      dput(dentry);
++      mutex_unlock(&root->i_mutex);
++
++      ext3_mb_history_init(sb);
++
++      printk("EXT3-fs: mballoc enabled\n");
++      return 0;
++}
++
++int ext3_mb_release(struct super_block *sb)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      int i;
++      
++      if (!test_opt(sb, MBALLOC))
++              return 0;
++
++      /* release freed, non-committed blocks */
++      spin_lock(&sbi->s_md_lock);
++      list_splice_init(&sbi->s_closed_transaction,
++                      &sbi->s_committed_transaction);
++      list_splice_init(&sbi->s_active_transaction,
++                      &sbi->s_committed_transaction);
++      spin_unlock(&sbi->s_md_lock);
++      ext3_mb_free_committed_blocks(sb);
++
++      if (sbi->s_group_info) {
++              for (i = 0; i < sbi->s_groups_count; i++) {
++                      if (sbi->s_group_info[i] == NULL)
++                              continue;
++                      kfree(sbi->s_group_info[i]);
++              }
++              kfree(sbi->s_group_info);
++      }
++      if (sbi->s_mb_offsets)
++              kfree(sbi->s_mb_offsets);
++      if (sbi->s_mb_maxs)
++              kfree(sbi->s_mb_maxs);
++      if (sbi->s_buddy_cache)
++              iput(sbi->s_buddy_cache);
++      if (sbi->s_blocks_reserved)
++              printk("ext3-fs: %ld blocks being reserved at umount!\n",
++                              sbi->s_blocks_reserved);
++      if (ext3_mb_stats) {
++              printk("EXT3-fs: mballoc: %u blocks %u reqs (%u success)\n",
++                      atomic_read(&sbi->s_bal_allocated),
++                      atomic_read(&sbi->s_bal_reqs),
++                      atomic_read(&sbi->s_bal_success));
++              printk("EXT3-fs: mballoc: %u extents scanned, %u goal hits, "
++                      "%u 2^N hits, %u breaks\n",
++                      atomic_read(&sbi->s_bal_ex_scanned),
++                      atomic_read(&sbi->s_bal_goals),
++                      atomic_read(&sbi->s_bal_2orders),
++                      atomic_read(&sbi->s_bal_breaks));
++              printk("EXT3-fs: mballoc: %lu generated and it took %Lu\n",
++                      sbi->s_mb_buddies_generated++,
++                      sbi->s_mb_generation_time);
++      }
++
++      ext3_mb_history_release(sb);
++
++      return 0;
++}
++
++void ext3_mb_free_committed_blocks(struct super_block *sb)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      int err, i, count = 0, count2 = 0;
++      struct ext3_free_metadata *md;
++      struct ext3_buddy e3b;
++
++      if (list_empty(&sbi->s_committed_transaction))
++              return;
++
++      /* there is committed blocks to be freed yet */
++      do {
++              /* get next array of blocks */
++              md = NULL;
++              spin_lock(&sbi->s_md_lock);
++              if (!list_empty(&sbi->s_committed_transaction)) {
++                      md = list_entry(sbi->s_committed_transaction.next,
++                                      struct ext3_free_metadata, list);
++                      list_del(&md->list);
++              }
++              spin_unlock(&sbi->s_md_lock);
++
++              if (md == NULL)
++                      break;
++
++              mb_debug("gonna free %u blocks in group %u (0x%p):",
++                              md->num, md->group, md);
++
++              err = ext3_mb_load_buddy(sb, md->group, &e3b);
++              BUG_ON(err != 0);
++
++              /* there are blocks to put in buddy to make them really free */
++              count += md->num;
++              count2++;
++              ext3_lock_group(sb, md->group);
++              for (i = 0; i < md->num; i++) {
++                      mb_debug(" %u", md->blocks[i]);
++                      mb_free_blocks(&e3b, md->blocks[i], 1);
++              }
++              mb_debug("\n");
++              ext3_unlock_group(sb, md->group);
++
++              /* balance refcounts from ext3_mb_free_metadata() */
++              page_cache_release(e3b.bd_buddy_page);
++              page_cache_release(e3b.bd_bitmap_page);
++
++              kfree(md);
++              ext3_mb_release_desc(&e3b);
++
++      } while (md);
++      mb_debug("freed %u blocks in %u structures\n", count, count2);
++}
++
++void ext3_mb_poll_new_transaction(struct super_block *sb, handle_t *handle)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++
++      if (sbi->s_last_transaction == handle->h_transaction->t_tid)
++              return;
++
++      /* new transaction! time to close last one and free blocks for
++       * committed transaction. we know that only transaction can be
++       * active, so previos transaction can be being logged and we
++       * know that transaction before previous is known to be already
++       * logged. this means that now we may free blocks freed in all
++       * transactions before previous one. hope I'm clear enough ... */
++
++      spin_lock(&sbi->s_md_lock);
++      if (sbi->s_last_transaction != handle->h_transaction->t_tid) {
++              mb_debug("new transaction %lu, old %lu\n",
++                              (unsigned long) handle->h_transaction->t_tid,
++                              (unsigned long) sbi->s_last_transaction);
++              list_splice_init(&sbi->s_closed_transaction,
++                                      &sbi->s_committed_transaction);
++              list_splice_init(&sbi->s_active_transaction,
++                                      &sbi->s_closed_transaction);
++              sbi->s_last_transaction = handle->h_transaction->t_tid;
++      }
++      spin_unlock(&sbi->s_md_lock);
++
++      ext3_mb_free_committed_blocks(sb);
++}
++
++int ext3_mb_free_metadata(handle_t *handle, struct ext3_buddy *e3b,
++                              int group, int block, int count)
++{
++      struct ext3_group_info *db = e3b->bd_info;
++      struct super_block *sb = e3b->bd_sb;
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      struct ext3_free_metadata *md;
++      int i;
++
++      J_ASSERT(e3b->bd_bitmap_page != NULL);
++      J_ASSERT(e3b->bd_buddy_page != NULL);
++
++      ext3_lock_group(sb, group);
++      for (i = 0; i < count; i++) {
++              md = db->bb_md_cur;
++              if (md && db->bb_tid != handle->h_transaction->t_tid) {
++                      db->bb_md_cur = NULL;
++                      md = NULL;
++              }
++
++              if (md == NULL) {
++                      ext3_unlock_group(sb, group);
++                      md = kmalloc(sizeof(*md), GFP_KERNEL);
++                      if (md == NULL)
++                              return -ENOMEM;
++                      md->num = 0;
++                      md->group = group;
++
++                      ext3_lock_group(sb, group);
++                      if (db->bb_md_cur == NULL) {
++                              spin_lock(&sbi->s_md_lock);
++                              list_add(&md->list, &sbi->s_active_transaction);
++                              spin_unlock(&sbi->s_md_lock);
++                              /* protect buddy cache from being freed,
++                               * otherwise we'll refresh it from
++                               * on-disk bitmap and lose not-yet-available
++                               * blocks */
++                              page_cache_get(e3b->bd_buddy_page);
++                              page_cache_get(e3b->bd_bitmap_page);
++                              db->bb_md_cur = md;
++                              db->bb_tid = handle->h_transaction->t_tid;
++                              mb_debug("new md 0x%p for group %u\n",
++                                                      md, md->group);
++                      } else {
++                              kfree(md);
++                              md = db->bb_md_cur;
++                      }
++              }
++
++              BUG_ON(md->num >= EXT3_BB_MAX_BLOCKS);
++              md->blocks[md->num] = block + i;
++              md->num++;
++              if (md->num == EXT3_BB_MAX_BLOCKS) {
++                      /* no more space, put full container on a sb's list */
++                      db->bb_md_cur = NULL;
++              }
++      }
++      ext3_unlock_group(sb, group);
++      return 0;
++}
++
++void ext3_mb_free_blocks(handle_t *handle, struct inode *inode,
++                      unsigned long block, unsigned long count,
++                      int metadata, int *freed)
++{
++      struct buffer_head *bitmap_bh = NULL;
++      struct ext3_group_desc *gdp;
++      struct ext3_super_block *es;
++      unsigned long bit, overflow;
++      struct buffer_head *gd_bh;
++      unsigned long block_group;
++      struct ext3_sb_info *sbi;
++      struct super_block *sb;
++      struct ext3_buddy e3b;
++      int err = 0, ret;
++
++      *freed = 0;
++      sb = inode->i_sb;
++      if (!sb) {
++              printk ("ext3_free_blocks: nonexistent device");
++              return;
++      }
++
++      ext3_mb_poll_new_transaction(sb, handle);
++
++      sbi = EXT3_SB(sb);
++      es = EXT3_SB(sb)->s_es;
++      if (block < le32_to_cpu(es->s_first_data_block) ||
++          block + count < block ||
++          block + count > le32_to_cpu(es->s_blocks_count)) {
++              ext3_error (sb, "ext3_free_blocks",
++                          "Freeing blocks not in datazone - "
++                          "block = %lu, count = %lu", block, count);
++              goto error_return;
++      }
++
++      ext3_debug("freeing block %lu\n", block);
++
++do_more:
++      overflow = 0;
++      block_group = (block - le32_to_cpu(es->s_first_data_block)) /
++                    EXT3_BLOCKS_PER_GROUP(sb);
++      bit = (block - le32_to_cpu(es->s_first_data_block)) %
++                    EXT3_BLOCKS_PER_GROUP(sb);
++      /*
++       * Check to see if we are freeing blocks across a group
++       * boundary.
++       */
++      if (bit + count > EXT3_BLOCKS_PER_GROUP(sb)) {
++              overflow = bit + count - EXT3_BLOCKS_PER_GROUP(sb);
++              count -= overflow;
++      }
++      brelse(bitmap_bh);
++      bitmap_bh = read_block_bitmap(sb, block_group);
++      if (!bitmap_bh)
++              goto error_return;
++      gdp = ext3_get_group_desc (sb, block_group, &gd_bh);
++      if (!gdp)
++              goto error_return;
++
++      if (in_range (le32_to_cpu(gdp->bg_block_bitmap), block, count) ||
++          in_range (le32_to_cpu(gdp->bg_inode_bitmap), block, count) ||
++          in_range (block, le32_to_cpu(gdp->bg_inode_table),
++                    EXT3_SB(sb)->s_itb_per_group) ||
++          in_range (block + count - 1, le32_to_cpu(gdp->bg_inode_table),
++                    EXT3_SB(sb)->s_itb_per_group))
++              ext3_error (sb, "ext3_free_blocks",
++                          "Freeing blocks in system zones - "
++                          "Block = %lu, count = %lu",
++                          block, count);
++
++      BUFFER_TRACE(bitmap_bh, "getting write access");
++      err = ext3_journal_get_write_access(handle, bitmap_bh);
++      if (err)
++              goto error_return;
++
++      /*
++       * We are about to modify some metadata.  Call the journal APIs
++       * to unshare ->b_data if a currently-committing transaction is
++       * using it
++       */
++      BUFFER_TRACE(gd_bh, "get_write_access");
++      err = ext3_journal_get_write_access(handle, gd_bh);
++      if (err)
++              goto error_return;
++
++      err = ext3_mb_load_buddy(sb, block_group, &e3b);
++      if (err)
++              goto error_return;
++
++#ifdef AGGRESSIVE_CHECK
++      {
++              int i;
++              for (i = 0; i < count; i++)
++                      J_ASSERT(mb_test_bit(bit + i, bitmap_bh->b_data));
++      }
++#endif
++      mb_clear_bits(bitmap_bh->b_data, bit, count);
++
++      /* We dirtied the bitmap block */
++      BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");
++      err = ext3_journal_dirty_metadata(handle, bitmap_bh);
++
++      if (metadata) {
++              /* blocks being freed are metadata. these blocks shouldn't
++               * be used until this transaction is committed */
++              ext3_mb_free_metadata(handle, &e3b, block_group, bit, count);
++      } else { 
++              ext3_lock_group(sb, block_group);
++              mb_free_blocks(&e3b, bit, count);
++              ext3_unlock_group(sb, block_group);
++      }
++
++      spin_lock(sb_bgl_lock(sbi, block_group));
++      gdp->bg_free_blocks_count =
++              cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) + count);
++      spin_unlock(sb_bgl_lock(sbi, block_group));
++      percpu_counter_mod(&sbi->s_freeblocks_counter, count);
++      
++      ext3_mb_release_desc(&e3b);
++
++      *freed = count;
++
++      /* And the group descriptor block */
++      BUFFER_TRACE(gd_bh, "dirtied group descriptor block");
++      ret = ext3_journal_dirty_metadata(handle, gd_bh);
++      if (!err) err = ret;
++
++      if (overflow && !err) {
++              block += count;
++              count = overflow;
++              goto do_more;
++      }
++      sb->s_dirt = 1;
++error_return:
++      brelse(bitmap_bh);
++      ext3_std_error(sb, err);
++      return;
++}
++
++int ext3_mb_reserve_blocks(struct super_block *sb, int blocks)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      int free, ret = -ENOSPC;
++
++      BUG_ON(blocks < 0);
++      spin_lock(&sbi->s_reserve_lock);
++      free = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
++      if (blocks <= free - sbi->s_blocks_reserved) {
++              sbi->s_blocks_reserved += blocks;
++              ret = 0;
++      }
++      spin_unlock(&sbi->s_reserve_lock);
++      return ret;
++}
++
++void ext3_mb_release_blocks(struct super_block *sb, int blocks)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++
++      BUG_ON(blocks < 0);
++      spin_lock(&sbi->s_reserve_lock);
++      sbi->s_blocks_reserved -= blocks;
++      WARN_ON(sbi->s_blocks_reserved < 0);
++      if (sbi->s_blocks_reserved < 0)
++              sbi->s_blocks_reserved = 0;
++      spin_unlock(&sbi->s_reserve_lock);
++}
++
++int ext3_new_block(handle_t *handle, struct inode *inode,
++              unsigned long goal, int *errp)
++{
++      int ret, len;
++
++      if (!test_opt(inode->i_sb, MBALLOC)) {
++              ret = ext3_new_block_old(handle, inode, goal, errp);
++              goto out;
++      }
++      len = 1;
++      ret = ext3_mb_new_blocks(handle, inode, goal, &len, 0, errp);
++out:
++      return ret;
++}
++
++
++void ext3_free_blocks(handle_t *handle, struct inode * inode,
++                      unsigned long block, unsigned long count, int metadata)
++{
++      struct super_block *sb;
++      int freed;
++
++      sb = inode->i_sb;
++      if (!test_opt(sb, MBALLOC))
++              ext3_free_blocks_sb(handle, sb, block, count, &freed);
++      else
++              ext3_mb_free_blocks(handle, inode, block, count, metadata, &freed);
++      if (freed)
++              DQUOT_FREE_BLOCK(inode, freed);
++      return;
++}
++
++#define EXT3_ROOT                 "ext3"
++#define EXT3_MB_STATS_NAME        "mb_stats"
++#define EXT3_MB_MAX_TO_SCAN_NAME  "mb_max_to_scan"
++#define EXT3_MB_MIN_TO_SCAN_NAME  "mb_min_to_scan"
++
++static int ext3_mb_stats_read(char *page, char **start, off_t off,
++              int count, int *eof, void *data)
++{
++      int len;
++
++      *eof = 1;
++      if (off != 0)
++              return 0;
++
++      len = sprintf(page, "%ld\n", ext3_mb_stats);
++      *start = page;
++      return len;
++}
++
++static int ext3_mb_stats_write(struct file *file, const char *buffer,
++              unsigned long count, void *data)
++{
++      char str[32];
++
++      if (count >= sizeof(str)) {
++              printk(KERN_ERR "EXT3: %s string to long, max %u bytes\n",
++                     EXT3_MB_STATS_NAME, (int)sizeof(str));
++              return -EOVERFLOW;
++      }
++
++      if (copy_from_user(str, buffer, count))
++              return -EFAULT;
++
++      /* Only set to 0 or 1 respectively; zero->0; non-zero->1 */
++      ext3_mb_stats = (simple_strtol(str, NULL, 0) != 0);
++      return count;
++}
++
++static int ext3_mb_max_to_scan_read(char *page, char **start, off_t off,
++              int count, int *eof, void *data)
++{
++      int len;
++
++      *eof = 1;
++      if (off != 0)
++              return 0;
++
++      len = sprintf(page, "%ld\n", ext3_mb_max_to_scan);
++      *start = page;
++      return len;
++}
++
++static int ext3_mb_max_to_scan_write(struct file *file, const char *buffer,
++              unsigned long count, void *data)
++{
++      char str[32];
++      long value;
++
++      if (count >= sizeof(str)) {
++              printk(KERN_ERR "EXT3: %s string to long, max %u bytes\n",
++                     EXT3_MB_MAX_TO_SCAN_NAME, (int)sizeof(str));
++              return -EOVERFLOW;
++      }
++
++      if (copy_from_user(str, buffer, count))
++              return -EFAULT;
++
++      /* Only set to 0 or 1 respectively; zero->0; non-zero->1 */
++      value = simple_strtol(str, NULL, 0);
++      if (value <= 0)
++              return -ERANGE;
++
++      ext3_mb_max_to_scan = value;    
++
++      return count;
++}
++
++static int ext3_mb_min_to_scan_read(char *page, char **start, off_t off,
++              int count, int *eof, void *data)
++{
++      int len;
++
++      *eof = 1;
++      if (off != 0)
++              return 0;
++
++      len = sprintf(page, "%ld\n", ext3_mb_min_to_scan);
++      *start = page;
++      return len;
++}
++
++static int ext3_mb_min_to_scan_write(struct file *file, const char *buffer,
++              unsigned long count, void *data)
++{
++      char str[32];
++      long value;
++
++      if (count >= sizeof(str)) {
++              printk(KERN_ERR "EXT3: %s string to long, max %u bytes\n",
++                     EXT3_MB_MIN_TO_SCAN_NAME, (int)sizeof(str));
++              return -EOVERFLOW;
++      }
++
++      if (copy_from_user(str, buffer, count))
++              return -EFAULT;
++
++      /* Only set to 0 or 1 respectively; zero->0; non-zero->1 */
++      value = simple_strtol(str, NULL, 0);
++      if (value <= 0)
++              return -ERANGE;
++
++      ext3_mb_min_to_scan = value;    
++
++      return count;
++}
++
++int __init init_ext3_proc(void)
++{
++      struct proc_dir_entry *proc_ext3_mb_stats;
++      struct proc_dir_entry *proc_ext3_mb_max_to_scan;
++      struct proc_dir_entry *proc_ext3_mb_min_to_scan;
++
++      proc_root_ext3 = proc_mkdir(EXT3_ROOT, proc_root_fs);
++      if (proc_root_ext3 == NULL) {
++              printk(KERN_ERR "EXT3: Unable to create %s\n", EXT3_ROOT);
++              return -EIO;
++      }
++
++      /* Initialize EXT3_MB_STATS_NAME */
++      proc_ext3_mb_stats = create_proc_entry(EXT3_MB_STATS_NAME,
++                      S_IFREG | S_IRUGO | S_IWUSR, proc_root_ext3);
++      if (proc_ext3_mb_stats == NULL) {
++              printk(KERN_ERR "EXT3: Unable to create %s\n",
++                              EXT3_MB_STATS_NAME);
++              remove_proc_entry(EXT3_ROOT, proc_root_fs);
++              return -EIO;
++      }
++
++      proc_ext3_mb_stats->data = NULL;
++      proc_ext3_mb_stats->read_proc  = ext3_mb_stats_read;
++      proc_ext3_mb_stats->write_proc = ext3_mb_stats_write;
++
++      /* Initialize EXT3_MAX_TO_SCAN_NAME */
++      proc_ext3_mb_max_to_scan = create_proc_entry(
++                      EXT3_MB_MAX_TO_SCAN_NAME,
++                      S_IFREG | S_IRUGO | S_IWUSR, proc_root_ext3);
++      if (proc_ext3_mb_max_to_scan == NULL) {
++              printk(KERN_ERR "EXT3: Unable to create %s\n",
++                              EXT3_MB_MAX_TO_SCAN_NAME);
++              remove_proc_entry(EXT3_MB_STATS_NAME, proc_root_ext3);
++              remove_proc_entry(EXT3_ROOT, proc_root_fs);
++              return -EIO;
++      }
++
++      proc_ext3_mb_max_to_scan->data = NULL;
++      proc_ext3_mb_max_to_scan->read_proc  = ext3_mb_max_to_scan_read;
++      proc_ext3_mb_max_to_scan->write_proc = ext3_mb_max_to_scan_write;
++
++      /* Initialize EXT3_MIN_TO_SCAN_NAME */
++      proc_ext3_mb_min_to_scan = create_proc_entry(
++                      EXT3_MB_MIN_TO_SCAN_NAME,
++                      S_IFREG | S_IRUGO | S_IWUSR, proc_root_ext3);
++      if (proc_ext3_mb_min_to_scan == NULL) {
++              printk(KERN_ERR "EXT3: Unable to create %s\n",
++                              EXT3_MB_MIN_TO_SCAN_NAME);
++              remove_proc_entry(EXT3_MB_MAX_TO_SCAN_NAME, proc_root_ext3);
++              remove_proc_entry(EXT3_MB_STATS_NAME, proc_root_ext3);
++              remove_proc_entry(EXT3_ROOT, proc_root_fs);
++              return -EIO;
++      }
++
++      proc_ext3_mb_min_to_scan->data = NULL;
++      proc_ext3_mb_min_to_scan->read_proc  = ext3_mb_min_to_scan_read;
++      proc_ext3_mb_min_to_scan->write_proc = ext3_mb_min_to_scan_write;
++
++      return 0;
++}
++
++void exit_ext3_proc(void)
++{
++      remove_proc_entry(EXT3_MB_STATS_NAME, proc_root_ext3);
++      remove_proc_entry(EXT3_MB_MAX_TO_SCAN_NAME, proc_root_ext3);
++      remove_proc_entry(EXT3_MB_MIN_TO_SCAN_NAME, proc_root_ext3);
++      remove_proc_entry(EXT3_ROOT, proc_root_fs);
++}
++
+Index: linux-2.6.16.i686/fs/ext3/extents.c
+===================================================================
+--- linux-2.6.16.i686.orig/fs/ext3/extents.c   2006-05-30 22:55:32.000000000 +0800
++++ linux-2.6.16.i686/fs/ext3/extents.c        2006-05-30 23:02:59.000000000 +0800
+@@ -771,7 +771,7 @@
+               for (i = 0; i < depth; i++) {
+                       if (!ablocks[i])
+                               continue;
+-                      ext3_free_blocks(handle, tree->inode, ablocks[i], 1);
++                      ext3_free_blocks(handle, tree->inode, ablocks[i], 1, 1);
+               }
+       }
+       kfree(ablocks);
+@@ -1428,7 +1428,7 @@
+                 path->p_idx->ei_leaf);
+       bh = sb_find_get_block(tree->inode->i_sb, path->p_idx->ei_leaf);
+       ext3_forget(handle, 1, tree->inode, bh, path->p_idx->ei_leaf);
+-      ext3_free_blocks(handle, tree->inode, path->p_idx->ei_leaf, 1);
++      ext3_free_blocks(handle, tree->inode, path->p_idx->ei_leaf, 1, 1);
+       return err;
+ }
+@@ -1913,10 +1913,12 @@
+       int needed = ext3_remove_blocks_credits(tree, ex, from, to);
+       handle_t *handle = ext3_journal_start(tree->inode, needed);
+       struct buffer_head *bh;
+-      int i;
++      int i, metadata = 0;
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
++      if (S_ISDIR(tree->inode->i_mode) || S_ISLNK(tree->inode->i_mode))
++              metadata = 1;
+       if (from >= ex->ee_block && to == ex->ee_block + ex->ee_len - 1) {
+               /* tail removal */
+               unsigned long num, start;
+@@ -1928,7 +1930,7 @@
+                       bh = sb_find_get_block(tree->inode->i_sb, start + i);
+                       ext3_forget(handle, 0, tree->inode, bh, start + i);
+               }
+-              ext3_free_blocks(handle, tree->inode, start, num);
++              ext3_free_blocks(handle, tree->inode, start, num, metadata);
+       } else if (from == ex->ee_block && to <= ex->ee_block + ex->ee_len - 1) {
+               printk("strange request: removal %lu-%lu from %u:%u\n",
+                      from, to, ex->ee_block, ex->ee_len);
+Index: linux-2.6.16.i686/fs/ext3/xattr.c
+===================================================================
+--- linux-2.6.16.i686.orig/fs/ext3/xattr.c     2006-03-20 13:53:29.000000000 +0800
++++ linux-2.6.16.i686/fs/ext3/xattr.c  2006-05-30 23:02:59.000000000 +0800
+@@ -484,7 +484,7 @@
+               ea_bdebug(bh, "refcount now=0; freeing");
+               if (ce)
+                       mb_cache_entry_free(ce);
+-              ext3_free_blocks(handle, inode, bh->b_blocknr, 1);
++              ext3_free_blocks(handle, inode, bh->b_blocknr, 1, 1);
+               get_bh(bh);
+               ext3_forget(handle, 1, inode, bh, bh->b_blocknr);
+       } else {
+@@ -804,7 +804,7 @@
+                       new_bh = sb_getblk(sb, block);
+                       if (!new_bh) {
+ getblk_failed:
+-                              ext3_free_blocks(handle, inode, block, 1);
++                              ext3_free_blocks(handle, inode, block, 1, 1);
+                               error = -EIO;
+                               goto cleanup;
+                       }
+Index: linux-2.6.16.i686/fs/ext3/balloc.c
+===================================================================
+--- linux-2.6.16.i686.orig/fs/ext3/balloc.c    2006-03-20 13:53:29.000000000 +0800
++++ linux-2.6.16.i686/fs/ext3/balloc.c 2006-05-30 23:02:59.000000000 +0800
+@@ -80,7 +80,7 @@
+  *
+  * Return buffer_head on success or NULL in case of failure.
+  */
+-static struct buffer_head *
++struct buffer_head *
+ read_block_bitmap(struct super_block *sb, unsigned int block_group)
+ {
+       struct ext3_group_desc * desc;
+@@ -491,24 +491,6 @@
+       return;
+ }
+-/* Free given blocks, update quota and i_blocks field */
+-void ext3_free_blocks(handle_t *handle, struct inode *inode,
+-                      unsigned long block, unsigned long count)
+-{
+-      struct super_block * sb;
+-      int dquot_freed_blocks;
+-
+-      sb = inode->i_sb;
+-      if (!sb) {
+-              printk ("ext3_free_blocks: nonexistent device");
+-              return;
+-      }
+-      ext3_free_blocks_sb(handle, sb, block, count, &dquot_freed_blocks);
+-      if (dquot_freed_blocks)
+-              DQUOT_FREE_BLOCK(inode, dquot_freed_blocks);
+-      return;
+-}
+-
+ /*
+  * For ext3 allocations, we must not reuse any blocks which are
+  * allocated in the bitmap buffer's "last committed data" copy.  This
+@@ -1154,7 +1136,7 @@
+  * bitmap, and then for any free bit if that fails.
+  * This function also updates quota and i_blocks field.
+  */
+-int ext3_new_block(handle_t *handle, struct inode *inode,
++int ext3_new_block_old(handle_t *handle, struct inode *inode,
+                       unsigned long goal, int *errp)
+ {
+       struct buffer_head *bitmap_bh = NULL;
+Index: linux-2.6.16.i686/fs/ext3/super.c
+===================================================================
+--- linux-2.6.16.i686.orig/fs/ext3/super.c     2006-05-30 22:55:32.000000000 +0800
++++ linux-2.6.16.i686/fs/ext3/super.c  2006-05-30 23:02:59.000000000 +0800
+@@ -392,6 +392,7 @@
+       struct ext3_super_block *es = sbi->s_es;
+       int i;
++      ext3_mb_release(sb);
+       ext3_ext_release(sb);
+       ext3_xattr_put_super(sb);
+       journal_destroy(sbi->s_journal);
+@@ -640,7 +641,7 @@
+       Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
+       Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
+       Opt_iopen, Opt_noiopen, Opt_iopen_nopriv,
+-      Opt_extents, Opt_extdebug,
++      Opt_extents, Opt_extdebug, Opt_mballoc,
+       Opt_grpquota
+ };
+@@ -694,6 +695,7 @@
+       {Opt_iopen_nopriv, "iopen_nopriv"},
+       {Opt_extents, "extents"},
+       {Opt_extdebug, "extdebug"},
++      {Opt_mballoc, "mballoc"},
+       {Opt_barrier, "barrier=%u"},
+       {Opt_err, NULL},
+       {Opt_resize, "resize"},
+@@ -1041,6 +1043,9 @@
+               case Opt_extdebug:
+                       set_opt (sbi->s_mount_opt, EXTDEBUG);
+                       break;
++              case Opt_mballoc:
++                      set_opt (sbi->s_mount_opt, MBALLOC);
++                      break;
+               default:
+                       printk (KERN_ERR
+                               "EXT3-fs: Unrecognized mount option \"%s\" "
+@@ -1766,6 +1771,7 @@
+               ext3_count_dirs(sb));
+       ext3_ext_init(sb);
++      ext3_mb_init(sb, needs_recovery);
+       lock_kernel();
+       return 0;
+@@ -2699,7 +2705,13 @@
+ static int __init init_ext3_fs(void)
+ {
+-      int err = init_ext3_xattr();
++      int err;
++
++      err = init_ext3_proc();
++      if (err)
++              return err;
++
++      err = init_ext3_xattr();
+       if (err)
+               return err;
+       err = init_inodecache();
+@@ -2721,6 +2733,7 @@
+       unregister_filesystem(&ext3_fs_type);
+       destroy_inodecache();
+       exit_ext3_xattr();
++      exit_ext3_proc();
+ }
+ int ext3_prep_san_write(struct inode *inode, long *blocks,
+Index: linux-2.6.16.i686/fs/ext3/Makefile
+===================================================================
+--- linux-2.6.16.i686.orig/fs/ext3/Makefile    2006-05-30 22:55:32.000000000 +0800
++++ linux-2.6.16.i686/fs/ext3/Makefile 2006-05-30 23:02:59.000000000 +0800
+@@ -6,7 +6,7 @@
+ ext3-y        := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
+          ioctl.o namei.o super.o symlink.o hash.o resize.o \
+-         extents.o
++         extents.o mballoc.o
+ ext3-$(CONFIG_EXT3_FS_XATTR)   += xattr.o xattr_user.o xattr_trusted.o
+ ext3-$(CONFIG_EXT3_FS_POSIX_ACL) += acl.o
+Index: linux-2.6.16.i686/include/linux/ext3_fs.h
+===================================================================
+--- linux-2.6.16.i686.orig/include/linux/ext3_fs.h     2006-05-30 22:55:32.000000000 +0800
++++ linux-2.6.16.i686/include/linux/ext3_fs.h  2006-05-30 23:02:59.000000000 +0800
+@@ -57,6 +57,14 @@
+ #define ext3_debug(f, a...)   do {} while (0)
+ #endif
++#define EXT3_MULTIBLOCK_ALLOCATOR     1
++
++#define EXT3_MB_HINT_MERGE            1
++#define EXT3_MB_HINT_RESERVED         2
++#define EXT3_MB_HINT_METADATA         4
++#define EXT3_MB_HINT_FIRST            8
++#define EXT3_MB_HINT_BEST             16
++
+ /*
+  * Special inodes numbers
+  */
+@@ -383,6 +391,7 @@
+ #define EXT3_MOUNT_IOPEN_NOPRIV               0x800000/* Make iopen world-readable */
+ #define EXT3_MOUNT_EXTENTS            0x1000000/* Extents support */
+ #define EXT3_MOUNT_EXTDEBUG           0x2000000/* Extents debug */
++#define EXT3_MOUNT_MBALLOC            0x800000/* Buddy allocation support */
+ /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
+ #ifndef clear_opt
+@@ -744,7 +753,7 @@
+ extern unsigned long ext3_bg_num_gdb(struct super_block *sb, int group);
+ extern int ext3_new_block (handle_t *, struct inode *, unsigned long, int *);
+ extern void ext3_free_blocks (handle_t *, struct inode *, unsigned long,
+-                            unsigned long);
++                            unsigned long, int);
+ extern void ext3_free_blocks_sb (handle_t *, struct super_block *,
+                                unsigned long, unsigned long, int *);
+ extern unsigned long ext3_count_free_blocks (struct super_block *);
+@@ -865,6 +874,17 @@
+ extern int ext3_ext_ioctl(struct inode *inode, struct file *filp,
+                         unsigned int cmd, unsigned long arg);
++/* mballoc.c */
++extern long ext3_mb_stats;
++extern long ext3_mb_max_to_scan;
++extern int ext3_mb_init(struct super_block *, int);
++extern int ext3_mb_release(struct super_block *);
++extern int ext3_mb_new_blocks(handle_t *, struct inode *, unsigned long, int *, int, int *);
++extern int ext3_mb_reserve_blocks(struct super_block *, int);
++extern void ext3_mb_release_blocks(struct super_block *, int);
++int __init init_ext3_proc(void);
++void exit_ext3_proc(void);
++
+ #endif        /* __KERNEL__ */
+ /* EXT3_IOC_CREATE_INUM at bottom of file (visible to kernel and user). */
+Index: linux-2.6.16.i686/include/linux/ext3_fs_sb.h
+===================================================================
+--- linux-2.6.16.i686.orig/include/linux/ext3_fs_sb.h  2006-03-20 13:53:29.000000000 +0800
++++ linux-2.6.16.i686/include/linux/ext3_fs_sb.h       2006-05-30 23:02:59.000000000 +0800
+@@ -21,8 +21,14 @@
+ #include <linux/wait.h>
+ #include <linux/blockgroup_lock.h>
+ #include <linux/percpu_counter.h>
++#include <linux/list.h>
+ #endif
+ #include <linux/rbtree.h>
++#include <linux/proc_fs.h>
++
++struct ext3_buddy_group_blocks;
++struct ext3_mb_history;
++#define EXT3_BB_MAX_BLOCKS
+ /*
+  * third extended-fs super-block data in memory
+@@ -78,6 +84,38 @@
+       char *s_qf_names[MAXQUOTAS];            /* Names of quota files with journalled quota */
+       int s_jquota_fmt;                       /* Format of quota to use */
+ #endif
++
++      /* for buddy allocator */
++      struct ext3_group_info **s_group_info;
++      struct inode *s_buddy_cache;
++      long s_blocks_reserved;
++      spinlock_t s_reserve_lock;
++      struct list_head s_active_transaction;
++      struct list_head s_closed_transaction;
++      struct list_head s_committed_transaction;
++      spinlock_t s_md_lock;
++      tid_t s_last_transaction;
++      int s_mb_factor;
++      unsigned short *s_mb_offsets, *s_mb_maxs;
++
++      /* history to debug policy */
++      struct ext3_mb_history *s_mb_history;
++      int s_mb_history_cur;
++      int s_mb_history_max;
++      struct proc_dir_entry *s_mb_proc;
++      spinlock_t s_mb_history_lock;
++
++      /* stats for buddy allocator */
++      atomic_t s_bal_reqs;    /* number of reqs with len > 1 */
++      atomic_t s_bal_success; /* we found long enough chunks */
++      atomic_t s_bal_allocated;       /* in blocks */
++      atomic_t s_bal_ex_scanned;      /* total extents scanned */
++      atomic_t s_bal_goals;   /* goal hits */
++      atomic_t s_bal_breaks;  /* too long searches */
++      atomic_t s_bal_2orders; /* 2^order hits */
++      spinlock_t s_bal_lock;
++      unsigned long s_mb_buddies_generated;
++      unsigned long long s_mb_generation_time;
+ };
+ #endif        /* _LINUX_EXT3_FS_SB */
index 2a64875..c77ebdd 100644 (file)
@@ -1,7 +1,7 @@
-Index: linux-2.6.5-7.201/include/linux/ext3_fs.h
+Index: linux-2.6.5-7.252-full/include/linux/ext3_fs.h
 ===================================================================
---- linux-2.6.5-7.201.orig/include/linux/ext3_fs.h     2005-12-17 02:53:30.000000000 +0300
-+++ linux-2.6.5-7.201/include/linux/ext3_fs.h  2005-12-17 03:13:38.000000000 +0300
+--- linux-2.6.5-7.252-full.orig/include/linux/ext3_fs.h        2006-04-25 17:42:19.000000000 +0400
++++ linux-2.6.5-7.252-full/include/linux/ext3_fs.h     2006-04-26 23:40:28.000000000 +0400
 @@ -57,6 +57,14 @@ struct statfs;
  #define ext3_debug(f, a...)   do {} while (0)
  #endif
@@ -31,8 +31,8 @@ Index: linux-2.6.5-7.201/include/linux/ext3_fs.h
  extern void ext3_free_blocks (handle_t *, struct inode *, unsigned long,
 -                            unsigned long);
 +                            unsigned long, int);
-+extern void ext3_free_blocks_old (handle_t *, struct inode *, unsigned long,
-+                                      unsigned long);
++extern void ext3_free_blocks_old(handle_t *, struct inode *, unsigned long,
++                               unsigned long);
  extern unsigned long ext3_count_free_blocks (struct super_block *);
  extern void ext3_check_blocks_bitmap (struct super_block *);
  extern struct ext3_group_desc * ext3_get_group_desc(struct super_block * sb,
@@ -54,10 +54,10 @@ Index: linux-2.6.5-7.201/include/linux/ext3_fs.h
  #endif        /* __KERNEL__ */
  
  #define EXT3_IOC_CREATE_INUM                  _IOW('f', 5, long)
-Index: linux-2.6.5-7.201/include/linux/ext3_fs_sb.h
+Index: linux-2.6.5-7.252-full/include/linux/ext3_fs_sb.h
 ===================================================================
---- linux-2.6.5-7.201.orig/include/linux/ext3_fs_sb.h  2005-12-17 02:53:25.000000000 +0300
-+++ linux-2.6.5-7.201/include/linux/ext3_fs_sb.h       2005-12-17 03:10:23.000000000 +0300
+--- linux-2.6.5-7.252-full.orig/include/linux/ext3_fs_sb.h     2006-04-25 17:42:19.000000000 +0400
++++ linux-2.6.5-7.252-full/include/linux/ext3_fs_sb.h  2006-04-26 23:40:28.000000000 +0400
 @@ -23,9 +23,15 @@
  #define EXT_INCLUDE
  #include <linux/blockgroup_lock.h>
@@ -74,13 +74,13 @@ Index: linux-2.6.5-7.201/include/linux/ext3_fs_sb.h
  
  /*
   * third extended-fs super-block data in memory
-@@ -78,6 +84,38 @@ struct ext3_sb_info {
+@@ -78,6 +84,43 @@ struct ext3_sb_info {
        struct timer_list turn_ro_timer;        /* For turning read-only (crash simulation) */
        wait_queue_head_t ro_wait_queue;        /* For people waiting for the fs to go read-only */
  #endif
 +
 +      /* for buddy allocator */
-+      struct ext3_group_info **s_group_info;
++      struct ext3_group_info ***s_group_info;
 +      struct inode *s_buddy_cache;
 +      long s_blocks_reserved;
 +      spinlock_t s_reserve_lock;
@@ -91,6 +91,7 @@ Index: linux-2.6.5-7.201/include/linux/ext3_fs_sb.h
 +      tid_t s_last_transaction;
 +      int s_mb_factor;
 +      unsigned short *s_mb_offsets, *s_mb_maxs;
++      unsigned long s_stripe;
 +
 +      /* history to debug policy */
 +      struct ext3_mb_history *s_mb_history;
@@ -111,12 +112,16 @@ Index: linux-2.6.5-7.201/include/linux/ext3_fs_sb.h
 +      unsigned long s_mb_buddies_generated;
 +      unsigned long long s_mb_generation_time;
  };
++
++#define EXT3_GROUP_INFO(sb, group)                                       \
++      EXT3_SB(sb)->s_group_info[(group) >> EXT3_DESC_PER_BLOCK_BITS(sb)] \
++                               [(group) & (EXT3_DESC_PER_BLOCK(sb) - 1)]
  
  #endif        /* _LINUX_EXT3_FS_SB */
-Index: linux-2.6.5-7.201/fs/ext3/super.c
+Index: linux-2.6.5-7.252-full/fs/ext3/super.c
 ===================================================================
---- linux-2.6.5-7.201.orig/fs/ext3/super.c     2005-12-17 02:53:30.000000000 +0300
-+++ linux-2.6.5-7.201/fs/ext3/super.c  2005-12-17 03:10:23.000000000 +0300
+--- linux-2.6.5-7.252-full.orig/fs/ext3/super.c        2006-04-25 17:42:19.000000000 +0400
++++ linux-2.6.5-7.252-full/fs/ext3/super.c     2006-04-26 23:40:28.000000000 +0400
 @@ -389,6 +389,7 @@ void ext3_put_super (struct super_block 
        struct ext3_super_block *es = sbi->s_es;
        int i;
@@ -125,34 +130,45 @@ Index: linux-2.6.5-7.201/fs/ext3/super.c
        ext3_ext_release(sb);
        ext3_xattr_put_super(sb);
        journal_destroy(sbi->s_journal);
-@@ -543,7 +544,7 @@ enum {
-       Opt_ignore, Opt_barrier,
+@@ -545,6 +546,7 @@ enum {
        Opt_err,
        Opt_iopen, Opt_noiopen, Opt_iopen_nopriv,
--      Opt_extents, Opt_extdebug,
-+      Opt_extents, Opt_extdebug, Opt_mballoc,
+       Opt_extents, Opt_noextents, Opt_extdebug,
++      Opt_mballoc, Opt_nomballoc, Opt_stripe,
  };
  
  static match_table_t tokens = {
-@@ -590,6 +591,7 @@ static match_table_t tokens = {
-       {Opt_iopen_nopriv, "iopen_nopriv"},
+@@ -591,6 +592,9 @@ static match_table_t tokens = {
        {Opt_extents, "extents"},
+       {Opt_noextents, "noextents"},
        {Opt_extdebug, "extdebug"},
 +      {Opt_mballoc, "mballoc"},
++      {Opt_nomballoc, "nomballoc"},
++      {Opt_stripe, "stripe=%u"},
        {Opt_barrier, "barrier=%u"},
        {Opt_err, NULL}
  };
-@@ -811,6 +813,9 @@ static int parse_options (char * options
+@@ -813,6 +815,19 @@ static int parse_options (char * options
                case Opt_extdebug:
                        set_opt (sbi->s_mount_opt, EXTDEBUG);
                        break;
 +              case Opt_mballoc:
-+                      set_opt (sbi->s_mount_opt, MBALLOC);
++                      set_opt(sbi->s_mount_opt, MBALLOC);
++                      break;
++              case Opt_nomballoc:
++                      clear_opt(sbi->s_mount_opt, MBALLOC);
++                      break;
++              case Opt_stripe:
++                      if (match_int(&args[0], &option))
++                              return 0;
++                      if (option < 0)
++                              return 0;
++                      sbi->s_stripe = option;
 +                      break;
                default:
                        printk (KERN_ERR
                                "EXT3-fs: Unrecognized mount option \"%s\" "
-@@ -1464,6 +1469,7 @@ static int ext3_fill_super (struct super
+@@ -1466,6 +1471,7 @@ static int ext3_fill_super (struct super
                ext3_count_dirs(sb));
  
        ext3_ext_init(sb);
@@ -160,7 +176,7 @@ Index: linux-2.6.5-7.201/fs/ext3/super.c
  
        return 0;
  
-@@ -2112,7 +2118,13 @@ static struct file_system_type ext3_fs_t
+@@ -2114,7 +2120,13 @@ static struct file_system_type ext3_fs_t
  
  static int __init init_ext3_fs(void)
  {
@@ -175,7 +191,7 @@ Index: linux-2.6.5-7.201/fs/ext3/super.c
        if (err)
                return err;
        err = init_inodecache();
-@@ -2141,6 +2153,7 @@ static void __exit exit_ext3_fs(void)
+@@ -2143,6 +2155,7 @@ static void __exit exit_ext3_fs(void)
        unregister_filesystem(&ext3_fs_type);
        destroy_inodecache();
        exit_ext3_xattr();
@@ -183,11 +199,11 @@ Index: linux-2.6.5-7.201/fs/ext3/super.c
  }
  
  int ext3_prep_san_write(struct inode *inode, long *blocks,
-Index: linux-2.6.5-7.201/fs/ext3/extents.c
+Index: linux-2.6.5-7.252-full/fs/ext3/extents.c
 ===================================================================
---- linux-2.6.5-7.201.orig/fs/ext3/extents.c   2005-12-17 02:53:29.000000000 +0300
-+++ linux-2.6.5-7.201/fs/ext3/extents.c        2005-12-17 03:10:23.000000000 +0300
-@@ -771,7 +771,7 @@ cleanup:
+--- linux-2.6.5-7.252-full.orig/fs/ext3/extents.c      2006-04-25 17:42:19.000000000 +0400
++++ linux-2.6.5-7.252-full/fs/ext3/extents.c   2006-04-26 23:40:28.000000000 +0400
+@@ -777,7 +777,7 @@ cleanup:
                for (i = 0; i < depth; i++) {
                        if (!ablocks[i])
                                continue;
@@ -196,7 +212,7 @@ Index: linux-2.6.5-7.201/fs/ext3/extents.c
                }
        }
        kfree(ablocks);
-@@ -1428,7 +1428,7 @@ int ext3_ext_rm_idx(handle_t *handle, st
+@@ -1434,7 +1434,7 @@ int ext3_ext_rm_idx(handle_t *handle, st
                  path->p_idx->ei_leaf);
        bh = sb_find_get_block(tree->inode->i_sb, path->p_idx->ei_leaf);
        ext3_forget(handle, 1, tree->inode, bh, path->p_idx->ei_leaf);
@@ -205,7 +221,7 @@ Index: linux-2.6.5-7.201/fs/ext3/extents.c
        return err;
  }
  
-@@ -1913,10 +1913,12 @@ ext3_remove_blocks(struct ext3_extents_t
+@@ -1919,10 +1919,12 @@ ext3_remove_blocks(struct ext3_extents_t
        int needed = ext3_remove_blocks_credits(tree, ex, from, to);
        handle_t *handle = ext3_journal_start(tree->inode, needed);
        struct buffer_head *bh;
@@ -219,7 +235,7 @@ Index: linux-2.6.5-7.201/fs/ext3/extents.c
        if (from >= ex->ee_block && to == ex->ee_block + ex->ee_len - 1) {
                /* tail removal */
                unsigned long num, start;
-@@ -1928,7 +1930,7 @@ ext3_remove_blocks(struct ext3_extents_t
+@@ -1934,7 +1936,7 @@ ext3_remove_blocks(struct ext3_extents_t
                        bh = sb_find_get_block(tree->inode->i_sb, start + i);
                        ext3_forget(handle, 0, tree->inode, bh, start + i);
                }
@@ -228,11 +244,11 @@ Index: linux-2.6.5-7.201/fs/ext3/extents.c
        } else if (from == ex->ee_block && to <= ex->ee_block + ex->ee_len - 1) {
                printk("strange request: removal %lu-%lu from %u:%u\n",
                       from, to, ex->ee_block, ex->ee_len);
-Index: linux-2.6.5-7.201/fs/ext3/inode.c
+Index: linux-2.6.5-7.252-full/fs/ext3/inode.c
 ===================================================================
---- linux-2.6.5-7.201.orig/fs/ext3/inode.c     2005-12-17 02:53:30.000000000 +0300
-+++ linux-2.6.5-7.201/fs/ext3/inode.c  2005-12-17 03:10:23.000000000 +0300
-@@ -572,7 +572,7 @@ static int ext3_alloc_branch(handle_t *h
+--- linux-2.6.5-7.252-full.orig/fs/ext3/inode.c        2006-04-25 17:42:19.000000000 +0400
++++ linux-2.6.5-7.252-full/fs/ext3/inode.c     2006-04-26 23:40:28.000000000 +0400
+@@ -574,7 +574,7 @@ static int ext3_alloc_branch(handle_t *h
                ext3_journal_forget(handle, branch[i].bh);
        }
        for (i = 0; i < keys; i++)
@@ -241,7 +257,7 @@ Index: linux-2.6.5-7.201/fs/ext3/inode.c
        return err;
  }
  
-@@ -673,7 +673,7 @@ err_out:
+@@ -675,7 +675,7 @@ err_out:
        if (err == -EAGAIN)
                for (i = 0; i < num; i++)
                        ext3_free_blocks(handle, inode, 
@@ -250,7 +266,7 @@ Index: linux-2.6.5-7.201/fs/ext3/inode.c
        return err;
  }
  
-@@ -1835,7 +1835,7 @@ ext3_clear_blocks(handle_t *handle, stru
+@@ -1837,7 +1837,7 @@ ext3_clear_blocks(handle_t *handle, stru
                }
        }
  
@@ -259,7 +275,7 @@ Index: linux-2.6.5-7.201/fs/ext3/inode.c
  }
  
  /**
-@@ -2006,7 +2006,7 @@ static void ext3_free_branches(handle_t 
+@@ -2008,7 +2008,7 @@ static void ext3_free_branches(handle_t 
                                ext3_journal_test_restart(handle, inode);
                        }
  
@@ -268,10 +284,10 @@ Index: linux-2.6.5-7.201/fs/ext3/inode.c
  
                        if (parent_bh) {
                                /*
-Index: linux-2.6.5-7.201/fs/ext3/balloc.c
+Index: linux-2.6.5-7.252-full/fs/ext3/balloc.c
 ===================================================================
---- linux-2.6.5-7.201.orig/fs/ext3/balloc.c    2005-10-11 00:12:45.000000000 +0400
-+++ linux-2.6.5-7.201/fs/ext3/balloc.c 2005-12-17 03:10:23.000000000 +0300
+--- linux-2.6.5-7.252-full.orig/fs/ext3/balloc.c       2006-02-14 15:26:58.000000000 +0300
++++ linux-2.6.5-7.252-full/fs/ext3/balloc.c    2006-04-26 23:40:28.000000000 +0400
 @@ -78,7 +78,7 @@ struct ext3_group_desc * ext3_get_group_
   *
   * Return buffer_head on success or NULL in case of failure.
@@ -299,10 +315,10 @@ Index: linux-2.6.5-7.201/fs/ext3/balloc.c
                        unsigned long goal, int *errp)
  {
        struct buffer_head *bitmap_bh = NULL;
-Index: linux-2.6.5-7.201/fs/ext3/xattr.c
+Index: linux-2.6.5-7.252-full/fs/ext3/xattr.c
 ===================================================================
---- linux-2.6.5-7.201.orig/fs/ext3/xattr.c     2005-12-17 02:53:26.000000000 +0300
-+++ linux-2.6.5-7.201/fs/ext3/xattr.c  2005-12-17 03:10:41.000000000 +0300
+--- linux-2.6.5-7.252-full.orig/fs/ext3/xattr.c        2006-04-25 17:42:19.000000000 +0400
++++ linux-2.6.5-7.252-full/fs/ext3/xattr.c     2006-04-26 23:40:28.000000000 +0400
 @@ -1371,7 +1371,7 @@ ext3_xattr_set_handle2(handle_t *handle,
                        new_bh = sb_getblk(sb, block);
                        if (!new_bh) {
@@ -330,11 +346,11 @@ Index: linux-2.6.5-7.201/fs/ext3/xattr.c
                get_bh(bh);
                ext3_forget(handle, 1, inode, bh, EXT3_I(inode)->i_file_acl);
        } else {
-Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
+Index: linux-2.6.5-7.252-full/fs/ext3/mballoc.c
 ===================================================================
---- linux-2.6.5-7.201.orig/fs/ext3/mballoc.c   2005-12-09 13:08:53.191437750 +0300
-+++ linux-2.6.5-7.201/fs/ext3/mballoc.c        2005-12-17 03:15:04.000000000 +0300
-@@ -0,0 +1,2430 @@
+--- linux-2.6.5-7.252-full.orig/fs/ext3/mballoc.c      2006-04-22 17:31:47.543334750 +0400
++++ linux-2.6.5-7.252-full/fs/ext3/mballoc.c   2006-04-26 23:42:45.000000000 +0400
+@@ -0,0 +1,2702 @@
 +/*
 + * Copyright (c) 2003-2005, Cluster File Systems, Inc, info@clusterfs.com
 + * Written by Alex Tomas <alex@clusterfs.com>
@@ -423,6 +439,12 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +
 +long ext3_mb_stats = 1;
 +
++/*
++ * for which requests use 2^N search using buddies
++ */
++long ext3_mb_order2_reqs = 8;
++
++
 +#ifdef EXT3_BB_MAX_BLOCKS
 +#undef EXT3_BB_MAX_BLOCKS
 +#endif
@@ -463,10 +485,10 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +
 +      /* search goals */
 +      struct ext3_free_extent ac_g_ex;
-+      
++
 +      /* the best found extent */
 +      struct ext3_free_extent ac_b_ex;
-+      
++
 +      /* number of iterations done. we have to track to limit searching */
 +      unsigned long ac_ex_scanned;
 +      __u16 ac_groups_scanned;
@@ -488,6 +510,8 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +struct ext3_mb_history {
 +      struct ext3_free_extent goal;   /* goal allocation */
 +      struct ext3_free_extent result; /* result allocation */
++      unsigned pid;
++      unsigned ino;
 +      __u16 found;    /* how many extents have been found */
 +      __u16 groups;   /* how many groups have been scanned */
 +      __u16 tail;     /* what tail broke some buddy */
@@ -510,9 +534,9 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +#define EXT3_MB_BUDDY(e3b)    ((e3b)->bd_buddy)
 +
 +#ifndef EXT3_MB_HISTORY
-+#define ext3_mb_store_history(sb,ac)
++#define ext3_mb_store_history(sb,ino,ac)
 +#else
-+static void ext3_mb_store_history(struct super_block *,
++static void ext3_mb_store_history(struct super_block *, unsigned ino,
 +                              struct ext3_allocation_context *ac);
 +#endif
 +
@@ -631,7 +655,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +              if (mb_check_counter++ % 300 != 0)
 +                      return;
 +      }
-+      
++
 +      while (order > 1) {
 +              buddy = mb_find_buddy(e3b, order, &max);
 +              J_ASSERT(buddy);
@@ -812,7 +836,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      sb = inode->i_sb;
 +      blocksize = 1 << inode->i_blkbits;
 +      blocks_per_page = PAGE_CACHE_SIZE / blocksize;
-+      
++
 +      groups_per_page = blocks_per_page >> 1;
 +      if (groups_per_page == 0)
 +              groups_per_page = 1;
@@ -827,9 +851,9 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +              memset(bh, 0, i);
 +      } else
 +              bh = &bhs;
-+      
++
 +      first_group = page->index * blocks_per_page / 2;
-+      
++
 +      /* read all groups the page covers into the cache */
 +      for (i = 0; i < groups_per_page; i++) {
 +              struct ext3_group_desc * desc;
@@ -884,11 +908,11 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +                      mb_debug("put buddy for group %u in page %lu/%x\n",
 +                              group, page->index, i * blocksize);
 +                      memset(data, 0xff, blocksize);
-+                      EXT3_SB(sb)->s_group_info[group]->bb_fragments = 0;
-+                      memset(EXT3_SB(sb)->s_group_info[group]->bb_counters, 0,
++                      EXT3_GROUP_INFO(sb, group)->bb_fragments = 0;
++                      memset(EXT3_GROUP_INFO(sb, group)->bb_counters, 0,
 +                              sizeof(unsigned short)*(sb->s_blocksize_bits+2));
 +                      ext3_mb_generate_buddy(sb, data, bitmap,
-+                                              EXT3_SB(sb)->s_group_info[group]);
++                                              EXT3_GROUP_INFO(sb, group));
 +              } else {
 +                      /* this is block of bitmap */
 +                      mb_debug("put bitmap for group %u in page %lu/%x\n",
@@ -921,7 +945,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      blocks_per_page = PAGE_CACHE_SIZE / sb->s_blocksize;
 +
 +      e3b->bd_blkbits = sb->s_blocksize_bits;
-+      e3b->bd_info = sbi->s_group_info[group];
++      e3b->bd_info = EXT3_GROUP_INFO(sb, group);
 +      e3b->bd_sb = sb;
 +      e3b->bd_group = group;
 +      e3b->bd_buddy_page = NULL;
@@ -997,14 +1021,14 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +ext3_lock_group(struct super_block *sb, int group)
 +{
 +      bit_spin_lock(EXT3_GROUP_INFO_LOCKED_BIT,
-+                      &EXT3_SB(sb)->s_group_info[group]->bb_state);
++                    &EXT3_GROUP_INFO(sb, group)->bb_state);
 +}
 +
 +static inline void
 +ext3_unlock_group(struct super_block *sb, int group)
 +{
 +      bit_spin_unlock(EXT3_GROUP_INFO_LOCKED_BIT,
-+                      &EXT3_SB(sb)->s_group_info[group]->bb_state);
++                      &EXT3_GROUP_INFO(sb, group)->bb_state);
 +}
 +
 +static int mb_find_order_for_block(struct ext3_buddy *e3b, int block)
@@ -1134,7 +1158,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +static int mb_find_extent(struct ext3_buddy *e3b, int order, int block,
 +                              int needed, struct ext3_free_extent *ex)
 +{
-+      int next, max, ord;
++      int next = block, max, ord;
 +      void *buddy;
 +
 +      J_ASSERT(ex != NULL);
@@ -1159,6 +1183,11 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      ex->fe_start = block << order;
 +      ex->fe_group = e3b->bd_group;
 +
++      /* calc difference from given start */
++      next = next - ex->fe_start;
++      ex->fe_len -= next;
++      ex->fe_start += next;
++
 +      while (needed > ex->fe_len && (buddy = mb_find_buddy(e3b, order, &max))) {
 +
 +              if (block + 1 >= max)
@@ -1354,7 +1383,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +
 +      ext3_lock_group(ac->ac_sb, group);
 +      max = mb_find_extent(e3b, 0, ex.fe_start, ex.fe_len, &ex);
-+      
++
 +      if (max > 0) {
 +              ac->ac_b_ex = ex;
 +              ext3_mb_use_best_found(ac, e3b);
@@ -1371,6 +1400,8 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +                              struct ext3_buddy *e3b)
 +{
 +      int group = ac->ac_g_ex.fe_group, max, err;
++      struct ext3_sb_info *sbi = EXT3_SB(ac->ac_sb);
++      struct ext3_super_block *es = sbi->s_es;
 +      struct ext3_free_extent ex;
 +
 +      err = ext3_mb_load_buddy(ac->ac_sb, group, e3b);
@@ -1379,9 +1410,27 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +
 +      ext3_lock_group(ac->ac_sb, group);
 +      max = mb_find_extent(e3b, 0, ac->ac_g_ex.fe_start,
-+                              ac->ac_g_ex.fe_len, &ex);
-+      
-+      if (max > 0) {
++                           ac->ac_g_ex.fe_len, &ex);
++
++      if (max >= ac->ac_g_ex.fe_len && ac->ac_g_ex.fe_len == sbi->s_stripe) {
++              unsigned long start;
++              start = (e3b->bd_group * EXT3_BLOCKS_PER_GROUP(ac->ac_sb) +
++                      ex.fe_start + le32_to_cpu(es->s_first_data_block));
++              if (start % sbi->s_stripe == 0) {
++                      ac->ac_found++;
++                      ac->ac_b_ex = ex;
++                      ext3_mb_use_best_found(ac, e3b);
++              }
++      } else if (max >= ac->ac_g_ex.fe_len) {
++              J_ASSERT(ex.fe_len > 0);
++              J_ASSERT(ex.fe_group == ac->ac_g_ex.fe_group);
++              J_ASSERT(ex.fe_start == ac->ac_g_ex.fe_start);
++              ac->ac_found++;
++              ac->ac_b_ex = ex;
++              ext3_mb_use_best_found(ac, e3b);
++      } else if (max > 0 && (ac->ac_flags & EXT3_MB_HINT_MERGE)) {
++              /* Sometimes, caller may want to merge even small
++               * number of blocks to an existing extent */
 +              J_ASSERT(ex.fe_len > 0);
 +              J_ASSERT(ex.fe_group == ac->ac_g_ex.fe_group);
 +              J_ASSERT(ex.fe_start == ac->ac_g_ex.fe_start);
@@ -1409,7 +1458,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      int i, k, max;
 +
 +      J_ASSERT(ac->ac_2order > 0);
-+      for (i = ac->ac_2order; i < sb->s_blocksize_bits + 1; i++) {
++      for (i = ac->ac_2order; i <= sb->s_blocksize_bits + 1; i++) {
 +              if (grp->bb_counters[i] == 0)
 +                      continue;
 +
@@ -1474,11 +1523,46 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      }
 +}
 +
++/*
++ * This is a special case for storages like raid5
++ * we try to find stripe-aligned chunks for stripe-size requests
++ */
++static void ext3_mb_scan_aligned(struct ext3_allocation_context *ac,
++                               struct ext3_buddy *e3b)
++{
++      struct super_block *sb = ac->ac_sb;
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      void *bitmap = EXT3_MB_BITMAP(e3b);
++      struct ext3_free_extent ex;
++      unsigned long i, max;
++
++      J_ASSERT(sbi->s_stripe != 0);
++
++      /* find first stripe-aligned block */
++      i = e3b->bd_group * EXT3_BLOCKS_PER_GROUP(sb)
++              + le32_to_cpu(sbi->s_es->s_first_data_block);
++      i = ((i + sbi->s_stripe - 1) / sbi->s_stripe) * sbi->s_stripe;
++      i = (i - le32_to_cpu(sbi->s_es->s_first_data_block))
++                      % EXT3_BLOCKS_PER_GROUP(sb);
++
++      while (i < sb->s_blocksize * 8) {
++              if (!mb_test_bit(i, bitmap)) {
++                      max = mb_find_extent(e3b, 0, i, sbi->s_stripe, &ex);
++                      if (max >= sbi->s_stripe) {
++                              ac->ac_found++;
++                              ac->ac_b_ex = ex;
++                              ext3_mb_use_best_found(ac, e3b);
++                              break;
++                      }
++              }
++              i += sbi->s_stripe;
++      }
++}
++
 +static int ext3_mb_good_group(struct ext3_allocation_context *ac,
 +                              int group, int cr)
 +{
-+      struct ext3_sb_info *sbi = EXT3_SB(ac->ac_sb);
-+      struct ext3_group_info *grp = sbi->s_group_info[group];
++      struct ext3_group_info *grp = EXT3_GROUP_INFO(ac->ac_sb, group);
 +      unsigned free, fragments, i, bits;
 +
 +      J_ASSERT(cr >= 0 && cr < 4);
@@ -1495,15 +1579,18 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +              case 0:
 +                      J_ASSERT(ac->ac_2order != 0);
 +                      bits = ac->ac_sb->s_blocksize_bits + 1;
-+                      for (i = ac->ac_2order; i < bits; i++)
++                      for (i = ac->ac_2order; i <= bits; i++)
 +                              if (grp->bb_counters[i] > 0)
 +                                      return 1;
++                      break;
 +              case 1:
 +                      if ((free / fragments) >= ac->ac_g_ex.fe_len)
 +                              return 1;
++                      break;
 +              case 2:
 +                      if (free >= ac->ac_g_ex.fe_len)
 +                              return 1;
++                      break;
 +              case 3:
 +                      return 1;
 +              default:
@@ -1604,23 +1691,27 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      ac.ac_2order = 0;
 +      ac.ac_criteria = 0;
 +
++      if (*len == 1 && sbi->s_stripe) {
++              /* looks like a metadata, let's use a dirty hack for raid5
++               * move all metadata in first groups in hope to hit cached
++               * sectors and thus avoid read-modify cycles in raid5 */
++              ac.ac_g_ex.fe_group = group = 0;
++      }
++
 +      /* probably, the request is for 2^8+ blocks (1/2/3/... MB) */
 +      i = ffs(*len);
-+      if (i >= 8) {
++      if (i >= ext3_mb_order2_reqs) {
 +              i--;
 +              if ((*len & (~(1 << i))) == 0)
 +                      ac.ac_2order = i;
 +      }
 +
-+      /* Sometimes, caller may want to merge even small
-+       * number of blocks to an existing extent */
-+      if (ac.ac_flags & EXT3_MB_HINT_MERGE) {
-+              err = ext3_mb_find_by_goal(&ac, &e3b);
-+              if (err)
-+                      goto out_err;
-+              if (ac.ac_status == AC_STATUS_FOUND)
-+                      goto found;
-+      }
++      /* first, try the goal */
++      err = ext3_mb_find_by_goal(&ac, &e3b);
++      if (err)
++              goto out_err;
++      if (ac.ac_status == AC_STATUS_FOUND)
++              goto found;
 +
 +      /* Let's just scan groups to find more-less suitable blocks */
 +      cr = ac.ac_2order ? 0 : 1;
@@ -1631,7 +1722,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +                      if (group == EXT3_SB(sb)->s_groups_count)
 +                              group = 0;
 +
-+                      if (EXT3_MB_GRP_NEED_INIT(sbi->s_group_info[group])) {
++                      if (EXT3_MB_GRP_NEED_INIT(EXT3_GROUP_INFO(sb, group))) {
 +                              /* we need full data about the group
 +                               * to make a good selection */
 +                              err = ext3_mb_load_buddy(ac.ac_sb, group, &e3b);
@@ -1659,6 +1750,8 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +                      ac.ac_groups_scanned++;
 +                      if (cr == 0)
 +                              ext3_mb_simple_scan_group(&ac, &e3b);
++                      else if (cr == 1 && *len == sbi->s_stripe) 
++                              ext3_mb_scan_aligned(&ac, &e3b);
 +                      else
 +                              ext3_mb_complex_scan_group(&ac, &e3b);
 +
@@ -1672,7 +1765,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      }
 +
 +      if (ac.ac_b_ex.fe_len > 0 && ac.ac_status != AC_STATUS_FOUND &&
-+                      !(ac.ac_flags & EXT3_MB_HINT_FIRST)) {
++          !(ac.ac_flags & EXT3_MB_HINT_FIRST)) {
 +              /*
 +               * We've been searching too long. Let's try to allocate
 +               * the best chunk we've found so far
@@ -1717,8 +1810,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +                      sbi->s_blocks_reserved, ac.ac_found);
 +              printk("EXT3-fs: groups: ");
 +              for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++)
-+                      printk("%d: %d ", i,
-+                              sbi->s_group_info[i]->bb_free);
++                      printk("%d: %d ", i, EXT3_GROUP_INFO(sb, i)->bb_free);
 +              printk("\n");
 +#endif
 +              goto out;
@@ -1756,7 +1848,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +              *errp = -EIO;
 +              goto out_err;
 +      }
-+      
++
 +      err = ext3_journal_get_write_access(handle, gdp_bh);
 +      if (err)
 +              goto out_err;
@@ -1825,7 +1917,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +               * path only, here is single block always */
 +              ext3_mb_release_blocks(sb, 1);
 +      }
-+      
++
 +      if (unlikely(ext3_mb_stats) && ac.ac_g_ex.fe_len > 1) {
 +              atomic_inc(&sbi->s_bal_reqs);
 +              atomic_add(*len, &sbi->s_bal_allocated);
@@ -1839,7 +1931,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +                      atomic_inc(&sbi->s_bal_breaks);
 +      }
 +
-+      ext3_mb_store_history(sb, &ac);
++      ext3_mb_store_history(sb, inode->i_ino, &ac);
 +
 +      return block;
 +}
@@ -1904,9 +1996,9 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      char buf[20], buf2[20];
 +
 +      if (v == SEQ_START_TOKEN) {
-+              seq_printf(seq, "%-17s %-17s %-5s %-5s %-2s %-5s %-5s %-6s\n",
-+                       "goal", "result", "found", "grps", "cr", "merge",
-+                       "tail", "broken");
++              seq_printf(seq, "%-5s %-8s %-17s %-17s %-5s %-5s %-2s %-5s %-5s %-6s\n",
++                       "pid", "inode", "goal", "result", "found", "grps", "cr",
++                       "merge", "tail", "broken");
 +              return 0;
 +      }
 +
@@ -1914,9 +2006,9 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +              hs->goal.fe_start, hs->goal.fe_len);
 +      sprintf(buf2, "%u/%u/%u", hs->result.fe_group,
 +              hs->result.fe_start, hs->result.fe_len);
-+      seq_printf(seq, "%-17s %-17s %-5u %-5u %-2u %-5s %-5u %-6u\n", buf,
-+                      buf2, hs->found, hs->groups, hs->cr, 
-+                      hs->merged ? "M" : "", hs->tail,
++      seq_printf(seq, "%-5u %-8u %-17s %-17s %-5u %-5u %-2u %-5s %-5u %-6u\n",
++                      hs->pid, hs->ino, buf, buf2, hs->found, hs->groups,
++                      hs->cr, hs->merged ? "M" : "", hs->tail,
 +                      hs->buddy ? 1 << hs->buddy : 0);
 +      return 0;
 +}
@@ -1950,7 +2042,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      s->max = sbi->s_mb_history_max;
 +      s->start = sbi->s_mb_history_cur % s->max;
 +      spin_unlock(&sbi->s_mb_history_lock);
-+      
++
 +      rc = seq_open(file, &ext3_mb_seq_history_ops);
 +      if (rc == 0) {
 +              struct seq_file *m = (struct seq_file *)file->private_data;
@@ -1974,10 +2066,104 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +
 +static struct file_operations ext3_mb_seq_history_fops = {
 +      .owner          = THIS_MODULE,
-+      .open           = ext3_mb_seq_history_open,
-+      .read           = seq_read,
-+      .llseek         = seq_lseek,
-+      .release        = ext3_mb_seq_history_release,
++      .open           = ext3_mb_seq_history_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = ext3_mb_seq_history_release,
++};
++
++static void *ext3_mb_seq_groups_start(struct seq_file *seq, loff_t *pos)
++{
++      struct super_block *sb = seq->private;
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      long group;
++
++      if (*pos < 0 || *pos >= sbi->s_groups_count)
++              return NULL;
++
++      group = *pos + 1;
++      return (void *) group;
++}
++
++static void *ext3_mb_seq_groups_next(struct seq_file *seq, void *v, loff_t *pos)
++{
++      struct super_block *sb = seq->private;
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      long group;
++
++      ++*pos;
++      if (*pos < 0 || *pos >= sbi->s_groups_count)
++              return NULL;
++      group = *pos + 1;
++      return (void *) group;;
++}
++
++static int ext3_mb_seq_groups_show(struct seq_file *seq, void *v)
++{
++      struct super_block *sb = seq->private;
++      long group = (long) v, i;
++      struct sg {
++              struct ext3_group_info info;
++              unsigned short counters[16];
++      } sg;
++
++      group--;
++      if (group == 0)
++              seq_printf(seq, "#%-5s: %-5s %-5s %-5s [ %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s ]\n",
++                       "group", "free", "frags", "first", "2^0", "2^1", "2^2", 
++                       "2^3", "2^4", "2^5", "2^6", "2^7", "2^8", "2^9", "2^10",
++                       "2^11", "2^12", "2^13");
++
++      i = (sb->s_blocksize_bits + 2) * sizeof(sg.info.bb_counters[0]) +
++              sizeof(struct ext3_group_info);
++      ext3_lock_group(sb, group);
++      memcpy(&sg, EXT3_GROUP_INFO(sb, group), i);
++      ext3_unlock_group(sb, group);
++
++      if (EXT3_MB_GRP_NEED_INIT(&sg.info))
++              return 0;
++
++      seq_printf(seq, "#%-5lu: %-5u %-5u %-5u [", group, sg.info.bb_free,
++                      sg.info.bb_fragments, sg.info.bb_first_free);
++      for (i = 0; i <= 13; i++)
++              seq_printf(seq, " %-5u", i <= sb->s_blocksize_bits + 1 ?
++                              sg.info.bb_counters[i] : 0);
++      seq_printf(seq, " ]\n");
++
++      return 0;
++}
++
++static void ext3_mb_seq_groups_stop(struct seq_file *seq, void *v)
++{
++}
++
++static struct seq_operations ext3_mb_seq_groups_ops = {
++      .start  = ext3_mb_seq_groups_start,
++      .next   = ext3_mb_seq_groups_next,
++      .stop   = ext3_mb_seq_groups_stop,
++      .show   = ext3_mb_seq_groups_show,
++};
++
++static int ext3_mb_seq_groups_open(struct inode *inode, struct file *file)
++{
++      struct super_block *sb = PDE(inode)->data;
++      int rc;
++
++      rc = seq_open(file, &ext3_mb_seq_groups_ops);
++      if (rc == 0) {
++              struct seq_file *m = (struct seq_file *)file->private_data;
++              m->private = sb;
++      }
++      return rc;
++
++}
++
++static struct file_operations ext3_mb_seq_groups_fops = {
++      .owner          = THIS_MODULE,
++      .open           = ext3_mb_seq_groups_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = seq_release,
 +};
 +
 +static void ext3_mb_history_release(struct super_block *sb)
@@ -1986,6 +2172,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      char name[64];
 +
 +      snprintf(name, sizeof(name) - 1, "%s", bdevname(sb->s_bdev, name));
++      remove_proc_entry("mb_groups", sbi->s_mb_proc);
 +      remove_proc_entry("mb_history", sbi->s_mb_proc);
 +      remove_proc_entry(name, proc_root_ext3);
 +
@@ -2008,6 +2195,11 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +                      p->proc_fops = &ext3_mb_seq_history_fops;
 +                      p->data = sb;
 +              }
++              p = create_proc_entry("mb_groups", S_IRUGO, sbi->s_mb_proc);
++              if (p) {
++                      p->proc_fops = &ext3_mb_seq_groups_fops;
++                      p->data = sb;
++              }
 +      }
 +
 +      sbi->s_mb_history_max = 1000;
@@ -2020,7 +2212,8 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +}
 +
 +static void
-+ext3_mb_store_history(struct super_block *sb, struct ext3_allocation_context *ac)
++ext3_mb_store_history(struct super_block *sb, unsigned ino,
++                      struct ext3_allocation_context *ac)
 +{
 +      struct ext3_sb_info *sbi = EXT3_SB(sb);
 +      struct ext3_mb_history h;
@@ -2028,6 +2221,8 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      if (likely(sbi->s_mb_history == NULL))
 +              return;
 +
++      h.pid = current->pid;
++      h.ino = ino;
 +      h.goal = ac->ac_g_ex;
 +      h.result = ac->ac_b_ex;
 +      h.found = ac->ac_found;
@@ -2055,21 +2250,40 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +int ext3_mb_init_backend(struct super_block *sb)
 +{
 +      struct ext3_sb_info *sbi = EXT3_SB(sb);
-+      int i, len;
-+
-+      len = sizeof(struct ext3_buddy_group_blocks *) * sbi->s_groups_count;
-+      sbi->s_group_info = kmalloc(len, GFP_KERNEL);
++      int i, j, len, metalen;
++      int num_meta_group_infos =
++              (sbi->s_groups_count + EXT3_DESC_PER_BLOCK(sb) - 1) >>
++                      EXT3_DESC_PER_BLOCK_BITS(sb);
++      struct ext3_group_info **meta_group_info;
++
++      /* An 8TB filesystem with 64-bit pointers requires a 4096 byte
++       * kmalloc. A 128kb malloc should suffice for a 256TB filesystem.
++       * So a two level scheme suffices for now. */
++      sbi->s_group_info = kmalloc(sizeof(*sbi->s_group_info) *
++                                  num_meta_group_infos, GFP_KERNEL);
 +      if (sbi->s_group_info == NULL) {
-+              printk(KERN_ERR "EXT3-fs: can't allocate mem for buddy\n");
++              printk(KERN_ERR "EXT3-fs: can't allocate buddy meta group\n");
 +              return -ENOMEM;
 +      }
-+      memset(sbi->s_group_info, 0, len);
-+
 +      sbi->s_buddy_cache = new_inode(sb);
 +      if (sbi->s_buddy_cache == NULL) {
 +              printk(KERN_ERR "EXT3-fs: can't get new inode\n");
-+              kfree(sbi->s_group_info);
-+              return -ENOMEM;
++              goto err_freesgi;
++      }
++
++      metalen = sizeof(*meta_group_info) << EXT3_DESC_PER_BLOCK_BITS(sb);
++      for (i = 0; i < num_meta_group_infos; i++) {
++              if ((i + 1) == num_meta_group_infos)
++                      metalen = sizeof(*meta_group_info) *
++                              (sbi->s_groups_count -
++                                      (i << EXT3_DESC_PER_BLOCK_BITS(sb)));
++              meta_group_info = kmalloc(metalen, GFP_KERNEL);
++              if (meta_group_info == NULL) {
++                      printk(KERN_ERR "EXT3-fs: can't allocate mem for a "
++                             "buddy group\n");
++                      goto err_freemeta;
++              }
++              sbi->s_group_info[i] = meta_group_info;
 +      }
 +
 +      /* 
@@ -2081,30 +2295,42 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      for (i = 0; i < sbi->s_groups_count; i++) {
 +              struct ext3_group_desc * desc;
 +
-+              sbi->s_group_info[i] = kmalloc(len, GFP_KERNEL);
-+              if (sbi->s_group_info[i] == NULL) {
++              meta_group_info =
++                      sbi->s_group_info[i >> EXT3_DESC_PER_BLOCK_BITS(sb)];
++              j = i & (EXT3_DESC_PER_BLOCK(sb) - 1);
++
++              meta_group_info[j] = kmalloc(len, GFP_KERNEL);
++              if (meta_group_info[j] == NULL) {
 +                      printk(KERN_ERR "EXT3-fs: can't allocate buddy mem\n");
-+                      goto err_out;
++                      i--;
++                      goto err_freebuddy;
 +              }
 +              desc = ext3_get_group_desc(sb, i, NULL);
 +              if (desc == NULL) {
 +                      printk(KERN_ERR"EXT3-fs: can't read descriptor %u\n",i);
-+                      goto err_out;
++                      goto err_freebuddy;
 +              }
-+              memset(sbi->s_group_info[i], 0, len);
++              memset(meta_group_info[j], 0, len);
 +              set_bit(EXT3_GROUP_INFO_NEED_INIT_BIT,
-+                      &sbi->s_group_info[i]->bb_state);
-+              sbi->s_group_info[i]->bb_free =
++                      &meta_group_info[j]->bb_state);
++              meta_group_info[j]->bb_free =
 +                      le16_to_cpu(desc->bg_free_blocks_count);
 +      }
 +
 +      return 0;
 +
-+err_out:
++err_freebuddy:
++      while (i >= 0) {
++              kfree(EXT3_GROUP_INFO(sb, i));
++              i--;
++      }
++      i = num_meta_group_infos;
++err_freemeta:
 +      while (--i >= 0)
 +              kfree(sbi->s_group_info[i]);
 +      iput(sbi->s_buddy_cache);
-+
++err_freesgi:
++      kfree(sbi->s_group_info);
 +      return -ENOMEM;
 +}
 +
@@ -2146,7 +2372,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +              max = max >> 1;
 +              i++;
 +      } while (i <= sb->s_blocksize_bits + 1);
-+      
++
 +
 +      /* init file for buddy data */
 +      if ((i = ext3_mb_init_backend(sb))) {
@@ -2183,8 +2409,8 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +int ext3_mb_release(struct super_block *sb)
 +{
 +      struct ext3_sb_info *sbi = EXT3_SB(sb);
-+      int i;
-+      
++      int i, num_meta_group_infos;
++
 +      if (!test_opt(sb, MBALLOC))
 +              return 0;
 +
@@ -2198,11 +2424,13 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      ext3_mb_free_committed_blocks(sb);
 +
 +      if (sbi->s_group_info) {
-+              for (i = 0; i < sbi->s_groups_count; i++) {
-+                      if (sbi->s_group_info[i] == NULL)
-+                              continue;
++              for (i = 0; i < sbi->s_groups_count; i++)
++                      kfree(EXT3_GROUP_INFO(sb, i));
++              num_meta_group_infos = (sbi->s_groups_count +
++                      EXT3_DESC_PER_BLOCK(sb) - 1) >>
++                      EXT3_DESC_PER_BLOCK_BITS(sb);
++              for (i = 0; i < num_meta_group_infos; i++)
 +                      kfree(sbi->s_group_info[i]);
-+              }
 +              kfree(sbi->s_group_info);
 +      }
 +      if (sbi->s_mb_offsets)
@@ -2496,7 +2724,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +              cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) + count);
 +      spin_unlock(sb_bgl_lock(sbi, block_group));
 +      percpu_counter_mod(&sbi->s_freeblocks_counter, count);
-+      
++
 +      ext3_mb_release_desc(&e3b);
 +
 +      *freed = count;
@@ -2580,10 +2808,11 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      return;
 +}
 +
-+#define EXT3_ROOT                 "ext3"
-+#define EXT3_MB_STATS_NAME        "mb_stats"
++#define EXT3_ROOT                "ext3"
++#define EXT3_MB_STATS_NAME       "mb_stats"
 +#define EXT3_MB_MAX_TO_SCAN_NAME  "mb_max_to_scan"
 +#define EXT3_MB_MIN_TO_SCAN_NAME  "mb_min_to_scan"
++#define EXT3_MB_ORDER2_REQ       "mb_order2_req"
 +
 +static int ext3_mb_stats_read(char *page, char **start, off_t off,
 +              int count, int *eof, void *data)
@@ -2671,6 +2900,45 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      return len;
 +}
 +
++static int ext3_mb_order2_req_write(struct file *file, const char *buffer,
++              unsigned long count, void *data)
++{
++      char str[32];
++      long value;
++
++      if (count >= sizeof(str)) {
++              printk(KERN_ERR "EXT3-fs: %s string too long, max %u bytes\n",
++                     EXT3_MB_MIN_TO_SCAN_NAME, (int)sizeof(str));
++              return -EOVERFLOW;
++      }
++
++      if (copy_from_user(str, buffer, count))
++              return -EFAULT;
++
++      /* Only set to 0 or 1 respectively; zero->0; non-zero->1 */
++      value = simple_strtol(str, NULL, 0);
++      if (value <= 0)
++              return -ERANGE;
++
++      ext3_mb_order2_reqs = value;    
++
++      return count;
++}
++
++static int ext3_mb_order2_req_read(char *page, char **start, off_t off,
++              int count, int *eof, void *data)
++{
++      int len;
++
++      *eof = 1;
++      if (off != 0)
++              return 0;
++
++      len = sprintf(page, "%ld\n", ext3_mb_order2_reqs);
++      *start = page;
++      return len;
++}
++
 +static int ext3_mb_min_to_scan_write(struct file *file, const char *buffer,
 +              unsigned long count, void *data)
 +{
@@ -2701,6 +2969,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      struct proc_dir_entry *proc_ext3_mb_stats;
 +      struct proc_dir_entry *proc_ext3_mb_max_to_scan;
 +      struct proc_dir_entry *proc_ext3_mb_min_to_scan;
++      struct proc_dir_entry *proc_ext3_mb_order2_req;
 +
 +      proc_root_ext3 = proc_mkdir(EXT3_ROOT, proc_root_fs);
 +      if (proc_root_ext3 == NULL) {
@@ -2755,6 +3024,24 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      proc_ext3_mb_min_to_scan->read_proc  = ext3_mb_min_to_scan_read;
 +      proc_ext3_mb_min_to_scan->write_proc = ext3_mb_min_to_scan_write;
 +
++      /* Initialize EXT3_ORDER2_REQ */
++      proc_ext3_mb_order2_req = create_proc_entry(
++                      EXT3_MB_ORDER2_REQ,
++                      S_IFREG | S_IRUGO | S_IWUSR, proc_root_ext3);
++      if (proc_ext3_mb_order2_req == NULL) {
++              printk(KERN_ERR "EXT3-fs: Unable to create %s\n",
++                              EXT3_MB_ORDER2_REQ);
++              remove_proc_entry(EXT3_MB_MIN_TO_SCAN_NAME, proc_root_ext3);
++              remove_proc_entry(EXT3_MB_MAX_TO_SCAN_NAME, proc_root_ext3);
++              remove_proc_entry(EXT3_MB_STATS_NAME, proc_root_ext3);
++              remove_proc_entry(EXT3_ROOT, proc_root_fs);
++              return -EIO;
++      }
++
++      proc_ext3_mb_order2_req->data = NULL;
++      proc_ext3_mb_order2_req->read_proc  = ext3_mb_order2_req_read;
++      proc_ext3_mb_order2_req->write_proc = ext3_mb_order2_req_write;
++
 +      return 0;
 +}
 +
@@ -2763,13 +3050,14 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      remove_proc_entry(EXT3_MB_STATS_NAME, proc_root_ext3);
 +      remove_proc_entry(EXT3_MB_MAX_TO_SCAN_NAME, proc_root_ext3);
 +      remove_proc_entry(EXT3_MB_MIN_TO_SCAN_NAME, proc_root_ext3);
++      remove_proc_entry(EXT3_MB_ORDER2_REQ, proc_root_ext3);
 +      remove_proc_entry(EXT3_ROOT, proc_root_fs);
 +}
-Index: linux-2.6.5-7.201/fs/ext3/Makefile
+Index: linux-2.6.5-7.252-full/fs/ext3/Makefile
 ===================================================================
---- linux-2.6.5-7.201.orig/fs/ext3/Makefile    2005-12-17 02:53:30.000000000 +0300
-+++ linux-2.6.5-7.201/fs/ext3/Makefile 2005-12-17 03:10:23.000000000 +0300
-@@ -6,7 +6,7 @@
+--- linux-2.6.5-7.252-full.orig/fs/ext3/Makefile       2006-04-25 17:42:19.000000000 +0400
++++ linux-2.6.5-7.252-full/fs/ext3/Makefile    2006-04-26 23:40:28.000000000 +0400
+@@ -6,7 +6,7 @@ obj-$(CONFIG_EXT3_FS) += ext3.o
  
  ext3-y        := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
           ioctl.o namei.o super.o symlink.o hash.o \
index 70f4f8a..fae9e30 100644 (file)
@@ -1,7 +1,7 @@
-Index: linux-2.6.12.6/include/linux/ext3_fs.h
+Index: linux-2.6.12.6-bull/include/linux/ext3_fs.h
 ===================================================================
---- linux-2.6.12.6.orig/include/linux/ext3_fs.h        2005-12-17 02:17:16.000000000 +0300
-+++ linux-2.6.12.6/include/linux/ext3_fs.h     2005-12-17 02:21:21.000000000 +0300
+--- linux-2.6.12.6-bull.orig/include/linux/ext3_fs.h   2006-04-29 20:39:09.000000000 +0400
++++ linux-2.6.12.6-bull/include/linux/ext3_fs.h        2006-04-29 20:39:10.000000000 +0400
 @@ -57,6 +57,14 @@ struct statfs;
  #define ext3_debug(f, a...)   do {} while (0)
  #endif
@@ -52,10 +52,10 @@ Index: linux-2.6.12.6/include/linux/ext3_fs.h
  #endif        /* __KERNEL__ */
  
  /* EXT3_IOC_CREATE_INUM at bottom of file (visible to kernel and user). */
-Index: linux-2.6.12.6/include/linux/ext3_fs_sb.h
+Index: linux-2.6.12.6-bull/include/linux/ext3_fs_sb.h
 ===================================================================
---- linux-2.6.12.6.orig/include/linux/ext3_fs_sb.h     2005-08-29 20:55:27.000000000 +0400
-+++ linux-2.6.12.6/include/linux/ext3_fs_sb.h  2005-12-17 02:21:21.000000000 +0300
+--- linux-2.6.12.6-bull.orig/include/linux/ext3_fs_sb.h        2005-08-29 20:55:27.000000000 +0400
++++ linux-2.6.12.6-bull/include/linux/ext3_fs_sb.h     2006-04-29 20:39:10.000000000 +0400
 @@ -21,8 +21,14 @@
  #include <linux/wait.h>
  #include <linux/blockgroup_lock.h>
@@ -71,13 +71,13 @@ Index: linux-2.6.12.6/include/linux/ext3_fs_sb.h
  
  /*
   * third extended-fs super-block data in memory
-@@ -78,6 +84,38 @@ struct ext3_sb_info {
+@@ -78,6 +84,43 @@ struct ext3_sb_info {
        char *s_qf_names[MAXQUOTAS];            /* Names of quota files with journalled quota */
        int s_jquota_fmt;                       /* Format of quota to use */
  #endif
 +
 +      /* for buddy allocator */
-+      struct ext3_group_info **s_group_info;
++      struct ext3_group_info ***s_group_info;
 +      struct inode *s_buddy_cache;
 +      long s_blocks_reserved;
 +      spinlock_t s_reserve_lock;
@@ -88,6 +88,7 @@ Index: linux-2.6.12.6/include/linux/ext3_fs_sb.h
 +      tid_t s_last_transaction;
 +      int s_mb_factor;
 +      unsigned short *s_mb_offsets, *s_mb_maxs;
++      unsigned long s_stripe;
 +
 +      /* history to debug policy */
 +      struct ext3_mb_history *s_mb_history;
@@ -108,12 +109,16 @@ Index: linux-2.6.12.6/include/linux/ext3_fs_sb.h
 +      unsigned long s_mb_buddies_generated;
 +      unsigned long long s_mb_generation_time;
  };
++
++#define EXT3_GROUP_INFO(sb, group)                                       \
++      EXT3_SB(sb)->s_group_info[(group) >> EXT3_DESC_PER_BLOCK_BITS(sb)] \
++                               [(group) & (EXT3_DESC_PER_BLOCK(sb) - 1)]
  
  #endif        /* _LINUX_EXT3_FS_SB */
-Index: linux-2.6.12.6/fs/ext3/super.c
+Index: linux-2.6.12.6-bull/fs/ext3/super.c
 ===================================================================
---- linux-2.6.12.6.orig/fs/ext3/super.c        2005-12-17 02:17:16.000000000 +0300
-+++ linux-2.6.12.6/fs/ext3/super.c     2005-12-17 02:21:21.000000000 +0300
+--- linux-2.6.12.6-bull.orig/fs/ext3/super.c   2006-04-29 20:39:09.000000000 +0400
++++ linux-2.6.12.6-bull/fs/ext3/super.c        2006-04-29 20:39:10.000000000 +0400
 @@ -387,6 +387,7 @@ static void ext3_put_super (struct super
        struct ext3_super_block *es = sbi->s_es;
        int i;
@@ -122,34 +127,45 @@ Index: linux-2.6.12.6/fs/ext3/super.c
        ext3_ext_release(sb);
        ext3_xattr_put_super(sb);
        journal_destroy(sbi->s_journal);
-@@ -597,7 +598,7 @@ enum {
-       Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0,
+@@ -597,6 +598,7 @@ enum {
        Opt_ignore, Opt_barrier, Opt_err, Opt_resize,
        Opt_iopen, Opt_noiopen, Opt_iopen_nopriv,
--      Opt_extents, Opt_extdebug,
-+      Opt_extents, Opt_extdebug, Opt_mballoc,
+       Opt_extents, Opt_noextents, Opt_extdebug,
++      Opt_mballoc, Opt_nomballoc, Opt_stripe,
  };
  
  static match_table_t tokens = {
-@@ -649,6 +651,7 @@ static match_table_t tokens = {
-       {Opt_iopen_nopriv, "iopen_nopriv"},
+@@ -650,6 +651,9 @@ static match_table_t tokens = {
        {Opt_extents, "extents"},
+       {Opt_noextents, "noextents"},
        {Opt_extdebug, "extdebug"},
 +      {Opt_mballoc, "mballoc"},
++      {Opt_nomballoc, "nomballoc"},
++      {Opt_stripe, "stripe=%u"},
        {Opt_barrier, "barrier=%u"},
        {Opt_err, NULL},
        {Opt_resize, "resize"},
-@@ -964,6 +967,9 @@ clear_qf_name:
+@@ -965,6 +967,19 @@ clear_qf_name:
                case Opt_extdebug:
                        set_opt (sbi->s_mount_opt, EXTDEBUG);
                        break;
 +              case Opt_mballoc:
-+                      set_opt (sbi->s_mount_opt, MBALLOC);
++                      set_opt(sbi->s_mount_opt, MBALLOC);
++                      break;
++              case Opt_nomballoc:
++                      clear_opt(sbi->s_mount_opt, MBALLOC);
++                      break;
++              case Opt_stripe:
++                      if (match_int(&args[0], &option))
++                              return 0;
++                      if (option < 0)
++                              return 0;
++                      sbi->s_stripe = option;
 +                      break;
                default:
                        printk (KERN_ERR
                                "EXT3-fs: Unrecognized mount option \"%s\" "
-@@ -1669,6 +1675,7 @@ static int ext3_fill_super (struct super
+@@ -1670,6 +1675,7 @@ static int ext3_fill_super (struct super
                ext3_count_dirs(sb));
  
        ext3_ext_init(sb);
@@ -157,7 +173,7 @@ Index: linux-2.6.12.6/fs/ext3/super.c
        lock_kernel();
        return 0;
  
-@@ -2548,7 +2555,13 @@ static struct file_system_type ext3_fs_t
+@@ -2549,7 +2555,13 @@ static struct file_system_type ext3_fs_t
  
  static int __init init_ext3_fs(void)
  {
@@ -172,7 +188,7 @@ Index: linux-2.6.12.6/fs/ext3/super.c
        if (err)
                return err;
        err = init_inodecache();
-@@ -2570,6 +2583,7 @@ static void __exit exit_ext3_fs(void)
+@@ -2571,6 +2583,7 @@ static void __exit exit_ext3_fs(void)
        unregister_filesystem(&ext3_fs_type);
        destroy_inodecache();
        exit_ext3_xattr();
@@ -180,11 +196,11 @@ Index: linux-2.6.12.6/fs/ext3/super.c
  }
  
  int ext3_prep_san_write(struct inode *inode, long *blocks,
-Index: linux-2.6.12.6/fs/ext3/extents.c
+Index: linux-2.6.12.6-bull/fs/ext3/extents.c
 ===================================================================
---- linux-2.6.12.6.orig/fs/ext3/extents.c      2005-12-17 02:17:16.000000000 +0300
-+++ linux-2.6.12.6/fs/ext3/extents.c   2005-12-17 02:21:21.000000000 +0300
-@@ -771,7 +771,7 @@ cleanup:
+--- linux-2.6.12.6-bull.orig/fs/ext3/extents.c 2006-04-29 20:39:09.000000000 +0400
++++ linux-2.6.12.6-bull/fs/ext3/extents.c      2006-04-29 20:39:10.000000000 +0400
+@@ -777,7 +777,7 @@ cleanup:
                for (i = 0; i < depth; i++) {
                        if (!ablocks[i])
                                continue;
@@ -193,7 +209,7 @@ Index: linux-2.6.12.6/fs/ext3/extents.c
                }
        }
        kfree(ablocks);
-@@ -1428,7 +1428,7 @@ int ext3_ext_rm_idx(handle_t *handle, st
+@@ -1434,7 +1434,7 @@ int ext3_ext_rm_idx(handle_t *handle, st
                  path->p_idx->ei_leaf);
        bh = sb_find_get_block(tree->inode->i_sb, path->p_idx->ei_leaf);
        ext3_forget(handle, 1, tree->inode, bh, path->p_idx->ei_leaf);
@@ -202,7 +218,7 @@ Index: linux-2.6.12.6/fs/ext3/extents.c
        return err;
  }
  
-@@ -1913,10 +1913,12 @@ ext3_remove_blocks(struct ext3_extents_t
+@@ -1919,10 +1919,12 @@ ext3_remove_blocks(struct ext3_extents_t
        int needed = ext3_remove_blocks_credits(tree, ex, from, to);
        handle_t *handle = ext3_journal_start(tree->inode, needed);
        struct buffer_head *bh;
@@ -216,7 +232,7 @@ Index: linux-2.6.12.6/fs/ext3/extents.c
        if (from >= ex->ee_block && to == ex->ee_block + ex->ee_len - 1) {
                /* tail removal */
                unsigned long num, start;
-@@ -1928,7 +1930,7 @@ ext3_remove_blocks(struct ext3_extents_t
+@@ -1934,7 +1936,7 @@ ext3_remove_blocks(struct ext3_extents_t
                        bh = sb_find_get_block(tree->inode->i_sb, start + i);
                        ext3_forget(handle, 0, tree->inode, bh, start + i);
                }
@@ -225,10 +241,10 @@ Index: linux-2.6.12.6/fs/ext3/extents.c
        } else if (from == ex->ee_block && to <= ex->ee_block + ex->ee_len - 1) {
                printk("strange request: removal %lu-%lu from %u:%u\n",
                       from, to, ex->ee_block, ex->ee_len);
-Index: linux-2.6.12.6/fs/ext3/inode.c
+Index: linux-2.6.12.6-bull/fs/ext3/inode.c
 ===================================================================
---- linux-2.6.12.6.orig/fs/ext3/inode.c        2005-12-17 02:17:16.000000000 +0300
-+++ linux-2.6.12.6/fs/ext3/inode.c     2005-12-17 02:21:21.000000000 +0300
+--- linux-2.6.12.6-bull.orig/fs/ext3/inode.c   2006-04-29 20:39:09.000000000 +0400
++++ linux-2.6.12.6-bull/fs/ext3/inode.c        2006-04-29 20:39:10.000000000 +0400
 @@ -564,7 +564,7 @@ static int ext3_alloc_branch(handle_t *h
                ext3_journal_forget(handle, branch[i].bh);
        }
@@ -256,10 +272,10 @@ Index: linux-2.6.12.6/fs/ext3/inode.c
  
                        if (parent_bh) {
                                /*
-Index: linux-2.6.12.6/fs/ext3/balloc.c
+Index: linux-2.6.12.6-bull/fs/ext3/balloc.c
 ===================================================================
---- linux-2.6.12.6.orig/fs/ext3/balloc.c       2005-08-29 20:55:27.000000000 +0400
-+++ linux-2.6.12.6/fs/ext3/balloc.c    2005-12-17 02:21:21.000000000 +0300
+--- linux-2.6.12.6-bull.orig/fs/ext3/balloc.c  2005-08-29 20:55:27.000000000 +0400
++++ linux-2.6.12.6-bull/fs/ext3/balloc.c       2006-04-29 20:39:10.000000000 +0400
 @@ -79,7 +79,7 @@ struct ext3_group_desc * ext3_get_group_
   *
   * Return buffer_head on success or NULL in case of failure.
@@ -303,10 +319,10 @@ Index: linux-2.6.12.6/fs/ext3/balloc.c
                        unsigned long goal, int *errp)
  {
        struct buffer_head *bitmap_bh = NULL;
-Index: linux-2.6.12.6/fs/ext3/xattr.c
+Index: linux-2.6.12.6-bull/fs/ext3/xattr.c
 ===================================================================
---- linux-2.6.12.6.orig/fs/ext3/xattr.c        2005-08-29 20:55:27.000000000 +0400
-+++ linux-2.6.12.6/fs/ext3/xattr.c     2005-12-17 02:21:33.000000000 +0300
+--- linux-2.6.12.6-bull.orig/fs/ext3/xattr.c   2005-08-29 20:55:27.000000000 +0400
++++ linux-2.6.12.6-bull/fs/ext3/xattr.c        2006-04-29 20:39:10.000000000 +0400
 @@ -484,7 +484,7 @@ ext3_xattr_release_block(handle_t *handl
                ea_bdebug(bh, "refcount now=0; freeing");
                if (ce)
@@ -325,11 +341,11 @@ Index: linux-2.6.12.6/fs/ext3/xattr.c
                                error = -EIO;
                                goto cleanup;
                        }
-Index: linux-2.6.12.6/fs/ext3/mballoc.c
+Index: linux-2.6.12.6-bull/fs/ext3/mballoc.c
 ===================================================================
---- linux-2.6.12.6.orig/fs/ext3/mballoc.c      2005-12-09 13:08:53.191437750 +0300
-+++ linux-2.6.12.6/fs/ext3/mballoc.c   2005-12-17 02:21:21.000000000 +0300
-@@ -0,0 +1,2429 @@
+--- linux-2.6.12.6-bull.orig/fs/ext3/mballoc.c 2006-04-22 17:31:47.543334750 +0400
++++ linux-2.6.12.6-bull/fs/ext3/mballoc.c      2006-04-30 01:24:11.000000000 +0400
+@@ -0,0 +1,2701 @@
 +/*
 + * Copyright (c) 2003-2005, Cluster File Systems, Inc, info@clusterfs.com
 + * Written by Alex Tomas <alex@clusterfs.com>
@@ -418,6 +434,12 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +
 +long ext3_mb_stats = 1;
 +
++/*
++ * for which requests use 2^N search using buddies
++ */
++long ext3_mb_order2_reqs = 8;
++
++
 +#ifdef EXT3_BB_MAX_BLOCKS
 +#undef EXT3_BB_MAX_BLOCKS
 +#endif
@@ -458,10 +480,10 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +
 +      /* search goals */
 +      struct ext3_free_extent ac_g_ex;
-+      
++
 +      /* the best found extent */
 +      struct ext3_free_extent ac_b_ex;
-+      
++
 +      /* number of iterations done. we have to track to limit searching */
 +      unsigned long ac_ex_scanned;
 +      __u16 ac_groups_scanned;
@@ -483,6 +505,8 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +struct ext3_mb_history {
 +      struct ext3_free_extent goal;   /* goal allocation */
 +      struct ext3_free_extent result; /* result allocation */
++      unsigned pid;
++      unsigned ino;
 +      __u16 found;    /* how many extents have been found */
 +      __u16 groups;   /* how many groups have been scanned */
 +      __u16 tail;     /* what tail broke some buddy */
@@ -505,9 +529,9 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +#define EXT3_MB_BUDDY(e3b)    ((e3b)->bd_buddy)
 +
 +#ifndef EXT3_MB_HISTORY
-+#define ext3_mb_store_history(sb,ac)
++#define ext3_mb_store_history(sb,ino,ac)
 +#else
-+static void ext3_mb_store_history(struct super_block *,
++static void ext3_mb_store_history(struct super_block *, unsigned ino,
 +                              struct ext3_allocation_context *ac);
 +#endif
 +
@@ -626,7 +650,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +              if (mb_check_counter++ % 300 != 0)
 +                      return;
 +      }
-+      
++
 +      while (order > 1) {
 +              buddy = mb_find_buddy(e3b, order, &max);
 +              J_ASSERT(buddy);
@@ -807,7 +831,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      sb = inode->i_sb;
 +      blocksize = 1 << inode->i_blkbits;
 +      blocks_per_page = PAGE_CACHE_SIZE / blocksize;
-+      
++
 +      groups_per_page = blocks_per_page >> 1;
 +      if (groups_per_page == 0)
 +              groups_per_page = 1;
@@ -822,9 +846,9 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +              memset(bh, 0, i);
 +      } else
 +              bh = &bhs;
-+      
++
 +      first_group = page->index * blocks_per_page / 2;
-+      
++
 +      /* read all groups the page covers into the cache */
 +      for (i = 0; i < groups_per_page; i++) {
 +              struct ext3_group_desc * desc;
@@ -879,11 +903,11 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +                      mb_debug("put buddy for group %u in page %lu/%x\n",
 +                              group, page->index, i * blocksize);
 +                      memset(data, 0xff, blocksize);
-+                      EXT3_SB(sb)->s_group_info[group]->bb_fragments = 0;
-+                      memset(EXT3_SB(sb)->s_group_info[group]->bb_counters, 0,
++                      EXT3_GROUP_INFO(sb, group)->bb_fragments = 0;
++                      memset(EXT3_GROUP_INFO(sb, group)->bb_counters, 0,
 +                              sizeof(unsigned short)*(sb->s_blocksize_bits+2));
 +                      ext3_mb_generate_buddy(sb, data, bitmap,
-+                                              EXT3_SB(sb)->s_group_info[group]);
++                                              EXT3_GROUP_INFO(sb, group));
 +              } else {
 +                      /* this is block of bitmap */
 +                      mb_debug("put bitmap for group %u in page %lu/%x\n",
@@ -916,7 +940,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      blocks_per_page = PAGE_CACHE_SIZE / sb->s_blocksize;
 +
 +      e3b->bd_blkbits = sb->s_blocksize_bits;
-+      e3b->bd_info = sbi->s_group_info[group];
++      e3b->bd_info = EXT3_GROUP_INFO(sb, group);
 +      e3b->bd_sb = sb;
 +      e3b->bd_group = group;
 +      e3b->bd_buddy_page = NULL;
@@ -992,14 +1016,14 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +ext3_lock_group(struct super_block *sb, int group)
 +{
 +      bit_spin_lock(EXT3_GROUP_INFO_LOCKED_BIT,
-+                      &EXT3_SB(sb)->s_group_info[group]->bb_state);
++                    &EXT3_GROUP_INFO(sb, group)->bb_state);
 +}
 +
 +static inline void
 +ext3_unlock_group(struct super_block *sb, int group)
 +{
 +      bit_spin_unlock(EXT3_GROUP_INFO_LOCKED_BIT,
-+                      &EXT3_SB(sb)->s_group_info[group]->bb_state);
++                      &EXT3_GROUP_INFO(sb, group)->bb_state);
 +}
 +
 +static int mb_find_order_for_block(struct ext3_buddy *e3b, int block)
@@ -1129,7 +1153,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +static int mb_find_extent(struct ext3_buddy *e3b, int order, int block,
 +                              int needed, struct ext3_free_extent *ex)
 +{
-+      int next, max, ord;
++      int next = block, max, ord;
 +      void *buddy;
 +
 +      J_ASSERT(ex != NULL);
@@ -1154,6 +1178,11 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      ex->fe_start = block << order;
 +      ex->fe_group = e3b->bd_group;
 +
++      /* calc difference from given start */
++      next = next - ex->fe_start;
++      ex->fe_len -= next;
++      ex->fe_start += next;
++
 +      while (needed > ex->fe_len && (buddy = mb_find_buddy(e3b, order, &max))) {
 +
 +              if (block + 1 >= max)
@@ -1349,7 +1378,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +
 +      ext3_lock_group(ac->ac_sb, group);
 +      max = mb_find_extent(e3b, 0, ex.fe_start, ex.fe_len, &ex);
-+      
++
 +      if (max > 0) {
 +              ac->ac_b_ex = ex;
 +              ext3_mb_use_best_found(ac, e3b);
@@ -1366,6 +1395,8 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +                              struct ext3_buddy *e3b)
 +{
 +      int group = ac->ac_g_ex.fe_group, max, err;
++      struct ext3_sb_info *sbi = EXT3_SB(ac->ac_sb);
++      struct ext3_super_block *es = sbi->s_es;
 +      struct ext3_free_extent ex;
 +
 +      err = ext3_mb_load_buddy(ac->ac_sb, group, e3b);
@@ -1374,9 +1405,27 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +
 +      ext3_lock_group(ac->ac_sb, group);
 +      max = mb_find_extent(e3b, 0, ac->ac_g_ex.fe_start,
-+                              ac->ac_g_ex.fe_len, &ex);
-+      
-+      if (max > 0) {
++                           ac->ac_g_ex.fe_len, &ex);
++
++      if (max >= ac->ac_g_ex.fe_len && ac->ac_g_ex.fe_len == sbi->s_stripe) {
++              unsigned long start;
++              start = (e3b->bd_group * EXT3_BLOCKS_PER_GROUP(ac->ac_sb) +
++                      ex.fe_start + le32_to_cpu(es->s_first_data_block));
++              if (start % sbi->s_stripe == 0) {
++                      ac->ac_found++;
++                      ac->ac_b_ex = ex;
++                      ext3_mb_use_best_found(ac, e3b);
++              }
++      } else if (max >= ac->ac_g_ex.fe_len) {
++              J_ASSERT(ex.fe_len > 0);
++              J_ASSERT(ex.fe_group == ac->ac_g_ex.fe_group);
++              J_ASSERT(ex.fe_start == ac->ac_g_ex.fe_start);
++              ac->ac_found++;
++              ac->ac_b_ex = ex;
++              ext3_mb_use_best_found(ac, e3b);
++      } else if (max > 0 && (ac->ac_flags & EXT3_MB_HINT_MERGE)) {
++              /* Sometimes, caller may want to merge even small
++               * number of blocks to an existing extent */
 +              J_ASSERT(ex.fe_len > 0);
 +              J_ASSERT(ex.fe_group == ac->ac_g_ex.fe_group);
 +              J_ASSERT(ex.fe_start == ac->ac_g_ex.fe_start);
@@ -1404,7 +1453,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      int i, k, max;
 +
 +      J_ASSERT(ac->ac_2order > 0);
-+      for (i = ac->ac_2order; i < sb->s_blocksize_bits + 1; i++) {
++      for (i = ac->ac_2order; i <= sb->s_blocksize_bits + 1; i++) {
 +              if (grp->bb_counters[i] == 0)
 +                      continue;
 +
@@ -1469,11 +1518,46 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      }
 +}
 +
++/*
++ * This is a special case for storages like raid5
++ * we try to find stripe-aligned chunks for stripe-size requests
++ */
++static void ext3_mb_scan_aligned(struct ext3_allocation_context *ac,
++                               struct ext3_buddy *e3b)
++{
++      struct super_block *sb = ac->ac_sb;
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      void *bitmap = EXT3_MB_BITMAP(e3b);
++      struct ext3_free_extent ex;
++      unsigned long i, max;
++
++      J_ASSERT(sbi->s_stripe != 0);
++
++      /* find first stripe-aligned block */
++      i = e3b->bd_group * EXT3_BLOCKS_PER_GROUP(sb)
++              + le32_to_cpu(sbi->s_es->s_first_data_block);
++      i = ((i + sbi->s_stripe - 1) / sbi->s_stripe) * sbi->s_stripe;
++      i = (i - le32_to_cpu(sbi->s_es->s_first_data_block))
++                      % EXT3_BLOCKS_PER_GROUP(sb);
++
++      while (i < sb->s_blocksize * 8) {
++              if (!mb_test_bit(i, bitmap)) {
++                      max = mb_find_extent(e3b, 0, i, sbi->s_stripe, &ex);
++                      if (max >= sbi->s_stripe) {
++                              ac->ac_found++;
++                              ac->ac_b_ex = ex;
++                              ext3_mb_use_best_found(ac, e3b);
++                              break;
++                      }
++              }
++              i += sbi->s_stripe;
++      }
++}
++
 +static int ext3_mb_good_group(struct ext3_allocation_context *ac,
 +                              int group, int cr)
 +{
-+      struct ext3_sb_info *sbi = EXT3_SB(ac->ac_sb);
-+      struct ext3_group_info *grp = sbi->s_group_info[group];
++      struct ext3_group_info *grp = EXT3_GROUP_INFO(ac->ac_sb, group);
 +      unsigned free, fragments, i, bits;
 +
 +      J_ASSERT(cr >= 0 && cr < 4);
@@ -1490,15 +1574,18 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +              case 0:
 +                      J_ASSERT(ac->ac_2order != 0);
 +                      bits = ac->ac_sb->s_blocksize_bits + 1;
-+                      for (i = ac->ac_2order; i < bits; i++)
++                      for (i = ac->ac_2order; i <= bits; i++)
 +                              if (grp->bb_counters[i] > 0)
 +                                      return 1;
++                      break;
 +              case 1:
 +                      if ((free / fragments) >= ac->ac_g_ex.fe_len)
 +                              return 1;
++                      break;
 +              case 2:
 +                      if (free >= ac->ac_g_ex.fe_len)
 +                              return 1;
++                      break;
 +              case 3:
 +                      return 1;
 +              default:
@@ -1599,23 +1686,27 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      ac.ac_2order = 0;
 +      ac.ac_criteria = 0;
 +
++      if (*len == 1 && sbi->s_stripe) {
++              /* looks like a metadata, let's use a dirty hack for raid5
++               * move all metadata in first groups in hope to hit cached
++               * sectors and thus avoid read-modify cycles in raid5 */
++              ac.ac_g_ex.fe_group = group = 0;
++      }
++
 +      /* probably, the request is for 2^8+ blocks (1/2/3/... MB) */
 +      i = ffs(*len);
-+      if (i >= 8) {
++      if (i >= ext3_mb_order2_reqs) {
 +              i--;
 +              if ((*len & (~(1 << i))) == 0)
 +                      ac.ac_2order = i;
 +      }
 +
-+      /* Sometimes, caller may want to merge even small
-+       * number of blocks to an existing extent */
-+      if (ac.ac_flags & EXT3_MB_HINT_MERGE) {
-+              err = ext3_mb_find_by_goal(&ac, &e3b);
-+              if (err)
-+                      goto out_err;
-+              if (ac.ac_status == AC_STATUS_FOUND)
-+                      goto found;
-+      }
++      /* first, try the goal */
++      err = ext3_mb_find_by_goal(&ac, &e3b);
++      if (err)
++              goto out_err;
++      if (ac.ac_status == AC_STATUS_FOUND)
++              goto found;
 +
 +      /* Let's just scan groups to find more-less suitable blocks */
 +      cr = ac.ac_2order ? 0 : 1;
@@ -1626,7 +1717,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +                      if (group == EXT3_SB(sb)->s_groups_count)
 +                              group = 0;
 +
-+                      if (EXT3_MB_GRP_NEED_INIT(sbi->s_group_info[group])) {
++                      if (EXT3_MB_GRP_NEED_INIT(EXT3_GROUP_INFO(sb, group))) {
 +                              /* we need full data about the group
 +                               * to make a good selection */
 +                              err = ext3_mb_load_buddy(ac.ac_sb, group, &e3b);
@@ -1654,6 +1745,8 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +                      ac.ac_groups_scanned++;
 +                      if (cr == 0)
 +                              ext3_mb_simple_scan_group(&ac, &e3b);
++                      else if (cr == 1 && *len == sbi->s_stripe) 
++                              ext3_mb_scan_aligned(&ac, &e3b);
 +                      else
 +                              ext3_mb_complex_scan_group(&ac, &e3b);
 +
@@ -1667,7 +1760,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      }
 +
 +      if (ac.ac_b_ex.fe_len > 0 && ac.ac_status != AC_STATUS_FOUND &&
-+                      !(ac.ac_flags & EXT3_MB_HINT_FIRST)) {
++          !(ac.ac_flags & EXT3_MB_HINT_FIRST)) {
 +              /*
 +               * We've been searching too long. Let's try to allocate
 +               * the best chunk we've found so far
@@ -1712,8 +1805,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +                      sbi->s_blocks_reserved, ac.ac_found);
 +              printk("EXT3-fs: groups: ");
 +              for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++)
-+                      printk("%d: %d ", i,
-+                              sbi->s_group_info[i]->bb_free);
++                      printk("%d: %d ", i, EXT3_GROUP_INFO(sb, i)->bb_free);
 +              printk("\n");
 +#endif
 +              goto out;
@@ -1751,7 +1843,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +              *errp = -EIO;
 +              goto out_err;
 +      }
-+      
++
 +      err = ext3_journal_get_write_access(handle, gdp_bh);
 +      if (err)
 +              goto out_err;
@@ -1820,7 +1912,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +               * path only, here is single block always */
 +              ext3_mb_release_blocks(sb, 1);
 +      }
-+      
++
 +      if (unlikely(ext3_mb_stats) && ac.ac_g_ex.fe_len > 1) {
 +              atomic_inc(&sbi->s_bal_reqs);
 +              atomic_add(*len, &sbi->s_bal_allocated);
@@ -1834,7 +1926,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +                      atomic_inc(&sbi->s_bal_breaks);
 +      }
 +
-+      ext3_mb_store_history(sb, &ac);
++      ext3_mb_store_history(sb, inode->i_ino, &ac);
 +
 +      return block;
 +}
@@ -1899,9 +1991,9 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      char buf[20], buf2[20];
 +
 +      if (v == SEQ_START_TOKEN) {
-+              seq_printf(seq, "%-17s %-17s %-5s %-5s %-2s %-5s %-5s %-6s\n",
-+                       "goal", "result", "found", "grps", "cr", "merge",
-+                       "tail", "broken");
++              seq_printf(seq, "%-5s %-8s %-17s %-17s %-5s %-5s %-2s %-5s %-5s %-6s\n",
++                       "pid", "inode", "goal", "result", "found", "grps", "cr",
++                       "merge", "tail", "broken");
 +              return 0;
 +      }
 +
@@ -1909,9 +2001,9 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +              hs->goal.fe_start, hs->goal.fe_len);
 +      sprintf(buf2, "%u/%u/%u", hs->result.fe_group,
 +              hs->result.fe_start, hs->result.fe_len);
-+      seq_printf(seq, "%-17s %-17s %-5u %-5u %-2u %-5s %-5u %-6u\n", buf,
-+                      buf2, hs->found, hs->groups, hs->cr, 
-+                      hs->merged ? "M" : "", hs->tail,
++      seq_printf(seq, "%-5u %-8u %-17s %-17s %-5u %-5u %-2u %-5s %-5u %-6u\n",
++                      hs->pid, hs->ino, buf, buf2, hs->found, hs->groups,
++                      hs->cr, hs->merged ? "M" : "", hs->tail,
 +                      hs->buddy ? 1 << hs->buddy : 0);
 +      return 0;
 +}
@@ -1945,7 +2037,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      s->max = sbi->s_mb_history_max;
 +      s->start = sbi->s_mb_history_cur % s->max;
 +      spin_unlock(&sbi->s_mb_history_lock);
-+      
++
 +      rc = seq_open(file, &ext3_mb_seq_history_ops);
 +      if (rc == 0) {
 +              struct seq_file *m = (struct seq_file *)file->private_data;
@@ -1969,10 +2061,104 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +
 +static struct file_operations ext3_mb_seq_history_fops = {
 +      .owner          = THIS_MODULE,
-+      .open           = ext3_mb_seq_history_open,
-+      .read           = seq_read,
-+      .llseek         = seq_lseek,
-+      .release        = ext3_mb_seq_history_release,
++      .open           = ext3_mb_seq_history_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = ext3_mb_seq_history_release,
++};
++
++static void *ext3_mb_seq_groups_start(struct seq_file *seq, loff_t *pos)
++{
++      struct super_block *sb = seq->private;
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      long group;
++
++      if (*pos < 0 || *pos >= sbi->s_groups_count)
++              return NULL;
++
++      group = *pos + 1;
++      return (void *) group;
++}
++
++static void *ext3_mb_seq_groups_next(struct seq_file *seq, void *v, loff_t *pos)
++{
++      struct super_block *sb = seq->private;
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      long group;
++
++      ++*pos;
++      if (*pos < 0 || *pos >= sbi->s_groups_count)
++              return NULL;
++      group = *pos + 1;
++      return (void *) group;;
++}
++
++static int ext3_mb_seq_groups_show(struct seq_file *seq, void *v)
++{
++      struct super_block *sb = seq->private;
++      long group = (long) v, i;
++      struct sg {
++              struct ext3_group_info info;
++              unsigned short counters[16];
++      } sg;
++
++      group--;
++      if (group == 0)
++              seq_printf(seq, "#%-5s: %-5s %-5s %-5s [ %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s ]\n",
++                       "group", "free", "frags", "first", "2^0", "2^1", "2^2", 
++                       "2^3", "2^4", "2^5", "2^6", "2^7", "2^8", "2^9", "2^10",
++                       "2^11", "2^12", "2^13");
++
++      i = (sb->s_blocksize_bits + 2) * sizeof(sg.info.bb_counters[0]) +
++              sizeof(struct ext3_group_info);
++      ext3_lock_group(sb, group);
++      memcpy(&sg, EXT3_GROUP_INFO(sb, group), i);
++      ext3_unlock_group(sb, group);
++
++      if (EXT3_MB_GRP_NEED_INIT(&sg.info))
++              return 0;
++
++      seq_printf(seq, "#%-5lu: %-5u %-5u %-5u [", group, sg.info.bb_free,
++                      sg.info.bb_fragments, sg.info.bb_first_free);
++      for (i = 0; i <= 13; i++)
++              seq_printf(seq, " %-5u", i <= sb->s_blocksize_bits + 1 ?
++                              sg.info.bb_counters[i] : 0);
++      seq_printf(seq, " ]\n");
++
++      return 0;
++}
++
++static void ext3_mb_seq_groups_stop(struct seq_file *seq, void *v)
++{
++}
++
++static struct seq_operations ext3_mb_seq_groups_ops = {
++      .start  = ext3_mb_seq_groups_start,
++      .next   = ext3_mb_seq_groups_next,
++      .stop   = ext3_mb_seq_groups_stop,
++      .show   = ext3_mb_seq_groups_show,
++};
++
++static int ext3_mb_seq_groups_open(struct inode *inode, struct file *file)
++{
++      struct super_block *sb = PDE(inode)->data;
++      int rc;
++
++      rc = seq_open(file, &ext3_mb_seq_groups_ops);
++      if (rc == 0) {
++              struct seq_file *m = (struct seq_file *)file->private_data;
++              m->private = sb;
++      }
++      return rc;
++
++}
++
++static struct file_operations ext3_mb_seq_groups_fops = {
++      .owner          = THIS_MODULE,
++      .open           = ext3_mb_seq_groups_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = seq_release,
 +};
 +
 +static void ext3_mb_history_release(struct super_block *sb)
@@ -1981,6 +2167,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      char name[64];
 +
 +      snprintf(name, sizeof(name) - 1, "%s", bdevname(sb->s_bdev, name));
++      remove_proc_entry("mb_groups", sbi->s_mb_proc);
 +      remove_proc_entry("mb_history", sbi->s_mb_proc);
 +      remove_proc_entry(name, proc_root_ext3);
 +
@@ -2003,6 +2190,11 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +                      p->proc_fops = &ext3_mb_seq_history_fops;
 +                      p->data = sb;
 +              }
++              p = create_proc_entry("mb_groups", S_IRUGO, sbi->s_mb_proc);
++              if (p) {
++                      p->proc_fops = &ext3_mb_seq_groups_fops;
++                      p->data = sb;
++              }
 +      }
 +
 +      sbi->s_mb_history_max = 1000;
@@ -2015,7 +2207,8 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +}
 +
 +static void
-+ext3_mb_store_history(struct super_block *sb, struct ext3_allocation_context *ac)
++ext3_mb_store_history(struct super_block *sb, unsigned ino,
++                      struct ext3_allocation_context *ac)
 +{
 +      struct ext3_sb_info *sbi = EXT3_SB(sb);
 +      struct ext3_mb_history h;
@@ -2023,6 +2216,8 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      if (likely(sbi->s_mb_history == NULL))
 +              return;
 +
++      h.pid = current->pid;
++      h.ino = ino;
 +      h.goal = ac->ac_g_ex;
 +      h.result = ac->ac_b_ex;
 +      h.found = ac->ac_found;
@@ -2050,21 +2245,40 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +int ext3_mb_init_backend(struct super_block *sb)
 +{
 +      struct ext3_sb_info *sbi = EXT3_SB(sb);
-+      int i, len;
-+
-+      len = sizeof(struct ext3_buddy_group_blocks *) * sbi->s_groups_count;
-+      sbi->s_group_info = kmalloc(len, GFP_KERNEL);
++      int i, j, len, metalen;
++      int num_meta_group_infos =
++              (sbi->s_groups_count + EXT3_DESC_PER_BLOCK(sb) - 1) >>
++                      EXT3_DESC_PER_BLOCK_BITS(sb);
++      struct ext3_group_info **meta_group_info;
++
++      /* An 8TB filesystem with 64-bit pointers requires a 4096 byte
++       * kmalloc. A 128kb malloc should suffice for a 256TB filesystem.
++       * So a two level scheme suffices for now. */
++      sbi->s_group_info = kmalloc(sizeof(*sbi->s_group_info) *
++                                  num_meta_group_infos, GFP_KERNEL);
 +      if (sbi->s_group_info == NULL) {
-+              printk(KERN_ERR "EXT3-fs: can't allocate mem for buddy\n");
++              printk(KERN_ERR "EXT3-fs: can't allocate buddy meta group\n");
 +              return -ENOMEM;
 +      }
-+      memset(sbi->s_group_info, 0, len);
-+
 +      sbi->s_buddy_cache = new_inode(sb);
 +      if (sbi->s_buddy_cache == NULL) {
 +              printk(KERN_ERR "EXT3-fs: can't get new inode\n");
-+              kfree(sbi->s_group_info);
-+              return -ENOMEM;
++              goto err_freesgi;
++      }
++
++      metalen = sizeof(*meta_group_info) << EXT3_DESC_PER_BLOCK_BITS(sb);
++      for (i = 0; i < num_meta_group_infos; i++) {
++              if ((i + 1) == num_meta_group_infos)
++                      metalen = sizeof(*meta_group_info) *
++                              (sbi->s_groups_count -
++                                      (i << EXT3_DESC_PER_BLOCK_BITS(sb)));
++              meta_group_info = kmalloc(metalen, GFP_KERNEL);
++              if (meta_group_info == NULL) {
++                      printk(KERN_ERR "EXT3-fs: can't allocate mem for a "
++                             "buddy group\n");
++                      goto err_freemeta;
++              }
++              sbi->s_group_info[i] = meta_group_info;
 +      }
 +
 +      /* 
@@ -2076,30 +2290,42 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      for (i = 0; i < sbi->s_groups_count; i++) {
 +              struct ext3_group_desc * desc;
 +
-+              sbi->s_group_info[i] = kmalloc(len, GFP_KERNEL);
-+              if (sbi->s_group_info[i] == NULL) {
++              meta_group_info =
++                      sbi->s_group_info[i >> EXT3_DESC_PER_BLOCK_BITS(sb)];
++              j = i & (EXT3_DESC_PER_BLOCK(sb) - 1);
++
++              meta_group_info[j] = kmalloc(len, GFP_KERNEL);
++              if (meta_group_info[j] == NULL) {
 +                      printk(KERN_ERR "EXT3-fs: can't allocate buddy mem\n");
-+                      goto err_out;
++                      i--;
++                      goto err_freebuddy;
 +              }
 +              desc = ext3_get_group_desc(sb, i, NULL);
 +              if (desc == NULL) {
 +                      printk(KERN_ERR"EXT3-fs: can't read descriptor %u\n",i);
-+                      goto err_out;
++                      goto err_freebuddy;
 +              }
-+              memset(sbi->s_group_info[i], 0, len);
++              memset(meta_group_info[j], 0, len);
 +              set_bit(EXT3_GROUP_INFO_NEED_INIT_BIT,
-+                      &sbi->s_group_info[i]->bb_state);
-+              sbi->s_group_info[i]->bb_free =
++                      &meta_group_info[j]->bb_state);
++              meta_group_info[j]->bb_free =
 +                      le16_to_cpu(desc->bg_free_blocks_count);
 +      }
 +
 +      return 0;
 +
-+err_out:
++err_freebuddy:
++      while (i >= 0) {
++              kfree(EXT3_GROUP_INFO(sb, i));
++              i--;
++      }
++      i = num_meta_group_infos;
++err_freemeta:
 +      while (--i >= 0)
 +              kfree(sbi->s_group_info[i]);
 +      iput(sbi->s_buddy_cache);
-+
++err_freesgi:
++      kfree(sbi->s_group_info);
 +      return -ENOMEM;
 +}
 +
@@ -2141,7 +2367,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +              max = max >> 1;
 +              i++;
 +      } while (i <= sb->s_blocksize_bits + 1);
-+      
++
 +
 +      /* init file for buddy data */
 +      if ((i = ext3_mb_init_backend(sb))) {
@@ -2178,8 +2404,8 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +int ext3_mb_release(struct super_block *sb)
 +{
 +      struct ext3_sb_info *sbi = EXT3_SB(sb);
-+      int i;
-+      
++      int i, num_meta_group_infos;
++
 +      if (!test_opt(sb, MBALLOC))
 +              return 0;
 +
@@ -2193,11 +2419,13 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      ext3_mb_free_committed_blocks(sb);
 +
 +      if (sbi->s_group_info) {
-+              for (i = 0; i < sbi->s_groups_count; i++) {
-+                      if (sbi->s_group_info[i] == NULL)
-+                              continue;
++              for (i = 0; i < sbi->s_groups_count; i++)
++                      kfree(EXT3_GROUP_INFO(sb, i));
++              num_meta_group_infos = (sbi->s_groups_count +
++                      EXT3_DESC_PER_BLOCK(sb) - 1) >>
++                      EXT3_DESC_PER_BLOCK_BITS(sb);
++              for (i = 0; i < num_meta_group_infos; i++)
 +                      kfree(sbi->s_group_info[i]);
-+              }
 +              kfree(sbi->s_group_info);
 +      }
 +      if (sbi->s_mb_offsets)
@@ -2491,7 +2719,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +              cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) + count);
 +      spin_unlock(sb_bgl_lock(sbi, block_group));
 +      percpu_counter_mod(&sbi->s_freeblocks_counter, count);
-+      
++
 +      ext3_mb_release_desc(&e3b);
 +
 +      *freed = count;
@@ -2574,10 +2802,11 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      return;
 +}
 +
-+#define EXT3_ROOT                 "ext3"
-+#define EXT3_MB_STATS_NAME        "mb_stats"
++#define EXT3_ROOT                "ext3"
++#define EXT3_MB_STATS_NAME       "mb_stats"
 +#define EXT3_MB_MAX_TO_SCAN_NAME  "mb_max_to_scan"
 +#define EXT3_MB_MIN_TO_SCAN_NAME  "mb_min_to_scan"
++#define EXT3_MB_ORDER2_REQ       "mb_order2_req"
 +
 +static int ext3_mb_stats_read(char *page, char **start, off_t off,
 +              int count, int *eof, void *data)
@@ -2665,6 +2894,45 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      return len;
 +}
 +
++static int ext3_mb_order2_req_write(struct file *file, const char *buffer,
++              unsigned long count, void *data)
++{
++      char str[32];
++      long value;
++
++      if (count >= sizeof(str)) {
++              printk(KERN_ERR "EXT3-fs: %s string too long, max %u bytes\n",
++                     EXT3_MB_MIN_TO_SCAN_NAME, (int)sizeof(str));
++              return -EOVERFLOW;
++      }
++
++      if (copy_from_user(str, buffer, count))
++              return -EFAULT;
++
++      /* Only set to 0 or 1 respectively; zero->0; non-zero->1 */
++      value = simple_strtol(str, NULL, 0);
++      if (value <= 0)
++              return -ERANGE;
++
++      ext3_mb_order2_reqs = value;    
++
++      return count;
++}
++
++static int ext3_mb_order2_req_read(char *page, char **start, off_t off,
++              int count, int *eof, void *data)
++{
++      int len;
++
++      *eof = 1;
++      if (off != 0)
++              return 0;
++
++      len = sprintf(page, "%ld\n", ext3_mb_order2_reqs);
++      *start = page;
++      return len;
++}
++
 +static int ext3_mb_min_to_scan_write(struct file *file, const char *buffer,
 +              unsigned long count, void *data)
 +{
@@ -2695,6 +2963,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      struct proc_dir_entry *proc_ext3_mb_stats;
 +      struct proc_dir_entry *proc_ext3_mb_max_to_scan;
 +      struct proc_dir_entry *proc_ext3_mb_min_to_scan;
++      struct proc_dir_entry *proc_ext3_mb_order2_req;
 +
 +      proc_root_ext3 = proc_mkdir(EXT3_ROOT, proc_root_fs);
 +      if (proc_root_ext3 == NULL) {
@@ -2749,6 +3018,24 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      proc_ext3_mb_min_to_scan->read_proc  = ext3_mb_min_to_scan_read;
 +      proc_ext3_mb_min_to_scan->write_proc = ext3_mb_min_to_scan_write;
 +
++      /* Initialize EXT3_ORDER2_REQ */
++      proc_ext3_mb_order2_req = create_proc_entry(
++                      EXT3_MB_ORDER2_REQ,
++                      S_IFREG | S_IRUGO | S_IWUSR, proc_root_ext3);
++      if (proc_ext3_mb_order2_req == NULL) {
++              printk(KERN_ERR "EXT3-fs: Unable to create %s\n",
++                              EXT3_MB_ORDER2_REQ);
++              remove_proc_entry(EXT3_MB_MIN_TO_SCAN_NAME, proc_root_ext3);
++              remove_proc_entry(EXT3_MB_MAX_TO_SCAN_NAME, proc_root_ext3);
++              remove_proc_entry(EXT3_MB_STATS_NAME, proc_root_ext3);
++              remove_proc_entry(EXT3_ROOT, proc_root_fs);
++              return -EIO;
++      }
++
++      proc_ext3_mb_order2_req->data = NULL;
++      proc_ext3_mb_order2_req->read_proc  = ext3_mb_order2_req_read;
++      proc_ext3_mb_order2_req->write_proc = ext3_mb_order2_req_write;
++
 +      return 0;
 +}
 +
@@ -2757,13 +3044,14 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      remove_proc_entry(EXT3_MB_STATS_NAME, proc_root_ext3);
 +      remove_proc_entry(EXT3_MB_MAX_TO_SCAN_NAME, proc_root_ext3);
 +      remove_proc_entry(EXT3_MB_MIN_TO_SCAN_NAME, proc_root_ext3);
++      remove_proc_entry(EXT3_MB_ORDER2_REQ, proc_root_ext3);
 +      remove_proc_entry(EXT3_ROOT, proc_root_fs);
 +}
-Index: linux-2.6.12.6/fs/ext3/Makefile
+Index: linux-2.6.12.6-bull/fs/ext3/Makefile
 ===================================================================
---- linux-2.6.12.6.orig/fs/ext3/Makefile       2005-12-17 02:17:16.000000000 +0300
-+++ linux-2.6.12.6/fs/ext3/Makefile    2005-12-17 02:21:21.000000000 +0300
-@@ -6,7 +6,7 @@
+--- linux-2.6.12.6-bull.orig/fs/ext3/Makefile  2006-04-29 20:39:09.000000000 +0400
++++ linux-2.6.12.6-bull/fs/ext3/Makefile       2006-04-29 20:39:10.000000000 +0400
+@@ -6,7 +6,7 @@ obj-$(CONFIG_EXT3_FS) += ext3.o
  
  ext3-y        := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
           ioctl.o namei.o super.o symlink.o hash.o resize.o \
diff --git a/ldiskfs/kernel_patches/patches/ext3-mballoc2-2.6.18-vanilla.patch b/ldiskfs/kernel_patches/patches/ext3-mballoc2-2.6.18-vanilla.patch
new file mode 100644 (file)
index 0000000..0040a6f
--- /dev/null
@@ -0,0 +1,2810 @@
+Index: linux-stage/fs/ext3/mballoc.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-stage/fs/ext3/mballoc.c      2006-07-16 02:29:49.000000000 +0800
+@@ -0,0 +1,2434 @@
++/*
++ * Copyright (c) 2003-2005, Cluster File Systems, Inc, info@clusterfs.com
++ * Written by Alex Tomas <alex@clusterfs.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public Licens
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-
++ */
++
++
++/*
++ * mballoc.c contains the multiblocks allocation routines
++ */
++
++#include <linux/config.h>
++#include <linux/time.h>
++#include <linux/fs.h>
++#include <linux/namei.h>
++#include <linux/jbd.h>
++#include <linux/ext3_fs.h>
++#include <linux/ext3_jbd.h>
++#include <linux/quotaops.h>
++#include <linux/buffer_head.h>
++#include <linux/module.h>
++#include <linux/swap.h>
++#include <linux/proc_fs.h>
++#include <linux/pagemap.h>
++#include <linux/seq_file.h>
++
++/*
++ * TODO:
++ *   - bitmap read-ahead (proposed by Oleg Drokin aka green)
++ *   - track min/max extents in each group for better group selection
++ *   - mb_mark_used() may allocate chunk right after splitting buddy
++ *   - special flag to advice allocator to look for requested + N blocks
++ *     this may improve interaction between extents and mballoc
++ *   - tree of groups sorted by number of free blocks
++ *   - percpu reservation code (hotpath)
++ *   - error handling
++ */
++
++/*
++ * with AGRESSIVE_CHECK allocator runs consistency checks over
++ * structures. these checks slow things down a lot
++ */
++#define AGGRESSIVE_CHECK__
++
++/*
++ */
++#define MB_DEBUG__
++#ifdef MB_DEBUG
++#define mb_debug(fmt,a...)    printk(fmt, ##a)
++#else
++#define mb_debug(fmt,a...)
++#endif
++
++/*
++ * with EXT3_MB_HISTORY mballoc stores last N allocations in memory
++ * and you can monitor it in /proc/fs/ext3/<dev>/mb_history
++ */
++#define EXT3_MB_HISTORY
++
++/*
++ * How long mballoc can look for a best extent (in found extents)
++ */
++long ext3_mb_max_to_scan = 500;
++
++/*
++ * How long mballoc must look for a best extent
++ */
++long ext3_mb_min_to_scan = 30;
++
++/*
++ * with 'ext3_mb_stats' allocator will collect stats that will be
++ * shown at umount. The collecting costs though!
++ */
++
++long ext3_mb_stats = 1;
++
++#ifdef EXT3_BB_MAX_BLOCKS
++#undef EXT3_BB_MAX_BLOCKS
++#endif
++#define EXT3_BB_MAX_BLOCKS    30
++
++struct ext3_free_metadata {
++      unsigned short group;
++      unsigned short num;
++      unsigned short blocks[EXT3_BB_MAX_BLOCKS];
++      struct list_head list;
++};
++
++struct ext3_group_info {
++      unsigned long   bb_state;
++      unsigned long   bb_tid;
++      struct ext3_free_metadata *bb_md_cur;
++      unsigned short  bb_first_free;
++      unsigned short  bb_free;
++      unsigned short  bb_fragments;
++      unsigned short  bb_counters[];
++};
++
++
++#define EXT3_GROUP_INFO_NEED_INIT_BIT 0
++#define EXT3_GROUP_INFO_LOCKED_BIT    1
++
++#define EXT3_MB_GRP_NEED_INIT(grp)    \
++      (test_bit(EXT3_GROUP_INFO_NEED_INIT_BIT, &(grp)->bb_state))
++
++struct ext3_free_extent {
++      __u16 fe_start;
++      __u16 fe_len;
++      __u16 fe_group;
++};
++
++struct ext3_allocation_context {
++      struct super_block *ac_sb;
++
++      /* search goals */
++      struct ext3_free_extent ac_g_ex;
++      
++      /* the best found extent */
++      struct ext3_free_extent ac_b_ex;
++      
++      /* number of iterations done. we have to track to limit searching */
++      unsigned long ac_ex_scanned;
++      __u16 ac_groups_scanned;
++      __u16 ac_found;
++      __u16 ac_tail;
++      __u16 ac_buddy;
++      __u8 ac_status; 
++      __u8 ac_flags;          /* allocation hints */
++      __u8 ac_criteria;
++      __u8 ac_repeats;
++      __u8 ac_2order;         /* if request is to allocate 2^N blocks and
++                               * N > 0, the field stores N, otherwise 0 */
++};
++
++#define AC_STATUS_CONTINUE    1
++#define AC_STATUS_FOUND               2
++#define AC_STATUS_BREAK               3
++
++struct ext3_mb_history {
++      struct ext3_free_extent goal;   /* goal allocation */
++      struct ext3_free_extent result; /* result allocation */
++      __u16 found;    /* how many extents have been found */
++      __u16 groups;   /* how many groups have been scanned */
++      __u16 tail;     /* what tail broke some buddy */
++      __u16 buddy;    /* buddy the tail ^^^ broke */
++      __u8 cr;        /* which phase the result extent was found at */
++      __u8 merged;
++};
++
++struct ext3_buddy {
++      struct page *bd_buddy_page;
++      void *bd_buddy;
++      struct page *bd_bitmap_page;
++      void *bd_bitmap;
++      struct ext3_group_info *bd_info;
++      struct super_block *bd_sb;
++      __u16 bd_blkbits;
++      __u16 bd_group;
++};
++#define EXT3_MB_BITMAP(e3b)   ((e3b)->bd_bitmap)
++#define EXT3_MB_BUDDY(e3b)    ((e3b)->bd_buddy)
++
++#ifndef EXT3_MB_HISTORY
++#define ext3_mb_store_history(sb,ac)
++#else
++static void ext3_mb_store_history(struct super_block *,
++                              struct ext3_allocation_context *ac);
++#endif
++
++#define in_range(b, first, len)       ((b) >= (first) && (b) <= (first) + (len) - 1)
++
++static struct proc_dir_entry *proc_root_ext3;
++
++int ext3_create (struct inode *, struct dentry *, int, struct nameidata *);
++struct buffer_head * read_block_bitmap(struct super_block *, unsigned int);
++int ext3_new_block_old(handle_t *, struct inode *, unsigned long, int *);
++int ext3_mb_reserve_blocks(struct super_block *, int);
++void ext3_mb_release_blocks(struct super_block *, int);
++void ext3_mb_poll_new_transaction(struct super_block *, handle_t *);
++void ext3_mb_free_committed_blocks(struct super_block *);
++
++#if BITS_PER_LONG == 64
++#define mb_correct_addr_and_bit(bit,addr)             \
++{                                                     \
++      bit += ((unsigned long) addr & 7UL) << 3;       \
++      addr = (void *) ((unsigned long) addr & ~7UL);  \
++}
++#elif BITS_PER_LONG == 32
++#define mb_correct_addr_and_bit(bit,addr)             \
++{                                                     \
++      bit += ((unsigned long) addr & 3UL) << 3;       \
++      addr = (void *) ((unsigned long) addr & ~3UL);  \
++}
++#else
++#error "how many bits you are?!"
++#endif
++
++static inline int mb_test_bit(int bit, void *addr)
++{
++      mb_correct_addr_and_bit(bit,addr);
++      return ext2_test_bit(bit, addr);
++}
++
++static inline void mb_set_bit(int bit, void *addr)
++{
++      mb_correct_addr_and_bit(bit,addr);
++      ext2_set_bit(bit, addr);
++}
++
++static inline void mb_set_bit_atomic(int bit, void *addr)
++{
++      mb_correct_addr_and_bit(bit,addr);
++      ext2_set_bit_atomic(NULL, bit, addr);
++}
++
++static inline void mb_clear_bit(int bit, void *addr)
++{
++      mb_correct_addr_and_bit(bit,addr);
++      ext2_clear_bit(bit, addr);
++}
++
++static inline void mb_clear_bit_atomic(int bit, void *addr)
++{
++      mb_correct_addr_and_bit(bit,addr);
++      ext2_clear_bit_atomic(NULL, bit, addr);
++}
++
++static inline int mb_find_next_zero_bit(void *addr, int max, int start)
++{
++      int fix;
++#if BITS_PER_LONG == 64
++      fix = ((unsigned long) addr & 7UL) << 3;
++      addr = (void *) ((unsigned long) addr & ~7UL);
++#elif BITS_PER_LONG == 32
++      fix = ((unsigned long) addr & 3UL) << 3;
++      addr = (void *) ((unsigned long) addr & ~3UL);
++#else
++#error "how many bits you are?!"
++#endif
++      max += fix;
++      start += fix;
++      return ext2_find_next_zero_bit(addr, max, start) - fix;
++}
++
++static inline void *mb_find_buddy(struct ext3_buddy *e3b, int order, int *max)
++{
++      char *bb;
++
++      J_ASSERT(EXT3_MB_BITMAP(e3b) != EXT3_MB_BUDDY(e3b));
++      J_ASSERT(max != NULL);
++
++      if (order > e3b->bd_blkbits + 1) {
++              *max = 0;
++              return NULL;
++      }
++
++      /* at order 0 we see each particular block */
++      *max = 1 << (e3b->bd_blkbits + 3);
++      if (order == 0)
++              return EXT3_MB_BITMAP(e3b);
++
++      bb = EXT3_MB_BUDDY(e3b) + EXT3_SB(e3b->bd_sb)->s_mb_offsets[order];
++      *max = EXT3_SB(e3b->bd_sb)->s_mb_maxs[order];
++
++      return bb;
++}
++
++#ifdef AGGRESSIVE_CHECK
++
++static void mb_check_buddy(struct ext3_buddy *e3b)
++{
++      int order = e3b->bd_blkbits + 1;
++      int max, max2, i, j, k, count;
++      int fragments = 0, fstart;
++      void *buddy, *buddy2;
++
++      if (!test_opt(e3b->bd_sb, MBALLOC))
++              return;
++
++      {
++              static int mb_check_counter = 0;
++              if (mb_check_counter++ % 300 != 0)
++                      return;
++      }
++      
++      while (order > 1) {
++              buddy = mb_find_buddy(e3b, order, &max);
++              J_ASSERT(buddy);
++              buddy2 = mb_find_buddy(e3b, order - 1, &max2);
++              J_ASSERT(buddy2);
++              J_ASSERT(buddy != buddy2);
++              J_ASSERT(max * 2 == max2);
++
++              count = 0;
++              for (i = 0; i < max; i++) {
++
++                      if (mb_test_bit(i, buddy)) {
++                              /* only single bit in buddy2 may be 1 */
++                              if (!mb_test_bit(i << 1, buddy2))
++                                      J_ASSERT(mb_test_bit((i<<1)+1, buddy2));
++                              else if (!mb_test_bit((i << 1) + 1, buddy2))
++                                      J_ASSERT(mb_test_bit(i << 1, buddy2));
++                              continue;
++                      }
++
++                      /* both bits in buddy2 must be 0 */
++                      J_ASSERT(mb_test_bit(i << 1, buddy2));
++                      J_ASSERT(mb_test_bit((i << 1) + 1, buddy2));
++
++                      for (j = 0; j < (1 << order); j++) {
++                              k = (i * (1 << order)) + j;
++                              J_ASSERT(!mb_test_bit(k, EXT3_MB_BITMAP(e3b)));
++                      }
++                      count++;
++              }
++              J_ASSERT(e3b->bd_info->bb_counters[order] == count);
++              order--;
++      }
++
++      fstart = -1;
++      buddy = mb_find_buddy(e3b, 0, &max);
++      for (i = 0; i < max; i++) {
++              if (!mb_test_bit(i, buddy)) {
++                      J_ASSERT(i >= e3b->bd_info->bb_first_free);
++                      if (fstart == -1) {
++                              fragments++;
++                              fstart = i;
++                      }
++                      continue;
++              }
++              fstart = -1;
++              /* check used bits only */
++              for (j = 0; j < e3b->bd_blkbits + 1; j++) {
++                      buddy2 = mb_find_buddy(e3b, j, &max2);
++                      k = i >> j;
++                      J_ASSERT(k < max2);
++                      J_ASSERT(mb_test_bit(k, buddy2));
++              }
++      }
++      J_ASSERT(!EXT3_MB_GRP_NEED_INIT(e3b->bd_info));
++      J_ASSERT(e3b->bd_info->bb_fragments == fragments);
++}
++
++#else
++#define mb_check_buddy(e3b)
++#endif
++
++/* find most significant bit */
++static int inline fmsb(unsigned short word)
++{
++      int order;
++
++      if (word > 255) {
++              order = 7;
++              word >>= 8;
++      } else {
++              order = -1;
++      }
++
++      do {
++              order++;
++              word >>= 1;
++      } while (word != 0);
++
++      return order;
++}
++
++static void inline
++ext3_mb_mark_free_simple(struct super_block *sb, void *buddy, unsigned first,
++                              int len, struct ext3_group_info *grp)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      unsigned short min, max, chunk, border;
++
++      mb_debug("mark %u/%u free\n", first, len);
++      J_ASSERT(len < EXT3_BLOCKS_PER_GROUP(sb));
++
++      border = 2 << sb->s_blocksize_bits;
++
++      while (len > 0) {
++              /* find how many blocks can be covered since this position */
++              max = ffs(first | border) - 1;
++
++              /* find how many blocks of power 2 we need to mark */
++              min = fmsb(len);
++
++              mb_debug("  %u/%u -> max %u, min %u\n",
++                      first & ((2 << sb->s_blocksize_bits) - 1),
++                      len, max, min);
++
++              if (max < min)
++                      min = max;
++              chunk = 1 << min;
++
++              /* mark multiblock chunks only */
++              grp->bb_counters[min]++;
++              if (min > 0) {
++                      mb_debug("    set %u at %u \n", first >> min,
++                              sbi->s_mb_offsets[min]);
++                      mb_clear_bit(first >> min, buddy + sbi->s_mb_offsets[min]);
++              }
++
++              len -= chunk;
++              first += chunk;
++      }
++}
++
++static void
++ext3_mb_generate_buddy(struct super_block *sb, void *buddy, void *bitmap,
++                      struct ext3_group_info *grp)
++{
++      unsigned short max = EXT3_BLOCKS_PER_GROUP(sb);
++      unsigned short i = 0, first, len;
++      unsigned free = 0, fragments = 0;
++      unsigned long long period = get_cycles();
++
++      i = mb_find_next_zero_bit(bitmap, max, 0);
++      grp->bb_first_free = i;
++      while (i < max) {
++              fragments++;
++              first = i;
++              i = find_next_bit(bitmap, max, i);
++              len = i - first;
++              free += len;
++              if (len > 1) 
++                      ext3_mb_mark_free_simple(sb, buddy, first, len, grp);
++              else
++                      grp->bb_counters[0]++;
++              if (i < max)
++                      i = mb_find_next_zero_bit(bitmap, max, i);
++      }
++      grp->bb_fragments = fragments;
++
++      /* bb_state shouldn't being modified because all
++       * others waits for init completion on page lock */
++      clear_bit(EXT3_GROUP_INFO_NEED_INIT_BIT, &grp->bb_state);
++      if (free != grp->bb_free) {
++              printk("EXT3-fs: %u blocks in bitmap, %u in group descriptor\n",
++                      free, grp->bb_free);
++              grp->bb_free = free;
++      }
++
++      period = get_cycles() - period;
++      spin_lock(&EXT3_SB(sb)->s_bal_lock);
++      EXT3_SB(sb)->s_mb_buddies_generated++;
++      EXT3_SB(sb)->s_mb_generation_time += period;
++      spin_unlock(&EXT3_SB(sb)->s_bal_lock);
++}
++
++static int ext3_mb_init_cache(struct page *page)
++{
++      int blocksize, blocks_per_page, groups_per_page;
++      int err = 0, i, first_group, first_block;
++      struct super_block *sb;
++      struct buffer_head *bhs;
++      struct buffer_head **bh;
++      struct inode *inode;
++      char *data, *bitmap;
++
++      mb_debug("init page %lu\n", page->index);
++
++      inode = page->mapping->host;
++      sb = inode->i_sb;
++      blocksize = 1 << inode->i_blkbits;
++      blocks_per_page = PAGE_CACHE_SIZE / blocksize;
++      
++      groups_per_page = blocks_per_page >> 1;
++      if (groups_per_page == 0)
++              groups_per_page = 1;
++
++      /* allocate buffer_heads to read bitmaps */
++      if (groups_per_page > 1) {
++              err = -ENOMEM;
++              i = sizeof(struct buffer_head *) * groups_per_page;
++              bh = kmalloc(i, GFP_NOFS);
++              if (bh == NULL)
++                      goto out;
++              memset(bh, 0, i);
++      } else
++              bh = &bhs;
++      
++      first_group = page->index * blocks_per_page / 2;
++      
++      /* read all groups the page covers into the cache */
++      for (i = 0; i < groups_per_page; i++) {
++              struct ext3_group_desc * desc;
++
++              if (first_group + i >= EXT3_SB(sb)->s_groups_count)
++                      break;
++
++              err = -EIO;
++              desc = ext3_get_group_desc(sb, first_group + i, NULL);
++              if (desc == NULL)
++                      goto out;
++
++              err = -ENOMEM;
++              bh[i] = sb_getblk(sb, le32_to_cpu(desc->bg_block_bitmap));
++              if (bh[i] == NULL)
++                      goto out;
++
++              if (buffer_uptodate(bh[i]))
++                      continue;
++
++              lock_buffer(bh[i]);
++              if (buffer_uptodate(bh[i])) {
++                      unlock_buffer(bh[i]);
++                      continue;
++              }
++
++              get_bh(bh[i]);
++              bh[i]->b_end_io = end_buffer_read_sync;
++              submit_bh(READ, bh[i]);
++              mb_debug("read bitmap for group %u\n", first_group + i);
++      }
++
++      /* wait for I/O completion */
++      for (i = 0; i < groups_per_page && bh[i]; i++)
++              wait_on_buffer(bh[i]);
++
++      /* XXX: I/O error handling here */
++
++      first_block = page->index * blocks_per_page;
++      for (i = 0; i < blocks_per_page; i++) {
++              int group;
++
++              group = (first_block + i) >> 1;
++              if (group >= EXT3_SB(sb)->s_groups_count)
++                      break;
++
++              data = page_address(page) + (i * blocksize);
++              bitmap = bh[group - first_group]->b_data;
++
++              if ((first_block + i) & 1) {
++                      /* this is block of buddy */
++                      mb_debug("put buddy for group %u in page %lu/%x\n",
++                              group, page->index, i * blocksize);
++                      memset(data, 0xff, blocksize);
++                      EXT3_SB(sb)->s_group_info[group]->bb_fragments = 0;
++                      memset(EXT3_SB(sb)->s_group_info[group]->bb_counters, 0,
++                              sizeof(unsigned short)*(sb->s_blocksize_bits+2));
++                      ext3_mb_generate_buddy(sb, data, bitmap,
++                                              EXT3_SB(sb)->s_group_info[group]);
++              } else {
++                      /* this is block of bitmap */
++                      mb_debug("put bitmap for group %u in page %lu/%x\n",
++                              group, page->index, i * blocksize);
++                      memcpy(data, bitmap, blocksize);
++              }
++      }
++      SetPageUptodate(page);
++
++out:
++      for (i = 0; i < groups_per_page && bh[i]; i++)
++              brelse(bh[i]);
++      if (bh && bh != &bhs)
++              kfree(bh);
++      return err;
++}
++
++static int ext3_mb_load_buddy(struct super_block *sb, int group,
++              struct ext3_buddy *e3b)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      struct inode *inode = sbi->s_buddy_cache;
++      int blocks_per_page, block, pnum, poff;
++      struct page *page;
++
++      mb_debug("load group %u\n", group);
++
++      blocks_per_page = PAGE_CACHE_SIZE / sb->s_blocksize;
++
++      e3b->bd_blkbits = sb->s_blocksize_bits;
++      e3b->bd_info = sbi->s_group_info[group];
++      e3b->bd_sb = sb;
++      e3b->bd_group = group;
++      e3b->bd_buddy_page = NULL;
++      e3b->bd_bitmap_page = NULL;
++
++      block = group * 2;
++      pnum = block / blocks_per_page;
++      poff = block % blocks_per_page;
++
++      page = find_get_page(inode->i_mapping, pnum);
++      if (page == NULL || !PageUptodate(page)) {
++              if (page)
++                      page_cache_release(page);
++              page = find_or_create_page(inode->i_mapping, pnum, GFP_NOFS);
++              if (page) {
++                      if (!PageUptodate(page))
++                              ext3_mb_init_cache(page);
++                      unlock_page(page);
++              }
++      }
++      if (page == NULL || !PageUptodate(page))
++              goto err;
++      e3b->bd_bitmap_page = page;
++      e3b->bd_bitmap = page_address(page) + (poff * sb->s_blocksize);
++      mark_page_accessed(page);
++
++      block++;
++      pnum = block / blocks_per_page;
++      poff = block % blocks_per_page;
++
++      page = find_get_page(inode->i_mapping, pnum);
++      if (page == NULL || !PageUptodate(page)) {
++              if (page)
++                      page_cache_release(page);
++              page = find_or_create_page(inode->i_mapping, pnum, GFP_NOFS);
++              if (page) {
++                      if (!PageUptodate(page))
++                              ext3_mb_init_cache(page);
++                      unlock_page(page);
++              }
++      }
++      if (page == NULL || !PageUptodate(page))
++              goto err;
++      e3b->bd_buddy_page = page;
++      e3b->bd_buddy = page_address(page) + (poff * sb->s_blocksize);
++      mark_page_accessed(page);
++
++      J_ASSERT(e3b->bd_bitmap_page != NULL);
++      J_ASSERT(e3b->bd_buddy_page != NULL);
++
++      return 0;
++
++err:
++      if (e3b->bd_bitmap_page)
++              page_cache_release(e3b->bd_bitmap_page);
++      if (e3b->bd_buddy_page)
++              page_cache_release(e3b->bd_buddy_page);
++      e3b->bd_buddy = NULL;
++      e3b->bd_bitmap = NULL;
++      return -EIO;
++}
++
++static void ext3_mb_release_desc(struct ext3_buddy *e3b)
++{
++      if (e3b->bd_bitmap_page)
++              page_cache_release(e3b->bd_bitmap_page);
++      if (e3b->bd_buddy_page)
++              page_cache_release(e3b->bd_buddy_page);
++}
++
++
++static inline void
++ext3_lock_group(struct super_block *sb, int group)
++{
++      bit_spin_lock(EXT3_GROUP_INFO_LOCKED_BIT,
++                      &EXT3_SB(sb)->s_group_info[group]->bb_state);
++}
++
++static inline void
++ext3_unlock_group(struct super_block *sb, int group)
++{
++      bit_spin_unlock(EXT3_GROUP_INFO_LOCKED_BIT,
++                      &EXT3_SB(sb)->s_group_info[group]->bb_state);
++}
++
++static int mb_find_order_for_block(struct ext3_buddy *e3b, int block)
++{
++      int order = 1;
++      void *bb;
++
++      J_ASSERT(EXT3_MB_BITMAP(e3b) != EXT3_MB_BUDDY(e3b));
++      J_ASSERT(block < (1 << (e3b->bd_blkbits + 3)));
++
++      bb = EXT3_MB_BUDDY(e3b);
++      while (order <= e3b->bd_blkbits + 1) {
++              block = block >> 1;
++              if (!mb_test_bit(block, bb)) {
++                      /* this block is part of buddy of order 'order' */
++                      return order;
++              }
++              bb += 1 << (e3b->bd_blkbits - order);
++              order++;
++      }
++      return 0;
++}
++
++static inline void mb_clear_bits(void *bm, int cur, int len)
++{
++      __u32 *addr;
++
++      len = cur + len;
++      while (cur < len) {
++              if ((cur & 31) == 0 && (len - cur) >= 32) {
++                      /* fast path: clear whole word at once */
++                      addr = bm + (cur >> 3);
++                      *addr = 0;
++                      cur += 32;
++                      continue;
++              }
++              mb_clear_bit_atomic(cur, bm);
++              cur++;
++      }
++}
++
++static inline void mb_set_bits(void *bm, int cur, int len)
++{
++      __u32 *addr;
++
++      len = cur + len;
++      while (cur < len) {
++              if ((cur & 31) == 0 && (len - cur) >= 32) {
++                      /* fast path: clear whole word at once */
++                      addr = bm + (cur >> 3);
++                      *addr = 0xffffffff;
++                      cur += 32;
++                      continue;
++              }
++              mb_set_bit_atomic(cur, bm);
++              cur++;
++      }
++}
++
++static int mb_free_blocks(struct ext3_buddy *e3b, int first, int count)
++{
++      int block = 0, max = 0, order;
++      void *buddy, *buddy2;
++
++      mb_check_buddy(e3b);
++
++      e3b->bd_info->bb_free += count;
++      if (first < e3b->bd_info->bb_first_free)
++              e3b->bd_info->bb_first_free = first;
++
++      /* let's maintain fragments counter */
++      if (first != 0)
++              block = !mb_test_bit(first - 1, EXT3_MB_BITMAP(e3b));
++      if (first + count < EXT3_SB(e3b->bd_sb)->s_mb_maxs[0])
++              max = !mb_test_bit(first + count, EXT3_MB_BITMAP(e3b));
++      if (block && max)
++              e3b->bd_info->bb_fragments--;
++      else if (!block && !max)
++              e3b->bd_info->bb_fragments++;
++
++      /* let's maintain buddy itself */
++      while (count-- > 0) {
++              block = first++;
++              order = 0;
++
++              J_ASSERT(mb_test_bit(block, EXT3_MB_BITMAP(e3b)));
++              mb_clear_bit(block, EXT3_MB_BITMAP(e3b));
++              e3b->bd_info->bb_counters[order]++;
++
++              /* start of the buddy */
++              buddy = mb_find_buddy(e3b, order, &max);
++
++              do {
++                      block &= ~1UL;
++                      if (mb_test_bit(block, buddy) ||
++                                      mb_test_bit(block + 1, buddy))
++                              break;
++
++                      /* both the buddies are free, try to coalesce them */
++                      buddy2 = mb_find_buddy(e3b, order + 1, &max);
++
++                      if (!buddy2)
++                              break;
++
++                      if (order > 0) {
++                              /* for special purposes, we don't set
++                               * free bits in bitmap */
++                              mb_set_bit(block, buddy);
++                              mb_set_bit(block + 1, buddy);
++                      }
++                      e3b->bd_info->bb_counters[order]--;
++                      e3b->bd_info->bb_counters[order]--;
++
++                      block = block >> 1;
++                      order++;
++                      e3b->bd_info->bb_counters[order]++;
++
++                      mb_clear_bit(block, buddy2);
++                      buddy = buddy2;
++              } while (1);
++      }
++      mb_check_buddy(e3b);
++
++      return 0;
++}
++
++static int mb_find_extent(struct ext3_buddy *e3b, int order, int block,
++                              int needed, struct ext3_free_extent *ex)
++{
++      int next, max, ord;
++      void *buddy;
++
++      J_ASSERT(ex != NULL);
++
++      buddy = mb_find_buddy(e3b, order, &max);
++      J_ASSERT(buddy);
++      J_ASSERT(block < max);
++      if (mb_test_bit(block, buddy)) {
++              ex->fe_len = 0;
++              ex->fe_start = 0;
++              ex->fe_group = 0;
++              return 0;
++      }
++
++      if (likely(order == 0)) {
++              /* find actual order */
++              order = mb_find_order_for_block(e3b, block);
++              block = block >> order;
++      }
++
++      ex->fe_len = 1 << order;
++      ex->fe_start = block << order;
++      ex->fe_group = e3b->bd_group;
++
++      while (needed > ex->fe_len && (buddy = mb_find_buddy(e3b, order, &max))) {
++
++              if (block + 1 >= max)
++                      break;
++
++              next = (block + 1) * (1 << order);
++              if (mb_test_bit(next, EXT3_MB_BITMAP(e3b)))
++                      break;
++
++              ord = mb_find_order_for_block(e3b, next);
++
++              order = ord;
++              block = next >> order;
++              ex->fe_len += 1 << order;
++      }
++
++      J_ASSERT(ex->fe_start + ex->fe_len <= (1 << (e3b->bd_blkbits + 3)));
++      return ex->fe_len;
++}
++
++static int mb_mark_used(struct ext3_buddy *e3b, struct ext3_free_extent *ex)
++{
++      int ord, mlen = 0, max = 0, cur;
++      int start = ex->fe_start;
++      int len = ex->fe_len;
++      unsigned ret = 0;
++      int len0 = len;
++      void *buddy;
++
++      mb_check_buddy(e3b);
++
++      e3b->bd_info->bb_free -= len;
++      if (e3b->bd_info->bb_first_free == start)
++              e3b->bd_info->bb_first_free += len;
++
++      /* let's maintain fragments counter */
++      if (start != 0)
++              mlen = !mb_test_bit(start - 1, EXT3_MB_BITMAP(e3b));
++      if (start + len < EXT3_SB(e3b->bd_sb)->s_mb_maxs[0])
++              max = !mb_test_bit(start + len, EXT3_MB_BITMAP(e3b));
++      if (mlen && max)
++              e3b->bd_info->bb_fragments++;
++      else if (!mlen && !max)
++              e3b->bd_info->bb_fragments--;
++
++      /* let's maintain buddy itself */
++      while (len) {
++              ord = mb_find_order_for_block(e3b, start);
++
++              if (((start >> ord) << ord) == start && len >= (1 << ord)) {
++                      /* the whole chunk may be allocated at once! */
++                      mlen = 1 << ord;
++                      buddy = mb_find_buddy(e3b, ord, &max);
++                      J_ASSERT((start >> ord) < max);
++                      mb_set_bit(start >> ord, buddy);
++                      e3b->bd_info->bb_counters[ord]--;
++                      start += mlen;
++                      len -= mlen;
++                      J_ASSERT(len >= 0);
++                      continue;
++              }
++
++              /* store for history */
++              if (ret == 0)
++                      ret = len | (ord << 16);
++
++              /* we have to split large buddy */
++              J_ASSERT(ord > 0);
++              buddy = mb_find_buddy(e3b, ord, &max);
++              mb_set_bit(start >> ord, buddy);
++              e3b->bd_info->bb_counters[ord]--;
++
++              ord--;
++              cur = (start >> ord) & ~1U;
++              buddy = mb_find_buddy(e3b, ord, &max);
++              mb_clear_bit(cur, buddy);
++              mb_clear_bit(cur + 1, buddy);
++              e3b->bd_info->bb_counters[ord]++;
++              e3b->bd_info->bb_counters[ord]++;
++      }
++
++      /* now drop all the bits in bitmap */
++      mb_set_bits(EXT3_MB_BITMAP(e3b), ex->fe_start, len0);
++
++      mb_check_buddy(e3b);
++
++      return ret;
++}
++
++/*
++ * Must be called under group lock!
++ */
++static void ext3_mb_use_best_found(struct ext3_allocation_context *ac,
++                                      struct ext3_buddy *e3b)
++{
++      unsigned long ret;
++
++      ac->ac_b_ex.fe_len = min(ac->ac_b_ex.fe_len, ac->ac_g_ex.fe_len);
++      ret = mb_mark_used(e3b, &ac->ac_b_ex);
++
++      ac->ac_status = AC_STATUS_FOUND;
++      ac->ac_tail = ret & 0xffff;
++      ac->ac_buddy = ret >> 16;
++}
++
++/*
++ * The routine checks whether found extent is good enough. If it is,
++ * then the extent gets marked used and flag is set to the context
++ * to stop scanning. Otherwise, the extent is compared with the
++ * previous found extent and if new one is better, then it's stored
++ * in the context. Later, the best found extent will be used, if
++ * mballoc can't find good enough extent.
++ *
++ * FIXME: real allocation policy is to be designed yet!
++ */
++static void ext3_mb_measure_extent(struct ext3_allocation_context *ac,
++                                      struct ext3_free_extent *ex,
++                                      struct ext3_buddy *e3b)
++{
++      struct ext3_free_extent *bex = &ac->ac_b_ex;
++      struct ext3_free_extent *gex = &ac->ac_g_ex;
++
++      J_ASSERT(ex->fe_len > 0);
++      J_ASSERT(ex->fe_len < (1 << ac->ac_sb->s_blocksize_bits) * 8);
++      J_ASSERT(ex->fe_start < (1 << ac->ac_sb->s_blocksize_bits) * 8);
++
++      ac->ac_found++;
++
++      /*
++       * The special case - take what you catch first
++       */
++      if (unlikely(ac->ac_flags & EXT3_MB_HINT_FIRST)) {
++              *bex = *ex;
++              ext3_mb_use_best_found(ac, e3b);
++              return;
++      }
++
++      /*
++       * Let's check whether the chuck is good enough
++       */
++      if (ex->fe_len == gex->fe_len) {
++              *bex = *ex;
++              ext3_mb_use_best_found(ac, e3b);
++              return;
++      }
++
++      /*
++       * If this is first found extent, just store it in the context
++       */
++      if (bex->fe_len == 0) {
++              *bex = *ex;
++              return;
++      }
++
++      /*
++       * If new found extent is better, store it in the context
++       */
++      if (bex->fe_len < gex->fe_len) {
++              /* if the request isn't satisfied, any found extent
++               * larger than previous best one is better */
++              if (ex->fe_len > bex->fe_len)
++                      *bex = *ex;
++      } else if (ex->fe_len > gex->fe_len) {
++              /* if the request is satisfied, then we try to find
++               * an extent that still satisfy the request, but is
++               * smaller than previous one */
++              *bex = *ex;
++      }
++
++      /*
++       * Let's scan at least few extents and don't pick up a first one
++       */
++      if (bex->fe_len > gex->fe_len && ac->ac_found > ext3_mb_min_to_scan)
++              ac->ac_status = AC_STATUS_BREAK;
++
++      /*
++       * We don't want to scan for a whole year
++       */
++      if (ac->ac_found > ext3_mb_max_to_scan)
++              ac->ac_status = AC_STATUS_BREAK;
++}
++
++static int ext3_mb_try_best_found(struct ext3_allocation_context *ac,
++                                      struct ext3_buddy *e3b)
++{
++      struct ext3_free_extent ex = ac->ac_b_ex;
++      int group = ex.fe_group, max, err;
++
++      J_ASSERT(ex.fe_len > 0);
++      err = ext3_mb_load_buddy(ac->ac_sb, group, e3b);
++      if (err)
++              return err;
++
++      ext3_lock_group(ac->ac_sb, group);
++      max = mb_find_extent(e3b, 0, ex.fe_start, ex.fe_len, &ex);
++      
++      if (max > 0) {
++              ac->ac_b_ex = ex;
++              ext3_mb_use_best_found(ac, e3b);
++      }
++
++      ext3_unlock_group(ac->ac_sb, group);
++
++      ext3_mb_release_desc(e3b);
++
++      return 0;
++}
++
++static int ext3_mb_find_by_goal(struct ext3_allocation_context *ac,
++                              struct ext3_buddy *e3b)
++{
++      int group = ac->ac_g_ex.fe_group, max, err;
++      struct ext3_free_extent ex;
++
++      err = ext3_mb_load_buddy(ac->ac_sb, group, e3b);
++      if (err)
++              return err;
++
++      ext3_lock_group(ac->ac_sb, group);
++      max = mb_find_extent(e3b, 0, ac->ac_g_ex.fe_start,
++                              ac->ac_g_ex.fe_len, &ex);
++      
++      if (max > 0) {
++              J_ASSERT(ex.fe_len > 0);
++              J_ASSERT(ex.fe_group == ac->ac_g_ex.fe_group);
++              J_ASSERT(ex.fe_start == ac->ac_g_ex.fe_start);
++              ac->ac_found++;
++              ac->ac_b_ex = ex;
++              ext3_mb_use_best_found(ac, e3b);
++      }
++      ext3_unlock_group(ac->ac_sb, group);
++
++      ext3_mb_release_desc(e3b);
++
++      return 0;
++}
++
++/*
++ * The routine scans buddy structures (not bitmap!) from given order
++ * to max order and tries to find big enough chunk to satisfy the req
++ */
++static void ext3_mb_simple_scan_group(struct ext3_allocation_context *ac,
++                                      struct ext3_buddy *e3b)
++{
++      struct super_block *sb = ac->ac_sb;
++      struct ext3_group_info *grp = e3b->bd_info;
++      void *buddy;
++      int i, k, max;
++
++      J_ASSERT(ac->ac_2order > 0);
++      for (i = ac->ac_2order; i < sb->s_blocksize_bits + 1; i++) {
++              if (grp->bb_counters[i] == 0)
++                      continue;
++
++              buddy = mb_find_buddy(e3b, i, &max);
++              if (buddy == NULL) {
++                      printk(KERN_ALERT "looking for wrong order?\n");
++                      break;
++              }
++
++              k = mb_find_next_zero_bit(buddy, max, 0);
++              J_ASSERT(k < max);
++
++              ac->ac_found++;
++
++              ac->ac_b_ex.fe_len = 1 << i;
++              ac->ac_b_ex.fe_start = k << i;
++              ac->ac_b_ex.fe_group = e3b->bd_group;
++              
++              ext3_mb_use_best_found(ac, e3b);
++              J_ASSERT(ac->ac_b_ex.fe_len == ac->ac_g_ex.fe_len);
++
++              if (unlikely(ext3_mb_stats))
++                      atomic_inc(&EXT3_SB(sb)->s_bal_2orders);
++
++              break;
++      }
++}
++
++/*
++ * The routine scans the group and measures all found extents.
++ * In order to optimize scanning, caller must pass number of
++ * free blocks in the group, so the routine can know upper limit.
++ */
++static void ext3_mb_complex_scan_group(struct ext3_allocation_context *ac,
++                                      struct ext3_buddy *e3b)
++{
++      struct super_block *sb = ac->ac_sb;
++      void *bitmap = EXT3_MB_BITMAP(e3b);
++      struct ext3_free_extent ex;
++      int i, free;
++
++      free = e3b->bd_info->bb_free;
++      J_ASSERT(free > 0);
++
++      i = e3b->bd_info->bb_first_free;
++
++      while (free && ac->ac_status == AC_STATUS_CONTINUE) {
++              i = mb_find_next_zero_bit(bitmap, sb->s_blocksize * 8, i);
++              if (i >= sb->s_blocksize * 8) {
++                      J_ASSERT(free == 0);
++                      break;
++              }
++
++              mb_find_extent(e3b, 0, i, ac->ac_g_ex.fe_len, &ex);
++              J_ASSERT(ex.fe_len > 0);
++              J_ASSERT(free >= ex.fe_len);
++
++              ext3_mb_measure_extent(ac, &ex, e3b);
++
++              i += ex.fe_len;
++              free -= ex.fe_len;
++      }
++}
++
++static int ext3_mb_good_group(struct ext3_allocation_context *ac,
++                              int group, int cr)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(ac->ac_sb);
++      struct ext3_group_info *grp = sbi->s_group_info[group];
++      unsigned free, fragments, i, bits;
++
++      J_ASSERT(cr >= 0 && cr < 4);
++      J_ASSERT(!EXT3_MB_GRP_NEED_INIT(grp));
++
++      free = grp->bb_free;
++      fragments = grp->bb_fragments;
++      if (free == 0)
++              return 0;
++      if (fragments == 0)
++              return 0;
++
++      switch (cr) {
++              case 0:
++                      J_ASSERT(ac->ac_2order != 0);
++                      bits = ac->ac_sb->s_blocksize_bits + 1;
++                      for (i = ac->ac_2order; i < bits; i++)
++                              if (grp->bb_counters[i] > 0)
++                                      return 1;
++              case 1:
++                      if ((free / fragments) >= ac->ac_g_ex.fe_len)
++                              return 1;
++              case 2:
++                      if (free >= ac->ac_g_ex.fe_len)
++                              return 1;
++              case 3:
++                      return 1;
++              default:
++                      BUG();
++      }
++
++      return 0;
++}
++
++int ext3_mb_new_blocks(handle_t *handle, struct inode *inode,
++                     unsigned long goal, int *len, int flags, int *errp)
++{
++      struct buffer_head *bitmap_bh = NULL;
++      struct ext3_allocation_context ac;
++      int i, group, block, cr, err = 0;
++      struct ext3_group_desc *gdp;
++      struct ext3_super_block *es;
++      struct buffer_head *gdp_bh;
++      struct ext3_sb_info *sbi;
++      struct super_block *sb;
++      struct ext3_buddy e3b;
++
++      J_ASSERT(len != NULL);
++      J_ASSERT(*len > 0);
++
++      sb = inode->i_sb;
++      if (!sb) {
++              printk("ext3_mb_new_nblocks: nonexistent device");
++              return 0;
++      }
++
++      if (!test_opt(sb, MBALLOC)) {
++              static int ext3_mballoc_warning = 0;
++              if (ext3_mballoc_warning == 0) {
++                      printk(KERN_ERR "EXT3-fs: multiblock request with "
++                              "mballoc disabled!\n");
++                      ext3_mballoc_warning++;
++              }
++              *len = 1;
++              err = ext3_new_block_old(handle, inode, goal, errp);
++              return err;
++      }
++
++      ext3_mb_poll_new_transaction(sb, handle);
++
++      sbi = EXT3_SB(sb);
++      es = EXT3_SB(sb)->s_es;
++
++      /*
++       * We can't allocate > group size
++       */
++      if (*len >= EXT3_BLOCKS_PER_GROUP(sb) - 10)
++              *len = EXT3_BLOCKS_PER_GROUP(sb) - 10;
++
++      if (!(flags & EXT3_MB_HINT_RESERVED)) {
++              /* someone asks for non-reserved blocks */
++              BUG_ON(*len > 1);
++              err = ext3_mb_reserve_blocks(sb, 1);
++              if (err) {
++                      *errp = err;
++                      return 0;
++              }
++      }
++
++      /*
++       * Check quota for allocation of this blocks.
++       */
++      while (*len && DQUOT_ALLOC_BLOCK(inode, *len))
++              *len -= 1;
++      if (*len == 0) {
++              *errp = -EDQUOT;
++              block = 0;
++              goto out;
++      }
++
++      /* start searching from the goal */
++      if (goal < le32_to_cpu(es->s_first_data_block) ||
++          goal >= le32_to_cpu(es->s_blocks_count))
++              goal = le32_to_cpu(es->s_first_data_block);
++      group = (goal - le32_to_cpu(es->s_first_data_block)) /
++                      EXT3_BLOCKS_PER_GROUP(sb);
++      block = ((goal - le32_to_cpu(es->s_first_data_block)) %
++                      EXT3_BLOCKS_PER_GROUP(sb));
++
++      /* set up allocation goals */
++      ac.ac_b_ex.fe_group = 0;
++      ac.ac_b_ex.fe_start = 0;
++      ac.ac_b_ex.fe_len = 0;
++      ac.ac_status = AC_STATUS_CONTINUE;
++      ac.ac_groups_scanned = 0;
++      ac.ac_ex_scanned = 0;
++      ac.ac_found = 0;
++      ac.ac_sb = inode->i_sb;
++      ac.ac_g_ex.fe_group = group;
++      ac.ac_g_ex.fe_start = block;
++      ac.ac_g_ex.fe_len = *len;
++      ac.ac_flags = flags;
++      ac.ac_2order = 0;
++      ac.ac_criteria = 0;
++
++      /* probably, the request is for 2^8+ blocks (1/2/3/... MB) */
++      i = ffs(*len);
++      if (i >= 8) {
++              i--;
++              if ((*len & (~(1 << i))) == 0)
++                      ac.ac_2order = i;
++      }
++
++      /* Sometimes, caller may want to merge even small
++       * number of blocks to an existing extent */
++      if (ac.ac_flags & EXT3_MB_HINT_MERGE) {
++              err = ext3_mb_find_by_goal(&ac, &e3b);
++              if (err)
++                      goto out_err;
++              if (ac.ac_status == AC_STATUS_FOUND)
++                      goto found;
++      }
++
++      /* Let's just scan groups to find more-less suitable blocks */
++      cr = ac.ac_2order ? 0 : 1;
++repeat:
++      for (; cr < 4 && ac.ac_status == AC_STATUS_CONTINUE; cr++) {
++              ac.ac_criteria = cr;
++              for (i = 0; i < EXT3_SB(sb)->s_groups_count; group++, i++) {
++                      if (group == EXT3_SB(sb)->s_groups_count)
++                              group = 0;
++
++                      if (EXT3_MB_GRP_NEED_INIT(sbi->s_group_info[group])) {
++                              /* we need full data about the group
++                               * to make a good selection */
++                              err = ext3_mb_load_buddy(ac.ac_sb, group, &e3b);
++                              if (err)
++                                      goto out_err;
++                              ext3_mb_release_desc(&e3b);
++                      }
++                              
++                      /* check is group good for our criteries */
++                      if (!ext3_mb_good_group(&ac, group, cr))
++                              continue;
++
++                      err = ext3_mb_load_buddy(ac.ac_sb, group, &e3b);
++                      if (err)
++                              goto out_err;
++
++                      ext3_lock_group(sb, group);
++                      if (!ext3_mb_good_group(&ac, group, cr)) {
++                              /* someone did allocation from this group */
++                              ext3_unlock_group(sb, group);
++                              ext3_mb_release_desc(&e3b);
++                              continue;
++                      }
++
++                      ac.ac_groups_scanned++;
++                      if (cr == 0)
++                              ext3_mb_simple_scan_group(&ac, &e3b);
++                      else
++                              ext3_mb_complex_scan_group(&ac, &e3b);
++
++                      ext3_unlock_group(sb, group);
++
++                      ext3_mb_release_desc(&e3b);
++
++                      if (err)
++                              goto out_err;
++                      if (ac.ac_status != AC_STATUS_CONTINUE)
++                              break;
++              }
++      }
++
++      if (ac.ac_b_ex.fe_len > 0 && ac.ac_status != AC_STATUS_FOUND &&
++                      !(ac.ac_flags & EXT3_MB_HINT_FIRST)) {
++              /*
++               * We've been searching too long. Let's try to allocate
++               * the best chunk we've found so far
++               */
++
++              /*if (ac.ac_found > ext3_mb_max_to_scan)
++                      printk(KERN_ERR "EXT3-fs: too long searching at "
++                              "%u (%d/%d)\n", cr, ac.ac_b_ex.fe_len,
++                              ac.ac_g_ex.fe_len);*/
++              ext3_mb_try_best_found(&ac, &e3b);
++              if (ac.ac_status != AC_STATUS_FOUND) {
++                      /*
++                       * Someone more lucky has already allocated it.
++                       * The only thing we can do is just take first
++                       * found block(s)
++                       */
++                      printk(KERN_ERR "EXT3-fs: and someone won our chunk\n");
++                      ac.ac_b_ex.fe_group = 0;
++                      ac.ac_b_ex.fe_start = 0;
++                      ac.ac_b_ex.fe_len = 0;
++                      ac.ac_status = AC_STATUS_CONTINUE;
++                      ac.ac_flags |= EXT3_MB_HINT_FIRST;
++                      cr = 3;
++                      goto repeat;
++              }
++      }
++
++      if (ac.ac_status != AC_STATUS_FOUND) {
++              /*
++               * We aren't lucky definitely
++               */
++              DQUOT_FREE_BLOCK(inode, *len);
++              *errp = -ENOSPC;
++              block = 0;
++#if 1
++              printk(KERN_ERR "EXT3-fs: cant allocate: status %d, flags %d\n",
++                      ac.ac_status, ac.ac_flags);
++              printk(KERN_ERR "EXT3-fs: goal %d, best found %d/%d/%d, cr %d\n",
++                      ac.ac_g_ex.fe_len, ac.ac_b_ex.fe_group,
++                      ac.ac_b_ex.fe_start, ac.ac_b_ex.fe_len, cr);
++              printk(KERN_ERR "EXT3-fs: %lu block reserved, %d found\n",
++                      sbi->s_blocks_reserved, ac.ac_found);
++              printk("EXT3-fs: groups: ");
++              for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++)
++                      printk("%d: %d ", i,
++                              sbi->s_group_info[i]->bb_free);
++              printk("\n");
++#endif
++              goto out;
++      }
++
++found:
++      J_ASSERT(ac.ac_b_ex.fe_len > 0);
++
++      /* good news - free block(s) have been found. now it's time
++       * to mark block(s) in good old journaled bitmap */
++      block = ac.ac_b_ex.fe_group * EXT3_BLOCKS_PER_GROUP(sb)
++                      + ac.ac_b_ex.fe_start
++                      + le32_to_cpu(es->s_first_data_block);
++
++      /* we made a desicion, now mark found blocks in good old
++       * bitmap to be journaled */
++
++      ext3_debug("using block group %d(%d)\n",
++                      ac.ac_b_group.group, gdp->bg_free_blocks_count);
++
++      bitmap_bh = read_block_bitmap(sb, ac.ac_b_ex.fe_group);
++      if (!bitmap_bh) {
++              *errp = -EIO;
++              goto out_err;
++      }
++
++      err = ext3_journal_get_write_access(handle, bitmap_bh);
++      if (err) {
++              *errp = err;
++              goto out_err;
++      }
++
++      gdp = ext3_get_group_desc(sb, ac.ac_b_ex.fe_group, &gdp_bh);
++      if (!gdp) {
++              *errp = -EIO;
++              goto out_err;
++      }
++      
++      err = ext3_journal_get_write_access(handle, gdp_bh);
++      if (err)
++              goto out_err;
++
++      block = ac.ac_b_ex.fe_group * EXT3_BLOCKS_PER_GROUP(sb)
++                      + ac.ac_b_ex.fe_start
++                      + le32_to_cpu(es->s_first_data_block);
++
++      if (block == le32_to_cpu(gdp->bg_block_bitmap) ||
++          block == le32_to_cpu(gdp->bg_inode_bitmap) ||
++          in_range(block, le32_to_cpu(gdp->bg_inode_table),
++                    EXT3_SB(sb)->s_itb_per_group))
++              ext3_error(sb, "ext3_new_block",
++                          "Allocating block in system zone - "
++                          "block = %u", block);
++#ifdef AGGRESSIVE_CHECK
++      for (i = 0; i < ac.ac_b_ex.fe_len; i++)
++              J_ASSERT(!mb_test_bit(ac.ac_b_ex.fe_start + i, bitmap_bh->b_data));
++#endif
++      mb_set_bits(bitmap_bh->b_data, ac.ac_b_ex.fe_start, ac.ac_b_ex.fe_len);
++
++      spin_lock(sb_bgl_lock(sbi, ac.ac_b_ex.fe_group));
++      gdp->bg_free_blocks_count =
++                      cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count)
++                                      - ac.ac_b_ex.fe_len);
++      spin_unlock(sb_bgl_lock(sbi, ac.ac_b_ex.fe_group));
++      percpu_counter_mod(&sbi->s_freeblocks_counter, - ac.ac_b_ex.fe_len);
++
++      err = ext3_journal_dirty_metadata(handle, bitmap_bh);
++      if (err)
++              goto out_err;
++      err = ext3_journal_dirty_metadata(handle, gdp_bh);
++      if (err)
++              goto out_err;
++
++      sb->s_dirt = 1;
++      *errp = 0;
++      brelse(bitmap_bh);
++
++      /* drop non-allocated, but dquote'd blocks */
++      J_ASSERT(*len >= ac.ac_b_ex.fe_len);
++      DQUOT_FREE_BLOCK(inode, *len - ac.ac_b_ex.fe_len);
++
++      *len = ac.ac_b_ex.fe_len;
++      J_ASSERT(*len > 0);
++      J_ASSERT(block != 0);
++      goto out;
++
++out_err:
++      /* if we've already allocated something, roll it back */
++      if (ac.ac_status == AC_STATUS_FOUND) {
++              /* FIXME: free blocks here */
++      }
++
++      DQUOT_FREE_BLOCK(inode, *len);
++      brelse(bitmap_bh);
++      *errp = err;
++      block = 0;
++out:
++      if (!(flags & EXT3_MB_HINT_RESERVED)) {
++              /* block wasn't reserved before and we reserved it
++               * at the beginning of allocation. it doesn't matter
++               * whether we allocated anything or we failed: time
++               * to release reservation. NOTE: because I expect
++               * any multiblock request from delayed allocation
++               * path only, here is single block always */
++              ext3_mb_release_blocks(sb, 1);
++      }
++      
++      if (unlikely(ext3_mb_stats) && ac.ac_g_ex.fe_len > 1) {
++              atomic_inc(&sbi->s_bal_reqs);
++              atomic_add(*len, &sbi->s_bal_allocated);
++              if (*len >= ac.ac_g_ex.fe_len)
++                      atomic_inc(&sbi->s_bal_success);
++              atomic_add(ac.ac_found, &sbi->s_bal_ex_scanned);
++              if (ac.ac_g_ex.fe_start == ac.ac_b_ex.fe_start &&
++                              ac.ac_g_ex.fe_group == ac.ac_b_ex.fe_group)
++                      atomic_inc(&sbi->s_bal_goals);
++              if (ac.ac_found > ext3_mb_max_to_scan)
++                      atomic_inc(&sbi->s_bal_breaks);
++      }
++
++      ext3_mb_store_history(sb, &ac);
++
++      return block;
++}
++EXPORT_SYMBOL(ext3_mb_new_blocks);
++
++#ifdef EXT3_MB_HISTORY
++struct ext3_mb_proc_session {
++      struct ext3_mb_history *history;
++      struct super_block *sb;
++      int start;
++      int max;
++};
++
++static void *ext3_mb_history_skip_empty(struct ext3_mb_proc_session *s,
++                                      struct ext3_mb_history *hs,
++                                      int first)
++{
++      if (hs == s->history + s->max)
++              hs = s->history;
++      if (!first && hs == s->history + s->start)
++              return NULL;
++      while (hs->goal.fe_len == 0) {
++              hs++;
++              if (hs == s->history + s->max)
++                      hs = s->history;
++              if (hs == s->history + s->start)
++                      return NULL;
++      }
++      return hs;
++}
++
++static void *ext3_mb_seq_history_start(struct seq_file *seq, loff_t *pos)
++{
++      struct ext3_mb_proc_session *s = seq->private;
++      struct ext3_mb_history *hs;
++      int l = *pos;
++
++      if (l == 0)
++              return SEQ_START_TOKEN;
++      hs = ext3_mb_history_skip_empty(s, s->history + s->start, 1);
++      if (!hs)
++              return NULL;
++      while (--l && (hs = ext3_mb_history_skip_empty(s, ++hs, 0)) != NULL);
++      return hs;
++}
++
++static void *ext3_mb_seq_history_next(struct seq_file *seq, void *v, loff_t *pos)
++{
++      struct ext3_mb_proc_session *s = seq->private;
++      struct ext3_mb_history *hs = v;
++
++      ++*pos;
++      if (v == SEQ_START_TOKEN)
++              return ext3_mb_history_skip_empty(s, s->history + s->start, 1);
++      else
++              return ext3_mb_history_skip_empty(s, ++hs, 0);
++}
++
++static int ext3_mb_seq_history_show(struct seq_file *seq, void *v)
++{
++      struct ext3_mb_history *hs = v;
++      char buf[20], buf2[20];
++
++      if (v == SEQ_START_TOKEN) {
++              seq_printf(seq, "%-17s %-17s %-5s %-5s %-2s %-5s %-5s %-6s\n",
++                       "goal", "result", "found", "grps", "cr", "merge",
++                       "tail", "broken");
++              return 0;
++      }
++
++      sprintf(buf, "%u/%u/%u", hs->goal.fe_group,
++              hs->goal.fe_start, hs->goal.fe_len);
++      sprintf(buf2, "%u/%u/%u", hs->result.fe_group,
++              hs->result.fe_start, hs->result.fe_len);
++      seq_printf(seq, "%-17s %-17s %-5u %-5u %-2u %-5s %-5u %-6u\n", buf,
++                      buf2, hs->found, hs->groups, hs->cr, 
++                      hs->merged ? "M" : "", hs->tail,
++                      hs->buddy ? 1 << hs->buddy : 0);
++      return 0;
++}
++
++static void ext3_mb_seq_history_stop(struct seq_file *seq, void *v)
++{
++}
++
++static struct seq_operations ext3_mb_seq_history_ops = {
++      .start  = ext3_mb_seq_history_start,
++      .next   = ext3_mb_seq_history_next,
++      .stop   = ext3_mb_seq_history_stop,
++      .show   = ext3_mb_seq_history_show,
++};
++
++static int ext3_mb_seq_history_open(struct inode *inode, struct file *file)
++{
++      struct super_block *sb = PDE(inode)->data;
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      struct ext3_mb_proc_session *s;
++      int rc, size;
++
++      s = kmalloc(sizeof(*s), GFP_KERNEL);
++      if (s == NULL)
++              return -EIO;
++      size = sizeof(struct ext3_mb_history) * sbi->s_mb_history_max;
++      s->history = kmalloc(size, GFP_KERNEL);
++      if (s == NULL) {
++              kfree(s);
++              return -EIO;
++      }
++
++      spin_lock(&sbi->s_mb_history_lock);
++      memcpy(s->history, sbi->s_mb_history, size);
++      s->max = sbi->s_mb_history_max;
++      s->start = sbi->s_mb_history_cur % s->max;
++      spin_unlock(&sbi->s_mb_history_lock);
++      
++      rc = seq_open(file, &ext3_mb_seq_history_ops);
++      if (rc == 0) {
++              struct seq_file *m = (struct seq_file *)file->private_data;
++              m->private = s;
++      } else {
++              kfree(s->history);
++              kfree(s);
++      }
++      return rc;
++
++}
++
++static int ext3_mb_seq_history_release(struct inode *inode, struct file *file)
++{
++      struct seq_file *seq = (struct seq_file *)file->private_data;
++      struct ext3_mb_proc_session *s = seq->private;
++      kfree(s->history);
++      kfree(s);
++      return seq_release(inode, file);
++}
++
++static struct file_operations ext3_mb_seq_history_fops = {
++      .owner          = THIS_MODULE,
++      .open           = ext3_mb_seq_history_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = ext3_mb_seq_history_release,
++};
++
++static void ext3_mb_history_release(struct super_block *sb)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      char name[64];
++
++      snprintf(name, sizeof(name) - 1, "%s", bdevname(sb->s_bdev, name));
++      remove_proc_entry("mb_history", sbi->s_mb_proc);
++      remove_proc_entry(name, proc_root_ext3);
++
++      if (sbi->s_mb_history)
++              kfree(sbi->s_mb_history);
++}
++
++static void ext3_mb_history_init(struct super_block *sb)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      char name[64];
++      int i;
++
++      snprintf(name, sizeof(name) - 1, "%s", bdevname(sb->s_bdev, name));
++      sbi->s_mb_proc = proc_mkdir(name, proc_root_ext3);
++      if (sbi->s_mb_proc != NULL) {
++              struct proc_dir_entry *p;
++              p = create_proc_entry("mb_history", S_IRUGO, sbi->s_mb_proc);
++              if (p) {
++                      p->proc_fops = &ext3_mb_seq_history_fops;
++                      p->data = sb;
++              }
++      }
++
++      sbi->s_mb_history_max = 1000;
++      sbi->s_mb_history_cur = 0;
++      spin_lock_init(&sbi->s_mb_history_lock);
++      i = sbi->s_mb_history_max * sizeof(struct ext3_mb_history);
++      sbi->s_mb_history = kmalloc(i, GFP_KERNEL);
++      memset(sbi->s_mb_history, 0, i);
++      /* if we can't allocate history, then we simple won't use it */
++}
++
++static void
++ext3_mb_store_history(struct super_block *sb, struct ext3_allocation_context *ac)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      struct ext3_mb_history h;
++
++      if (likely(sbi->s_mb_history == NULL))
++              return;
++
++      h.goal = ac->ac_g_ex;
++      h.result = ac->ac_b_ex;
++      h.found = ac->ac_found;
++      h.cr = ac->ac_criteria;
++      h.groups = ac->ac_groups_scanned;
++      h.tail = ac->ac_tail;
++      h.buddy = ac->ac_buddy;
++      h.merged = 0;
++      if (ac->ac_g_ex.fe_start == ac->ac_b_ex.fe_start &&
++                      ac->ac_g_ex.fe_group == ac->ac_b_ex.fe_group)
++              h.merged = 1;
++
++      spin_lock(&sbi->s_mb_history_lock);
++      memcpy(sbi->s_mb_history + sbi->s_mb_history_cur, &h, sizeof(h));
++      if (++sbi->s_mb_history_cur >= sbi->s_mb_history_max)
++              sbi->s_mb_history_cur = 0;
++      spin_unlock(&sbi->s_mb_history_lock);
++}
++
++#else
++#define ext3_mb_history_release(sb)
++#define ext3_mb_history_init(sb)
++#endif
++
++int ext3_mb_init_backend(struct super_block *sb)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      int i, len;
++
++      len = sizeof(struct ext3_buddy_group_blocks *) * sbi->s_groups_count;
++      sbi->s_group_info = kmalloc(len, GFP_KERNEL);
++      if (sbi->s_group_info == NULL) {
++              printk(KERN_ERR "EXT3-fs: can't allocate mem for buddy\n");
++              return -ENOMEM;
++      }
++      memset(sbi->s_group_info, 0, len);
++
++      sbi->s_buddy_cache = new_inode(sb);
++      if (sbi->s_buddy_cache == NULL) {
++              printk(KERN_ERR "EXT3-fs: can't get new inode\n");
++              kfree(sbi->s_group_info);
++              return -ENOMEM;
++      }
++
++      /* 
++       * calculate needed size. if change bb_counters size,
++       * don't forget about ext3_mb_generate_buddy()
++       */
++      len = sizeof(struct ext3_group_info);
++      len += sizeof(unsigned short) * (sb->s_blocksize_bits + 2);
++      for (i = 0; i < sbi->s_groups_count; i++) {
++              struct ext3_group_desc * desc;
++
++              sbi->s_group_info[i] = kmalloc(len, GFP_KERNEL);
++              if (sbi->s_group_info[i] == NULL) {
++                      printk(KERN_ERR "EXT3-fs: cant allocate mem for buddy\n");
++                      goto err_out;
++              }
++              desc = ext3_get_group_desc(sb, i, NULL);
++              if (desc == NULL) {
++                      printk(KERN_ERR "EXT3-fs: cant read descriptor %u\n", i);
++                      goto err_out;
++              }
++              memset(sbi->s_group_info[i], 0, len);
++              set_bit(EXT3_GROUP_INFO_NEED_INIT_BIT,
++                      &sbi->s_group_info[i]->bb_state);
++              sbi->s_group_info[i]->bb_free =
++                      le16_to_cpu(desc->bg_free_blocks_count);
++      }
++
++      return 0;
++
++err_out:
++      while (--i >= 0)
++              kfree(sbi->s_group_info[i]);
++      iput(sbi->s_buddy_cache);
++
++      return -ENOMEM;
++}
++
++int ext3_mb_init(struct super_block *sb, int needs_recovery)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      struct inode *root = sb->s_root->d_inode;
++      unsigned i, offset, max;
++      struct dentry *dentry;
++
++      if (!test_opt(sb, MBALLOC))
++              return 0;
++
++      i = (sb->s_blocksize_bits + 2) * sizeof(unsigned short);
++
++      sbi->s_mb_offsets = kmalloc(i, GFP_KERNEL);
++      if (sbi->s_mb_offsets == NULL) {
++              clear_opt(sbi->s_mount_opt, MBALLOC);
++              return -ENOMEM;
++      }
++      sbi->s_mb_maxs = kmalloc(i, GFP_KERNEL);
++      if (sbi->s_mb_maxs == NULL) {
++              clear_opt(sbi->s_mount_opt, MBALLOC);
++              kfree(sbi->s_mb_maxs);
++              return -ENOMEM;
++      }
++
++       /* order 0 is regular bitmap */
++      sbi->s_mb_maxs[0] = sb->s_blocksize << 3;
++      sbi->s_mb_offsets[0] = 0;
++
++      i = 1;
++      offset = 0;
++      max = sb->s_blocksize << 2;
++      do {
++              sbi->s_mb_offsets[i] = offset;
++              sbi->s_mb_maxs[i] = max;
++              offset += 1 << (sb->s_blocksize_bits - i);
++              max = max >> 1;
++              i++;
++      } while (i <= sb->s_blocksize_bits + 1);
++      
++
++      /* init file for buddy data */
++      if ((i = ext3_mb_init_backend(sb))) {
++              clear_opt(sbi->s_mount_opt, MBALLOC);
++              kfree(sbi->s_mb_offsets);
++              kfree(sbi->s_mb_maxs);
++              return i;
++      }
++
++      spin_lock_init(&sbi->s_reserve_lock);
++      spin_lock_init(&sbi->s_md_lock);
++      INIT_LIST_HEAD(&sbi->s_active_transaction);
++      INIT_LIST_HEAD(&sbi->s_closed_transaction);
++      INIT_LIST_HEAD(&sbi->s_committed_transaction);
++      spin_lock_init(&sbi->s_bal_lock);
++
++      /* remove old on-disk buddy file */
++      mutex_lock(&root->i_mutex);
++      dentry = lookup_one_len(".buddy", sb->s_root, strlen(".buddy"));
++      if (dentry->d_inode != NULL) {
++              i = vfs_unlink(root, dentry);
++              if (i != 0)
++                      printk("EXT3-fs: can't remove .buddy file: %d\n", i);
++      }
++      dput(dentry);
++      mutex_unlock(&root->i_mutex);
++
++      ext3_mb_history_init(sb);
++
++      printk("EXT3-fs: mballoc enabled\n");
++      return 0;
++}
++
++int ext3_mb_release(struct super_block *sb)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      int i;
++      
++      if (!test_opt(sb, MBALLOC))
++              return 0;
++
++      /* release freed, non-committed blocks */
++      spin_lock(&sbi->s_md_lock);
++      list_splice_init(&sbi->s_closed_transaction,
++                      &sbi->s_committed_transaction);
++      list_splice_init(&sbi->s_active_transaction,
++                      &sbi->s_committed_transaction);
++      spin_unlock(&sbi->s_md_lock);
++      ext3_mb_free_committed_blocks(sb);
++
++      if (sbi->s_group_info) {
++              for (i = 0; i < sbi->s_groups_count; i++) {
++                      if (sbi->s_group_info[i] == NULL)
++                              continue;
++                      kfree(sbi->s_group_info[i]);
++              }
++              kfree(sbi->s_group_info);
++      }
++      if (sbi->s_mb_offsets)
++              kfree(sbi->s_mb_offsets);
++      if (sbi->s_mb_maxs)
++              kfree(sbi->s_mb_maxs);
++      if (sbi->s_buddy_cache)
++              iput(sbi->s_buddy_cache);
++      if (sbi->s_blocks_reserved)
++              printk("ext3-fs: %ld blocks being reserved at umount!\n",
++                              sbi->s_blocks_reserved);
++      if (ext3_mb_stats) {
++              printk("EXT3-fs: mballoc: %u blocks %u reqs (%u success)\n",
++                      atomic_read(&sbi->s_bal_allocated),
++                      atomic_read(&sbi->s_bal_reqs),
++                      atomic_read(&sbi->s_bal_success));
++              printk("EXT3-fs: mballoc: %u extents scanned, %u goal hits, "
++                      "%u 2^N hits, %u breaks\n",
++                      atomic_read(&sbi->s_bal_ex_scanned),
++                      atomic_read(&sbi->s_bal_goals),
++                      atomic_read(&sbi->s_bal_2orders),
++                      atomic_read(&sbi->s_bal_breaks));
++              printk("EXT3-fs: mballoc: %lu generated and it took %Lu\n",
++                      sbi->s_mb_buddies_generated++,
++                      sbi->s_mb_generation_time);
++      }
++
++      ext3_mb_history_release(sb);
++
++      return 0;
++}
++
++void ext3_mb_free_committed_blocks(struct super_block *sb)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      int err, i, count = 0, count2 = 0;
++      struct ext3_free_metadata *md;
++      struct ext3_buddy e3b;
++
++      if (list_empty(&sbi->s_committed_transaction))
++              return;
++
++      /* there is committed blocks to be freed yet */
++      do {
++              /* get next array of blocks */
++              md = NULL;
++              spin_lock(&sbi->s_md_lock);
++              if (!list_empty(&sbi->s_committed_transaction)) {
++                      md = list_entry(sbi->s_committed_transaction.next,
++                                      struct ext3_free_metadata, list);
++                      list_del(&md->list);
++              }
++              spin_unlock(&sbi->s_md_lock);
++
++              if (md == NULL)
++                      break;
++
++              mb_debug("gonna free %u blocks in group %u (0x%p):",
++                              md->num, md->group, md);
++
++              err = ext3_mb_load_buddy(sb, md->group, &e3b);
++              BUG_ON(err != 0);
++
++              /* there are blocks to put in buddy to make them really free */
++              count += md->num;
++              count2++;
++              ext3_lock_group(sb, md->group);
++              for (i = 0; i < md->num; i++) {
++                      mb_debug(" %u", md->blocks[i]);
++                      mb_free_blocks(&e3b, md->blocks[i], 1);
++              }
++              mb_debug("\n");
++              ext3_unlock_group(sb, md->group);
++
++              /* balance refcounts from ext3_mb_free_metadata() */
++              page_cache_release(e3b.bd_buddy_page);
++              page_cache_release(e3b.bd_bitmap_page);
++
++              kfree(md);
++              ext3_mb_release_desc(&e3b);
++
++      } while (md);
++      mb_debug("freed %u blocks in %u structures\n", count, count2);
++}
++
++void ext3_mb_poll_new_transaction(struct super_block *sb, handle_t *handle)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++
++      if (sbi->s_last_transaction == handle->h_transaction->t_tid)
++              return;
++
++      /* new transaction! time to close last one and free blocks for
++       * committed transaction. we know that only transaction can be
++       * active, so previos transaction can be being logged and we
++       * know that transaction before previous is known to be already
++       * logged. this means that now we may free blocks freed in all
++       * transactions before previous one. hope I'm clear enough ... */
++
++      spin_lock(&sbi->s_md_lock);
++      if (sbi->s_last_transaction != handle->h_transaction->t_tid) {
++              mb_debug("new transaction %lu, old %lu\n",
++                              (unsigned long) handle->h_transaction->t_tid,
++                              (unsigned long) sbi->s_last_transaction);
++              list_splice_init(&sbi->s_closed_transaction,
++                                      &sbi->s_committed_transaction);
++              list_splice_init(&sbi->s_active_transaction,
++                                      &sbi->s_closed_transaction);
++              sbi->s_last_transaction = handle->h_transaction->t_tid;
++      }
++      spin_unlock(&sbi->s_md_lock);
++
++      ext3_mb_free_committed_blocks(sb);
++}
++
++int ext3_mb_free_metadata(handle_t *handle, struct ext3_buddy *e3b,
++                              int group, int block, int count)
++{
++      struct ext3_group_info *db = e3b->bd_info;
++      struct super_block *sb = e3b->bd_sb;
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      struct ext3_free_metadata *md;
++      int i;
++
++      J_ASSERT(e3b->bd_bitmap_page != NULL);
++      J_ASSERT(e3b->bd_buddy_page != NULL);
++
++      ext3_lock_group(sb, group);
++      for (i = 0; i < count; i++) {
++              md = db->bb_md_cur;
++              if (md && db->bb_tid != handle->h_transaction->t_tid) {
++                      db->bb_md_cur = NULL;
++                      md = NULL;
++              }
++
++              if (md == NULL) {
++                      ext3_unlock_group(sb, group);
++                      md = kmalloc(sizeof(*md), GFP_KERNEL);
++                      if (md == NULL)
++                              return -ENOMEM;
++                      md->num = 0;
++                      md->group = group;
++
++                      ext3_lock_group(sb, group);
++                      if (db->bb_md_cur == NULL) {
++                              spin_lock(&sbi->s_md_lock);
++                              list_add(&md->list, &sbi->s_active_transaction);
++                              spin_unlock(&sbi->s_md_lock);
++                              /* protect buddy cache from being freed,
++                               * otherwise we'll refresh it from
++                               * on-disk bitmap and lose not-yet-available
++                               * blocks */
++                              page_cache_get(e3b->bd_buddy_page);
++                              page_cache_get(e3b->bd_bitmap_page);
++                              db->bb_md_cur = md;
++                              db->bb_tid = handle->h_transaction->t_tid;
++                              mb_debug("new md 0x%p for group %u\n",
++                                                      md, md->group);
++                      } else {
++                              kfree(md);
++                              md = db->bb_md_cur;
++                      }
++              }
++
++              BUG_ON(md->num >= EXT3_BB_MAX_BLOCKS);
++              md->blocks[md->num] = block + i;
++              md->num++;
++              if (md->num == EXT3_BB_MAX_BLOCKS) {
++                      /* no more space, put full container on a sb's list */
++                      db->bb_md_cur = NULL;
++              }
++      }
++      ext3_unlock_group(sb, group);
++      return 0;
++}
++
++void ext3_mb_free_blocks(handle_t *handle, struct inode *inode,
++                      unsigned long block, unsigned long count,
++                      int metadata, int *freed)
++{
++      struct buffer_head *bitmap_bh = NULL;
++      struct ext3_group_desc *gdp;
++      struct ext3_super_block *es;
++      unsigned long bit, overflow;
++      struct buffer_head *gd_bh;
++      unsigned long block_group;
++      struct ext3_sb_info *sbi;
++      struct super_block *sb;
++      struct ext3_buddy e3b;
++      int err = 0, ret;
++
++      *freed = 0;
++      sb = inode->i_sb;
++      if (!sb) {
++              printk ("ext3_free_blocks: nonexistent device");
++              return;
++      }
++
++      ext3_mb_poll_new_transaction(sb, handle);
++
++      sbi = EXT3_SB(sb);
++      es = EXT3_SB(sb)->s_es;
++      if (block < le32_to_cpu(es->s_first_data_block) ||
++          block + count < block ||
++          block + count > le32_to_cpu(es->s_blocks_count)) {
++              ext3_error (sb, "ext3_free_blocks",
++                          "Freeing blocks not in datazone - "
++                          "block = %lu, count = %lu", block, count);
++              goto error_return;
++      }
++
++      ext3_debug("freeing block %lu\n", block);
++
++do_more:
++      overflow = 0;
++      block_group = (block - le32_to_cpu(es->s_first_data_block)) /
++                    EXT3_BLOCKS_PER_GROUP(sb);
++      bit = (block - le32_to_cpu(es->s_first_data_block)) %
++                    EXT3_BLOCKS_PER_GROUP(sb);
++      /*
++       * Check to see if we are freeing blocks across a group
++       * boundary.
++       */
++      if (bit + count > EXT3_BLOCKS_PER_GROUP(sb)) {
++              overflow = bit + count - EXT3_BLOCKS_PER_GROUP(sb);
++              count -= overflow;
++      }
++      brelse(bitmap_bh);
++      bitmap_bh = read_block_bitmap(sb, block_group);
++      if (!bitmap_bh)
++              goto error_return;
++      gdp = ext3_get_group_desc (sb, block_group, &gd_bh);
++      if (!gdp)
++              goto error_return;
++
++      if (in_range (le32_to_cpu(gdp->bg_block_bitmap), block, count) ||
++          in_range (le32_to_cpu(gdp->bg_inode_bitmap), block, count) ||
++          in_range (block, le32_to_cpu(gdp->bg_inode_table),
++                    EXT3_SB(sb)->s_itb_per_group) ||
++          in_range (block + count - 1, le32_to_cpu(gdp->bg_inode_table),
++                    EXT3_SB(sb)->s_itb_per_group))
++              ext3_error (sb, "ext3_free_blocks",
++                          "Freeing blocks in system zones - "
++                          "Block = %lu, count = %lu",
++                          block, count);
++
++      BUFFER_TRACE(bitmap_bh, "getting write access");
++      err = ext3_journal_get_write_access(handle, bitmap_bh);
++      if (err)
++              goto error_return;
++
++      /*
++       * We are about to modify some metadata.  Call the journal APIs
++       * to unshare ->b_data if a currently-committing transaction is
++       * using it
++       */
++      BUFFER_TRACE(gd_bh, "get_write_access");
++      err = ext3_journal_get_write_access(handle, gd_bh);
++      if (err)
++              goto error_return;
++
++      err = ext3_mb_load_buddy(sb, block_group, &e3b);
++      if (err)
++              goto error_return;
++
++#ifdef AGGRESSIVE_CHECK
++      {
++              int i;
++              for (i = 0; i < count; i++)
++                      J_ASSERT(mb_test_bit(bit + i, bitmap_bh->b_data));
++      }
++#endif
++      mb_clear_bits(bitmap_bh->b_data, bit, count);
++
++      /* We dirtied the bitmap block */
++      BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");
++      err = ext3_journal_dirty_metadata(handle, bitmap_bh);
++
++      if (metadata) {
++              /* blocks being freed are metadata. these blocks shouldn't
++               * be used until this transaction is committed */
++              ext3_mb_free_metadata(handle, &e3b, block_group, bit, count);
++      } else { 
++              ext3_lock_group(sb, block_group);
++              mb_free_blocks(&e3b, bit, count);
++              ext3_unlock_group(sb, block_group);
++      }
++
++      spin_lock(sb_bgl_lock(sbi, block_group));
++      gdp->bg_free_blocks_count =
++              cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) + count);
++      spin_unlock(sb_bgl_lock(sbi, block_group));
++      percpu_counter_mod(&sbi->s_freeblocks_counter, count);
++      
++      ext3_mb_release_desc(&e3b);
++
++      *freed = count;
++
++      /* And the group descriptor block */
++      BUFFER_TRACE(gd_bh, "dirtied group descriptor block");
++      ret = ext3_journal_dirty_metadata(handle, gd_bh);
++      if (!err) err = ret;
++
++      if (overflow && !err) {
++              block += count;
++              count = overflow;
++              goto do_more;
++      }
++      sb->s_dirt = 1;
++error_return:
++      brelse(bitmap_bh);
++      ext3_std_error(sb, err);
++      return;
++}
++
++int ext3_mb_reserve_blocks(struct super_block *sb, int blocks)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      int free, ret = -ENOSPC;
++
++      BUG_ON(blocks < 0);
++      spin_lock(&sbi->s_reserve_lock);
++      free = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
++      if (blocks <= free - sbi->s_blocks_reserved) {
++              sbi->s_blocks_reserved += blocks;
++              ret = 0;
++      }
++      spin_unlock(&sbi->s_reserve_lock);
++      return ret;
++}
++
++void ext3_mb_release_blocks(struct super_block *sb, int blocks)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++
++      BUG_ON(blocks < 0);
++      spin_lock(&sbi->s_reserve_lock);
++      sbi->s_blocks_reserved -= blocks;
++      WARN_ON(sbi->s_blocks_reserved < 0);
++      if (sbi->s_blocks_reserved < 0)
++              sbi->s_blocks_reserved = 0;
++      spin_unlock(&sbi->s_reserve_lock);
++}
++
++int ext3_new_block(handle_t *handle, struct inode *inode,
++              unsigned long goal, int *errp)
++{
++      int ret, len;
++
++      if (!test_opt(inode->i_sb, MBALLOC)) {
++              ret = ext3_new_block_old(handle, inode, goal, errp);
++              goto out;
++      }
++      len = 1;
++      ret = ext3_mb_new_blocks(handle, inode, goal, &len, 0, errp);
++out:
++      return ret;
++}
++
++
++void ext3_free_blocks(handle_t *handle, struct inode * inode,
++                      unsigned long block, unsigned long count, int metadata)
++{
++      struct super_block *sb;
++      int freed;
++
++      sb = inode->i_sb;
++      if (!test_opt(sb, MBALLOC))
++              ext3_free_blocks_sb(handle, sb, block, count, &freed);
++      else
++              ext3_mb_free_blocks(handle, inode, block, count, metadata, &freed);
++      if (freed)
++              DQUOT_FREE_BLOCK(inode, freed);
++      return;
++}
++
++#define EXT3_ROOT                 "ext3"
++#define EXT3_MB_STATS_NAME        "mb_stats"
++#define EXT3_MB_MAX_TO_SCAN_NAME  "mb_max_to_scan"
++#define EXT3_MB_MIN_TO_SCAN_NAME  "mb_min_to_scan"
++
++static int ext3_mb_stats_read(char *page, char **start, off_t off,
++              int count, int *eof, void *data)
++{
++      int len;
++
++      *eof = 1;
++      if (off != 0)
++              return 0;
++
++      len = sprintf(page, "%ld\n", ext3_mb_stats);
++      *start = page;
++      return len;
++}
++
++static int ext3_mb_stats_write(struct file *file, const char *buffer,
++              unsigned long count, void *data)
++{
++      char str[32];
++
++      if (count >= sizeof(str)) {
++              printk(KERN_ERR "EXT3: %s string to long, max %u bytes\n",
++                     EXT3_MB_STATS_NAME, (int)sizeof(str));
++              return -EOVERFLOW;
++      }
++
++      if (copy_from_user(str, buffer, count))
++              return -EFAULT;
++
++      /* Only set to 0 or 1 respectively; zero->0; non-zero->1 */
++      ext3_mb_stats = (simple_strtol(str, NULL, 0) != 0);
++      return count;
++}
++
++static int ext3_mb_max_to_scan_read(char *page, char **start, off_t off,
++              int count, int *eof, void *data)
++{
++      int len;
++
++      *eof = 1;
++      if (off != 0)
++              return 0;
++
++      len = sprintf(page, "%ld\n", ext3_mb_max_to_scan);
++      *start = page;
++      return len;
++}
++
++static int ext3_mb_max_to_scan_write(struct file *file, const char *buffer,
++              unsigned long count, void *data)
++{
++      char str[32];
++      long value;
++
++      if (count >= sizeof(str)) {
++              printk(KERN_ERR "EXT3: %s string to long, max %u bytes\n",
++                     EXT3_MB_MAX_TO_SCAN_NAME, (int)sizeof(str));
++              return -EOVERFLOW;
++      }
++
++      if (copy_from_user(str, buffer, count))
++              return -EFAULT;
++
++      /* Only set to 0 or 1 respectively; zero->0; non-zero->1 */
++      value = simple_strtol(str, NULL, 0);
++      if (value <= 0)
++              return -ERANGE;
++
++      ext3_mb_max_to_scan = value;    
++
++      return count;
++}
++
++static int ext3_mb_min_to_scan_read(char *page, char **start, off_t off,
++              int count, int *eof, void *data)
++{
++      int len;
++
++      *eof = 1;
++      if (off != 0)
++              return 0;
++
++      len = sprintf(page, "%ld\n", ext3_mb_min_to_scan);
++      *start = page;
++      return len;
++}
++
++static int ext3_mb_min_to_scan_write(struct file *file, const char *buffer,
++              unsigned long count, void *data)
++{
++      char str[32];
++      long value;
++
++      if (count >= sizeof(str)) {
++              printk(KERN_ERR "EXT3: %s string to long, max %u bytes\n",
++                     EXT3_MB_MIN_TO_SCAN_NAME, (int)sizeof(str));
++              return -EOVERFLOW;
++      }
++
++      if (copy_from_user(str, buffer, count))
++              return -EFAULT;
++
++      /* Only set to 0 or 1 respectively; zero->0; non-zero->1 */
++      value = simple_strtol(str, NULL, 0);
++      if (value <= 0)
++              return -ERANGE;
++
++      ext3_mb_min_to_scan = value;    
++
++      return count;
++}
++
++int __init init_ext3_proc(void)
++{
++      struct proc_dir_entry *proc_ext3_mb_stats;
++      struct proc_dir_entry *proc_ext3_mb_max_to_scan;
++      struct proc_dir_entry *proc_ext3_mb_min_to_scan;
++
++      proc_root_ext3 = proc_mkdir(EXT3_ROOT, proc_root_fs);
++      if (proc_root_ext3 == NULL) {
++              printk(KERN_ERR "EXT3: Unable to create %s\n", EXT3_ROOT);
++              return -EIO;
++      }
++
++      /* Initialize EXT3_MB_STATS_NAME */
++      proc_ext3_mb_stats = create_proc_entry(EXT3_MB_STATS_NAME,
++                      S_IFREG | S_IRUGO | S_IWUSR, proc_root_ext3);
++      if (proc_ext3_mb_stats == NULL) {
++              printk(KERN_ERR "EXT3: Unable to create %s\n",
++                              EXT3_MB_STATS_NAME);
++              remove_proc_entry(EXT3_ROOT, proc_root_fs);
++              return -EIO;
++      }
++
++      proc_ext3_mb_stats->data = NULL;
++      proc_ext3_mb_stats->read_proc  = ext3_mb_stats_read;
++      proc_ext3_mb_stats->write_proc = ext3_mb_stats_write;
++
++      /* Initialize EXT3_MAX_TO_SCAN_NAME */
++      proc_ext3_mb_max_to_scan = create_proc_entry(
++                      EXT3_MB_MAX_TO_SCAN_NAME,
++                      S_IFREG | S_IRUGO | S_IWUSR, proc_root_ext3);
++      if (proc_ext3_mb_max_to_scan == NULL) {
++              printk(KERN_ERR "EXT3: Unable to create %s\n",
++                              EXT3_MB_MAX_TO_SCAN_NAME);
++              remove_proc_entry(EXT3_MB_STATS_NAME, proc_root_ext3);
++              remove_proc_entry(EXT3_ROOT, proc_root_fs);
++              return -EIO;
++      }
++
++      proc_ext3_mb_max_to_scan->data = NULL;
++      proc_ext3_mb_max_to_scan->read_proc  = ext3_mb_max_to_scan_read;
++      proc_ext3_mb_max_to_scan->write_proc = ext3_mb_max_to_scan_write;
++
++      /* Initialize EXT3_MIN_TO_SCAN_NAME */
++      proc_ext3_mb_min_to_scan = create_proc_entry(
++                      EXT3_MB_MIN_TO_SCAN_NAME,
++                      S_IFREG | S_IRUGO | S_IWUSR, proc_root_ext3);
++      if (proc_ext3_mb_min_to_scan == NULL) {
++              printk(KERN_ERR "EXT3: Unable to create %s\n",
++                              EXT3_MB_MIN_TO_SCAN_NAME);
++              remove_proc_entry(EXT3_MB_MAX_TO_SCAN_NAME, proc_root_ext3);
++              remove_proc_entry(EXT3_MB_STATS_NAME, proc_root_ext3);
++              remove_proc_entry(EXT3_ROOT, proc_root_fs);
++              return -EIO;
++      }
++
++      proc_ext3_mb_min_to_scan->data = NULL;
++      proc_ext3_mb_min_to_scan->read_proc  = ext3_mb_min_to_scan_read;
++      proc_ext3_mb_min_to_scan->write_proc = ext3_mb_min_to_scan_write;
++
++      return 0;
++}
++
++void exit_ext3_proc(void)
++{
++      remove_proc_entry(EXT3_MB_STATS_NAME, proc_root_ext3);
++      remove_proc_entry(EXT3_MB_MAX_TO_SCAN_NAME, proc_root_ext3);
++      remove_proc_entry(EXT3_MB_MIN_TO_SCAN_NAME, proc_root_ext3);
++      remove_proc_entry(EXT3_ROOT, proc_root_fs);
++}
++
+Index: linux-stage/fs/ext3/extents.c
+===================================================================
+--- linux-stage.orig/fs/ext3/extents.c 2006-07-16 02:29:43.000000000 +0800
++++ linux-stage/fs/ext3/extents.c      2006-07-16 02:29:49.000000000 +0800
+@@ -771,7 +771,7 @@ cleanup:
+               for (i = 0; i < depth; i++) {
+                       if (!ablocks[i])
+                               continue;
+-                      ext3_free_blocks(handle, tree->inode, ablocks[i], 1);
++                      ext3_free_blocks(handle, tree->inode, ablocks[i], 1, 1);
+               }
+       }
+       kfree(ablocks);
+@@ -1428,7 +1428,7 @@ int ext3_ext_rm_idx(handle_t *handle, st
+                 path->p_idx->ei_leaf);
+       bh = sb_find_get_block(tree->inode->i_sb, path->p_idx->ei_leaf);
+       ext3_forget(handle, 1, tree->inode, bh, path->p_idx->ei_leaf);
+-      ext3_free_blocks(handle, tree->inode, path->p_idx->ei_leaf, 1);
++      ext3_free_blocks(handle, tree->inode, path->p_idx->ei_leaf, 1, 1);
+       return err;
+ }
+@@ -1913,10 +1913,12 @@ ext3_remove_blocks(struct ext3_extents_t
+       int needed = ext3_remove_blocks_credits(tree, ex, from, to);
+       handle_t *handle = ext3_journal_start(tree->inode, needed);
+       struct buffer_head *bh;
+-      int i;
++      int i, metadata = 0;
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
++      if (S_ISDIR(tree->inode->i_mode) || S_ISLNK(tree->inode->i_mode))
++              metadata = 1;
+       if (from >= ex->ee_block && to == ex->ee_block + ex->ee_len - 1) {
+               /* tail removal */
+               unsigned long num, start;
+@@ -1928,7 +1930,7 @@ ext3_remove_blocks(struct ext3_extents_t
+                       bh = sb_find_get_block(tree->inode->i_sb, start + i);
+                       ext3_forget(handle, 0, tree->inode, bh, start + i);
+               }
+-              ext3_free_blocks(handle, tree->inode, start, num);
++              ext3_free_blocks(handle, tree->inode, start, num, metadata);
+       } else if (from == ex->ee_block && to <= ex->ee_block + ex->ee_len - 1) {
+               printk("strange request: removal %lu-%lu from %u:%u\n",
+                      from, to, ex->ee_block, ex->ee_len);
+Index: linux-stage/fs/ext3/xattr.c
+===================================================================
+--- linux-stage.orig/fs/ext3/xattr.c   2006-07-16 02:29:43.000000000 +0800
++++ linux-stage/fs/ext3/xattr.c        2006-07-16 02:29:49.000000000 +0800
+@@ -484,7 +484,7 @@ ext3_xattr_release_block(handle_t *handl
+               ea_bdebug(bh, "refcount now=0; freeing");
+               if (ce)
+                       mb_cache_entry_free(ce);
+-              ext3_free_blocks(handle, inode, bh->b_blocknr, 1);
++              ext3_free_blocks(handle, inode, bh->b_blocknr, 1, 1);
+               get_bh(bh);
+               ext3_forget(handle, 1, inode, bh, bh->b_blocknr);
+       } else {
+@@ -805,7 +805,7 @@ inserted:
+                       new_bh = sb_getblk(sb, block);
+                       if (!new_bh) {
+ getblk_failed:
+-                              ext3_free_blocks(handle, inode, block, 1);
++                              ext3_free_blocks(handle, inode, block, 1, 1);
+                               error = -EIO;
+                               goto cleanup;
+                       }
+Index: linux-stage/fs/ext3/balloc.c
+===================================================================
+--- linux-stage.orig/fs/ext3/balloc.c  2006-07-16 02:29:43.000000000 +0800
++++ linux-stage/fs/ext3/balloc.c       2006-07-16 02:33:13.000000000 +0800
+@@ -79,7 +79,7 @@ struct ext3_group_desc * ext3_get_group_
+  *
+  * Return buffer_head on success or NULL in case of failure.
+  */
+-static struct buffer_head *
++struct buffer_head *
+ read_block_bitmap(struct super_block *sb, unsigned int block_group)
+ {
+       struct ext3_group_desc * desc;
+@@ -490,24 +490,6 @@ error_return:
+       return;
+ }
+-/* Free given blocks, update quota and i_blocks field */
+-void ext3_free_blocks(handle_t *handle, struct inode *inode,
+-                      ext3_fsblk_t block, unsigned long count)
+-{
+-      struct super_block * sb;
+-      unsigned long dquot_freed_blocks;
+-
+-      sb = inode->i_sb;
+-      if (!sb) {
+-              printk ("ext3_free_blocks: nonexistent device");
+-              return;
+-      }
+-      ext3_free_blocks_sb(handle, sb, block, count, &dquot_freed_blocks);
+-      if (dquot_freed_blocks)
+-              DQUOT_FREE_BLOCK(inode, dquot_freed_blocks);
+-      return;
+-}
+-
+ /*
+  * For ext3 allocations, we must not reuse any blocks which are
+  * allocated in the bitmap buffer's "last committed data" copy.  This
+@@ -1463,7 +1445,7 @@ out:
+       return 0;
+ }
+-ext3_fsblk_t ext3_new_block(handle_t *handle, struct inode *inode,
++ext3_fsblk_t ext3_new_block_old(handle_t *handle, struct inode *inode,
+                       ext3_fsblk_t goal, int *errp)
+ {
+       unsigned long count = 1;
+Index: linux-stage/fs/ext3/super.c
+===================================================================
+--- linux-stage.orig/fs/ext3/super.c   2006-07-16 02:29:43.000000000 +0800
++++ linux-stage/fs/ext3/super.c        2006-07-16 02:29:49.000000000 +0800
+@@ -391,6 +391,7 @@ static void ext3_put_super (struct super
+       struct ext3_super_block *es = sbi->s_es;
+       int i;
++      ext3_mb_release(sb);
+       ext3_ext_release(sb);
+       ext3_xattr_put_super(sb);
+       journal_destroy(sbi->s_journal);
+@@ -641,7 +642,7 @@ enum {
+       Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
+       Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
+       Opt_iopen, Opt_noiopen, Opt_iopen_nopriv,
+-      Opt_extents, Opt_extdebug,
++      Opt_extents, Opt_extdebug, Opt_mballoc,
+       Opt_grpquota
+ };
+@@ -696,6 +697,7 @@ static match_table_t tokens = {
+       {Opt_iopen_nopriv, "iopen_nopriv"},
+       {Opt_extents, "extents"},
+       {Opt_extdebug, "extdebug"},
++      {Opt_mballoc, "mballoc"},
+       {Opt_barrier, "barrier=%u"},
+       {Opt_err, NULL},
+       {Opt_resize, "resize"},
+@@ -1047,6 +1049,9 @@ clear_qf_name:
+               case Opt_extdebug:
+                       set_opt (sbi->s_mount_opt, EXTDEBUG);
+                       break;
++              case Opt_mballoc:
++                      set_opt (sbi->s_mount_opt, MBALLOC);
++                      break;
+               default:
+                       printk (KERN_ERR
+                               "EXT3-fs: Unrecognized mount option \"%s\" "
+@@ -1773,6 +1778,7 @@ static int ext3_fill_super (struct super
+               "writeback");
+       ext3_ext_init(sb);
++      ext3_mb_init(sb, needs_recovery);
+       lock_kernel();
+       return 0;
+@@ -2712,7 +2718,13 @@ static struct file_system_type ext3_fs_t
+ static int __init init_ext3_fs(void)
+ {
+-      int err = init_ext3_xattr();
++      int err;
++
++      err = init_ext3_proc();
++      if (err)
++              return err;
++
++      err = init_ext3_xattr();
+       if (err)
+               return err;
+       err = init_inodecache();
+@@ -2734,6 +2746,7 @@ static void __exit exit_ext3_fs(void)
+       unregister_filesystem(&ext3_fs_type);
+       destroy_inodecache();
+       exit_ext3_xattr();
++      exit_ext3_proc();
+ }
+ int ext3_prep_san_write(struct inode *inode, long *blocks,
+Index: linux-stage/fs/ext3/Makefile
+===================================================================
+--- linux-stage.orig/fs/ext3/Makefile  2006-07-16 02:29:43.000000000 +0800
++++ linux-stage/fs/ext3/Makefile       2006-07-16 02:29:49.000000000 +0800
+@@ -6,7 +6,7 @@ obj-$(CONFIG_EXT3_FS) += ext3.o
+ ext3-y        := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
+          ioctl.o namei.o super.o symlink.o hash.o resize.o \
+-         extents.o
++         extents.o mballoc.o
+ ext3-$(CONFIG_EXT3_FS_XATTR)   += xattr.o xattr_user.o xattr_trusted.o
+ ext3-$(CONFIG_EXT3_FS_POSIX_ACL) += acl.o
+Index: linux-stage/include/linux/ext3_fs.h
+===================================================================
+--- linux-stage.orig/include/linux/ext3_fs.h   2006-07-16 02:29:43.000000000 +0800
++++ linux-stage/include/linux/ext3_fs.h        2006-07-16 02:29:49.000000000 +0800
+@@ -53,6 +53,14 @@
+ #define ext3_debug(f, a...)   do {} while (0)
+ #endif
++#define EXT3_MULTIBLOCK_ALLOCATOR     1
++
++#define EXT3_MB_HINT_MERGE            1
++#define EXT3_MB_HINT_RESERVED         2
++#define EXT3_MB_HINT_METADATA         4
++#define EXT3_MB_HINT_FIRST            8
++#define EXT3_MB_HINT_BEST             16
++
+ /*
+  * Special inodes numbers
+  */
+@@ -379,6 +387,7 @@ struct ext3_inode {
+ #define EXT3_MOUNT_IOPEN_NOPRIV               0x800000/* Make iopen world-readable */
+ #define EXT3_MOUNT_EXTENTS            0x1000000/* Extents support */
+ #define EXT3_MOUNT_EXTDEBUG           0x2000000/* Extents debug */
++#define EXT3_MOUNT_MBALLOC            0x800000/* Buddy allocation support */
+ /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
+ #ifndef clear_opt
+@@ -749,12 +758,12 @@ ext3_group_first_block_no(struct super_b
+ /* balloc.c */
+ extern int ext3_bg_has_super(struct super_block *sb, int group);
+ extern unsigned long ext3_bg_num_gdb(struct super_block *sb, int group);
+-extern ext3_fsblk_t ext3_new_block (handle_t *handle, struct inode *inode,
+-                      ext3_fsblk_t goal, int *errp);
++//extern ext3_fsblk_t ext3_new_block (handle_t *handle, struct inode *inode,
++//                    ext3_fsblk_t goal, int *errp);
+ extern ext3_fsblk_t ext3_new_blocks (handle_t *handle, struct inode *inode,
+                       ext3_fsblk_t goal, unsigned long *count, int *errp);
+ extern void ext3_free_blocks (handle_t *handle, struct inode *inode,
+-                      ext3_fsblk_t block, unsigned long count);
++                      ext3_fsblk_t block, unsigned long count, int metadata);
+ extern void ext3_free_blocks_sb (handle_t *handle, struct super_block *sb,
+                                ext3_fsblk_t block, unsigned long count,
+                               unsigned long *pdquot_freed_blocks);
+@@ -881,6 +890,17 @@ extern void ext3_extents_initialize_bloc
+ extern int ext3_ext_ioctl(struct inode *inode, struct file *filp,
+                         unsigned int cmd, unsigned long arg);
++/* mballoc.c */
++extern long ext3_mb_stats;
++extern long ext3_mb_max_to_scan;
++extern int ext3_mb_init(struct super_block *, int);
++extern int ext3_mb_release(struct super_block *);
++extern int ext3_mb_new_blocks(handle_t *, struct inode *, unsigned long, int *, int, int *);
++extern int ext3_mb_reserve_blocks(struct super_block *, int);
++extern void ext3_mb_release_blocks(struct super_block *, int);
++int __init init_ext3_proc(void);
++void exit_ext3_proc(void);
++
+ #endif        /* __KERNEL__ */
+ /* EXT3_IOC_CREATE_INUM at bottom of file (visible to kernel and user). */
+Index: linux-stage/include/linux/ext3_fs_sb.h
+===================================================================
+--- linux-stage.orig/include/linux/ext3_fs_sb.h        2006-07-16 02:29:43.000000000 +0800
++++ linux-stage/include/linux/ext3_fs_sb.h     2006-07-16 02:29:49.000000000 +0800
+@@ -21,8 +21,14 @@
+ #include <linux/wait.h>
+ #include <linux/blockgroup_lock.h>
+ #include <linux/percpu_counter.h>
++#include <linux/list.h>
+ #endif
+ #include <linux/rbtree.h>
++#include <linux/proc_fs.h>
++
++struct ext3_buddy_group_blocks;
++struct ext3_mb_history;
++#define EXT3_BB_MAX_BLOCKS
+ /*
+  * third extended-fs super-block data in memory
+@@ -78,6 +84,38 @@ struct ext3_sb_info {
+       char *s_qf_names[MAXQUOTAS];            /* Names of quota files with journalled quota */
+       int s_jquota_fmt;                       /* Format of quota to use */
+ #endif
++
++      /* for buddy allocator */
++      struct ext3_group_info **s_group_info;
++      struct inode *s_buddy_cache;
++      long s_blocks_reserved;
++      spinlock_t s_reserve_lock;
++      struct list_head s_active_transaction;
++      struct list_head s_closed_transaction;
++      struct list_head s_committed_transaction;
++      spinlock_t s_md_lock;
++      tid_t s_last_transaction;
++      int s_mb_factor;
++      unsigned short *s_mb_offsets, *s_mb_maxs;
++
++      /* history to debug policy */
++      struct ext3_mb_history *s_mb_history;
++      int s_mb_history_cur;
++      int s_mb_history_max;
++      struct proc_dir_entry *s_mb_proc;
++      spinlock_t s_mb_history_lock;
++
++      /* stats for buddy allocator */
++      atomic_t s_bal_reqs;    /* number of reqs with len > 1 */
++      atomic_t s_bal_success; /* we found long enough chunks */
++      atomic_t s_bal_allocated;       /* in blocks */
++      atomic_t s_bal_ex_scanned;      /* total extents scanned */
++      atomic_t s_bal_goals;   /* goal hits */
++      atomic_t s_bal_breaks;  /* too long searches */
++      atomic_t s_bal_2orders; /* 2^order hits */
++      spinlock_t s_bal_lock;
++      unsigned long s_mb_buddies_generated;
++      unsigned long long s_mb_generation_time;
+ };
+ #endif        /* _LINUX_EXT3_FS_SB */
+Index: linux-stage/fs/ext3/inode.c
+===================================================================
+--- linux-stage.orig/fs/ext3/inode.c   2006-07-16 02:29:43.000000000 +0800
++++ linux-stage/fs/ext3/inode.c        2006-07-16 02:29:49.000000000 +0800
+@@ -562,7 +562,7 @@ static int ext3_alloc_blocks(handle_t *h
+       return ret;
+ failed_out:
+       for (i = 0; i <index; i++)
+-              ext3_free_blocks(handle, inode, new_blocks[i], 1);
++              ext3_free_blocks(handle, inode, new_blocks[i], 1, 1);
+       return ret;
+ }
+@@ -661,9 +661,9 @@ failed:
+               ext3_journal_forget(handle, branch[i].bh);
+       }
+       for (i = 0; i <indirect_blks; i++)
+-              ext3_free_blocks(handle, inode, new_blocks[i], 1);
++              ext3_free_blocks(handle, inode, new_blocks[i], 1, 1);
+-      ext3_free_blocks(handle, inode, new_blocks[i], num);
++      ext3_free_blocks(handle, inode, new_blocks[i], num, 1);
+       return err;
+ }
+@@ -760,9 +760,9 @@ err_out:
+       for (i = 1; i <= num; i++) {
+               BUFFER_TRACE(where[i].bh, "call journal_forget");
+               ext3_journal_forget(handle, where[i].bh);
+-              ext3_free_blocks(handle,inode,le32_to_cpu(where[i-1].key),1);
++              ext3_free_blocks(handle,inode,le32_to_cpu(where[i-1].key),1,1);
+       }
+-      ext3_free_blocks(handle, inode, le32_to_cpu(where[num].key), blks);
++      ext3_free_blocks(handle, inode, le32_to_cpu(where[num].key), blks, 1);
+       return err;
+ }
+@@ -2007,7 +2007,7 @@ static void ext3_clear_blocks(handle_t *
+               }
+       }
+-      ext3_free_blocks(handle, inode, block_to_free, count);
++      ext3_free_blocks(handle, inode, block_to_free, count, 1);
+ }
+ /**
+@@ -2180,7 +2180,7 @@ static void ext3_free_branches(handle_t 
+                               ext3_journal_test_restart(handle, inode);
+                       }
+-                      ext3_free_blocks(handle, inode, nr, 1);
++                      ext3_free_blocks(handle, inode, nr, 1, 1);
+                       if (parent_bh) {
+                               /*
index 01e7387..e34c411 100644 (file)
@@ -1,7 +1,7 @@
-Index: linux-2.6.9-full/include/linux/ext3_fs.h
+Index: linux-stage/include/linux/ext3_fs.h
 ===================================================================
---- linux-2.6.9-full.orig/include/linux/ext3_fs.h      2005-12-16 23:16:41.000000000 +0300
-+++ linux-2.6.9-full/include/linux/ext3_fs.h   2005-12-16 23:16:42.000000000 +0300
+--- linux-stage.orig/include/linux/ext3_fs.h   2006-05-25 10:36:04.000000000 -0600
++++ linux-stage/include/linux/ext3_fs.h        2006-05-25 10:36:04.000000000 -0600
 @@ -57,6 +57,14 @@ struct statfs;
  #define ext3_debug(f, a...)   do {} while (0)
  #endif
@@ -52,10 +52,10 @@ Index: linux-2.6.9-full/include/linux/ext3_fs.h
  #endif        /* __KERNEL__ */
  
  /* EXT3_IOC_CREATE_INUM at bottom of file (visible to kernel and user). */
-Index: linux-2.6.9-full/include/linux/ext3_fs_sb.h
+Index: linux-stage/include/linux/ext3_fs_sb.h
 ===================================================================
---- linux-2.6.9-full.orig/include/linux/ext3_fs_sb.h   2005-12-16 23:16:39.000000000 +0300
-+++ linux-2.6.9-full/include/linux/ext3_fs_sb.h        2005-12-16 23:16:42.000000000 +0300
+--- linux-stage.orig/include/linux/ext3_fs_sb.h        2006-05-25 10:36:04.000000000 -0600
++++ linux-stage/include/linux/ext3_fs_sb.h     2006-05-25 10:59:14.000000000 -0600
 @@ -23,9 +23,15 @@
  #define EXT_INCLUDE
  #include <linux/blockgroup_lock.h>
@@ -72,13 +72,13 @@ Index: linux-2.6.9-full/include/linux/ext3_fs_sb.h
  
  /*
   * third extended-fs super-block data in memory
-@@ -81,6 +87,38 @@ struct ext3_sb_info {
+@@ -81,6 +87,43 @@ struct ext3_sb_info {
        char *s_qf_names[MAXQUOTAS];            /* Names of quota files with journalled quota */
        int s_jquota_fmt;                       /* Format of quota to use */
  #endif
 +
 +      /* for buddy allocator */
-+      struct ext3_group_info **s_group_info;
++      struct ext3_group_info ***s_group_info;
 +      struct inode *s_buddy_cache;
 +      long s_blocks_reserved;
 +      spinlock_t s_reserve_lock;
@@ -89,6 +89,7 @@ Index: linux-2.6.9-full/include/linux/ext3_fs_sb.h
 +      tid_t s_last_transaction;
 +      int s_mb_factor;
 +      unsigned short *s_mb_offsets, *s_mb_maxs;
++      unsigned long s_stripe;
 +
 +      /* history to debug policy */
 +      struct ext3_mb_history *s_mb_history;
@@ -109,13 +110,17 @@ Index: linux-2.6.9-full/include/linux/ext3_fs_sb.h
 +      unsigned long s_mb_buddies_generated;
 +      unsigned long long s_mb_generation_time;
  };
++
++#define EXT3_GROUP_INFO(sb, group)                                       \
++      EXT3_SB(sb)->s_group_info[(group) >> EXT3_DESC_PER_BLOCK_BITS(sb)] \
++                               [(group) & (EXT3_DESC_PER_BLOCK(sb) - 1)]
  
  #endif        /* _LINUX_EXT3_FS_SB */
-Index: linux-2.6.9-full/fs/ext3/super.c
+Index: linux-stage/fs/ext3/super.c
 ===================================================================
---- linux-2.6.9-full.orig/fs/ext3/super.c      2005-12-16 23:16:41.000000000 +0300
-+++ linux-2.6.9-full/fs/ext3/super.c   2005-12-16 23:16:42.000000000 +0300
-@@ -394,6 +394,7 @@ void ext3_put_super (struct super_block 
+--- linux-stage.orig/fs/ext3/super.c   2006-05-25 10:36:04.000000000 -0600
++++ linux-stage/fs/ext3/super.c        2006-05-25 10:36:04.000000000 -0600
+@@ -394,6 +394,7 @@ void ext3_put_super (struct super_block
        struct ext3_super_block *es = sbi->s_es;
        int i;
  
@@ -123,34 +128,45 @@ Index: linux-2.6.9-full/fs/ext3/super.c
        ext3_ext_release(sb);
        ext3_xattr_put_super(sb);
        journal_destroy(sbi->s_journal);
-@@ -596,7 +597,7 @@ enum {
-       Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0,
+@@ -597,6 +598,7 @@ enum {
        Opt_ignore, Opt_barrier, Opt_err, Opt_resize,
        Opt_iopen, Opt_noiopen, Opt_iopen_nopriv,
--      Opt_extents, Opt_extdebug,
-+      Opt_extents, Opt_extdebug, Opt_mballoc,
+       Opt_extents, Opt_noextents, Opt_extdebug,
++      Opt_mballoc, Opt_nomballoc, Opt_stripe,
  };
  
  static match_table_t tokens = {
-@@ -647,6 +649,7 @@ static match_table_t tokens = {
-       {Opt_iopen_nopriv, "iopen_nopriv"},
+@@ -649,6 +651,9 @@ static match_table_t tokens = {
        {Opt_extents, "extents"},
+       {Opt_noextents, "noextents"},
        {Opt_extdebug, "extdebug"},
 +      {Opt_mballoc, "mballoc"},
++      {Opt_nomballoc, "nomballoc"},
++      {Opt_stripe, "stripe=%u"},
        {Opt_barrier, "barrier=%u"},
        {Opt_err, NULL},
        {Opt_resize, "resize"},
-@@ -957,6 +960,9 @@ clear_qf_name:
+@@ -962,6 +967,19 @@ static int parse_options (char * options
                case Opt_extdebug:
                        set_opt (sbi->s_mount_opt, EXTDEBUG);
                        break;
 +              case Opt_mballoc:
-+                      set_opt (sbi->s_mount_opt, MBALLOC);
++                      set_opt(sbi->s_mount_opt, MBALLOC);
++                      break;
++              case Opt_nomballoc:
++                      clear_opt(sbi->s_mount_opt, MBALLOC);
++                      break;
++              case Opt_stripe:
++                      if (match_int(&args[0], &option))
++                              return 0;
++                      if (option < 0)
++                              return 0;
++                      sbi->s_stripe = option;
 +                      break;
                default:
                        printk (KERN_ERR
                                "EXT3-fs: Unrecognized mount option \"%s\" "
-@@ -1646,6 +1652,7 @@ static int ext3_fill_super (struct super
+@@ -1651,6 +1669,7 @@ static int ext3_fill_super (struct super
                ext3_count_dirs(sb));
  
        ext3_ext_init(sb);
@@ -158,7 +174,7 @@ Index: linux-2.6.9-full/fs/ext3/super.c
  
        return 0;
  
-@@ -2428,7 +2435,13 @@ static struct file_system_type ext3_fs_t
+@@ -2433,7 +2452,13 @@ static struct file_system_type ext3_fs_t
  
  static int __init init_ext3_fs(void)
  {
@@ -173,7 +189,7 @@ Index: linux-2.6.9-full/fs/ext3/super.c
        if (err)
                return err;
        err = init_inodecache();
-@@ -2450,6 +2463,7 @@ static void __exit exit_ext3_fs(void)
+@@ -2455,6 +2480,7 @@ static void __exit exit_ext3_fs(void)
        unregister_filesystem(&ext3_fs_type);
        destroy_inodecache();
        exit_ext3_xattr();
@@ -181,11 +197,11 @@ Index: linux-2.6.9-full/fs/ext3/super.c
  }
  
  int ext3_prep_san_write(struct inode *inode, long *blocks,
-Index: linux-2.6.9-full/fs/ext3/extents.c
+Index: linux-stage/fs/ext3/extents.c
 ===================================================================
---- linux-2.6.9-full.orig/fs/ext3/extents.c    2005-12-16 23:16:41.000000000 +0300
-+++ linux-2.6.9-full/fs/ext3/extents.c 2005-12-16 23:16:42.000000000 +0300
-@@ -771,7 +771,7 @@ cleanup:
+--- linux-stage.orig/fs/ext3/extents.c 2006-05-25 10:36:04.000000000 -0600
++++ linux-stage/fs/ext3/extents.c      2006-05-25 10:36:04.000000000 -0600
+@@ -777,7 +777,7 @@ cleanup:
                for (i = 0; i < depth; i++) {
                        if (!ablocks[i])
                                continue;
@@ -194,7 +210,7 @@ Index: linux-2.6.9-full/fs/ext3/extents.c
                }
        }
        kfree(ablocks);
-@@ -1428,7 +1428,7 @@ int ext3_ext_rm_idx(handle_t *handle, st
+@@ -1434,7 +1434,7 @@ int ext3_ext_rm_idx(handle_t *handle, st
                  path->p_idx->ei_leaf);
        bh = sb_find_get_block(tree->inode->i_sb, path->p_idx->ei_leaf);
        ext3_forget(handle, 1, tree->inode, bh, path->p_idx->ei_leaf);
@@ -203,7 +219,7 @@ Index: linux-2.6.9-full/fs/ext3/extents.c
        return err;
  }
  
-@@ -1913,10 +1913,12 @@ ext3_remove_blocks(struct ext3_extents_t
+@@ -1919,10 +1919,12 @@ ext3_remove_blocks(struct ext3_extents_t
        int needed = ext3_remove_blocks_credits(tree, ex, from, to);
        handle_t *handle = ext3_journal_start(tree->inode, needed);
        struct buffer_head *bh;
@@ -217,7 +233,7 @@ Index: linux-2.6.9-full/fs/ext3/extents.c
        if (from >= ex->ee_block && to == ex->ee_block + ex->ee_len - 1) {
                /* tail removal */
                unsigned long num, start;
-@@ -1928,7 +1930,7 @@ ext3_remove_blocks(struct ext3_extents_t
+@@ -1934,7 +1936,7 @@ ext3_remove_blocks(struct ext3_extents_t
                        bh = sb_find_get_block(tree->inode->i_sb, start + i);
                        ext3_forget(handle, 0, tree->inode, bh, start + i);
                }
@@ -226,10 +242,10 @@ Index: linux-2.6.9-full/fs/ext3/extents.c
        } else if (from == ex->ee_block && to <= ex->ee_block + ex->ee_len - 1) {
                printk("strange request: removal %lu-%lu from %u:%u\n",
                       from, to, ex->ee_block, ex->ee_len);
-Index: linux-2.6.9-full/fs/ext3/inode.c
+Index: linux-stage/fs/ext3/inode.c
 ===================================================================
---- linux-2.6.9-full.orig/fs/ext3/inode.c      2005-12-16 23:16:41.000000000 +0300
-+++ linux-2.6.9-full/fs/ext3/inode.c   2005-12-16 23:16:42.000000000 +0300
+--- linux-stage.orig/fs/ext3/inode.c   2006-05-25 10:36:04.000000000 -0600
++++ linux-stage/fs/ext3/inode.c        2006-05-25 10:36:04.000000000 -0600
 @@ -572,7 +572,7 @@ static int ext3_alloc_branch(handle_t *h
                ext3_journal_forget(handle, branch[i].bh);
        }
@@ -257,7 +273,7 @@ Index: linux-2.6.9-full/fs/ext3/inode.c
  }
  
  /**
-@@ -2004,7 +2004,7 @@ static void ext3_free_branches(handle_t 
+@@ -2004,7 +2004,7 @@ static void ext3_free_branches(handle_t
                                ext3_journal_test_restart(handle, inode);
                        }
  
@@ -266,10 +282,10 @@ Index: linux-2.6.9-full/fs/ext3/inode.c
  
                        if (parent_bh) {
                                /*
-Index: linux-2.6.9-full/fs/ext3/balloc.c
+Index: linux-stage/fs/ext3/balloc.c
 ===================================================================
---- linux-2.6.9-full.orig/fs/ext3/balloc.c     2005-10-27 21:44:24.000000000 +0400
-+++ linux-2.6.9-full/fs/ext3/balloc.c  2005-12-16 23:16:42.000000000 +0300
+--- linux-stage.orig/fs/ext3/balloc.c  2006-05-25 10:36:02.000000000 -0600
++++ linux-stage/fs/ext3/balloc.c       2006-05-25 10:36:04.000000000 -0600
 @@ -79,7 +79,7 @@ struct ext3_group_desc * ext3_get_group_
   *
   * Return buffer_head on success or NULL in case of failure.
@@ -279,7 +295,7 @@ Index: linux-2.6.9-full/fs/ext3/balloc.c
  read_block_bitmap(struct super_block *sb, unsigned int block_group)
  {
        struct ext3_group_desc * desc;
-@@ -450,24 +450,6 @@ error_return:
+@@ -451,24 +451,6 @@
        return;
  }
  
@@ -304,7 +320,7 @@ Index: linux-2.6.9-full/fs/ext3/balloc.c
  /*
   * For ext3 allocations, we must not reuse any blocks which are
   * allocated in the bitmap buffer's "last committed data" copy.  This
-@@ -1140,7 +1122,7 @@ int ext3_should_retry_alloc(struct super
+@@ -1131,7 +1113,7 @@
   * bitmap, and then for any free bit if that fails.
   * This function also updates quota and i_blocks field.
   */
@@ -313,10 +329,10 @@ Index: linux-2.6.9-full/fs/ext3/balloc.c
                        unsigned long goal, int *errp)
  {
        struct buffer_head *bitmap_bh = NULL;
-Index: linux-2.6.9-full/fs/ext3/xattr.c
+Index: linux-stage/fs/ext3/xattr.c
 ===================================================================
---- linux-2.6.9-full.orig/fs/ext3/xattr.c      2005-12-16 23:16:40.000000000 +0300
-+++ linux-2.6.9-full/fs/ext3/xattr.c   2005-12-16 23:16:42.000000000 +0300
+--- linux-stage.orig/fs/ext3/xattr.c   2006-05-25 10:36:04.000000000 -0600
++++ linux-stage/fs/ext3/xattr.c        2006-05-25 10:36:04.000000000 -0600
 @@ -1281,7 +1281,7 @@ ext3_xattr_set_handle2(handle_t *handle,
                        new_bh = sb_getblk(sb, block);
                        if (!new_bh) {
@@ -344,11 +360,11 @@ Index: linux-2.6.9-full/fs/ext3/xattr.c
                get_bh(bh);
                ext3_forget(handle, 1, inode, bh, EXT3_I(inode)->i_file_acl);
        } else {
-Index: linux-2.6.9-full/fs/ext3/mballoc.c
+Index: linux-stage/fs/ext3/mballoc.c
 ===================================================================
---- linux-2.6.9-full.orig/fs/ext3/mballoc.c    2005-12-16 17:46:19.148560250 +0300
-+++ linux-2.6.9-full/fs/ext3/mballoc.c 2005-12-17 00:10:15.000000000 +0300
-@@ -0,0 +1,2429 @@
+--- linux-stage.orig/fs/ext3/mballoc.c 2006-05-23 17:33:37.579436680 -0600
++++ linux-stage/fs/ext3/mballoc.c      2006-05-25 10:59:14.000000000 -0600
+@@ -0,0 +1,2701 @@
 +/*
 + * Copyright (c) 2003-2005, Cluster File Systems, Inc, info@clusterfs.com
 + * Written by Alex Tomas <alex@clusterfs.com>
@@ -437,6 +453,12 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +
 +long ext3_mb_stats = 1;
 +
++/*
++ * for which requests use 2^N search using buddies
++ */
++long ext3_mb_order2_reqs = 8;
++
++
 +#ifdef EXT3_BB_MAX_BLOCKS
 +#undef EXT3_BB_MAX_BLOCKS
 +#endif
@@ -477,10 +499,10 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +
 +      /* search goals */
 +      struct ext3_free_extent ac_g_ex;
-+      
++
 +      /* the best found extent */
 +      struct ext3_free_extent ac_b_ex;
-+      
++
 +      /* number of iterations done. we have to track to limit searching */
 +      unsigned long ac_ex_scanned;
 +      __u16 ac_groups_scanned;
@@ -502,6 +524,8 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +struct ext3_mb_history {
 +      struct ext3_free_extent goal;   /* goal allocation */
 +      struct ext3_free_extent result; /* result allocation */
++      unsigned pid;
++      unsigned ino;
 +      __u16 found;    /* how many extents have been found */
 +      __u16 groups;   /* how many groups have been scanned */
 +      __u16 tail;     /* what tail broke some buddy */
@@ -524,9 +548,9 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +#define EXT3_MB_BUDDY(e3b)    ((e3b)->bd_buddy)
 +
 +#ifndef EXT3_MB_HISTORY
-+#define ext3_mb_store_history(sb,ac)
++#define ext3_mb_store_history(sb,ino,ac)
 +#else
-+static void ext3_mb_store_history(struct super_block *,
++static void ext3_mb_store_history(struct super_block *, unsigned ino,
 +                              struct ext3_allocation_context *ac);
 +#endif
 +
@@ -645,7 +669,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +              if (mb_check_counter++ % 300 != 0)
 +                      return;
 +      }
-+      
++
 +      while (order > 1) {
 +              buddy = mb_find_buddy(e3b, order, &max);
 +              J_ASSERT(buddy);
@@ -826,7 +850,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      sb = inode->i_sb;
 +      blocksize = 1 << inode->i_blkbits;
 +      blocks_per_page = PAGE_CACHE_SIZE / blocksize;
-+      
++
 +      groups_per_page = blocks_per_page >> 1;
 +      if (groups_per_page == 0)
 +              groups_per_page = 1;
@@ -841,9 +865,9 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +              memset(bh, 0, i);
 +      } else
 +              bh = &bhs;
-+      
++
 +      first_group = page->index * blocks_per_page / 2;
-+      
++
 +      /* read all groups the page covers into the cache */
 +      for (i = 0; i < groups_per_page; i++) {
 +              struct ext3_group_desc * desc;
@@ -898,11 +922,11 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +                      mb_debug("put buddy for group %u in page %lu/%x\n",
 +                              group, page->index, i * blocksize);
 +                      memset(data, 0xff, blocksize);
-+                      EXT3_SB(sb)->s_group_info[group]->bb_fragments = 0;
-+                      memset(EXT3_SB(sb)->s_group_info[group]->bb_counters, 0,
++                      EXT3_GROUP_INFO(sb, group)->bb_fragments = 0;
++                      memset(EXT3_GROUP_INFO(sb, group)->bb_counters, 0,
 +                              sizeof(unsigned short)*(sb->s_blocksize_bits+2));
 +                      ext3_mb_generate_buddy(sb, data, bitmap,
-+                                              EXT3_SB(sb)->s_group_info[group]);
++                                              EXT3_GROUP_INFO(sb, group));
 +              } else {
 +                      /* this is block of bitmap */
 +                      mb_debug("put bitmap for group %u in page %lu/%x\n",
@@ -935,7 +959,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      blocks_per_page = PAGE_CACHE_SIZE / sb->s_blocksize;
 +
 +      e3b->bd_blkbits = sb->s_blocksize_bits;
-+      e3b->bd_info = sbi->s_group_info[group];
++      e3b->bd_info = EXT3_GROUP_INFO(sb, group);
 +      e3b->bd_sb = sb;
 +      e3b->bd_group = group;
 +      e3b->bd_buddy_page = NULL;
@@ -1011,14 +1035,14 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +ext3_lock_group(struct super_block *sb, int group)
 +{
 +      bit_spin_lock(EXT3_GROUP_INFO_LOCKED_BIT,
-+                      &EXT3_SB(sb)->s_group_info[group]->bb_state);
++                    &EXT3_GROUP_INFO(sb, group)->bb_state);
 +}
 +
 +static inline void
 +ext3_unlock_group(struct super_block *sb, int group)
 +{
 +      bit_spin_unlock(EXT3_GROUP_INFO_LOCKED_BIT,
-+                      &EXT3_SB(sb)->s_group_info[group]->bb_state);
++                      &EXT3_GROUP_INFO(sb, group)->bb_state);
 +}
 +
 +static int mb_find_order_for_block(struct ext3_buddy *e3b, int block)
@@ -1148,7 +1172,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +static int mb_find_extent(struct ext3_buddy *e3b, int order, int block,
 +                              int needed, struct ext3_free_extent *ex)
 +{
-+      int next, max, ord;
++      int next = block, max, ord;
 +      void *buddy;
 +
 +      J_ASSERT(ex != NULL);
@@ -1173,6 +1197,11 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      ex->fe_start = block << order;
 +      ex->fe_group = e3b->bd_group;
 +
++      /* calc difference from given start */
++      next = next - ex->fe_start;
++      ex->fe_len -= next;
++      ex->fe_start += next;
++
 +      while (needed > ex->fe_len && (buddy = mb_find_buddy(e3b, order, &max))) {
 +
 +              if (block + 1 >= max)
@@ -1368,7 +1397,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +
 +      ext3_lock_group(ac->ac_sb, group);
 +      max = mb_find_extent(e3b, 0, ex.fe_start, ex.fe_len, &ex);
-+      
++
 +      if (max > 0) {
 +              ac->ac_b_ex = ex;
 +              ext3_mb_use_best_found(ac, e3b);
@@ -1385,6 +1414,8 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +                              struct ext3_buddy *e3b)
 +{
 +      int group = ac->ac_g_ex.fe_group, max, err;
++      struct ext3_sb_info *sbi = EXT3_SB(ac->ac_sb);
++      struct ext3_super_block *es = sbi->s_es;
 +      struct ext3_free_extent ex;
 +
 +      err = ext3_mb_load_buddy(ac->ac_sb, group, e3b);
@@ -1393,9 +1424,27 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +
 +      ext3_lock_group(ac->ac_sb, group);
 +      max = mb_find_extent(e3b, 0, ac->ac_g_ex.fe_start,
-+                              ac->ac_g_ex.fe_len, &ex);
-+      
-+      if (max > 0) {
++                           ac->ac_g_ex.fe_len, &ex);
++
++      if (max >= ac->ac_g_ex.fe_len && ac->ac_g_ex.fe_len == sbi->s_stripe) {
++              unsigned long start;
++              start = (e3b->bd_group * EXT3_BLOCKS_PER_GROUP(ac->ac_sb) +
++                      ex.fe_start + le32_to_cpu(es->s_first_data_block));
++              if (start % sbi->s_stripe == 0) {
++                      ac->ac_found++;
++                      ac->ac_b_ex = ex;
++                      ext3_mb_use_best_found(ac, e3b);
++              }
++      } else if (max >= ac->ac_g_ex.fe_len) {
++              J_ASSERT(ex.fe_len > 0);
++              J_ASSERT(ex.fe_group == ac->ac_g_ex.fe_group);
++              J_ASSERT(ex.fe_start == ac->ac_g_ex.fe_start);
++              ac->ac_found++;
++              ac->ac_b_ex = ex;
++              ext3_mb_use_best_found(ac, e3b);
++      } else if (max > 0 && (ac->ac_flags & EXT3_MB_HINT_MERGE)) {
++              /* Sometimes, caller may want to merge even small
++               * number of blocks to an existing extent */
 +              J_ASSERT(ex.fe_len > 0);
 +              J_ASSERT(ex.fe_group == ac->ac_g_ex.fe_group);
 +              J_ASSERT(ex.fe_start == ac->ac_g_ex.fe_start);
@@ -1423,7 +1472,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      int i, k, max;
 +
 +      J_ASSERT(ac->ac_2order > 0);
-+      for (i = ac->ac_2order; i < sb->s_blocksize_bits + 1; i++) {
++      for (i = ac->ac_2order; i <= sb->s_blocksize_bits + 1; i++) {
 +              if (grp->bb_counters[i] == 0)
 +                      continue;
 +
@@ -1488,11 +1537,46 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      }
 +}
 +
++/*
++ * This is a special case for storages like raid5
++ * we try to find stripe-aligned chunks for stripe-size requests
++ */
++static void ext3_mb_scan_aligned(struct ext3_allocation_context *ac,
++                               struct ext3_buddy *e3b)
++{
++      struct super_block *sb = ac->ac_sb;
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      void *bitmap = EXT3_MB_BITMAP(e3b);
++      struct ext3_free_extent ex;
++      unsigned long i, max;
++
++      J_ASSERT(sbi->s_stripe != 0);
++
++      /* find first stripe-aligned block */
++      i = e3b->bd_group * EXT3_BLOCKS_PER_GROUP(sb)
++              + le32_to_cpu(sbi->s_es->s_first_data_block);
++      i = ((i + sbi->s_stripe - 1) / sbi->s_stripe) * sbi->s_stripe;
++      i = (i - le32_to_cpu(sbi->s_es->s_first_data_block))
++                      % EXT3_BLOCKS_PER_GROUP(sb);
++
++      while (i < sb->s_blocksize * 8) {
++              if (!mb_test_bit(i, bitmap)) {
++                      max = mb_find_extent(e3b, 0, i, sbi->s_stripe, &ex);
++                      if (max >= sbi->s_stripe) {
++                              ac->ac_found++;
++                              ac->ac_b_ex = ex;
++                              ext3_mb_use_best_found(ac, e3b);
++                              break;
++                      }
++              }
++              i += sbi->s_stripe;
++      }
++}
++
 +static int ext3_mb_good_group(struct ext3_allocation_context *ac,
 +                              int group, int cr)
 +{
-+      struct ext3_sb_info *sbi = EXT3_SB(ac->ac_sb);
-+      struct ext3_group_info *grp = sbi->s_group_info[group];
++      struct ext3_group_info *grp = EXT3_GROUP_INFO(ac->ac_sb, group);
 +      unsigned free, fragments, i, bits;
 +
 +      J_ASSERT(cr >= 0 && cr < 4);
@@ -1509,15 +1593,18 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +              case 0:
 +                      J_ASSERT(ac->ac_2order != 0);
 +                      bits = ac->ac_sb->s_blocksize_bits + 1;
-+                      for (i = ac->ac_2order; i < bits; i++)
++                      for (i = ac->ac_2order; i <= bits; i++)
 +                              if (grp->bb_counters[i] > 0)
 +                                      return 1;
++                      break;
 +              case 1:
 +                      if ((free / fragments) >= ac->ac_g_ex.fe_len)
 +                              return 1;
++                      break;
 +              case 2:
 +                      if (free >= ac->ac_g_ex.fe_len)
 +                              return 1;
++                      break;
 +              case 3:
 +                      return 1;
 +              default:
@@ -1618,23 +1705,27 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      ac.ac_2order = 0;
 +      ac.ac_criteria = 0;
 +
++      if (*len == 1 && sbi->s_stripe) {
++              /* looks like a metadata, let's use a dirty hack for raid5
++               * move all metadata in first groups in hope to hit cached
++               * sectors and thus avoid read-modify cycles in raid5 */
++              ac.ac_g_ex.fe_group = group = 0;
++      }
++
 +      /* probably, the request is for 2^8+ blocks (1/2/3/... MB) */
 +      i = ffs(*len);
-+      if (i >= 8) {
++      if (i >= ext3_mb_order2_reqs) {
 +              i--;
 +              if ((*len & (~(1 << i))) == 0)
 +                      ac.ac_2order = i;
 +      }
 +
-+      /* Sometimes, caller may want to merge even small
-+       * number of blocks to an existing extent */
-+      if (ac.ac_flags & EXT3_MB_HINT_MERGE) {
-+              err = ext3_mb_find_by_goal(&ac, &e3b);
-+              if (err)
-+                      goto out_err;
-+              if (ac.ac_status == AC_STATUS_FOUND)
-+                      goto found;
-+      }
++      /* first, try the goal */
++      err = ext3_mb_find_by_goal(&ac, &e3b);
++      if (err)
++              goto out_err;
++      if (ac.ac_status == AC_STATUS_FOUND)
++              goto found;
 +
 +      /* Let's just scan groups to find more-less suitable blocks */
 +      cr = ac.ac_2order ? 0 : 1;
@@ -1645,7 +1736,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +                      if (group == EXT3_SB(sb)->s_groups_count)
 +                              group = 0;
 +
-+                      if (EXT3_MB_GRP_NEED_INIT(sbi->s_group_info[group])) {
++                      if (EXT3_MB_GRP_NEED_INIT(EXT3_GROUP_INFO(sb, group))) {
 +                              /* we need full data about the group
 +                               * to make a good selection */
 +                              err = ext3_mb_load_buddy(ac.ac_sb, group, &e3b);
@@ -1673,6 +1764,8 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +                      ac.ac_groups_scanned++;
 +                      if (cr == 0)
 +                              ext3_mb_simple_scan_group(&ac, &e3b);
++                      else if (cr == 1 && *len == sbi->s_stripe) 
++                              ext3_mb_scan_aligned(&ac, &e3b);
 +                      else
 +                              ext3_mb_complex_scan_group(&ac, &e3b);
 +
@@ -1686,7 +1779,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      }
 +
 +      if (ac.ac_b_ex.fe_len > 0 && ac.ac_status != AC_STATUS_FOUND &&
-+                      !(ac.ac_flags & EXT3_MB_HINT_FIRST)) {
++          !(ac.ac_flags & EXT3_MB_HINT_FIRST)) {
 +              /*
 +               * We've been searching too long. Let's try to allocate
 +               * the best chunk we've found so far
@@ -1731,8 +1824,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +                      sbi->s_blocks_reserved, ac.ac_found);
 +              printk("EXT3-fs: groups: ");
 +              for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++)
-+                      printk("%d: %d ", i,
-+                              sbi->s_group_info[i]->bb_free);
++                      printk("%d: %d ", i, EXT3_GROUP_INFO(sb, i)->bb_free);
 +              printk("\n");
 +#endif
 +              goto out;
@@ -1770,7 +1862,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +              *errp = -EIO;
 +              goto out_err;
 +      }
-+      
++
 +      err = ext3_journal_get_write_access(handle, gdp_bh);
 +      if (err)
 +              goto out_err;
@@ -1839,7 +1931,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +               * path only, here is single block always */
 +              ext3_mb_release_blocks(sb, 1);
 +      }
-+      
++
 +      if (unlikely(ext3_mb_stats) && ac.ac_g_ex.fe_len > 1) {
 +              atomic_inc(&sbi->s_bal_reqs);
 +              atomic_add(*len, &sbi->s_bal_allocated);
@@ -1853,7 +1945,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +                      atomic_inc(&sbi->s_bal_breaks);
 +      }
 +
-+      ext3_mb_store_history(sb, &ac);
++      ext3_mb_store_history(sb, inode->i_ino, &ac);
 +
 +      return block;
 +}
@@ -1918,9 +2010,9 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      char buf[20], buf2[20];
 +
 +      if (v == SEQ_START_TOKEN) {
-+              seq_printf(seq, "%-17s %-17s %-5s %-5s %-2s %-5s %-5s %-6s\n",
-+                       "goal", "result", "found", "grps", "cr", "merge",
-+                       "tail", "broken");
++              seq_printf(seq, "%-5s %-8s %-17s %-17s %-5s %-5s %-2s %-5s %-5s %-6s\n",
++                       "pid", "inode", "goal", "result", "found", "grps", "cr",
++                       "merge", "tail", "broken");
 +              return 0;
 +      }
 +
@@ -1928,9 +2020,9 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +              hs->goal.fe_start, hs->goal.fe_len);
 +      sprintf(buf2, "%u/%u/%u", hs->result.fe_group,
 +              hs->result.fe_start, hs->result.fe_len);
-+      seq_printf(seq, "%-17s %-17s %-5u %-5u %-2u %-5s %-5u %-6u\n", buf,
-+                      buf2, hs->found, hs->groups, hs->cr, 
-+                      hs->merged ? "M" : "", hs->tail,
++      seq_printf(seq, "%-5u %-8u %-17s %-17s %-5u %-5u %-2u %-5s %-5u %-6u\n",
++                      hs->pid, hs->ino, buf, buf2, hs->found, hs->groups,
++                      hs->cr, hs->merged ? "M" : "", hs->tail,
 +                      hs->buddy ? 1 << hs->buddy : 0);
 +      return 0;
 +}
@@ -1964,7 +2056,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      s->max = sbi->s_mb_history_max;
 +      s->start = sbi->s_mb_history_cur % s->max;
 +      spin_unlock(&sbi->s_mb_history_lock);
-+      
++
 +      rc = seq_open(file, &ext3_mb_seq_history_ops);
 +      if (rc == 0) {
 +              struct seq_file *m = (struct seq_file *)file->private_data;
@@ -1988,10 +2080,104 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +
 +static struct file_operations ext3_mb_seq_history_fops = {
 +      .owner          = THIS_MODULE,
-+      .open           = ext3_mb_seq_history_open,
-+      .read           = seq_read,
-+      .llseek         = seq_lseek,
-+      .release        = ext3_mb_seq_history_release,
++      .open           = ext3_mb_seq_history_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = ext3_mb_seq_history_release,
++};
++
++static void *ext3_mb_seq_groups_start(struct seq_file *seq, loff_t *pos)
++{
++      struct super_block *sb = seq->private;
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      long group;
++
++      if (*pos < 0 || *pos >= sbi->s_groups_count)
++              return NULL;
++
++      group = *pos + 1;
++      return (void *) group;
++}
++
++static void *ext3_mb_seq_groups_next(struct seq_file *seq, void *v, loff_t *pos)
++{
++      struct super_block *sb = seq->private;
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      long group;
++
++      ++*pos;
++      if (*pos < 0 || *pos >= sbi->s_groups_count)
++              return NULL;
++      group = *pos + 1;
++      return (void *) group;;
++}
++
++static int ext3_mb_seq_groups_show(struct seq_file *seq, void *v)
++{
++      struct super_block *sb = seq->private;
++      long group = (long) v, i;
++      struct sg {
++              struct ext3_group_info info;
++              unsigned short counters[16];
++      } sg;
++
++      group--;
++      if (group == 0)
++              seq_printf(seq, "#%-5s: %-5s %-5s %-5s [ %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s ]\n",
++                       "group", "free", "frags", "first", "2^0", "2^1", "2^2", 
++                       "2^3", "2^4", "2^5", "2^6", "2^7", "2^8", "2^9", "2^10",
++                       "2^11", "2^12", "2^13");
++
++      i = (sb->s_blocksize_bits + 2) * sizeof(sg.info.bb_counters[0]) +
++              sizeof(struct ext3_group_info);
++      ext3_lock_group(sb, group);
++      memcpy(&sg, EXT3_GROUP_INFO(sb, group), i);
++      ext3_unlock_group(sb, group);
++
++      if (EXT3_MB_GRP_NEED_INIT(&sg.info))
++              return 0;
++
++      seq_printf(seq, "#%-5lu: %-5u %-5u %-5u [", group, sg.info.bb_free,
++                      sg.info.bb_fragments, sg.info.bb_first_free);
++      for (i = 0; i <= 13; i++)
++              seq_printf(seq, " %-5u", i <= sb->s_blocksize_bits + 1 ?
++                              sg.info.bb_counters[i] : 0);
++      seq_printf(seq, " ]\n");
++
++      return 0;
++}
++
++static void ext3_mb_seq_groups_stop(struct seq_file *seq, void *v)
++{
++}
++
++static struct seq_operations ext3_mb_seq_groups_ops = {
++      .start  = ext3_mb_seq_groups_start,
++      .next   = ext3_mb_seq_groups_next,
++      .stop   = ext3_mb_seq_groups_stop,
++      .show   = ext3_mb_seq_groups_show,
++};
++
++static int ext3_mb_seq_groups_open(struct inode *inode, struct file *file)
++{
++      struct super_block *sb = PDE(inode)->data;
++      int rc;
++
++      rc = seq_open(file, &ext3_mb_seq_groups_ops);
++      if (rc == 0) {
++              struct seq_file *m = (struct seq_file *)file->private_data;
++              m->private = sb;
++      }
++      return rc;
++
++}
++
++static struct file_operations ext3_mb_seq_groups_fops = {
++      .owner          = THIS_MODULE,
++      .open           = ext3_mb_seq_groups_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = seq_release,
 +};
 +
 +static void ext3_mb_history_release(struct super_block *sb)
@@ -2000,6 +2186,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      char name[64];
 +
 +      snprintf(name, sizeof(name) - 1, "%s", bdevname(sb->s_bdev, name));
++      remove_proc_entry("mb_groups", sbi->s_mb_proc);
 +      remove_proc_entry("mb_history", sbi->s_mb_proc);
 +      remove_proc_entry(name, proc_root_ext3);
 +
@@ -2022,6 +2209,11 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +                      p->proc_fops = &ext3_mb_seq_history_fops;
 +                      p->data = sb;
 +              }
++              p = create_proc_entry("mb_groups", S_IRUGO, sbi->s_mb_proc);
++              if (p) {
++                      p->proc_fops = &ext3_mb_seq_groups_fops;
++                      p->data = sb;
++              }
 +      }
 +
 +      sbi->s_mb_history_max = 1000;
@@ -2034,7 +2226,8 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +}
 +
 +static void
-+ext3_mb_store_history(struct super_block *sb, struct ext3_allocation_context *ac)
++ext3_mb_store_history(struct super_block *sb, unsigned ino,
++                      struct ext3_allocation_context *ac)
 +{
 +      struct ext3_sb_info *sbi = EXT3_SB(sb);
 +      struct ext3_mb_history h;
@@ -2042,6 +2235,8 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      if (likely(sbi->s_mb_history == NULL))
 +              return;
 +
++      h.pid = current->pid;
++      h.ino = ino;
 +      h.goal = ac->ac_g_ex;
 +      h.result = ac->ac_b_ex;
 +      h.found = ac->ac_found;
@@ -2069,21 +2264,40 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +int ext3_mb_init_backend(struct super_block *sb)
 +{
 +      struct ext3_sb_info *sbi = EXT3_SB(sb);
-+      int i, len;
-+
-+      len = sizeof(struct ext3_buddy_group_blocks *) * sbi->s_groups_count;
-+      sbi->s_group_info = kmalloc(len, GFP_KERNEL);
++      int i, j, len, metalen;
++      int num_meta_group_infos =
++              (sbi->s_groups_count + EXT3_DESC_PER_BLOCK(sb) - 1) >>
++                      EXT3_DESC_PER_BLOCK_BITS(sb);
++      struct ext3_group_info **meta_group_info;
++
++      /* An 8TB filesystem with 64-bit pointers requires a 4096 byte
++       * kmalloc. A 128kb malloc should suffice for a 256TB filesystem.
++       * So a two level scheme suffices for now. */
++      sbi->s_group_info = kmalloc(sizeof(*sbi->s_group_info) *
++                                  num_meta_group_infos, GFP_KERNEL);
 +      if (sbi->s_group_info == NULL) {
-+              printk(KERN_ERR "EXT3-fs: can't allocate mem for buddy\n");
++              printk(KERN_ERR "EXT3-fs: can't allocate buddy meta group\n");
 +              return -ENOMEM;
 +      }
-+      memset(sbi->s_group_info, 0, len);
-+
 +      sbi->s_buddy_cache = new_inode(sb);
 +      if (sbi->s_buddy_cache == NULL) {
 +              printk(KERN_ERR "EXT3-fs: can't get new inode\n");
-+              kfree(sbi->s_group_info);
-+              return -ENOMEM;
++              goto err_freesgi;
++      }
++
++      metalen = sizeof(*meta_group_info) << EXT3_DESC_PER_BLOCK_BITS(sb);
++      for (i = 0; i < num_meta_group_infos; i++) {
++              if ((i + 1) == num_meta_group_infos)
++                      metalen = sizeof(*meta_group_info) *
++                              (sbi->s_groups_count -
++                                      (i << EXT3_DESC_PER_BLOCK_BITS(sb)));
++              meta_group_info = kmalloc(metalen, GFP_KERNEL);
++              if (meta_group_info == NULL) {
++                      printk(KERN_ERR "EXT3-fs: can't allocate mem for a "
++                             "buddy group\n");
++                      goto err_freemeta;
++              }
++              sbi->s_group_info[i] = meta_group_info;
 +      }
 +
 +      /* 
@@ -2095,30 +2309,42 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      for (i = 0; i < sbi->s_groups_count; i++) {
 +              struct ext3_group_desc * desc;
 +
-+              sbi->s_group_info[i] = kmalloc(len, GFP_KERNEL);
-+              if (sbi->s_group_info[i] == NULL) {
++              meta_group_info =
++                      sbi->s_group_info[i >> EXT3_DESC_PER_BLOCK_BITS(sb)];
++              j = i & (EXT3_DESC_PER_BLOCK(sb) - 1);
++
++              meta_group_info[j] = kmalloc(len, GFP_KERNEL);
++              if (meta_group_info[j] == NULL) {
 +                      printk(KERN_ERR "EXT3-fs: can't allocate buddy mem\n");
-+                      goto err_out;
++                      i--;
++                      goto err_freebuddy;
 +              }
 +              desc = ext3_get_group_desc(sb, i, NULL);
 +              if (desc == NULL) {
 +                      printk(KERN_ERR"EXT3-fs: can't read descriptor %u\n",i);
-+                      goto err_out;
++                      goto err_freebuddy;
 +              }
-+              memset(sbi->s_group_info[i], 0, len);
++              memset(meta_group_info[j], 0, len);
 +              set_bit(EXT3_GROUP_INFO_NEED_INIT_BIT,
-+                      &sbi->s_group_info[i]->bb_state);
-+              sbi->s_group_info[i]->bb_free =
++                      &meta_group_info[j]->bb_state);
++              meta_group_info[j]->bb_free =
 +                      le16_to_cpu(desc->bg_free_blocks_count);
 +      }
 +
 +      return 0;
 +
-+err_out:
++err_freebuddy:
++      while (i >= 0) {
++              kfree(EXT3_GROUP_INFO(sb, i));
++              i--;
++      }
++      i = num_meta_group_infos;
++err_freemeta:
 +      while (--i >= 0)
 +              kfree(sbi->s_group_info[i]);
 +      iput(sbi->s_buddy_cache);
-+
++err_freesgi:
++      kfree(sbi->s_group_info);
 +      return -ENOMEM;
 +}
 +
@@ -2160,7 +2386,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +              max = max >> 1;
 +              i++;
 +      } while (i <= sb->s_blocksize_bits + 1);
-+      
++
 +
 +      /* init file for buddy data */
 +      if ((i = ext3_mb_init_backend(sb))) {
@@ -2197,8 +2423,8 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +int ext3_mb_release(struct super_block *sb)
 +{
 +      struct ext3_sb_info *sbi = EXT3_SB(sb);
-+      int i;
-+      
++      int i, num_meta_group_infos;
++
 +      if (!test_opt(sb, MBALLOC))
 +              return 0;
 +
@@ -2212,11 +2438,13 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      ext3_mb_free_committed_blocks(sb);
 +
 +      if (sbi->s_group_info) {
-+              for (i = 0; i < sbi->s_groups_count; i++) {
-+                      if (sbi->s_group_info[i] == NULL)
-+                              continue;
++              for (i = 0; i < sbi->s_groups_count; i++)
++                      kfree(EXT3_GROUP_INFO(sb, i));
++              num_meta_group_infos = (sbi->s_groups_count +
++                      EXT3_DESC_PER_BLOCK(sb) - 1) >>
++                      EXT3_DESC_PER_BLOCK_BITS(sb);
++              for (i = 0; i < num_meta_group_infos; i++)
 +                      kfree(sbi->s_group_info[i]);
-+              }
 +              kfree(sbi->s_group_info);
 +      }
 +      if (sbi->s_mb_offsets)
@@ -2510,7 +2738,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +              cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) + count);
 +      spin_unlock(sb_bgl_lock(sbi, block_group));
 +      percpu_counter_mod(&sbi->s_freeblocks_counter, count);
-+      
++
 +      ext3_mb_release_desc(&e3b);
 +
 +      *freed = count;
@@ -2593,10 +2821,11 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      return;
 +}
 +
-+#define EXT3_ROOT                 "ext3"
-+#define EXT3_MB_STATS_NAME        "mb_stats"
++#define EXT3_ROOT                "ext3"
++#define EXT3_MB_STATS_NAME       "mb_stats"
 +#define EXT3_MB_MAX_TO_SCAN_NAME  "mb_max_to_scan"
 +#define EXT3_MB_MIN_TO_SCAN_NAME  "mb_min_to_scan"
++#define EXT3_MB_ORDER2_REQ       "mb_order2_req"
 +
 +static int ext3_mb_stats_read(char *page, char **start, off_t off,
 +              int count, int *eof, void *data)
@@ -2684,6 +2913,45 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      return len;
 +}
 +
++static int ext3_mb_order2_req_write(struct file *file, const char *buffer,
++              unsigned long count, void *data)
++{
++      char str[32];
++      long value;
++
++      if (count >= sizeof(str)) {
++              printk(KERN_ERR "EXT3-fs: %s string too long, max %u bytes\n",
++                     EXT3_MB_MIN_TO_SCAN_NAME, (int)sizeof(str));
++              return -EOVERFLOW;
++      }
++
++      if (copy_from_user(str, buffer, count))
++              return -EFAULT;
++
++      /* Only set to 0 or 1 respectively; zero->0; non-zero->1 */
++      value = simple_strtol(str, NULL, 0);
++      if (value <= 0)
++              return -ERANGE;
++
++      ext3_mb_order2_reqs = value;    
++
++      return count;
++}
++
++static int ext3_mb_order2_req_read(char *page, char **start, off_t off,
++              int count, int *eof, void *data)
++{
++      int len;
++
++      *eof = 1;
++      if (off != 0)
++              return 0;
++
++      len = sprintf(page, "%ld\n", ext3_mb_order2_reqs);
++      *start = page;
++      return len;
++}
++
 +static int ext3_mb_min_to_scan_write(struct file *file, const char *buffer,
 +              unsigned long count, void *data)
 +{
@@ -2691,7 +2959,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      long value;
 +
 +      if (count >= sizeof(str)) {
-+              printk(KERN_ERR "EXT3: %s string too long, max %u bytes\n",
++              printk(KERN_ERR "EXT3-fs: %s string too long, max %u bytes\n",
 +                     EXT3_MB_MIN_TO_SCAN_NAME, (int)sizeof(str));
 +              return -EOVERFLOW;
 +      }
@@ -2714,10 +2982,11 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      struct proc_dir_entry *proc_ext3_mb_stats;
 +      struct proc_dir_entry *proc_ext3_mb_max_to_scan;
 +      struct proc_dir_entry *proc_ext3_mb_min_to_scan;
++      struct proc_dir_entry *proc_ext3_mb_order2_req;
 +
 +      proc_root_ext3 = proc_mkdir(EXT3_ROOT, proc_root_fs);
 +      if (proc_root_ext3 == NULL) {
-+              printk(KERN_ERR "EXT3: Unable to create %s\n", EXT3_ROOT);
++              printk(KERN_ERR "EXT3-fs: Unable to create %s\n", EXT3_ROOT);
 +              return -EIO;
 +      }
 +
@@ -2725,7 +2994,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      proc_ext3_mb_stats = create_proc_entry(EXT3_MB_STATS_NAME,
 +                      S_IFREG | S_IRUGO | S_IWUSR, proc_root_ext3);
 +      if (proc_ext3_mb_stats == NULL) {
-+              printk(KERN_ERR "EXT3: Unable to create %s\n",
++              printk(KERN_ERR "EXT3-fs: Unable to create %s\n",
 +                              EXT3_MB_STATS_NAME);
 +              remove_proc_entry(EXT3_ROOT, proc_root_fs);
 +              return -EIO;
@@ -2740,7 +3009,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +                      EXT3_MB_MAX_TO_SCAN_NAME,
 +                      S_IFREG | S_IRUGO | S_IWUSR, proc_root_ext3);
 +      if (proc_ext3_mb_max_to_scan == NULL) {
-+              printk(KERN_ERR "EXT3: Unable to create %s\n",
++              printk(KERN_ERR "EXT3-fs: Unable to create %s\n",
 +                              EXT3_MB_MAX_TO_SCAN_NAME);
 +              remove_proc_entry(EXT3_MB_STATS_NAME, proc_root_ext3);
 +              remove_proc_entry(EXT3_ROOT, proc_root_fs);
@@ -2756,7 +3025,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +                      EXT3_MB_MIN_TO_SCAN_NAME,
 +                      S_IFREG | S_IRUGO | S_IWUSR, proc_root_ext3);
 +      if (proc_ext3_mb_min_to_scan == NULL) {
-+              printk(KERN_ERR "EXT3: Unable to create %s\n",
++              printk(KERN_ERR "EXT3-fs: Unable to create %s\n",
 +                              EXT3_MB_MIN_TO_SCAN_NAME);
 +              remove_proc_entry(EXT3_MB_MAX_TO_SCAN_NAME, proc_root_ext3);
 +              remove_proc_entry(EXT3_MB_STATS_NAME, proc_root_ext3);
@@ -2768,6 +3037,24 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      proc_ext3_mb_min_to_scan->read_proc  = ext3_mb_min_to_scan_read;
 +      proc_ext3_mb_min_to_scan->write_proc = ext3_mb_min_to_scan_write;
 +
++      /* Initialize EXT3_ORDER2_REQ */
++      proc_ext3_mb_order2_req = create_proc_entry(
++                      EXT3_MB_ORDER2_REQ,
++                      S_IFREG | S_IRUGO | S_IWUSR, proc_root_ext3);
++      if (proc_ext3_mb_order2_req == NULL) {
++              printk(KERN_ERR "EXT3-fs: Unable to create %s\n",
++                              EXT3_MB_ORDER2_REQ);
++              remove_proc_entry(EXT3_MB_MIN_TO_SCAN_NAME, proc_root_ext3);
++              remove_proc_entry(EXT3_MB_MAX_TO_SCAN_NAME, proc_root_ext3);
++              remove_proc_entry(EXT3_MB_STATS_NAME, proc_root_ext3);
++              remove_proc_entry(EXT3_ROOT, proc_root_fs);
++              return -EIO;
++      }
++
++      proc_ext3_mb_order2_req->data = NULL;
++      proc_ext3_mb_order2_req->read_proc  = ext3_mb_order2_req_read;
++      proc_ext3_mb_order2_req->write_proc = ext3_mb_order2_req_write;
++
 +      return 0;
 +}
 +
@@ -2776,12 +3063,13 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      remove_proc_entry(EXT3_MB_STATS_NAME, proc_root_ext3);
 +      remove_proc_entry(EXT3_MB_MAX_TO_SCAN_NAME, proc_root_ext3);
 +      remove_proc_entry(EXT3_MB_MIN_TO_SCAN_NAME, proc_root_ext3);
++      remove_proc_entry(EXT3_MB_ORDER2_REQ, proc_root_ext3);
 +      remove_proc_entry(EXT3_ROOT, proc_root_fs);
 +}
-Index: linux-2.6.9-full/fs/ext3/Makefile
+Index: linux-stage/fs/ext3/Makefile
 ===================================================================
---- linux-2.6.9-full.orig/fs/ext3/Makefile     2005-12-16 23:16:41.000000000 +0300
-+++ linux-2.6.9-full/fs/ext3/Makefile  2005-12-16 23:16:42.000000000 +0300
+--- linux-stage.orig/fs/ext3/Makefile  2006-05-25 10:36:04.000000000 -0600
++++ linux-stage/fs/ext3/Makefile       2006-05-25 10:36:04.000000000 -0600
 @@ -6,7 +6,7 @@
  
  ext3-y        := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
diff --git a/ldiskfs/kernel_patches/patches/ext3-sector_t-overflow-2.6.12.patch b/ldiskfs/kernel_patches/patches/ext3-sector_t-overflow-2.6.12.patch
new file mode 100644 (file)
index 0000000..ef0f4a4
--- /dev/null
@@ -0,0 +1,64 @@
+Subject: Avoid disk sector_t overflow for >2TB ext3 filesystem
+From: Mingming Cao <cmm@us.ibm.com>
+
+
+If ext3 filesystem is larger than 2TB, and sector_t is a u32 (i.e.
+CONFIG_LBD not defined in the kernel), the calculation of the disk sector
+will overflow.  Add check at ext3_fill_super() and ext3_group_extend() to
+prevent mount/remount/resize >2TB ext3 filesystem if sector_t size is 4
+bytes.
+
+Verified this patch on a 32 bit platform without CONFIG_LBD defined
+(sector_t is 32 bits long), mount refuse to mount a 10TB ext3.
+
+Signed-off-by: Mingming Cao<cmm@us.ibm.com>
+Acked-by: Andreas Dilger <adilger@clusterfs.com>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+---
+
+ fs/ext3/resize.c |   10 ++++++++++
+ fs/ext3/super.c  |   10 ++++++++++
+ 2 files changed, 20 insertions(+)
+
+diff -puN fs/ext3/resize.c~avoid-disk-sector_t-overflow-for-2tb-ext3-filesystem fs/ext3/resize.c
+--- devel/fs/ext3/resize.c~avoid-disk-sector_t-overflow-for-2tb-ext3-filesystem        2006-05-22 14:09:53.000000000 -0700
++++ devel-akpm/fs/ext3/resize.c        2006-05-22 14:10:56.000000000 -0700
+@@ -926,6 +926,16 @@ int ext3_group_extend(struct super_block
+       if (n_blocks_count == 0 || n_blocks_count == o_blocks_count)
+               return 0;
++      if (n_blocks_count > (sector_t)(~0ULL) >> (sb->s_blocksize_bits - 9)) {
++              printk(KERN_ERR "EXT3-fs: filesystem on %s: "
++                     "too large to resize to %lu blocks safely\n",
++                     sb->s_id, n_blocks_count);
++              if (sizeof(sector_t) < 8)
++                      ext3_warning(sb, __FUNCTION__,
++                                   "CONFIG_LBD not enabled\n");
++              return -EINVAL;
++      }
++
+       if (n_blocks_count < o_blocks_count) {
+               ext3_warning(sb, __FUNCTION__,
+                            "can't shrink FS - resize aborted");
+diff -puN fs/ext3/super.c~avoid-disk-sector_t-overflow-for-2tb-ext3-filesystem fs/ext3/super.c
+--- devel/fs/ext3/super.c~avoid-disk-sector_t-overflow-for-2tb-ext3-filesystem 2006-05-22 14:09:53.000000000 -0700
++++ devel-akpm/fs/ext3/super.c 2006-05-22 14:11:10.000000000 -0700
+@@ -1565,6 +1565,17 @@ static int ext3_fill_super (struct super
+               goto failed_mount;
+       }
++      if (le32_to_cpu(es->s_blocks_count) >
++          (sector_t)(~0ULL) >> (sb->s_blocksize_bits - 9)) {
++              printk(KERN_ERR "EXT3-fs: filesystem on %s: "
++                     "too large to mount safely - %u blocks\n", sb->s_id,
++                     le32_to_cpu(es->s_blocks_count));
++              if (sizeof(sector_t) < 8)
++                      printk(KERN_WARNING
++                             "EXT3-fs: CONFIG_LBD not enabled\n");
++              goto failed_mount;
++      }
++
+       if (EXT3_BLOCKS_PER_GROUP(sb) == 0)
+               goto cantfind_ext3;
+       sbi->s_groups_count = (le32_to_cpu(es->s_blocks_count) -
+_
diff --git a/ldiskfs/kernel_patches/patches/ext3-sector_t-overflow-2.6.5-suse.patch b/ldiskfs/kernel_patches/patches/ext3-sector_t-overflow-2.6.5-suse.patch
new file mode 100644 (file)
index 0000000..fe655da
--- /dev/null
@@ -0,0 +1,44 @@
+Subject: Avoid disk sector_t overflow for >2TB ext3 filesystem
+From: Mingming Cao <cmm@us.ibm.com>
+
+
+If ext3 filesystem is larger than 2TB, and sector_t is a u32 (i.e. 
+CONFIG_LBD not defined in the kernel), the calculation of the disk sector
+will overflow.  Add check at ext3_fill_super() and ext3_group_extend() to
+prevent mount/remount/resize >2TB ext3 filesystem if sector_t size is 4
+bytes.
+
+Verified this patch on a 32 bit platform without CONFIG_LBD defined
+(sector_t is 32 bits long), mount refuse to mount a 10TB ext3.
+
+Signed-off-by: Mingming Cao<cmm@us.ibm.com>
+Acked-by: Andreas Dilger <adilger@clusterfs.com>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+---
+
+ fs/ext3/resize.c |   10 ++++++++++
+ fs/ext3/super.c  |   10 ++++++++++
+ 2 files changed, 20 insertions(+)
+
+diff -puN fs/ext3/super.c~avoid-disk-sector_t-overflow-for-2tb-ext3-filesystem fs/ext3/super.c
+--- devel/fs/ext3/super.c~avoid-disk-sector_t-overflow-for-2tb-ext3-filesystem 2006-05-22 14:09:53.000000000 -0700
++++ devel-akpm/fs/ext3/super.c 2006-05-22 14:11:10.000000000 -0700
+@@ -1565,6 +1565,17 @@ static int ext3_fill_super (struct super
+               goto failed_mount;
+       }
++      if (le32_to_cpu(es->s_blocks_count) >
++          (sector_t)(~0ULL) >> (sb->s_blocksize_bits - 9)) {
++              printk(KERN_ERR "EXT3-fs: filesystem on %s: "
++                     "too large to mount safely - %u blocks\n", sb->s_id,
++                     le32_to_cpu(es->s_blocks_count));
++              if (sizeof(sector_t) < 8)
++                      printk(KERN_WARNING
++                             "EXT3-fs: CONFIG_LBD not enabled\n");
++              goto failed_mount;
++      }
++
+       sbi->s_groups_count = (le32_to_cpu(es->s_blocks_count) -
+                              le32_to_cpu(es->s_first_data_block) +
+                              EXT3_BLOCKS_PER_GROUP(sb) - 1) /
+_
diff --git a/ldiskfs/kernel_patches/patches/ext3-sector_t-overflow-2.6.9-rhel4.patch b/ldiskfs/kernel_patches/patches/ext3-sector_t-overflow-2.6.9-rhel4.patch
new file mode 100644 (file)
index 0000000..9bfdf80
--- /dev/null
@@ -0,0 +1,64 @@
+Subject: Avoid disk sector_t overflow for >2TB ext3 filesystem
+From: Mingming Cao <cmm@us.ibm.com>
+
+
+If ext3 filesystem is larger than 2TB, and sector_t is a u32 (i.e. 
+CONFIG_LBD not defined in the kernel), the calculation of the disk sector
+will overflow.  Add check at ext3_fill_super() and ext3_group_extend() to
+prevent mount/remount/resize >2TB ext3 filesystem if sector_t size is 4
+bytes.
+
+Verified this patch on a 32 bit platform without CONFIG_LBD defined
+(sector_t is 32 bits long), mount refuse to mount a 10TB ext3.
+
+Signed-off-by: Mingming Cao<cmm@us.ibm.com>
+Acked-by: Andreas Dilger <adilger@clusterfs.com>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+---
+
+ fs/ext3/resize.c |   10 ++++++++++
+ fs/ext3/super.c  |   10 ++++++++++
+ 2 files changed, 20 insertions(+)
+
+diff -puN fs/ext3/resize.c~avoid-disk-sector_t-overflow-for-2tb-ext3-filesystem fs/ext3/resize.c
+--- devel/fs/ext3/resize.c~avoid-disk-sector_t-overflow-for-2tb-ext3-filesystem        2006-05-22 14:09:53.000000000 -0700
++++ devel-akpm/fs/ext3/resize.c        2006-05-22 14:10:56.000000000 -0700
+@@ -926,6 +926,16 @@ int ext3_group_extend(struct super_block
+       if (n_blocks_count == 0 || n_blocks_count == o_blocks_count)
+               return 0;
++      if (n_blocks_count > (sector_t)(~0ULL) >> (sb->s_blocksize_bits - 9)) {
++              printk(KERN_ERR "EXT3-fs: filesystem on %s: "
++                     "too large to resize to %lu blocks safely\n",
++                     sb->s_id, n_blocks_count);
++              if (sizeof(sector_t) < 8)
++                      ext3_warning(sb, __FUNCTION__,
++                                   "CONFIG_LBD not enabled\n");
++              return -EINVAL;
++      }
++
+       if (n_blocks_count < o_blocks_count) {
+               ext3_warning(sb, __FUNCTION__,
+                            "can't shrink FS - resize aborted");
+diff -puN fs/ext3/super.c~avoid-disk-sector_t-overflow-for-2tb-ext3-filesystem fs/ext3/super.c
+--- devel/fs/ext3/super.c~avoid-disk-sector_t-overflow-for-2tb-ext3-filesystem 2006-05-22 14:09:53.000000000 -0700
++++ devel-akpm/fs/ext3/super.c 2006-05-22 14:11:10.000000000 -0700
+@@ -1565,6 +1565,17 @@ static int ext3_fill_super (struct super
+               goto failed_mount;
+       }
++      if (le32_to_cpu(es->s_blocks_count) >
++          (sector_t)(~0ULL) >> (sb->s_blocksize_bits - 9)) {
++              printk(KERN_ERR "EXT3-fs: filesystem on %s: "
++                     "too large to mount safely - %u blocks\n", sb->s_id,
++                     le32_to_cpu(es->s_blocks_count));
++              if (sizeof(sector_t) < 8)
++                      printk(KERN_WARNING
++                             "EXT3-fs: CONFIG_LBD not enabled\n");
++              goto failed_mount;
++      }
++
+       sbi->s_groups_count = (le32_to_cpu(es->s_blocks_count) -
+                              le32_to_cpu(es->s_first_data_block) +
+                              EXT3_BLOCKS_PER_GROUP(sb) - 1) /
+_
index 1c5c6ab..b586a2f 100644 (file)
@@ -19,16 +19,19 @@ Index: uml-2.6.3/fs/ext3/ialloc.c
  {
        struct super_block *sb;
        struct buffer_head *bitmap_bh = NULL;
-@@ -448,6 +449,38 @@
+@@ -448,6 +449,41 @@
  
        sbi = EXT3_SB(sb);
        es = sbi->s_es;
 +      if (goal) {
 +              group = (goal - 1) / EXT3_INODES_PER_GROUP(sb);
 +              ino = (goal - 1) % EXT3_INODES_PER_GROUP(sb);
++              err = -EIO;
++
 +              gdp = ext3_get_group_desc(sb, group, &bh2);
++              if (!gdp)
++                      goto fail;
 +
-+              err = -EIO;
 +              bitmap_bh = read_inode_bitmap (sb, group);
 +              if (!bitmap_bh)
 +                      goto fail;
index a4867a5..33535dc 100644 (file)
@@ -19,16 +19,19 @@ Index: uml-2.6.3/fs/ext3/ialloc.c
  {
        struct super_block *sb;
        struct buffer_head *bitmap_bh = NULL;
-@@ -448,6 +449,38 @@
+@@ -448,6 +449,41 @@
  
        sbi = EXT3_SB(sb);
        es = sbi->s_es;
 +      if (goal) {
 +              group = (goal - 1) / EXT3_INODES_PER_GROUP(sb);
 +              ino = (goal - 1) % EXT3_INODES_PER_GROUP(sb);
++              err = -EIO;
++
 +              gdp = ext3_get_group_desc(sb, group, &bh2);
++              if (!gdp)
++                      goto fail;
 +
-+              err = -EIO;
 +              bitmap_bh = read_inode_bitmap (sb, group);
 +              if (!bitmap_bh)
 +                      goto fail;
diff --git a/ldiskfs/kernel_patches/patches/iopen-2.6-fc5.patch b/ldiskfs/kernel_patches/patches/iopen-2.6-fc5.patch
new file mode 100644 (file)
index 0000000..6bbcec5
--- /dev/null
@@ -0,0 +1,448 @@
+Index: linux-2.6.16.i686/fs/ext3/iopen.c
+===================================================================
+--- linux-2.6.16.i686.orig/fs/ext3/iopen.c     2006-05-31 04:14:15.752410384 +0800
++++ linux-2.6.16.i686/fs/ext3/iopen.c  2006-05-30 22:52:38.000000000 +0800
+@@ -0,0 +1,259 @@
++/*
++ * linux/fs/ext3/iopen.c
++ *
++ * Special support for open by inode number
++ *
++ * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu).
++ *
++ * This file may be redistributed under the terms of the GNU General
++ * Public License.
++ *
++ *
++ * Invariants:
++ *   - there is only ever a single DCACHE_NFSD_DISCONNECTED dentry alias
++ *     for an inode at one time.
++ *   - there are never both connected and DCACHE_NFSD_DISCONNECTED dentry
++ *     aliases on an inode at the same time.
++ *
++ * If we have any connected dentry aliases for an inode, use one of those
++ * in iopen_lookup().  Otherwise, we instantiate a single NFSD_DISCONNECTED
++ * dentry for this inode, which thereafter will be found by the dcache
++ * when looking up this inode number in __iopen__, so we don't return here
++ * until it is gone.
++ *
++ * If we get an inode via a regular name lookup, then we "rename" the
++ * NFSD_DISCONNECTED dentry to the proper name and parent.  This ensures
++ * existing users of the disconnected dentry will continue to use the same
++ * dentry as the connected users, and there will never be both kinds of
++ * dentry aliases at one time.
++ */
++
++#include <linux/sched.h>
++#include <linux/fs.h>
++#include <linux/ext3_jbd.h>
++#include <linux/jbd.h>
++#include <linux/ext3_fs.h>
++#include <linux/smp_lock.h>
++#include <linux/dcache.h>
++#include <linux/security.h>
++#include "iopen.h"
++
++#ifndef assert
++#define assert(test) J_ASSERT(test)
++#endif
++
++#define IOPEN_NAME_LEN        32
++
++/*
++ * This implements looking up an inode by number.
++ */
++static struct dentry *iopen_lookup(struct inode * dir, struct dentry *dentry,
++                                 struct nameidata *nd)
++{
++      struct inode *inode;
++      unsigned long ino;
++      struct list_head *lp;
++      struct dentry *alternate;
++      char buf[IOPEN_NAME_LEN];
++
++      if (dentry->d_name.len >= IOPEN_NAME_LEN)
++              return ERR_PTR(-ENAMETOOLONG);
++
++      memcpy(buf, dentry->d_name.name, dentry->d_name.len);
++      buf[dentry->d_name.len] = 0;
++
++      if (strcmp(buf, ".") == 0)
++              ino = dir->i_ino;
++      else if (strcmp(buf, "..") == 0)
++              ino = EXT3_ROOT_INO;
++      else
++              ino = simple_strtoul(buf, 0, 0);
++
++      if ((ino != EXT3_ROOT_INO &&
++           //ino != EXT3_ACL_IDX_INO &&
++           //ino != EXT3_ACL_DATA_INO &&
++           ino < EXT3_FIRST_INO(dir->i_sb)) ||
++          ino > le32_to_cpu(EXT3_SB(dir->i_sb)->s_es->s_inodes_count))
++              return ERR_PTR(-ENOENT);
++
++      inode = iget(dir->i_sb, ino);
++      if (!inode)
++              return ERR_PTR(-EACCES);
++      if (is_bad_inode(inode)) {
++              iput(inode);
++              return ERR_PTR(-ENOENT);
++      }
++
++      assert(list_empty(&dentry->d_alias));           /* d_instantiate */
++      assert(d_unhashed(dentry));                     /* d_rehash */
++
++      /* preferrably return a connected dentry */
++      spin_lock(&dcache_lock);
++      list_for_each(lp, &inode->i_dentry) {
++              alternate = list_entry(lp, struct dentry, d_alias);
++              assert(!(alternate->d_flags & DCACHE_DISCONNECTED));
++      }
++
++      if (!list_empty(&inode->i_dentry)) {
++              alternate = list_entry(inode->i_dentry.next,
++                                     struct dentry, d_alias);
++              dget_locked(alternate);
++              spin_lock(&alternate->d_lock);
++              alternate->d_flags |= DCACHE_REFERENCED;
++              spin_unlock(&alternate->d_lock);
++              iput(inode);
++              spin_unlock(&dcache_lock);
++              return alternate;
++      }
++      dentry->d_flags |= DCACHE_DISCONNECTED;
++
++      /* d_add(), but don't drop dcache_lock before adding dentry to inode */
++      list_add(&dentry->d_alias, &inode->i_dentry);   /* d_instantiate */
++      dentry->d_inode = inode;
++      spin_unlock(&dcache_lock);
++
++      d_rehash(dentry);
++
++      return NULL;
++}
++
++/* This function is spliced into ext3_lookup and does the move of a
++ * disconnected dentry (if it exists) to a connected dentry.
++ */
++struct dentry *iopen_connect_dentry(struct dentry *dentry, struct inode *inode,
++                                  int rehash)
++{
++      struct dentry *tmp, *goal = NULL;
++      struct list_head *lp;
++
++      /* verify this dentry is really new */
++      assert(dentry->d_inode == NULL);
++      assert(list_empty(&dentry->d_alias));           /* d_instantiate */
++      if (rehash)
++              assert(d_unhashed(dentry));             /* d_rehash */
++      assert(list_empty(&dentry->d_subdirs));
++
++      spin_lock(&dcache_lock);
++      if (!inode)
++              goto do_rehash;
++
++      if (!test_opt(inode->i_sb, IOPEN))
++              goto do_instantiate;
++
++      /* preferrably return a connected dentry */
++      list_for_each(lp, &inode->i_dentry) {
++              tmp = list_entry(lp, struct dentry, d_alias);
++              if (tmp->d_flags & DCACHE_DISCONNECTED) {
++                      assert(tmp->d_alias.next == &inode->i_dentry);
++                      assert(tmp->d_alias.prev == &inode->i_dentry);
++                      goal = tmp;
++                      dget_locked(goal);
++                      break;
++              }
++      }
++
++      if (!goal)
++              goto do_instantiate;
++
++      /* Move the goal to the de hash queue */
++      goal->d_flags &= ~DCACHE_DISCONNECTED;
++      security_d_instantiate(goal, inode);
++      __d_drop(dentry);
++      spin_unlock(&dcache_lock);
++      d_rehash(dentry);
++      d_move(goal, dentry);
++      iput(inode);
++
++      return goal;
++
++      /* d_add(), but don't drop dcache_lock before adding dentry to inode */
++do_instantiate:
++      list_add(&dentry->d_alias, &inode->i_dentry);   /* d_instantiate */
++      dentry->d_inode = inode;
++do_rehash:
++      spin_unlock(&dcache_lock);
++      if (rehash)
++              d_rehash(dentry);
++
++      return NULL;
++}
++
++/*
++ * These are the special structures for the iopen pseudo directory.
++ */
++
++static struct inode_operations iopen_inode_operations = {
++      lookup:         iopen_lookup,           /* BKL held */
++};
++
++static struct file_operations iopen_file_operations = {
++      read:           generic_read_dir,
++};
++
++static int match_dentry(struct dentry *dentry, const char *name)
++{
++      int     len;
++
++      len = strlen(name);
++      if (dentry->d_name.len != len)
++              return 0;
++      if (strncmp(dentry->d_name.name, name, len))
++              return 0;
++      return 1;
++}
++
++/*
++ * This function is spliced into ext3_lookup and returns 1 the file
++ * name is __iopen__ and dentry has been filled in appropriately.
++ */
++int ext3_check_for_iopen(struct inode *dir, struct dentry *dentry)
++{
++      struct inode *inode;
++
++      if (dir->i_ino != EXT3_ROOT_INO ||
++          !test_opt(dir->i_sb, IOPEN) ||
++          !match_dentry(dentry, "__iopen__"))
++              return 0;
++
++      inode = iget(dir->i_sb, EXT3_BAD_INO);
++
++      if (!inode)
++              return 0;
++      d_add(dentry, inode);
++      return 1;
++}
++
++/*
++ * This function is spliced into read_inode; it returns 1 if inode
++ * number is the one for /__iopen__, in which case the inode is filled
++ * in appropriately.  Otherwise, this fuction returns 0.
++ */
++int ext3_iopen_get_inode(struct inode *inode)
++{
++      if (inode->i_ino != EXT3_BAD_INO)
++              return 0;
++
++      inode->i_mode = S_IFDIR | S_IRUSR | S_IXUSR;
++      if (test_opt(inode->i_sb, IOPEN_NOPRIV))
++              inode->i_mode |= 0777;
++      inode->i_uid = 0;
++      inode->i_gid = 0;
++      inode->i_nlink = 1;
++      inode->i_size = 4096;
++      inode->i_atime = CURRENT_TIME;
++      inode->i_ctime = CURRENT_TIME;
++      inode->i_mtime = CURRENT_TIME;
++      EXT3_I(inode)->i_dtime = 0;
++      inode->i_blksize = PAGE_SIZE;   /* This is the optimal IO size
++                                       * (for stat), not the fs block
++                                       * size */
++      inode->i_blocks = 0;
++      inode->i_version = 1;
++      inode->i_generation = 0;
++
++      inode->i_op = &iopen_inode_operations;
++      inode->i_fop = &iopen_file_operations;
++      inode->i_mapping->a_ops = 0;
++
++      return 1;
++}
+Index: linux-2.6.16.i686/fs/ext3/iopen.h
+===================================================================
+--- linux-2.6.16.i686.orig/fs/ext3/iopen.h     2006-05-31 04:14:15.752410384 +0800
++++ linux-2.6.16.i686/fs/ext3/iopen.h  2006-05-30 22:52:38.000000000 +0800
+@@ -0,0 +1,15 @@
++/*
++ * iopen.h
++ *
++ * Special support for opening files by inode number.
++ *
++ * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu).
++ *
++ * This file may be redistributed under the terms of the GNU General
++ * Public License.
++ */
++
++extern int ext3_check_for_iopen(struct inode *dir, struct dentry *dentry);
++extern int ext3_iopen_get_inode(struct inode *inode);
++extern struct dentry *iopen_connect_dentry(struct dentry *dentry,
++                                         struct inode *inode, int rehash);
+Index: linux-2.6.16.i686/fs/ext3/inode.c
+===================================================================
+--- linux-2.6.16.i686.orig/fs/ext3/inode.c     2006-05-30 22:52:03.000000000 +0800
++++ linux-2.6.16.i686/fs/ext3/inode.c  2006-05-30 22:52:38.000000000 +0800
+@@ -37,6 +37,7 @@
+ #include <linux/mpage.h>
+ #include <linux/uio.h>
+ #include "xattr.h"
++#include "iopen.h"
+ #include "acl.h"
+ static int ext3_writepage_trans_blocks(struct inode *inode);
+@@ -2448,6 +2449,8 @@
+       ei->i_default_acl = EXT3_ACL_NOT_CACHED;
+ #endif
+       ei->i_block_alloc_info = NULL;
++      if (ext3_iopen_get_inode(inode))
++              return;
+       if (__ext3_get_inode_loc(inode, &iloc, 0))
+               goto bad_inode;
+Index: linux-2.6.16.i686/fs/ext3/super.c
+===================================================================
+--- linux-2.6.16.i686.orig/fs/ext3/super.c     2006-05-30 22:52:03.000000000 +0800
++++ linux-2.6.16.i686/fs/ext3/super.c  2006-05-30 22:52:38.000000000 +0800
+@@ -634,6 +634,7 @@
+       Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
+       Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
+       Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
++      Opt_iopen, Opt_noiopen, Opt_iopen_nopriv,
+       Opt_grpquota
+ };
+@@ -682,6 +683,9 @@
+       {Opt_noquota, "noquota"},
+       {Opt_quota, "quota"},
+       {Opt_usrquota, "usrquota"},
++      {Opt_iopen, "iopen"},
++      {Opt_noiopen, "noiopen"},
++      {Opt_iopen_nopriv, "iopen_nopriv"},
+       {Opt_barrier, "barrier=%u"},
+       {Opt_err, NULL},
+       {Opt_resize, "resize"},
+@@ -996,6 +1000,18 @@
+                       else
+                               clear_opt(sbi->s_mount_opt, BARRIER);
+                       break;
++              case Opt_iopen:
++                      set_opt (sbi->s_mount_opt, IOPEN);
++                      clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
++                      break;
++              case Opt_noiopen:
++                      clear_opt (sbi->s_mount_opt, IOPEN);
++                      clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
++                      break;
++              case Opt_iopen_nopriv:
++                      set_opt (sbi->s_mount_opt, IOPEN);
++                      set_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
++                      break;
+               case Opt_ignore:
+                       break;
+               case Opt_resize:
+Index: linux-2.6.16.i686/fs/ext3/namei.c
+===================================================================
+--- linux-2.6.16.i686.orig/fs/ext3/namei.c     2006-05-30 22:52:00.000000000 +0800
++++ linux-2.6.16.i686/fs/ext3/namei.c  2006-05-30 22:55:19.000000000 +0800
+@@ -39,6 +39,7 @@
+ #include "namei.h"
+ #include "xattr.h"
++#include "iopen.h"
+ #include "acl.h"
+ /*
+@@ -995,6 +996,9 @@
+       if (dentry->d_name.len > EXT3_NAME_LEN)
+               return ERR_PTR(-ENAMETOOLONG);
++      if (ext3_check_for_iopen(dir, dentry))
++              return NULL;
++
+       bh = ext3_find_entry(dentry, &de);
+       inode = NULL;
+       if (bh) {
+@@ -1005,7 +1009,7 @@
+               if (!inode)
+                       return ERR_PTR(-EACCES);
+       }
+-      return d_splice_alias(inode, dentry);
++      return iopen_connect_dentry(dentry, inode, 1);
+ }
+@@ -2046,10 +2050,6 @@
+                             inode->i_nlink);
+       inode->i_version++;
+       inode->i_nlink = 0;
+-      /* There's no need to set i_disksize: the fact that i_nlink is
+-       * zero will ensure that the right thing happens during any
+-       * recovery. */
+-      inode->i_size = 0;
+       ext3_orphan_add(handle, inode);
+       inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
+       ext3_mark_inode_dirty(handle, inode);
+@@ -2173,6 +2173,23 @@
+       return err;
+ }
++/* Like ext3_add_nondir() except for call to iopen_connect_dentry */
++static int ext3_add_link(handle_t *handle, struct dentry *dentry,
++                       struct inode *inode)
++{
++      int err = ext3_add_entry(handle, dentry, inode);
++      if (!err) {
++              err = ext3_mark_inode_dirty(handle, inode);
++              if (err == 0) {
++                      dput(iopen_connect_dentry(dentry, inode, 0));
++                      return 0;
++              }
++      }
++      ext3_dec_count(handle, inode);
++      iput(inode);
++      return err;
++}
++
+ static int ext3_link (struct dentry * old_dentry,
+               struct inode * dir, struct dentry *dentry)
+ {
+@@ -2196,7 +2213,8 @@
+       ext3_inc_count(handle, inode);
+       atomic_inc(&inode->i_count);
+-      err = ext3_add_nondir(handle, dentry, inode);
++      err = ext3_add_link(handle, dentry, inode);
++      ext3_orphan_del(handle, inode);
+       ext3_journal_stop(handle);
+       if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries))
+               goto retry;
+Index: linux-2.6.16.i686/fs/ext3/Makefile
+===================================================================
+--- linux-2.6.16.i686.orig/fs/ext3/Makefile    2006-03-20 13:53:29.000000000 +0800
++++ linux-2.6.16.i686/fs/ext3/Makefile 2006-05-30 22:52:38.000000000 +0800
+@@ -4,7 +4,7 @@
+ obj-$(CONFIG_EXT3_FS) += ext3.o
+-ext3-y        := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
++ext3-y        := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
+          ioctl.o namei.o super.o symlink.o hash.o resize.o
+ ext3-$(CONFIG_EXT3_FS_XATTR)   += xattr.o xattr_user.o xattr_trusted.o
+Index: linux-2.6.16.i686/include/linux/ext3_fs.h
+===================================================================
+--- linux-2.6.16.i686.orig/include/linux/ext3_fs.h     2006-05-30 22:52:00.000000000 +0800
++++ linux-2.6.16.i686/include/linux/ext3_fs.h  2006-05-30 22:52:38.000000000 +0800
+@@ -375,6 +375,8 @@
+ #define EXT3_MOUNT_QUOTA              0x80000 /* Some quota option set */
+ #define EXT3_MOUNT_USRQUOTA           0x100000 /* "old" user quota */
+ #define EXT3_MOUNT_GRPQUOTA           0x200000 /* "old" group quota */
++#define EXT3_MOUNT_IOPEN              0x400000        /* Allow access via iopen */
++#define EXT3_MOUNT_IOPEN_NOPRIV               0x800000/* Make iopen world-readable */
+ /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
+ #ifndef _LINUX_EXT2_FS_H
diff --git a/ldiskfs/kernel_patches/series/ldiskfs-2.6-fc3.series b/ldiskfs/kernel_patches/series/ldiskfs-2.6-fc3.series
new file mode 100644 (file)
index 0000000..5395486
--- /dev/null
@@ -0,0 +1,22 @@
+ext3-wantedi-2.6-rhel4.patch
+ext3-san-jdike-2.6-suse.patch
+iopen-2.6-rhel4.patch 
+export_symbols-ext3-2.6-suse.patch
+ext3-map_inode_page-2.6-suse.patch
+ext3-ea-in-inode-2.6-rhel4.patch
+export-ext3-2.6-rhel4.patch
+ext3-include-fixes-2.6-rhel4.patch
+ext3-extents-2.6.9-rhel4.patch
+ext3-mballoc2-2.6.9-rhel4.patch 
+ext3-nlinks-2.6.9.patch
+ext3-ialloc-2.6.patch
+ext3-lookup-dotdot-2.6.9.patch
+ext3-tall-htree.patch
+ext3-htree-path.patch
+ext3-htree-r5-hash.patch
+ext3-htree-path-ops.patch
+ext3-hash-selection.patch
+ext3-htree-comments.patch
+ext3-iam-ops.patch
+ext3-iam-separate.patch 
+ext3-iam-uapi.patch 
diff --git a/ldiskfs/kernel_patches/series/ldiskfs-2.6-fc5.series b/ldiskfs/kernel_patches/series/ldiskfs-2.6-fc5.series
new file mode 100644 (file)
index 0000000..1c853bd
--- /dev/null
@@ -0,0 +1,12 @@
+ext3-wantedi-2.6-rhel4.patch
+ext3-san-jdike-2.6-suse.patch
+iopen-2.6-fc5.patch
+ext3-map_inode_page-2.6-suse.patch
+export-ext3-2.6-rhel4.patch
+ext3-include-fixes-2.6-rhel4.patch
+ext3-extents-2.6.15.patch
+ext3-mballoc2-2.6-fc5.patch
+ext3-nlinks-2.6.9.patch
+ext3-ialloc-2.6.patch
+ext3-remove-cond_resched-calls-2.6.12.patch
+ext3-filterdata-2.6.15.patch
index f6d42cd..2f2f413 100644 (file)
@@ -16,6 +16,9 @@ ext3-htree-r5-hash.patch
 ext3-htree-path-ops.patch
 ext3-hash-selection.patch
 ext3-htree-comments.patch
+ext3-lookup-dotdot-2.6.9.patch
+ext3-sector_t-overflow-2.6.9-rhel4.patch
+ext3-check-jbd-errors-2.6.9.patch
 ext3-iam-ops.patch
 ext3-iam-separate.patch 
 ext3-iam-uapi.patch 
index 2584c1d..f3be0ea 100644 (file)
@@ -12,3 +12,6 @@ ext3-nlinks-2.6.7.patch
 ext3-rename-reserve-2.6-suse.patch
 ext3-htree-dot-2.6.5-suse.patch 
 ext3-ialloc-2.6.patch
+ext3-lookup-dotdot-2.6.9.patch
+ext3-sector_t-overflow-2.6.5-suse.patch
+ext3-check-jbd-errors-2.6.5.patch
index 7d0a383..53c060b 100644 (file)
@@ -11,3 +11,5 @@ ext3-ialloc-2.6.patch
 ext3-remove-cond_resched-calls-2.6.12.patch
 ext3-htree-dot-2.6.patch
 ext3-external-journal-2.6.12.patch
+ext3-lookup-dotdot-2.6.9.patch
+ext3-sector_t-overflow-2.6.12.patch
diff --git a/ldiskfs/kernel_patches/series/ldiskfs-2.6.18-vanilla.series b/ldiskfs/kernel_patches/series/ldiskfs-2.6.18-vanilla.series
new file mode 100644 (file)
index 0000000..f379cec
--- /dev/null
@@ -0,0 +1,13 @@
+ext3-wantedi-2.6-rhel4.patch
+ext3-san-jdike-2.6-suse.patch
+iopen-2.6-fc5.patch
+ext3-map_inode_page-2.6-suse.patch
+export-ext3-2.6-rhel4.patch
+ext3-include-fixes-2.6-rhel4.patch
+ext3-extents-2.6.18-vanilla.patch
+ext3-mballoc2-2.6.18-vanilla.patch
+ext3-nlinks-2.6.9.patch
+ext3-ialloc-2.6.patch
+ext3-remove-cond_resched-calls-2.6.12.patch
+ext3-filterdata-2.6.15.patch
+ext3-multi-mount-protection-2.6.18-vanilla.patch
index 727f180..6ecae2e 100644 (file)
@@ -1,5 +1,91 @@
 tbd         Cluster File Systems, Inc. <info@clusterfs.com>
+       * version 1.6.0
+       * CONFIGURATION CHANGE.  This version of Lustre WILL NOT
+        INTEROPERATE with older versions automatically.  In many cases a
+        special upgrade step is needed. Please read the
+        user documentation before upgrading any part of a live system.
+       * WIRE PROTOCOL CHANGE from previous 1.6 beta versions.  This
+         version will not interoperate with older 1.6 betas.  
+       * WARNING: Lustre configuration and startup changes are required with
+        this release.  See https://mail.clusterfs.com/wikis/lustre/MountConf
+        for details.
+       * bug fixes
+
+
+Severity   : enhancement
+Bugzilla   : 4226
+Description: Permanently set tunables
+Details    : All writable /proc/fs/lustre tunables can now be permanently
+             set on a per-server basis, at mkfs time or on a live
+            system.
+       
+Severity   : enhancement
+Bugzilla   : 10547
+Description: Lustre message v2
+Details    : Add lustre message format v2.
+
+Severity   : enhancement
+Bugzilla   : 8007
+Description: MountConf
+Details    : Lustre configuration is now managed via mkfs and mount
+            commands instead of lmc and lconf.  New obd types (MGS, MGC)
+            are added for dynamic configuration management.  See
+            https://mail.clusterfs.com/wikis/lustre/MountConf for
+            details.
+
+Severity   : enhancement
+Bugzilla   : 4482
+Description: dynamic OST addition
+Details    : OSTs can now be added to a live filesystem
+
+Severity   : enhancement
+Bugzilla   : 9851
+Description: startup order invariance
+Details    : MDTs and OSTs can be started in any order.  Clients only
+            require the MDT to complete startup.
+       
+Severity   : enhancement
+Bugzilla   : 4899
+Description: parallel, asynchronous orphan cleanup
+Details    : orphan cleanup is now performed in separate threads for each
+            OST, allowing parallel non-blocking operation.
+
+Severity   : enhancement
+Bugzilla   : 9862
+Description: optimized stripe assignment
+Details    : stripe assignments are now made based on ost space available,
+            ost previous usage, and OSS previous usage, in order to try
+            to optimize storage space and networking resources. 
+       
+Severity   : enhancement
+Bugzilla   : 9866
+Description: client OST exclusion list
+Details    : Clients can be started with a list of OSTs that should be
+            declared "inactive" for known non-responsive OSTs.
+
+Severity   : minor
+Bugzilla   : 6062
+Description: SPEC SFS validation failure on NFS v2 over lustre.
+Details    : Changes the blocksize for regular files to be 2x RPC size,
+             and not depend on stripe size.
+       
+Severity   : enhancement
+Bugzilla   : 9293
+Description: Multiple MD RPCs in flight.
+Details    : Further unserialise some read-only MDS RPCs - learn about intents.
+             To avoid overly-overloading MDS, introduce a limit on number of
+             MDS RPCs in flight for a single client and add /proc controls
+             to adjust this limit.
+
+       
+------------------------------------------------------------------------------
+
+tbd         Cluster File Systems, Inc. <info@clusterfs.com>
        * version 1.4.7
+       * Support for kernels:
+       2.6.9-34.EL (RHEL 4)
+       2.6.5-7.252 (SLES 9)
+       2.6.12.6 vanilla (kernel.org)
        * bug fixes
 
 Severity   : major
@@ -45,10 +131,11 @@ Severity   : enhancement
 Bugzilla   : 9340
 Description: allow number of MDS service threads to be changed at module load
 Details    : It is now possible to change the number of MDS service threads
-            running.  Adding "options mds mds_num_threads=N" will set the
-            number of threads for the next time Lustre is restarted (assuming
-            the "mds" module is also reloaded at that time).  The default
-            number of threads will stay the same, 32 for most systems.
+            running.  Adding "options mds mds_num_threads={N}" to the MDS's
+            /etc/modprobe.conf will set the number of threads for the next
+            time Lustre is restarted (assuming the "mds" module is also
+            reloaded at that time).  The default number of threads will
+            stay the same, 32 for most systems.
 
 Severity   : major
 Frequency  : rare
@@ -109,7 +196,7 @@ Details    : When running an obd_echo server it did not start the ping_evictor
             service startup instead of the OBD startup.
 
 Severity   : enhancement
-Bugzilla   : 10393 (patchless)
+Bugzilla   : 10193 (patchless)
 Description: Remove dependency on various unexported kernel interfaces.
 Details    : No longer need reparent_to_init, exit_mm, exit_files,
             sock_getsockopt, filemap_populate, FMODE_EXEC, put_filp.
@@ -157,6 +244,7 @@ Details    : Use asynchronous set_info RPCs to send the "evict_by_nid" to
             and also offers similar improvements for other set_info RPCs.
 
 Severity   : minor
+Frequency  : common
 Bugzilla   : 10265
 Description: excessive CPU usage during initial read phase on client
 Details    : During the initial read phase on a client, it would agressively
@@ -167,10 +255,257 @@ Details    : During the initial read phase on a client, it would agressively
             /proc/fs/lustre/llite/*/max_read_ahead_whole_mb, 2MB by default).
 
 Severity   : minor
+Frequency  : rare
 Bugzilla   : 10450
 Description: MDS crash when receiving packet with unknown intent.
 Details    : Do not LBUG in unknown intent case, just return -EFAULT
 
+Severity   : enhancement
+Bugzilla   : 9293, 9385
+Description: MDS RPCs are serialised on client. This is unnecessary for some.
+Details    : Do not serialize getattr (non-intent version) and statfs.
+
+Severity   : minor
+Frequency  : occasional, when OST network is overloaded/intermittent
+Bugzilla   : 10416 
+Description: client evicted by OST after bulk IO timeout
+Details    : If a client sends a bulk IO request (read or write) the OST
+            may evict the client if it is unresposive to its data GET/PUT
+            request.  This is incorrect if the network is overloaded (takes
+            too long to transfer the RPC data) or dropped the OST GET/PUT
+            request.  There is no need to evict the client at all, since
+            the pinger and/or lock callbacks will handle this, and the
+            client can restart the bulk request.
+
+Severity   : minor
+Frequency  : Always when mmapping file with no objects
+Bugzilla   : 10438 
+Description: client crashes when mmapping file with no objects
+Details    : Check that we actually have objects in a file before doing any
+            operations on objects in ll_vm_open, ll_vm_close and
+            ll_glimpse_size.
+
+Severity   : minor
+Frequency  : Rare
+Bugzilla   : 10484
+Description: Request leak when working with deleted CWD
+Details    : Introduce advanced request refcount tracking for requests
+            referenced from lustre intent.
+
+Severity   : Enhancement
+Bugzilla   : 10482
+Description: Cache open file handles on client.
+Details    : MDS now will return special lock along with openhandle, if
+            requested and client is allowed to hold openhandle, even if unused,
+            until such a lock is revoked. Helps NFS a lot, since NFS is opening
+            closing files for every read/write openration.
+
+Severity   : Enhancement
+Bugzilla   : 9291
+Description: Cache open negative dentries on client when possible.
+Details    : Guard negative dentries with UPDATE lock on parent dir, drop
+            negative dentries on lock revocation.
+
+Severity   : minor
+Frequency  : Always
+Bugzilla   : 10510
+Description: Remounting a client read-only wasn't possible with a zconf mount
+Details    : It wasn't possible to remount a client read-only with llmount.
+
+Severity   : enhancement
+Description: Include MPICH 1.2.6 Lustre ADIO interface patch
+Details    : In lustre/contrib/ or /usr/share/lustre in RPM a patch for
+            MPICH is included to add Lustre-specific ADIO interfaces.
+            This is based closely on the UFS ADIO layer and only differs
+            in file creation, in order to allow the OST striping to be set.
+            This is user-contributed code and not supported by CFS.
+
+Severity   : minor
+Frequency  : Always
+Bugzilla   : 9486
+Description: extended inode attributes (immutable, append-only) work improperly
+            when 2.4 and 2.6 kernels are used on client/server or vice versa
+Details    : Introduce kernel-independent values for these flags.
+
+Severity   : enhancement
+Frequency  : Always
+Bugzilla   : 10248
+Description: Allow fractional MB tunings for lustre in /proc/ filesystem.
+Details    : Many of the /proc/ tunables can only be tuned at a megabyte
+            granularity. Now, Fractional MB granularity is be supported,
+            this is very useful for low memory system.
+
+Severity   : enhancement
+Bugzilla   : 9292
+Description: Getattr by fid
+Details    : Getting a file attributes by its fid, obtaining UPDATE|LOOKUP 
+            locks, avoids extra getattr rpc requests to MDS, allows '/' to 
+            have locks and avoids getattr rpc requests for it on every stat.
+
+Severity   : major
+Frequency  : Always, for filesystems larger than 2TB
+Bugzilla   : 6191
+Description: ldiskfs crash at mount for filesystem larger than 2TB with mballoc
+Details    : Kenrel kmalloc limits allocations to 128kB and this prevents
+            filesystems larger than 2TB to be mounted with mballoc enabled.
+
+Severity   : critical
+Frequency  : Always, for 32-bit kernel without CONFIG_LBD and filesystem > 2TB
+Bugzilla   : 6191
+Description: ldiskfs crash at mount for filesystem larger than 2TB with mballoc
+Details    : If a 32-bit kernel is compiled without CONFIG_LBD enabled and a
+            filesystems larger than 2TB is mounted then the kernel will
+            silently corrupt the start of the filesystem.  CONFIG_LBD is
+            enabled for all CFS-supported kernels, but the possibility of
+            this happening with a modified kernel config exists.
+
+Severity   : enhancement
+Bugzilla   : 10462
+Description: add client O_DIRECT support for 2.6 kernels
+Details    : It is now possible to do O_DIRECT reads and writes to files
+            in the Lustre client mountpoint on 2.6 kernel clients.
+
+Severity   : enhancement
+Bugzilla   : 10446
+Description: parallel glimpse, setattr, statfs, punch, destroy requests
+Details    : Sends glimpse, setattr, statfs, punch, destroy requests to OSTs in
+            parallel, not waiting for response from every OST before sending
+            a rpc to the next OST.
+
+Severity   : minor
+Frequency  : rare
+Bugzilla   : 10150
+Description: setattr vs write race when updating file timestamps
+Details    : Client processes that update a file timestamp into the past
+            right after writing to the file (e.g. tar) it is possible that
+            the updated file modification time can be reset to the current
+            time due to a race between processing the setattr and write RPC.
+
+Severity   : enhancement
+Bugzilla   : 10318
+Description: Bring 'lfs find' closer in line with regular Linux find.
+Details    : lfs find util supports -atime, -mtime, -ctime, -maxdepth, -print,
+            -print0 options and obtains all the needed info through the lustre
+            ioctls.
+
+Severity   : enhancement
+Bugzilla   : 6221
+Description: support up to 1024 configured devices on one node
+Details    : change obd_dev array from statically allocated to dynamically
+            allocated structs as they are first used to reduce memory usage
+
+Severity   : minor
+Frequency  : rare
+Bugzilla   : 10437
+Description: Flush dirty partially truncated pages during truncate
+Details    : Immediatelly flush partially truncated pages in filter_setattr,
+            this way we completely avoid having any pages in page cache on OST
+            and can retire ugly workarounds during writes to flush such pages.
+
+Severity   : minor
+Frequency  : rare
+Bugzilla   : 10409
+Description: i_sem vs transaction deadlock in mds_obd_destroy during unlink.
+Details    : protect inode from truncation within vfs_unlink() context
+            just take a reference before calling vfs_unlink() and release it
+            when parent's i_sem is free.
+
+Severity   : major
+Frequency  : rare
+Bugzilla   : 4778
+Description: last_id value checked outside lock on OST caused LASSERT failure
+Details    : If there were multiple MDS->OST object precreate requests in
+            flight, it was possible that the OST's last object id was checked
+            outside a lock and incorrectly tripped an assertion.  Move checks
+            inside locks, and discard old precreate requests.
+
+Severity   : minor
+Frequency  : always, if extents are used on OSTs
+Bugzilla   : 10703
+Description: index ei_leaf_hi (48-bit extension) is not zeroed in extent index
+Details    : OSTs using the extents format would not zero the high 16 bits of
+            the index physical block number.  This is not a problem for any
+            OST filesystems smaller than 16TB, and no kernels support ext3
+            filesystems larger than 16TB yet.  This is fixed in 1.4.7 (all
+            new/modified files) and can be fixed for existing filesystems
+            with e2fsprogs-1.39-cfs1.
+
+Severity   : minor
+Frequency  : rare
+Bugzilla   : 9387
+Description: import connection selection may be incorrect if timer wraps
+Details    : Using a 32-bit jiffies timer with HZ=1000 may cause backup
+            import connections to be ignored if the 32-bit jiffies counter
+            wraps.  Use a 64-bit jiffies counter.
+
+Severity   : minor
+Frequency  : very large clusters immediately after boot
+Bugzilla   : 10083
+Description: LNET request buffers exhausted under heavy short-term load
+Details    : If a large number of client requests are generated on a service
+            that has previously never seen so many requests it is possible
+            that the request buffer growth cannot keep up with the spike in
+            demand.  Instead of dropping incoming requests, they are held in
+            the LND until the RPC service can accept more requests.
+
+Severity   : minor
+Frequency  : Sometimes during replay
+Bugzilla   : 9314
+Description: Assertion failure in ll_local_open after replay.
+Details    : If replay happened on an open request reply before we were able
+             to set replay handler, reply will become not swabbed tripping the
+             assertion in ll_local_open. Now we set the handler right after
+             recognising of open request
+
+Severity   : minor
+Frequency  : very rare
+Bugzilla   : 10669
+Description: Deadlock: extent lock cancellation callback vs import invalidation
+Details    : If extent lock cancellation callback takes long enough time, and it
+            happens that import gets invalidated in process, there is a
+            deadlock on page_lock in extent lock cancellation vs ns_lock in
+            import invalidation processes. The fix is to not try to match
+            locks from inactive OSTs.
+
+Severity   : trivial
+Frequency  : very rare
+Bugzilla   : 10584
+Description: kernel reports "badness in vsnprintf"
+Details    : Reading from the "recovery_status" /proc file in small chunks
+            may cause a negative length in lprocfs_obd_rd_recovery_status()
+            call to vsnprintf() (which is otherwise harmless).  Exit early
+            if there is no more space in the output buffer.
+
+Severity   : enhancement
+Bugzilla   : 2259
+Description: clear OBD RPC statistics by writing to them
+Details    : It is now possible to clear the OBD RPC statistics by writing
+            to the "stats" file.
+
+Severity   : minor
+Frequency  : always
+Bugzilla   : 10611
+Description: Inability to activate failout mode
+Details    : lconf script incorrectly assumed that in pythong string's numeric
+            value is used in comparisons.
+
+Severity   : minor
+Frequency  : always with multiple stripes per file
+Bugzilla   : 10671
+Description: Inefficient object allocation for mutli-stripe files
+Details    : When selecting which OSTs to stripe files over, for files with
+            a stripe count that divides evenly into the number of OSTs,
+            the MDS is always picking the same starting OST for each file.
+            Return the OST selection heuristic to the original design.
+
+Severity   : trivial
+Frequency  : rare
+Bugzilla   : 10673
+Description: mount failures may take full timeout to return an error
+Details    : Under some heavy load conditions it is possible that a
+            failed mount can wait for the full obd_timeout interval,
+            possibly several minutes, before reporting an error.
+            Instead return an error as soon as the status is known.
 
 ------------------------------------------------------------------------------
 
@@ -183,9 +518,9 @@ Details    : Do not LBUG in unknown intent case, just return -EFAULT
         this release.  See https://bugzilla.clusterfs.com/show_bug.cgi?id=10052
         for details.
        * bug fixes
-       * Support for newer kernels:
-       2.6.9-22.0.2.EL (RHEL 4),
-       2.6.5-7.244 (SLES 9) - same as 1.4.5.2.
+       * Support for kernels:
+       2.6.9-22.0.2.EL (RHEL 4)
+       2.6.5-7.244 (SLES 9)
        2.6.12.6 vanilla (kernel.org)
 
 
@@ -574,8 +909,8 @@ Severity   : enhancement
 Bugzilla   : 4928, 7341, 9758
 Description: allow number of OST service threads to be specified
 Details    : a module parameter allows the number of OST service threads
-            to be specified via "options ost ost_num_threads=X" in
-            /etc/modules.conf or /etc/modutils.conf.
+            to be specified via "options ost ost_num_threads={N}" in the
+            OSS's /etc/modules.conf or /etc/modprobe.conf.
 
 Severity   : major
 Frequency  : rare
@@ -700,6 +1035,14 @@ Details    : If a client is repeatedly creating and unlinking files it
             client node to run out of memory.  Instead flush old inodes
             from client cache that have the same inode number as a new inode.
 
+Severity   : minor
+Frequency  : SLES9 2.6.5 kernel and long filenames only
+Bugzilla   : 9969, 10379
+Description: utime reports stale NFS file handle
+Details    : SLES9 uses out-of-dentry names in some cases, which confused
+            the lustre dentry revalidation.  Change it to always use the
+            in-dentry qstr.
+
 Severity   : major
 Frequency  : rare, unless heavy write-truncate concurrency is continuous
 Bugzilla   : 4180, 6984, 7171, 9963, 9331
index c9e56a5..3b06838 100644 (file)
@@ -5,12 +5,13 @@
 
 AUTOMAKE_OPTIONS = foreign
 
-ALWAYS_SUBDIRS := include fid lvfs obdclass ldlm ptlrpc osc lov obdecho \
-       mgc doc utils tests conf scripts autoconf
+# also update lustre/autoconf/lustre-core.m4 AC_CONFIG_FILES
+ALWAYS_SUBDIRS := include lvfs obdclass ldlm ptlrpc osc lov obdecho \
+       mgc fid fld doc utils tests scripts autoconf contrib
 
 SERVER_SUBDIRS := ldiskfs obdfilter ost mds mgs mdt cmm mdd osd
 
-CLIENT_SUBDIRS := mdc lmv llite fld
+CLIENT_SUBDIRS := mdc lmv llite
 
 QUOTA_SUBDIRS := quota
 
@@ -58,27 +59,11 @@ sources: $(LDISKFS) lvfs-sources obdclass-sources lustre_build_version
 
 all-recursive: lustre_build_version
 
+BUILD_VER_H=$(top_builddir)/lustre/include/linux/lustre_build_version.h
+
 lustre_build_version:
        perl $(top_builddir)/lustre/scripts/version_tag.pl $(top_srcdir) $(top_builddir) > tmpver
        echo "#define LUSTRE_RELEASE @RELEASE@" >> tmpver
-       cmp -s $(top_builddir)/lustre/include/linux/lustre_build_version.h tmpver \
-                2> /dev/null &&                                            \
-                $(RM) tmpver ||                                            \
-                mv tmpver $(top_builddir)/lustre/include/linux/lustre_build_version.h
-
-CSTK=/tmp/checkstack
-CSTKO=/tmp/checkstack.orig
-
-checkstack:
-       [ -f ${CSTK} -a ! -s ${CSTKO} ] && mv ${CSTK} ${CSTKO} || true
-       for i in ${SUBDIRS} lnet/klnds/*; do                                 \
-               MOD=$$i/`basename $$i`.o;                                    \
-               [ -f $$MOD ] && objdump -d $$MOD | perl tests/checkstack.pl; \
-       done | sort -nr > ${CSTK}
-       [ -f ${CSTKO} ] && ! diff -u ${CSTKO} ${CSTK} || head -30 ${CSTK}
-
-checkstack-update:
-       [ -f ${CSTK} ] && mv ${CSTK} ${CSTKO}
-
-checkstack-clean:
-       rm -f ${CSTK} ${CSTKO}
+       cmp -s $(BUILD_VER_H) tmpver > tmpdiff 2> /dev/null &&          \
+                $(RM) tmpver tmpdiff ||                                        \
+               mv -f tmpver $(BUILD_VER_H)
index 47a58f5..a7e1fc3 100644 (file)
@@ -26,9 +26,6 @@ AC_SUBST(demodir)
 
 pkgexampledir='${pkgdatadir}/examples'
 AC_SUBST(pkgexampledir)
-
-pymoddir='${pkglibdir}/python/Lustre'
-AC_SUBST(pymoddir)
 ])
 
 #
@@ -363,8 +360,12 @@ case $BACKINGFS in
                case $LINUXRELEASE in
                2.6.5*) LDISKFS_SERIES="2.6-suse.series" ;;
                2.6.9*) LDISKFS_SERIES="2.6-rhel4.series" ;;
+               2.6.10-ac*) LDISKFS_SERIES="2.6-fc3.series" ;;
                2.6.10*) LDISKFS_SERIES="2.6-rhel4.series" ;;
                2.6.12*) LDISKFS_SERIES="2.6.12-vanilla.series" ;;
+               2.6.15*) LDISKFS_SERIES="2.6-fc5.series";;
+               2.6.16*) LDISKFS_SERIES="2.6-fc5.series";;
+               2.6.18*) LDISKFS_SERIES="2.6.18-vanilla.series";;
                *) AC_MSG_WARN([Unknown kernel version $LINUXRELEASE, fix lustre/autoconf/lustre-core.m4])
                esac
                AC_MSG_RESULT([$LDISKFS_SERIES])
@@ -487,13 +488,111 @@ LB_LINUX_TRY_COMPILE([
 ])
 ])
 
+AC_DEFUN([LC_BIT_SPINLOCK_H],
+[LB_CHECK_FILE([$LINUX/include/linux/bit_spinlock.h],[
+       AC_MSG_CHECKING([if bit_spinlock.h can be compiled])
+       LB_LINUX_TRY_COMPILE([
+               #include <asm/processor.h>
+               #include <linux/spinlock.h>
+               #include <linux/bit_spinlock.h>
+       ],[],[
+               AC_MSG_RESULT([yes])
+               AC_DEFINE(HAVE_BIT_SPINLOCK_H, 1, [Kernel has bit_spinlock.h])
+       ],[
+               AC_MSG_RESULT([no])
+       ])
+],
+[])
+])
+
+#
+# LC_POSIX_ACL_XATTR
+#
+# If we have xattr_acl.h 
+#
+AC_DEFUN([LC_XATTR_ACL],
+[LB_CHECK_FILE([$LINUX/include/linux/xattr_acl.h],[
+       AC_MSG_CHECKING([if xattr_acl.h can be compiled])
+       LB_LINUX_TRY_COMPILE([
+               #include <linux/xattr_acl.h>
+       ],[],[
+               AC_MSG_RESULT([yes])
+               AC_DEFINE(HAVE_XATTR_ACL, 1, [Kernel has xattr_acl])
+       ],[
+               AC_MSG_RESULT([no])
+       ])
+],
+[])
+])
+
+AC_DEFUN([LC_STRUCT_INTENT_FILE],
+[AC_MSG_CHECKING([if struct open_intent has a file field])
+LB_LINUX_TRY_COMPILE([
+        #include <linux/fs.h>
+        #include <linux/namei.h>
+],[
+        struct open_intent intent;
+        &intent.file;
+],[
+        AC_MSG_RESULT([yes])
+        AC_DEFINE(HAVE_FILE_IN_STRUCT_INTENT, 1, [struct open_intent has a file field])
+],[
+        AC_MSG_RESULT([no])
+])
+])
+
+
+AC_DEFUN([LC_POSIX_ACL_XATTR_H],
+[LB_CHECK_FILE([$LINUX/include/linux/posix_acl_xattr.h],[
+        AC_MSG_CHECKING([if linux/posix_acl_xattr.h can be compiled])
+        LB_LINUX_TRY_COMPILE([
+                #include <linux/posix_acl_xattr.h>
+        ],[],[
+                AC_MSG_RESULT([yes])
+                AC_DEFINE(HAVE_LINUX_POSIX_ACL_XATTR_H, 1, [linux/posix_acl_xattr.h found])
+
+        ],[
+                AC_MSG_RESULT([no])
+        ])
+$1
+],[
+AC_MSG_RESULT([no])
+])
+])
+
+AC_DEFUN([LC_LUSTRE_VERSION_H],
+[LB_CHECK_FILE([$LINUX/include/linux/lustre_version.h],[
+       rm -f "$LUSTRE/include/linux/lustre_version.h"
+],[
+       touch "$LUSTRE/include/linux/lustre_version.h"
+       if test x$enable_server = xyes ; then
+               AC_MSG_WARN([Patchless build detected, disabling server building])
+               enable_server='no'
+       fi
+])
+])
+
+AC_DEFUN([LC_FUNC_SET_FS_PWD],
+[AC_MSG_CHECKING([if kernel exports show_task])
+have_show_task=0
+        if grep -q "EXPORT_SYMBOL(show_task)" \
+                 "$LINUX/fs/namespace.c" 2>/dev/null ; then
+               AC_DEFINE(HAVE_SET_FS_PWD, 1, [set_fs_pwd is exported])
+               AC_MSG_RESULT([yes])
+       else
+               AC_MSG_RESULT([no])
+        fi
+])
+
+
 #
 # LC_PROG_LINUX
 #
 # Lustre linux kernel checks
 #
 AC_DEFUN([LC_PROG_LINUX],
-[if test x$enable_server = xyes ; then
+[ LC_LUSTRE_VERSION_H
+if test x$enable_server = xyes ; then
        LC_CONFIG_BACKINGFS
 fi
 LC_CONFIG_PINGER
@@ -515,6 +614,11 @@ LC_FUNC_PAGE_MAPPED
 LC_STRUCT_FILE_OPS_UNLOCKED_IOCTL
 LC_FILEMAP_POPULATE
 LC_D_ADD_UNIQUE
+LC_BIT_SPINLOCK_H
+LC_XATTR_ACL
+LC_STRUCT_INTENT_FILE
+LC_POSIX_ACL_XATTR_H
+LC_FUNC_SET_FS_PWD
 ])
 
 #
@@ -602,7 +706,7 @@ AC_DEFUN([LC_CONFIGURE],
 [LC_CONFIG_OBD_BUFFER_SIZE
 
 # include/liblustre.h
-AC_CHECK_HEADERS([asm/page.h sys/user.h sys/vfs.h stdint.h])
+AC_CHECK_HEADERS([asm/page.h sys/user.h sys/vfs.h stdint.h blkid/blkid.h])
 
 # include/lustre/lustre_user.h
 # See note there re: __ASM_X86_64_PROCESSOR_H
@@ -618,12 +722,8 @@ AC_CHECK_HEADERS([linux/types.h sys/types.h linux/unistd.h unistd.h])
 AC_CHECK_HEADERS([netinet/in.h arpa/inet.h catamount/data.h])
 AC_CHECK_FUNCS([inet_ntoa])
 
-# llite/xattr.c
-AC_CHECK_HEADERS([linux/xattr_acl.h])
-
-# use universal lustre headers 
-# i.e: include/obd.h instead of include/linux/obd.h
-AC_CHECK_FILE($PWD/lustre/include/obd.h, [AC_DEFINE(UNIV_LUSTRE_HEADERS, 1, [Use universal lustre headers])])
+# utils/llverfs.c
+AC_CHECK_HEADERS([ext2fs/ext2fs.h])
 
 # Super safe df
 AC_ARG_ENABLE([mindf],
@@ -650,6 +750,8 @@ AM_CONDITIONAL(MPITESTS, test x$enable_mpitests = xyes, Build MPI Tests)
 AM_CONDITIONAL(CLIENT, test x$enable_client = xyes)
 AM_CONDITIONAL(SERVER, test x$enable_server = xyes)
 AM_CONDITIONAL(QUOTA, test x$enable_quota = xyes)
+AM_CONDITIONAL(BLKID, test x$ac_cv_header_blkid_blkid_h = xyes)
+AM_CONDITIONAL(EXT2FS_DEVEL, test x$ac_cv_header_ext2fs_ext2fs_h = xyes)
 ])
 
 #
@@ -662,7 +764,7 @@ AC_DEFUN([LC_CONFIG_FILES],
 lustre/Makefile
 lustre/autoMakefile
 lustre/autoconf/Makefile
-lustre/conf/Makefile
+lustre/contrib/Makefile
 lustre/doc/Makefile
 lustre/include/Makefile
 lustre/include/lustre_ver.h
@@ -671,6 +773,8 @@ lustre/include/lustre/Makefile
 lustre/kernel_patches/targets/2.6-suse.target
 lustre/kernel_patches/targets/2.6-vanilla.target
 lustre/kernel_patches/targets/2.6-rhel4.target
+lustre/kernel_patches/targets/2.6-fc5.target
+lustre/kernel_patches/targets/2.6-patchless.target
 lustre/kernel_patches/targets/hp_pnnl-2.4.target
 lustre/kernel_patches/targets/rh-2.4.target
 lustre/kernel_patches/targets/rhel-2.4.target
@@ -727,7 +831,6 @@ lustre/quota/autoMakefile
 lustre/scripts/Makefile
 lustre/scripts/version_tag.pl
 lustre/tests/Makefile
-lustre/utils/Lustre/Makefile
 lustre/utils/Makefile
 ])
 case $lb_target_os in
diff --git a/lustre/contrib/.cvsignore b/lustre/contrib/.cvsignore
new file mode 100644 (file)
index 0000000..282522d
--- /dev/null
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/lustre/contrib/Makefile.am b/lustre/contrib/Makefile.am
new file mode 100644 (file)
index 0000000..5a8e66c
--- /dev/null
@@ -0,0 +1,5 @@
+# Contributions Makefile
+
+EXTRA_DIST = mpich-*.patch
+pkgdata_DATA = $(EXTRA_DIST)
+
diff --git a/lustre/contrib/README b/lustre/contrib/README
new file mode 100644 (file)
index 0000000..73270f3
--- /dev/null
@@ -0,0 +1,2 @@
+The files in this directory are user-contributed and are not supported by
+CFS in any way.
diff --git a/lustre/contrib/mpich-1.2.6-lustre.patch b/lustre/contrib/mpich-1.2.6-lustre.patch
new file mode 100644 (file)
index 0000000..d32fab9
--- /dev/null
@@ -0,0 +1,1829 @@
+diff -r -u --new-file mpich-1.2.6/romio/adio/ad_lustre/ad_lustre.c mpich-1.2.6/romio/adio/ad_lustre/ad_lustre.c
+--- mpich-1.2.6/romio/adio/ad_lustre/ad_lustre.c       1969-12-31 19:00:00.000000000 -0500
++++ mpich-1.2.6/romio/adio/ad_lustre/ad_lustre.c       2005-12-06 11:54:37.883130927 -0500
+@@ -0,0 +1,37 @@
++/* -*- Mode: C; c-basic-offset:4 ; -*- */
++/* 
++ *   $Id: ad_lustre.c,v 1.1.1.1 2004/11/04 11:03:38 liam Exp $
++ *
++ *   Copyright (C) 2001 University of Chicago. 
++ *   See COPYRIGHT notice in top-level directory.
++ */
++
++#include "ad_lustre.h"
++
++/* adioi.h has the ADIOI_Fns_struct define */
++#include "adioi.h"
++
++struct ADIOI_Fns_struct ADIO_LUSTRE_operations = {
++    ADIOI_LUSTRE_Open, /* Open */
++    ADIOI_LUSTRE_ReadContig, /* ReadContig */
++    ADIOI_LUSTRE_WriteContig, /* WriteContig */
++    ADIOI_GEN_ReadStridedColl, /* ReadStridedColl */
++    ADIOI_GEN_WriteStridedColl, /* WriteStridedColl */
++    ADIOI_GEN_SeekIndividual, /* SeekIndividual */
++    ADIOI_LUSTRE_Fcntl, /* Fcntl */
++    ADIOI_LUSTRE_SetInfo, /* SetInfo */
++    ADIOI_GEN_ReadStrided, /* ReadStrided */
++    ADIOI_GEN_WriteStrided, /* WriteStrided */
++    ADIOI_LUSTRE_Close, /* Close */
++    ADIOI_LUSTRE_IreadContig, /* IreadContig */
++    ADIOI_LUSTRE_IwriteContig, /* IwriteContig */
++    ADIOI_LUSTRE_ReadDone, /* ReadDone */
++    ADIOI_LUSTRE_WriteDone, /* WriteDone */
++    ADIOI_LUSTRE_ReadComplete, /* ReadComplete */
++    ADIOI_LUSTRE_WriteComplete, /* WriteComplete */
++    ADIOI_LUSTRE_IreadStrided, /* IreadStrided */
++    ADIOI_LUSTRE_IwriteStrided, /* IwriteStrided */
++    ADIOI_GEN_Flush, /* Flush */
++    ADIOI_LUSTRE_Resize, /* Resize */
++    ADIOI_GEN_Delete, /* Delete */
++};
+diff -r -u --new-file mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_close.c mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_close.c
+--- mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_close.c 1969-12-31 19:00:00.000000000 -0500
++++ mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_close.c 2005-12-06 11:54:37.895129327 -0500
+@@ -0,0 +1,32 @@
++/* -*- Mode: C; c-basic-offset:4 ; -*- */
++/* 
++ *   $Id: ad_lustre_close.c,v 1.1.1.1 2004/11/04 11:03:38 liam Exp $    
++ *
++ *   Copyright (C) 1997 University of Chicago. 
++ *   See COPYRIGHT notice in top-level directory.
++ */
++
++#include "ad_lustre.h"
++
++void ADIOI_LUSTRE_Close(ADIO_File fd, int *error_code)
++{
++    int err;
++#if defined(MPICH2) || !defined(PRINT_ERR_MSG)
++    static char myname[] = "ADIOI_LUSTRE_CLOSE";
++#endif
++
++    err = close(fd->fd_sys);
++    if (err == -1) {
++#ifdef MPICH2
++      *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io",
++          "**io %s", strerror(errno));
++#elif defined(PRINT_ERR_MSG)
++                      *error_code = MPI_ERR_UNKNOWN;
++#else
++      *error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ADIO_ERROR,
++                            myname, "I/O Error", "%s", strerror(errno));
++      ADIOI_Error(fd, *error_code, myname);       
++#endif
++    }
++    else *error_code = MPI_SUCCESS;
++}
+diff -r -u --new-file mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_done.c mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_done.c
+--- mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_done.c  1969-12-31 19:00:00.000000000 -0500
++++ mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_done.c  2005-12-06 11:54:37.898128927 -0500
+@@ -0,0 +1,188 @@
++/* -*- Mode: C; c-basic-offset:4 ; -*- */
++/* 
++ *   $Id: ad_lustre_done.c,v 1.1.1.1 2004/11/04 11:03:38 liam Exp $    
++ *
++ *   Copyright (C) 1997 University of Chicago. 
++ *   See COPYRIGHT notice in top-level directory.
++ */
++
++#include "ad_lustre.h"
++
++int ADIOI_LUSTRE_ReadDone(ADIO_Request *request, ADIO_Status *status, int *error_code)  
++{
++#ifndef NO_AIO
++    int done=0;
++#if defined(MPICH2) || !defined(PRINT_ERR_MSG)
++    static char myname[] = "ADIOI_LUSTRE_READDONE";
++#endif
++#ifdef AIO_SUN 
++    aio_result_t *result=0, *tmp;
++#else
++    int err;
++#endif
++#ifdef AIO_HANDLE_IN_AIOCB
++    struct aiocb *tmp1;
++#endif
++#endif
++
++    if (*request == ADIO_REQUEST_NULL) {
++      *error_code = MPI_SUCCESS;
++      return 1;
++    }
++
++#ifdef NO_AIO
++/* HP, FreeBSD, Linux */
++#ifdef HAVE_STATUS_SET_BYTES
++    MPIR_Status_set_bytes(status, (*request)->datatype, (*request)->nbytes);
++#endif
++    (*request)->fd->async_count--;
++    ADIOI_Free_request((ADIOI_Req_node *) (*request));
++    *request = ADIO_REQUEST_NULL;
++    *error_code = MPI_SUCCESS;
++    return 1;
++#endif    
++
++#ifdef AIO_SUN
++    if ((*request)->queued) {
++      tmp = (aio_result_t *) (*request)->handle;
++      if (tmp->aio_return == AIO_INPROGRESS) {
++          done = 0;
++          *error_code = MPI_SUCCESS;
++      }
++      else if (tmp->aio_return != -1) {
++          result = (aio_result_t *) aiowait(0); /* dequeue any one request */
++          done = 1;
++          (*request)->nbytes = tmp->aio_return;
++          *error_code = MPI_SUCCESS;
++      }
++      else {
++#ifdef MPICH2
++          *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io",
++              "**io %s", strerror(tmp->aio_errno));
++          return;
++#elif defined(PRINT_ERR_MSG)
++          *error_code = MPI_ERR_UNKNOWN;
++#else
++          *error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ADIO_ERROR,
++                       myname, "I/O Error", "%s", strerror(tmp->aio_errno));
++          ADIOI_Error((*request)->fd, *error_code, myname);       
++#endif
++      }
++    } /* if ((*request)->queued) ... */
++    else {
++      /* ADIOI_Complete_Async completed this request, but request object
++           was not freed. */
++      done = 1;
++      *error_code = MPI_SUCCESS;
++    }
++#ifdef HAVE_STATUS_SET_BYTES
++    if (done && ((*request)->nbytes != -1))
++      MPIR_Status_set_bytes(status, (*request)->datatype, (*request)->nbytes);
++#endif
++
++#endif
++
++#ifdef AIO_HANDLE_IN_AIOCB
++/* IBM */
++    if ((*request)->queued) {
++      tmp1 = (struct aiocb *) (*request)->handle;
++      errno = aio_error(tmp1->aio_handle);
++      if (errno == EINPROG) {
++          done = 0;
++          *error_code = MPI_SUCCESS;
++      }
++      else {
++          err = aio_return(tmp1->aio_handle);
++          (*request)->nbytes = err;
++          errno = aio_error(tmp1->aio_handle);
++      
++          done = 1;
++
++          if (err == -1) {
++#ifdef MPICH2
++              *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io",
++                  "**io %s", strerror(errno));
++              return;
++#elif defined(PRINT_ERR_MSG)
++                              *error_code = MPI_ERR_UNKNOWN;
++#else
++              *error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ADIO_ERROR,
++                            myname, "I/O Error", "%s", strerror(errno));
++              ADIOI_Error((*request)->fd, *error_code, myname);           
++#endif
++          }
++          else *error_code = MPI_SUCCESS;
++      }
++    } /* if ((*request)->queued) */
++    else {
++      done = 1;
++      *error_code = MPI_SUCCESS;
++    }
++#ifdef HAVE_STATUS_SET_BYTES
++    if (done && ((*request)->nbytes != -1))
++      MPIR_Status_set_bytes(status, (*request)->datatype, (*request)->nbytes);
++#endif
++
++#elif (!defined(NO_AIO) && !defined(AIO_SUN))
++/* DEC, SGI IRIX 5 and 6 */
++    if ((*request)->queued) {
++      errno = aio_error((const struct aiocb *) (*request)->handle);
++      if (errno == EINPROGRESS) {
++          done = 0;
++          *error_code = MPI_SUCCESS;
++      }
++      else {
++          err = aio_return((struct aiocb *) (*request)->handle); 
++          (*request)->nbytes = err;
++          errno = aio_error((struct aiocb *) (*request)->handle);
++
++          done = 1;
++
++          if (err == -1) {
++#ifdef MPICH2
++              *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io",
++                  "**io %s", strerror(errno));
++              return;
++#elif defined(PRINT_ERR_MSG)
++                              *error_code = MPI_ERR_UNKNOWN;
++#else /* MPICH-1 */
++              *error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ADIO_ERROR,
++                            myname, "I/O Error", "%s", strerror(errno));
++              ADIOI_Error((*request)->fd, *error_code, myname);           
++#endif
++          }
++          else *error_code = MPI_SUCCESS;
++      }
++    } /* if ((*request)->queued) */
++    else {
++      done = 1;
++      *error_code = MPI_SUCCESS;
++    }
++#ifdef HAVE_STATUS_SET_BYTES
++    if (done && ((*request)->nbytes != -1))
++      MPIR_Status_set_bytes(status, (*request)->datatype, (*request)->nbytes);
++#endif
++
++#endif
++
++#ifndef NO_AIO
++    if (done) {
++      /* if request is still queued in the system, it is also there
++           on ADIOI_Async_list. Delete it from there. */
++      if ((*request)->queued) ADIOI_Del_req_from_list(request);
++
++      (*request)->fd->async_count--;
++      if ((*request)->handle) ADIOI_Free((*request)->handle);
++      ADIOI_Free_request((ADIOI_Req_node *) (*request));
++      *request = ADIO_REQUEST_NULL;
++    }
++    return done;
++#endif
++
++}
++
++
++int ADIOI_LUSTRE_WriteDone(ADIO_Request *request, ADIO_Status *status, int *error_code)  
++{
++    return ADIOI_LUSTRE_ReadDone(request, status, error_code);
++} 
+diff -r -u --new-file mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_fcntl.c mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_fcntl.c
+--- mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_fcntl.c 1969-12-31 19:00:00.000000000 -0500
++++ mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_fcntl.c 2005-12-06 11:54:37.901128527 -0500
+@@ -0,0 +1,126 @@
++/* -*- Mode: C; c-basic-offset:4 ; -*- */
++/* 
++ *   $Id: ad_lustre_fcntl.c,v 1.1.1.1 2004/11/04 11:03:38 liam Exp $    
++ *
++ *   Copyright (C) 1997 University of Chicago. 
++ *   See COPYRIGHT notice in top-level directory.
++ */
++
++#include "ad_lustre.h"
++#include "adio_extern.h"
++/* #ifdef MPISGI
++#include "mpisgi2.h"
++#endif */
++
++void ADIOI_LUSTRE_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, int *error_code)
++{
++    int i, ntimes;
++    ADIO_Offset curr_fsize, alloc_size, size, len, done;
++    ADIO_Status status;
++    char *buf;
++#if defined(MPICH2) || !defined(PRINT_ERR_MSG)
++    static char myname[] = "ADIOI_LUSTRE_FCNTL";
++#endif
++
++    switch(flag) {
++    case ADIO_FCNTL_GET_FSIZE:
++      fcntl_struct->fsize = lseek(fd->fd_sys, 0, SEEK_END);
++      if (fd->fp_sys_posn != -1) 
++           lseek(fd->fd_sys, fd->fp_sys_posn, SEEK_SET);
++      if (fcntl_struct->fsize == -1) {
++#ifdef MPICH2
++          *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io",
++              "**io %s", strerror(errno));
++#elif defined(PRINT_ERR_MSG)
++                      *error_code = MPI_ERR_UNKNOWN;
++#else /* MPICH-1 */
++          *error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ADIO_ERROR,
++                            myname, "I/O Error", "%s", strerror(errno));
++          ADIOI_Error(fd, *error_code, myname);           
++#endif
++      }
++      else *error_code = MPI_SUCCESS;
++      break;
++
++    case ADIO_FCNTL_SET_DISKSPACE:
++      /* will be called by one process only */
++      /* On file systems with no preallocation function, I have to 
++           explicitly write 
++           to allocate space. Since there could be holes in the file, 
++           I need to read up to the current file size, write it back, 
++           and then write beyond that depending on how much 
++           preallocation is needed.
++           read/write in sizes of no more than ADIOI_PREALLOC_BUFSZ */
++
++      curr_fsize = lseek(fd->fd_sys, 0, SEEK_END);
++      alloc_size = fcntl_struct->diskspace;
++
++      size = ADIOI_MIN(curr_fsize, alloc_size);
++      
++      ntimes = (size + ADIOI_PREALLOC_BUFSZ - 1)/ADIOI_PREALLOC_BUFSZ;
++      buf = (char *) ADIOI_Malloc(ADIOI_PREALLOC_BUFSZ);
++      done = 0;
++
++      for (i=0; i<ntimes; i++) {
++          len = ADIOI_MIN(size-done, ADIOI_PREALLOC_BUFSZ);
++          ADIO_ReadContig(fd, buf, len, MPI_BYTE, ADIO_EXPLICIT_OFFSET, done,
++                          &status, error_code);
++          if (*error_code != MPI_SUCCESS) {
++              ADIOI_Free(buf);
++#ifdef MPICH2
++              *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io",
++                  "**io %s", strerror(errno));
++#elif defined(PRINT_ERR_MSG)
++              FPRINTF(stderr, "ADIOI_LUSTRE_Fcntl: To preallocate disk space, ROMIO needs to read the file and write it back, but is unable to read the file. Please give the file read permission and open it with MPI_MODE_RDWR.\n");
++              MPI_Abort(MPI_COMM_WORLD, 1);
++#else /* MPICH-1 */
++              *error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_PREALLOC_PERM,
++                            myname, (char *) 0, (char *) 0);
++              ADIOI_Error(fd, *error_code, myname);
++#endif
++                return;  
++          }
++          ADIO_WriteContig(fd, buf, len, MPI_BYTE, ADIO_EXPLICIT_OFFSET, 
++                             done, &status, error_code);
++          if (*error_code != MPI_SUCCESS) return;
++          done += len;
++      }
++
++      if (alloc_size > curr_fsize) {
++          memset(buf, 0, ADIOI_PREALLOC_BUFSZ); 
++          size = alloc_size - curr_fsize;
++          ntimes = (size + ADIOI_PREALLOC_BUFSZ - 1)/ADIOI_PREALLOC_BUFSZ;
++          for (i=0; i<ntimes; i++) {
++              len = ADIOI_MIN(alloc_size-done, ADIOI_PREALLOC_BUFSZ);
++              ADIO_WriteContig(fd, buf, len, MPI_BYTE, ADIO_EXPLICIT_OFFSET, 
++                               done, &status, error_code);
++              if (*error_code != MPI_SUCCESS) return;
++              done += len;  
++          }
++      }
++      ADIOI_Free(buf);
++      if (fd->fp_sys_posn != -1) 
++          lseek(fd->fd_sys, fd->fp_sys_posn, SEEK_SET);
++      *error_code = MPI_SUCCESS;
++      break;
++
++    case ADIO_FCNTL_SET_IOMODE:
++        /* for implementing PFS I/O modes. will not occur in MPI-IO
++           implementation.*/
++      if (fd->iomode != fcntl_struct->iomode) {
++          fd->iomode = fcntl_struct->iomode;
++          MPI_Barrier(MPI_COMM_WORLD);
++      }
++      *error_code = MPI_SUCCESS;
++      break;
++
++    case ADIO_FCNTL_SET_ATOMICITY:
++      fd->atomicity = (fcntl_struct->atomicity == 0) ? 0 : 1;
++      *error_code = MPI_SUCCESS;
++      break;
++
++    default:
++      FPRINTF(stderr, "Unknown flag passed to ADIOI_LUSTRE_Fcntl\n");
++      MPI_Abort(MPI_COMM_WORLD, 1);
++    }
++}
+diff -r -u --new-file mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_flush.c mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_flush.c
+--- mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_flush.c 1969-12-31 19:00:00.000000000 -0500
++++ mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_flush.c 2005-12-06 11:54:37.903128261 -0500
+@@ -0,0 +1,14 @@
++/* -*- Mode: C; c-basic-offset:4 ; -*- */
++/* 
++ *   $Id: ad_lustre_flush.c,v 1.1.1.1 2004/11/04 11:03:38 liam Exp $    
++ *
++ *   Copyright (C) 1997 University of Chicago. 
++ *   See COPYRIGHT notice in top-level directory.
++ */
++
++#include "ad_lustre.h"
++
++void ADIOI_LUSTRE_Flush(ADIO_File fd, int *error_code)
++{
++    ADIOI_GEN_Flush(fd, error_code);
++}
+diff -r -u --new-file mpich-1.2.6/romio/adio/ad_lustre/ad_lustre.h mpich-1.2.6/romio/adio/ad_lustre/ad_lustre.h
+--- mpich-1.2.6/romio/adio/ad_lustre/ad_lustre.h       1969-12-31 19:00:00.000000000 -0500
++++ mpich-1.2.6/romio/adio/ad_lustre/ad_lustre.h       2005-12-06 11:54:37.891129861 -0500
+@@ -0,0 +1,36 @@
++/* -*- Mode: C; c-basic-offset:4 ; -*- */
++/* 
++ *   $Id: ad_lustre.h,v 1.2 2005/07/07 14:38:17 liam Exp $    
++ *
++ *   Copyright (C) 1997 University of Chicago. 
++ *   See COPYRIGHT notice in top-level directory.
++ */
++
++#ifndef AD_UNIX_INCLUDE
++#define AD_UNIX_INCLUDE
++
++/* temp*/
++#define HAVE_ASM_TYPES_H 1
++
++#include <unistd.h>
++#include <linux/types.h>
++#include <fcntl.h>
++#include <sys/ioctl.h>
++#include "lustre/lustre_user.h"
++#include "adio.h"
++
++#ifndef NO_AIO
++#ifdef AIO_SUN
++#include <sys/asynch.h>
++#else
++#include <aio.h>
++#ifdef NEEDS_ADIOCB_T
++typedef struct adiocb adiocb_t;
++#endif
++#endif
++#endif
++
++int ADIOI_LUSTRE_aio(ADIO_File fd, void *buf, int len, ADIO_Offset offset,
++                int wr, void *handle);
++
++#endif
+diff -r -u --new-file mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_hints.c mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_hints.c
+--- mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_hints.c 1969-12-31 19:00:00.000000000 -0500
++++ mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_hints.c 2005-12-06 11:54:37.904128127 -0500
+@@ -0,0 +1,130 @@
++/* -*- Mode: C; c-basic-offset:4 ; -*- */
++/* 
++ *   $Id: ad_lustre_hints.c,v 1.2 2005/07/07 14:38:17 liam Exp $    
++ *
++ *   Copyright (C) 1997 University of Chicago. 
++ *   See COPYRIGHT notice in top-level directory.
++ */
++
++#include "ad_lustre.h"
++
++void ADIOI_LUSTRE_SetInfo(ADIO_File fd, MPI_Info users_info, int *error_code)
++{
++    char *value, *value_in_fd;
++    int flag, tmp_val, str_factor=-1, str_unit=0, start_iodev=-1;
++    struct lov_user_md lum = { 0 };
++    int err, myrank, fd_sys, perm, amode, old_mask;
++
++    if ( (fd->info) == MPI_INFO_NULL) {
++      /* This must be part of the open call. can set striping parameters 
++           if necessary. */ 
++      MPI_Info_create(&(fd->info));
++      
++      /* has user specified striping or server buffering parameters 
++           and do they have the same value on all processes? */
++      if (users_info != MPI_INFO_NULL) {
++          value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char));
++
++          MPI_Info_get(users_info, "striping_factor", MPI_MAX_INFO_VAL, 
++                       value, &flag);
++          if (flag) {
++              str_factor=atoi(value);
++              tmp_val = str_factor;
++              MPI_Bcast(&tmp_val, 1, MPI_INT, 0, fd->comm);
++              if (tmp_val != str_factor) {
++                  FPRINTF(stderr, "ADIOI_LUSTRE_SetInfo: the value for key \"striping_factor\" must be the same on all processes\n");
++                  MPI_Abort(MPI_COMM_WORLD, 1);
++              }
++          }
++
++          MPI_Info_get(users_info, "striping_unit", MPI_MAX_INFO_VAL, 
++                       value, &flag);
++          if (flag) {
++              str_unit=atoi(value);
++              tmp_val = str_unit;
++              MPI_Bcast(&tmp_val, 1, MPI_INT, 0, fd->comm);
++              if (tmp_val != str_unit) {
++                  FPRINTF(stderr, "ADIOI_LUSTRE_SetInfo: the value for key \"striping_unit\" must be the same on all processes\n");
++                  MPI_Abort(MPI_COMM_WORLD, 1);
++              }
++          }
++
++          MPI_Info_get(users_info, "start_iodevice", MPI_MAX_INFO_VAL, 
++                       value, &flag);
++          if (flag) {
++              start_iodev=atoi(value);
++              tmp_val = start_iodev;
++              MPI_Bcast(&tmp_val, 1, MPI_INT, 0, fd->comm);
++              if (tmp_val != start_iodev) {
++                  FPRINTF(stderr, "ADIOI_LUSTRE_SetInfo: the value for key \"start_iodevice\" must be the same on all processes\n");
++                  MPI_Abort(MPI_COMM_WORLD, 1);
++              }
++          }
++
++         /* if user has specified striping info, process 0 tries to set it */
++          if ((str_factor > 0) || (str_unit > 0) || (start_iodev >= 0)) {
++              MPI_Comm_rank(fd->comm, &myrank);
++              if (!myrank) {
++                  if (fd->perm == ADIO_PERM_NULL) {
++                      old_mask = umask(022);
++                      umask(old_mask);
++                      perm = old_mask ^ 0666;
++                  }
++                  else perm = fd->perm;
++
++                  amode = 0;
++                  if (fd->access_mode & ADIO_CREATE)
++                      amode = amode | O_CREAT;
++                  if (fd->access_mode & ADIO_RDWR ||
++                      (fd->access_mode & ADIO_RDONLY &&
++                       fd->access_mode & ADIO_WRONLY))
++                      amode = amode | O_RDWR;
++                  else if (fd->access_mode & ADIO_WRONLY)
++                      amode = amode | O_WRONLY;
++                  else if (fd->access_mode & ADIO_RDONLY)
++                      amode = amode | O_RDONLY;
++                  if (fd->access_mode & ADIO_EXCL)
++                      amode = amode | O_EXCL;
++
++                  /* we need to create file so ensure this is set */
++                    amode = amode | O_LOV_DELAY_CREATE | O_CREAT;
++
++                    fd_sys = open(fd->filename, amode, perm);
++                    if (fd_sys == -1) { 
++                      if (errno != EEXIST) 
++                          FPRINTF(stderr, "ADIOI_LUSTRE_SetInfo: Failure to open file %s %d %d\n",strerror(errno), amode, perm);
++                    } else {
++                        lum.lmm_magic = LOV_USER_MAGIC;
++                        lum.lmm_pattern = 0;
++                        lum.lmm_stripe_size = str_unit;
++                        lum.lmm_stripe_count = str_factor;
++                        lum.lmm_stripe_offset = start_iodev;
++
++                        err = ioctl(fd_sys, LL_IOC_LOV_SETSTRIPE, &lum);
++                        if (err == -1 && errno != EEXIST) { 
++                          FPRINTF(stderr, "ADIOI_LUSTRE_SetInfo: Failure to set stripe info %s \n",strerror(errno));
++                        }
++
++                        close(fd_sys);
++                   }
++
++              }
++              MPI_Barrier(fd->comm);
++          }
++
++          ADIOI_Free(value);
++      }
++      
++      /* set the values for collective I/O and data sieving parameters */
++      ADIOI_GEN_SetInfo(fd, users_info, error_code);
++    }
++    
++    else {
++      /* The file has been opened previously and fd->fd_sys is a valid
++           file descriptor. cannot set striping parameters now. */
++      
++      /* set the values for collective I/O and data sieving parameters */
++      ADIOI_GEN_SetInfo(fd, users_info, error_code);
++
++    }
++    
++    *error_code = MPI_SUCCESS;
++}
+diff -r -u --new-file mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_iread.c mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_iread.c
+--- mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_iread.c 1969-12-31 19:00:00.000000000 -0500
++++ mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_iread.c 2005-12-06 11:54:37.904128127 -0500
+@@ -0,0 +1,106 @@
++/* -*- Mode: C; c-basic-offset:4 ; -*- */
++/* 
++ *   $Id: ad_lustre_iread.c,v 1.1.1.1 2004/11/04 11:03:38 liam Exp $    
++ *
++ *   Copyright (C) 1997 University of Chicago. 
++ *   See COPYRIGHT notice in top-level directory.
++ */
++
++#include "ad_lustre.h"
++
++void ADIOI_LUSTRE_IreadContig(ADIO_File fd, void *buf, int count, 
++                MPI_Datatype datatype, int file_ptr_type,
++                ADIO_Offset offset, ADIO_Request *request, int *error_code)  
++{
++    int len, typesize;
++#ifdef NO_AIO
++    ADIO_Status status;
++#else
++    int err=-1;
++#if defined(MPICH2) || !defined(PRINT_ERR_MSG)
++    static char myname[] = "ADIOI_LUSTRE_IREADCONTIG";
++#endif
++#endif
++
++    (*request) = ADIOI_Malloc_request();
++    (*request)->optype = ADIOI_READ;
++    (*request)->fd = fd;
++    (*request)->datatype = datatype;
++
++    MPI_Type_size(datatype, &typesize);
++    len = count * typesize;
++
++#ifdef NO_AIO
++    /* HP, FreeBSD, Linux */
++    /* no support for nonblocking I/O. Use blocking I/O. */
++
++    ADIOI_LUSTRE_ReadContig(fd, buf, len, MPI_BYTE, file_ptr_type, offset, 
++                       &status, error_code);  
++    (*request)->queued = 0;
++#ifdef HAVE_STATUS_SET_BYTES
++    if (*error_code == MPI_SUCCESS) {
++      MPI_Get_elements(&status, MPI_BYTE, &len);
++      (*request)->nbytes = len;
++    }
++#endif
++
++#else
++    if (file_ptr_type == ADIO_INDIVIDUAL) offset = fd->fp_ind;
++    err = ADIOI_LUSTRE_aio(fd, buf, len, offset, 0, &((*request)->handle));
++    if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind += len;
++
++    (*request)->queued = 1;
++    ADIOI_Add_req_to_list(request);
++
++    if (err == -1) {
++#ifdef MPICH2
++      *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io",
++          "**io %s", strerror(errno));
++      return;
++#elif defined(PRINT_ERR_MSG)
++                      *error_code = MPI_ERR_UNKNOWN;
++#else /* MPICH-1 */
++      *error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ADIO_ERROR,
++                            myname, "I/O Error", "%s", strerror(errno));
++      ADIOI_Error(fd, *error_code, myname);       
++#endif
++    }
++    else *error_code = MPI_SUCCESS;
++#endif  /* NO_AIO */
++
++    fd->fp_sys_posn = -1;   /* set it to null. */
++    fd->async_count++;
++}
++
++
++
++void ADIOI_LUSTRE_IreadStrided(ADIO_File fd, void *buf, int count, 
++                     MPI_Datatype datatype, int file_ptr_type,
++                       ADIO_Offset offset, ADIO_Request *request, int
++                       *error_code)
++{
++    ADIO_Status status;
++#ifdef HAVE_STATUS_SET_BYTES
++    int typesize;
++#endif
++
++    *request = ADIOI_Malloc_request();
++    (*request)->optype = ADIOI_READ;
++    (*request)->fd = fd;
++    (*request)->datatype = datatype;
++    (*request)->queued = 0;
++    (*request)->handle = 0;
++
++/* call the blocking version. It is faster because it does data sieving. */
++    ADIOI_LUSTRE_ReadStrided(fd, buf, count, datatype, file_ptr_type, 
++                            offset, &status, error_code);  
++
++    fd->async_count++;
++
++#ifdef HAVE_STATUS_SET_BYTES
++    if (*error_code == MPI_SUCCESS) {
++      MPI_Type_size(datatype, &typesize);
++      (*request)->nbytes = count * typesize;
++    }
++#endif
++}
+diff -r -u --new-file mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_iwrite.c mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_iwrite.c
+--- mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_iwrite.c        1969-12-31 19:00:00.000000000 -0500
++++ mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_iwrite.c        2005-12-06 11:54:37.906127861 -0500
+@@ -0,0 +1,268 @@
++/* -*- Mode: C; c-basic-offset:4 ; -*- */
++/* 
++ *   $Id: ad_lustre_iwrite.c,v 1.1.1.1 2004/11/04 11:03:38 liam Exp $    
++ *
++ *   Copyright (C) 1997 University of Chicago. 
++ *   See COPYRIGHT notice in top-level directory.
++ */
++
++#include "ad_lustre.h"
++
++void ADIOI_LUSTRE_IwriteContig(ADIO_File fd, void *buf, int count, 
++                MPI_Datatype datatype, int file_ptr_type,
++                ADIO_Offset offset, ADIO_Request *request, int *error_code)  
++{
++    int len, typesize;
++#ifdef NO_AIO
++    ADIO_Status status;
++#else
++    int err=-1;
++#if defined(MPICH2) || !defined(PRINT_ERR_MSG)
++    static char myname[] = "ADIOI_LUSTRE_IWRITECONTIG";
++#endif
++#endif
++
++    *request = ADIOI_Malloc_request();
++    (*request)->optype = ADIOI_WRITE;
++    (*request)->fd = fd;
++    (*request)->datatype = datatype;
++
++    MPI_Type_size(datatype, &typesize);
++    len = count * typesize;
++
++#ifdef NO_AIO
++    /* HP, FreeBSD, Linux */
++    /* no support for nonblocking I/O. Use blocking I/O. */
++
++    ADIOI_LUSTRE_WriteContig(fd, buf, len, MPI_BYTE, file_ptr_type, offset, 
++                        &status, error_code);  
++    (*request)->queued = 0;
++#ifdef HAVE_STATUS_SET_BYTES
++    if (*error_code == MPI_SUCCESS) {
++      MPI_Get_elements(&status, MPI_BYTE, &len);
++      (*request)->nbytes = len;
++    }
++#endif
++
++#else
++    if (file_ptr_type == ADIO_INDIVIDUAL) offset = fd->fp_ind;
++    err = ADIOI_LUSTRE_aio(fd, buf, len, offset, 1, &((*request)->handle));
++    if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind += len;
++
++    (*request)->queued = 1;
++    ADIOI_Add_req_to_list(request);
++
++    if (err == -1) {
++#ifdef MPICH2
++      *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io",
++          "**io %s", strerror(errno));
++      return;
++#elif defined(PRINT_ERR_MSG)
++                      *error_code = MPI_ERR_UNKNOWN;
++#else /* MPICH-1 */
++      *error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ADIO_ERROR,
++                            myname, "I/O Error", "%s", strerror(errno));
++      ADIOI_Error(fd, *error_code, myname);       
++#endif
++    }
++    else *error_code = MPI_SUCCESS;
++#endif /* NO_AIO */
++
++    fd->fp_sys_posn = -1;   /* set it to null. */
++    fd->async_count++;
++}
++
++
++
++
++void ADIOI_LUSTRE_IwriteStrided(ADIO_File fd, void *buf, int count, 
++                     MPI_Datatype datatype, int file_ptr_type,
++                       ADIO_Offset offset, ADIO_Request *request, int
++                       *error_code)
++{
++    ADIO_Status status;
++#ifdef HAVE_STATUS_SET_BYTES
++    int typesize;
++#endif
++
++    *request = ADIOI_Malloc_request();
++    (*request)->optype = ADIOI_WRITE;
++    (*request)->fd = fd;
++    (*request)->datatype = datatype;
++    (*request)->queued = 0;
++    (*request)->handle = 0;
++
++/* call the blocking version. It is faster because it does data sieving. */
++    ADIOI_LUSTRE_WriteStrided(fd, buf, count, datatype, file_ptr_type, 
++                            offset, &status, error_code);  
++
++    fd->async_count++;
++
++#ifdef HAVE_STATUS_SET_BYTES
++    if (*error_code == MPI_SUCCESS) {
++      MPI_Type_size(datatype, &typesize);
++      (*request)->nbytes = count * typesize;
++    }
++#endif
++}
++
++
++/* This function is for implementation convenience. It is not user-visible.
++   It takes care of the differences in the interface for nonblocking I/O
++   on various Unix machines! If wr==1 write, wr==0 read. */
++
++int ADIOI_LUSTRE_aio(ADIO_File fd, void *buf, int len, ADIO_Offset offset,
++                int wr, void *handle)
++{
++    int err=-1, fd_sys;
++
++#ifndef NO_AIO
++    int error_code;
++#ifdef AIO_SUN 
++    aio_result_t *result;
++#else
++    struct aiocb *aiocbp;
++#endif
++#endif
++
++    fd_sys = fd->fd_sys;
++
++#ifdef AIO_SUN
++    result = (aio_result_t *) ADIOI_Malloc(sizeof(aio_result_t));
++    result->aio_return = AIO_INPROGRESS;
++    if (wr) err = aiowrite(fd_sys, buf, len, offset, SEEK_SET, result); 
++    else err = aioread(fd_sys, buf, len, offset, SEEK_SET, result);
++
++    if (err == -1) {
++      if (errno == EAGAIN) { 
++       /* the man pages say EPROCLIM, but in reality errno is set to EAGAIN! */
++
++        /* exceeded the max. no. of outstanding requests.
++           complete all previous async. requests and try again.*/
++
++          ADIOI_Complete_async(&error_code);
++          if (wr) err = aiowrite(fd_sys, buf, len, offset, SEEK_SET, result); 
++          else err = aioread(fd_sys, buf, len, offset, SEEK_SET, result);
++
++          while (err == -1) {
++              if (errno == EAGAIN) {
++                    /* sleep and try again */
++                    sleep(1);
++                  if (wr) err = aiowrite(fd_sys, buf, len, offset, SEEK_SET, result); 
++                  else err = aioread(fd_sys, buf, len, offset, SEEK_SET, result);
++              }
++                else {
++                    FPRINTF(stderr, "Unknown errno %d in ADIOI_LUSTRE_aio\n", errno);
++                    MPI_Abort(MPI_COMM_WORLD, 1);
++                }
++          }
++      }
++        else {
++            FPRINTF(stderr, "Unknown errno %d in ADIOI_LUSTRE_aio\n", errno);
++            MPI_Abort(MPI_COMM_WORLD, 1);
++        }
++    }
++
++    *((aio_result_t **) handle) = result;
++#endif
++
++#ifdef NO_FD_IN_AIOCB
++/* IBM */
++    aiocbp = (struct aiocb *) ADIOI_Malloc(sizeof(struct aiocb));
++    aiocbp->aio_whence = SEEK_SET;
++    aiocbp->aio_offset = offset;
++    aiocbp->aio_buf = buf;
++    aiocbp->aio_nbytes = len;
++    if (wr) err = aio_write(fd_sys, aiocbp);
++    else err = aio_read(fd_sys, aiocbp);
++
++    if (err == -1) {
++      if (errno == EAGAIN) {
++        /* exceeded the max. no. of outstanding requests.
++          complete all previous async. requests and try again. */
++
++          ADIOI_Complete_async(&error_code);
++          if (wr) err = aio_write(fd_sys, aiocbp);
++          else err = aio_read(fd_sys, aiocbp);
++
++            while (err == -1) {
++                if (errno == EAGAIN) {
++                    /* sleep and try again */
++                    sleep(1);
++                  if (wr) err = aio_write(fd_sys, aiocbp);
++                  else err = aio_read(fd_sys, aiocbp);
++              }
++                else {
++                    FPRINTF(stderr, "Unknown errno %d in ADIOI_LUSTRE_aio\n", errno);
++                    MPI_Abort(MPI_COMM_WORLD, 1);
++                }
++            }
++      }
++        else {
++            FPRINTF(stderr, "Unknown errno %d in ADIOI_LUSTRE_aio\n", errno);
++            MPI_Abort(MPI_COMM_WORLD, 1);
++        }
++    }
++
++    *((struct aiocb **) handle) = aiocbp;
++
++#elif (!defined(NO_AIO) && !defined(AIO_SUN))
++/* DEC, SGI IRIX 5 and 6 */
++
++    aiocbp = (struct aiocb *) ADIOI_Calloc(sizeof(struct aiocb), 1);
++    aiocbp->aio_fildes = fd_sys;
++    aiocbp->aio_offset = offset;
++    aiocbp->aio_buf = buf;
++    aiocbp->aio_nbytes = len;
++
++#ifdef AIO_PRIORITY_DEFAULT
++/* DEC */
++    aiocbp->aio_reqprio = AIO_PRIO_DFL;   /* not needed in DEC Unix 4.0 */
++    aiocbp->aio_sigevent.sigev_signo = 0;
++#else
++    aiocbp->aio_reqprio = 0;
++#endif
++
++#ifdef AIO_SIGNOTIFY_NONE
++/* SGI IRIX 6 */
++    aiocbp->aio_sigevent.sigev_notify = SIGEV_NONE;
++#else
++    aiocbp->aio_sigevent.sigev_signo = 0;
++#endif
++
++    if (wr) err = aio_write(aiocbp);
++    else err = aio_read(aiocbp);
++
++    if (err == -1) {
++      if (errno == EAGAIN) {
++        /* exceeded the max. no. of outstanding requests.
++           complete all previous async. requests and try again. */
++
++          ADIOI_Complete_async(&error_code);
++          if (wr) err = aio_write(aiocbp);
++          else err = aio_read(aiocbp);
++
++          while (err == -1) {
++              if (errno == EAGAIN) {
++                  /* sleep and try again */
++                  sleep(1);
++                  if (wr) err = aio_write(aiocbp);
++                  else err = aio_read(aiocbp);
++              }
++              else {
++                  FPRINTF(stderr, "Unknown errno %d in ADIOI_LUSTRE_aio\n", errno);
++                  MPI_Abort(MPI_COMM_WORLD, 1);
++              }
++          }
++        }
++      else {
++          FPRINTF(stderr, "Unknown errno %d in ADIOI_LUSTRE_aio\n", errno);
++          MPI_Abort(MPI_COMM_WORLD, 1);
++      }
++    }
++
++    *((struct aiocb **) handle) = aiocbp;
++#endif
++
++    return err;
++}
+diff -r -u --new-file mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_open.c mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_open.c
+--- mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_open.c  1969-12-31 19:00:00.000000000 -0500
++++ mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_open.c  2005-12-06 11:54:37.906127861 -0500
+@@ -0,0 +1,100 @@
++/* -*- Mode: C; c-basic-offset:4 ; -*- */
++/* 
++ *   $Id: ad_lustre_open.c,v 1.1.1.1 2004/11/04 11:03:38 liam Exp $    
++ *
++ *   Copyright (C) 1997 University of Chicago. 
++ *   See COPYRIGHT notice in top-level directory.
++ */
++
++#include "ad_lustre.h"
++
++void ADIOI_LUSTRE_Open(ADIO_File fd, int *error_code)
++{
++    int perm, old_mask, amode;
++    struct lov_user_md lum = { 0 };
++    char *value;
++
++#if defined(MPICH2) || !defined(PRINT_ERR_MSG)
++    static char myname[] = "ADIOI_LUSTRE_OPEN";
++#endif
++
++    if (fd->perm == ADIO_PERM_NULL) {
++      old_mask = umask(022);
++      umask(old_mask);
++      perm = old_mask ^ 0666;
++    }
++    else perm = fd->perm;
++
++    amode = 0;
++    if (fd->access_mode & ADIO_CREATE)
++      amode = amode | O_CREAT;
++    if (fd->access_mode & ADIO_RDONLY)
++      amode = amode | O_RDONLY;
++    if (fd->access_mode & ADIO_WRONLY)
++      amode = amode | O_WRONLY;
++    if (fd->access_mode & ADIO_RDWR)
++      amode = amode | O_RDWR;
++    if (fd->access_mode & ADIO_EXCL)
++      amode = amode | O_EXCL;
++
++    fd->fd_sys = open(fd->filename, amode, perm);
++
++    if (fd->fd_sys != -1) {
++        int err;
++
++        value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char));
++
++        /* get file striping information and set it in info */
++        lum.lmm_magic = LOV_USER_MAGIC;
++        err = ioctl(fd->fd_sys, LL_IOC_LOV_GETSTRIPE, (void *) &lum);
++
++        if (!err) {
++            sprintf(value, "%d", lum.lmm_stripe_size);
++            MPI_Info_set(fd->info, "striping_unit", value);
++
++            sprintf(value, "%d", lum.lmm_stripe_count);
++            MPI_Info_set(fd->info, "striping_factor", value);
++
++            sprintf(value, "%d", lum.lmm_stripe_offset);
++            MPI_Info_set(fd->info, "start_iodevice", value);
++        }
++        ADIOI_Free(value);
++
++        if (fd->access_mode & ADIO_APPEND)
++            fd->fp_ind = fd->fp_sys_posn = lseek(fd->fd_sys, 0, SEEK_END);
++    }
++
++
++    if ((fd->fd_sys != -1) && (fd->access_mode & ADIO_APPEND))
++      fd->fp_ind = fd->fp_sys_posn = lseek(fd->fd_sys, 0, SEEK_END);
++
++    if (fd->fd_sys == -1) {
++#ifdef MPICH2
++      if (errno == ENAMETOOLONG)
++          *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_BAD_FILE, "**filenamelong", "**filenamelong %s %d", fd->filename, strlen(fd->filename) );
++      else if (errno == ENOENT)
++          *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_NO_SUCH_FILE, "**filenoexist", "**filenoexist %s", fd->filename );
++      else if (errno == ENOTDIR || errno == ELOOP)
++          *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_BAD_FILE, "**filenamedir", "**filenamedir %s", fd->filename );
++      else if (errno == EACCES) {
++          *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_ACCESS, "**fileaccess", "**fileaccess %s", 
++                                             fd->filename );
++      }
++      else if (errno == EROFS) {
++          /* Read only file or file system and write access requested */
++          *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_READ_ONLY, "**ioneedrd", 0 );
++      }
++      else {
++          *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io",
++          "**io %s", strerror(errno));
++      }
++#elif defined(PRINT_ERR_MSG)
++                      *error_code = MPI_ERR_UNKNOWN;
++#else /* MPICH-1 */
++      *error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ADIO_ERROR,
++                            myname, "I/O Error", "%s", strerror(errno));
++      ADIOI_Error(ADIO_FILE_NULL, *error_code, myname);           
++#endif
++    }
++    else *error_code = MPI_SUCCESS;
++}
+diff -r -u --new-file mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_rdcoll.c mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_rdcoll.c
+--- mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_rdcoll.c        1969-12-31 19:00:00.000000000 -0500
++++ mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_rdcoll.c        2005-12-06 11:54:37.907127727 -0500
+@@ -0,0 +1,18 @@
++/* -*- Mode: C; c-basic-offset:4 ; -*- */
++/* 
++ *   $Id: ad_lustre_rdcoll.c,v 1.1.1.1 2004/11/04 11:03:38 liam Exp $    
++ *
++ *   Copyright (C) 1997 University of Chicago. 
++ *   See COPYRIGHT notice in top-level directory.
++ */
++
++#include "ad_lustre.h"
++
++void ADIOI_LUSTRE_ReadStridedColl(ADIO_File fd, void *buf, int count,
++                       MPI_Datatype datatype, int file_ptr_type,
++                       ADIO_Offset offset, ADIO_Status *status, int
++                       *error_code)
++{
++    ADIOI_GEN_ReadStridedColl(fd, buf, count, datatype, file_ptr_type,
++                            offset, status, error_code);
++}
+diff -r -u --new-file mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_read.c mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_read.c
+--- mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_read.c  1969-12-31 19:00:00.000000000 -0500
++++ mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_read.c  2005-12-06 11:54:37.907127727 -0500
+@@ -0,0 +1,67 @@
++/* -*- Mode: C; c-basic-offset:4 ; -*- */
++/* 
++ *   $Id: ad_lustre_read.c,v 1.1.1.1 2004/11/04 11:03:38 liam Exp $    
++ *
++ *   Copyright (C) 1997 University of Chicago. 
++ *   See COPYRIGHT notice in top-level directory.
++ */
++
++#include "ad_lustre.h"
++
++void ADIOI_LUSTRE_ReadContig(ADIO_File fd, void *buf, int count, 
++                     MPI_Datatype datatype, int file_ptr_type,
++                   ADIO_Offset offset, ADIO_Status *status, int *error_code)
++{
++    int err=-1, datatype_size, len;
++#if defined(MPICH2) || !defined(PRINT_ERR_MSG)
++    static char myname[] = "ADIOI_LUSTRE_READCONTIG";
++#endif
++
++    MPI_Type_size(datatype, &datatype_size);
++    len = datatype_size * count;
++
++    if (file_ptr_type == ADIO_EXPLICIT_OFFSET) {
++      if (fd->fp_sys_posn != offset) 
++          lseek(fd->fd_sys, offset, SEEK_SET);
++      err = read(fd->fd_sys, buf, len);
++      fd->fp_sys_posn = offset + len;
++      /* individual file pointer not updated */        
++    }
++    else {  /* read from curr. location of ind. file pointer */
++      if (fd->fp_sys_posn != fd->fp_ind)
++          lseek(fd->fd_sys, fd->fp_ind, SEEK_SET);
++      err = read(fd->fd_sys, buf, len);
++      fd->fp_ind += err; 
++      fd->fp_sys_posn = fd->fp_ind;
++    }         
++
++#ifdef HAVE_STATUS_SET_BYTES
++    if (err != -1) MPIR_Status_set_bytes(status, datatype, err);
++#endif
++
++    if (err == -1) {
++#ifdef MPICH2
++      *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io",
++          "**io %s", strerror(errno));
++#elif defined(PRINT_ERR_MSG)
++                      *error_code = MPI_ERR_UNKNOWN;
++#else /* MPICH-1 */
++      *error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ADIO_ERROR,
++                            myname, "I/O Error", "%s", strerror(errno));
++      ADIOI_Error(fd, *error_code, myname);       
++#endif
++    }
++    else *error_code = MPI_SUCCESS;
++}
++
++
++
++
++void ADIOI_LUSTRE_ReadStrided(ADIO_File fd, void *buf, int count,
++                       MPI_Datatype datatype, int file_ptr_type,
++                       ADIO_Offset offset, ADIO_Status *status, int
++                       *error_code)
++{
++    ADIOI_GEN_ReadStrided(fd, buf, count, datatype, file_ptr_type,
++                        offset, status, error_code);
++}
+diff -r -u --new-file mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_resize.c mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_resize.c
+--- mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_resize.c        1969-12-31 19:00:00.000000000 -0500
++++ mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_resize.c        2005-12-06 11:54:37.909127460 -0500
+@@ -0,0 +1,32 @@
++/* -*- Mode: C; c-basic-offset:4 ; -*- */
++/* 
++ *   $Id: ad_lustre_resize.c,v 1.1.1.1 2004/11/04 11:03:38 liam Exp $    
++ *
++ *   Copyright (C) 1997 University of Chicago. 
++ *   See COPYRIGHT notice in top-level directory.
++ */
++
++#include "ad_lustre.h"
++
++void ADIOI_LUSTRE_Resize(ADIO_File fd, ADIO_Offset size, int *error_code)
++{
++    int err;
++#if defined(MPICH2) || !defined(PRINT_ERR_MSG)
++    static char myname[] = "ADIOI_LUSTRE_RESIZE";
++#endif
++    
++    err = ftruncate(fd->fd_sys, size);
++    if (err == -1) {
++#ifdef MPICH2
++      *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io",
++          "**io %s", strerror(errno));
++#elif defined(PRINT_ERR_MSG)
++                      *error_code = MPI_ERR_UNKNOWN;
++#else /* MPICH-1 */
++      *error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ADIO_ERROR,
++                            myname, "I/O Error", "%s", strerror(errno));
++      ADIOI_Error(fd, *error_code, myname);       
++#endif
++    }
++    else *error_code = MPI_SUCCESS;
++}
+diff -r -u --new-file mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_seek.c mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_seek.c
+--- mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_seek.c  1969-12-31 19:00:00.000000000 -0500
++++ mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_seek.c  2005-12-06 11:54:37.911127194 -0500
+@@ -0,0 +1,15 @@
++/* -*- Mode: C; c-basic-offset:4 ; -*- */
++/* 
++ *   $Id: ad_lustre_seek.c,v 1.1.1.1 2004/11/04 11:03:38 liam Exp $    
++ *
++ *   Copyright (C) 1997 University of Chicago. 
++ *   See COPYRIGHT notice in top-level directory.
++ */
++
++#include "ad_lustre.h"
++
++ADIO_Offset ADIOI_LUSTRE_SeekIndividual(ADIO_File fd, ADIO_Offset offset, 
++                    int whence, int *error_code)
++{
++    return ADIOI_GEN_SeekIndividual(fd, offset, whence, error_code);
++}
+diff -r -u --new-file mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_wait.c mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_wait.c
+--- mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_wait.c  1969-12-31 19:00:00.000000000 -0500
++++ mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_wait.c  2005-12-06 11:54:37.914126794 -0500
+@@ -0,0 +1,188 @@
++/* -*- Mode: C; c-basic-offset:4 ; -*- */
++/* 
++ *   $Id: ad_lustre_wait.c,v 1.1.1.1 2004/11/04 11:03:38 liam Exp $    
++ *
++ *   Copyright (C) 1997 University of Chicago. 
++ *   See COPYRIGHT notice in top-level directory.
++ */
++
++#include "ad_lustre.h"
++
++void ADIOI_LUSTRE_ReadComplete(ADIO_Request *request, ADIO_Status *status, int *error_code)  
++{
++#ifndef NO_AIO
++#if defined(MPICH2) || !defined(PRINT_ERR_MSG)
++    static char myname[] = "ADIOI_LUSTRE_READCOMPLETE";
++#endif
++#ifdef AIO_SUN 
++    aio_result_t *result=0, *tmp;
++#else
++    int err;
++#endif
++#ifdef AIO_HANDLE_IN_AIOCB
++    struct aiocb *tmp1;
++#endif
++#endif
++
++    if (*request == ADIO_REQUEST_NULL) {
++      *error_code = MPI_SUCCESS;
++      return;
++    }
++
++#ifdef AIO_SUN
++    if ((*request)->queued) {  /* dequeue it */
++      tmp = (aio_result_t *) (*request)->handle;
++      while (tmp->aio_return == AIO_INPROGRESS) usleep(1000); 
++      /* sleep for 1 ms., until done. Is 1 ms. a good number? */
++      /* when done, dequeue any one request */
++      result = (aio_result_t *) aiowait(0);
++
++        (*request)->nbytes = tmp->aio_return;
++
++      if (tmp->aio_return == -1) {
++#ifdef MPICH2
++          *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io",
++              "**io %s", strerror(tmp->aio_errno));
++          return;
++#elif defined(PRINT_ERR_MSG)
++                      *error_code = MPI_ERR_UNKNOWN;
++#else /* MPICH-1 */
++          *error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ADIO_ERROR,
++                        myname, "I/O Error", "%s", strerror(tmp->aio_errno));
++          ADIOI_Error((*request)->fd, *error_code, myname);       
++#endif
++      }
++      else *error_code = MPI_SUCCESS;
++
++/* aiowait only dequeues a request. The completion of a request can be
++   checked by just checking the aio_return flag in the handle passed
++   to the original aioread()/aiowrite(). Therefore, I need to ensure
++   that aiowait() is called exactly once for each previous
++   aioread()/aiowrite(). This is also taken care of in ADIOI_xxxDone */
++    }
++    else *error_code = MPI_SUCCESS;
++
++#ifdef HAVE_STATUS_SET_BYTES
++    if ((*request)->nbytes != -1)
++      MPIR_Status_set_bytes(status, (*request)->datatype, (*request)->nbytes);
++#endif
++
++#endif
++    
++#ifdef AIO_HANDLE_IN_AIOCB
++/* IBM */
++    if ((*request)->queued) {
++      do {
++          err = aio_suspend(1, (struct aiocb **) &((*request)->handle));
++      } while ((err == -1) && (errno == EINTR));
++
++      tmp1 = (struct aiocb *) (*request)->handle;
++      if (err != -1) {
++          err = aio_return(tmp1->aio_handle);
++          (*request)->nbytes = err;
++          errno = aio_error(tmp1->aio_handle);
++      }
++      else (*request)->nbytes = -1;
++
++/* on DEC, it is required to call aio_return to dequeue the request.
++   IBM man pages don't indicate what function to use for dequeue.
++   I'm assuming it is aio_return! POSIX says aio_return may be called 
++   only once on a given handle. */
++
++      if (err == -1) {
++#ifdef MPICH2
++          *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io",
++              "**io %s", strerror(errno));
++          return;
++#elif defined(PRINT_ERR_MSG)
++                      *error_code = MPI_ERR_UNKNOWN;
++#else /* MPICH-1 */
++          *error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ADIO_ERROR,
++             myname, "I/O Error", "%s", strerror(errno));
++          ADIOI_Error((*request)->fd, *error_code, myname);       
++#endif
++      }
++      else *error_code = MPI_SUCCESS;
++    } /* if ((*request)->queued)  */
++    else *error_code = MPI_SUCCESS;
++
++#ifdef HAVE_STATUS_SET_BYTES
++    if ((*request)->nbytes != -1)
++      MPIR_Status_set_bytes(status, (*request)->datatype, (*request)->nbytes);
++#endif
++
++#elif (!defined(NO_AIO) && !defined(AIO_SUN))
++/* DEC, SGI IRIX 5 and 6 */
++    if ((*request)->queued) {
++      do {
++          err = aio_suspend((const aiocb_t **) &((*request)->handle), 1, 0);
++      } while ((err == -1) && (errno == EINTR));
++
++      if (err != -1) {
++          err = aio_return((struct aiocb *) (*request)->handle); 
++          (*request)->nbytes = err;
++          errno = aio_error((struct aiocb *) (*request)->handle);
++      }
++      else (*request)->nbytes = -1;
++
++      if (err == -1) {
++#ifdef MPICH2
++          *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io",
++              "**io %s", strerror(errno));
++          return;
++#elif defined(PRINT_ERR_MSG)
++                      *error_code = MPI_ERR_UNKNOWN;
++#else /* MPICH-1 */
++          *error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ADIO_ERROR,
++                          myname, "I/O Error", "%s", strerror(errno));
++          ADIOI_Error((*request)->fd, *error_code, myname);       
++#endif
++      }
++      else *error_code = MPI_SUCCESS;
++    } /* if ((*request)->queued) */
++    else *error_code = MPI_SUCCESS;
++#ifdef HAVE_STATUS_SET_BYTES
++    if ((*request)->nbytes != -1)
++      MPIR_Status_set_bytes(status, (*request)->datatype, (*request)->nbytes);
++#endif
++#endif
++
++#ifndef NO_AIO
++    if ((*request)->queued != -1) {
++
++      /* queued = -1 is an internal hack used when the request must
++         be completed, but the request object should not be
++         freed. This is used in ADIOI_Complete_async, because the user
++         will call MPI_Wait later, which would require status to
++         be filled. Ugly but works. queued = -1 should be used only
++         in ADIOI_Complete_async. 
++           This should not affect the user in any way. */
++
++      /* if request is still queued in the system, it is also there
++           on ADIOI_Async_list. Delete it from there. */
++      if ((*request)->queued) ADIOI_Del_req_from_list(request);
++
++      (*request)->fd->async_count--;
++      if ((*request)->handle) ADIOI_Free((*request)->handle);
++      ADIOI_Free_request((ADIOI_Req_node *) (*request));
++      *request = ADIO_REQUEST_NULL;
++    }
++
++#else
++/* HP, FreeBSD, Linux */
++
++#ifdef HAVE_STATUS_SET_BYTES
++    MPIR_Status_set_bytes(status, (*request)->datatype, (*request)->nbytes);
++#endif
++    (*request)->fd->async_count--;
++    ADIOI_Free_request((ADIOI_Req_node *) (*request));
++    *request = ADIO_REQUEST_NULL;
++    *error_code = MPI_SUCCESS;
++#endif    
++}
++
++
++void ADIOI_LUSTRE_WriteComplete(ADIO_Request *request, ADIO_Status *status, int *error_code)  
++{
++    ADIOI_LUSTRE_ReadComplete(request, status, error_code);
++}
+diff -r -u --new-file mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_wrcoll.c mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_wrcoll.c
+--- mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_wrcoll.c        1969-12-31 19:00:00.000000000 -0500
++++ mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_wrcoll.c        2005-12-06 11:54:37.914126794 -0500
+@@ -0,0 +1,18 @@
++/* -*- Mode: C; c-basic-offset:4 ; -*- */
++/* 
++ *   $Id: ad_lustre_wrcoll.c,v 1.1.1.1 2004/11/04 11:03:38 liam Exp $    
++ *
++ *   Copyright (C) 1997 University of Chicago. 
++ *   See COPYRIGHT notice in top-level directory.
++ */
++
++#include "ad_lustre.h"
++
++void ADIOI_LUSTRE_WriteStridedColl(ADIO_File fd, void *buf, int count,
++                       MPI_Datatype datatype, int file_ptr_type,
++                       ADIO_Offset offset, ADIO_Status *status, int
++                       *error_code)
++{
++    ADIOI_GEN_WriteStridedColl(fd, buf, count, datatype, file_ptr_type,
++                            offset, status, error_code);
++}
+diff -r -u --new-file mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_write.c mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_write.c
+--- mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_write.c 1969-12-31 19:00:00.000000000 -0500
++++ mpich-1.2.6/romio/adio/ad_lustre/ad_lustre_write.c 2005-12-06 11:54:37.914126794 -0500
+@@ -0,0 +1,66 @@
++/* -*- Mode: C; c-basic-offset:4 ; -*- */
++/* 
++ *   $Id: ad_lustre_write.c,v 1.1.1.1 2004/11/04 11:03:38 liam Exp $    
++ *
++ *   Copyright (C) 1997 University of Chicago. 
++ *   See COPYRIGHT notice in top-level directory.
++ */
++
++#include "ad_lustre.h"
++
++void ADIOI_LUSTRE_WriteContig(ADIO_File fd, void *buf, int count, 
++                   MPI_Datatype datatype, int file_ptr_type,
++                 ADIO_Offset offset, ADIO_Status *status, int *error_code)
++{
++    int err=-1, datatype_size, len;
++#if defined(MPICH2) || !defined(PRINT_ERR_MSG)
++    static char myname[] = "ADIOI_LUSTRE_WRITECONTIG";
++#endif
++
++    MPI_Type_size(datatype, &datatype_size);
++    len = datatype_size * count;
++
++    if (file_ptr_type == ADIO_EXPLICIT_OFFSET) {
++      if (fd->fp_sys_posn != offset)
++          lseek(fd->fd_sys, offset, SEEK_SET);
++      err = write(fd->fd_sys, buf, len);
++      fd->fp_sys_posn = offset + err;
++      /* individual file pointer not updated */        
++    }
++    else { /* write from curr. location of ind. file pointer */
++      if (fd->fp_sys_posn != fd->fp_ind)
++          lseek(fd->fd_sys, fd->fp_ind, SEEK_SET);
++      err = write(fd->fd_sys, buf, len);
++      fd->fp_ind += err;
++      fd->fp_sys_posn = fd->fp_ind;
++    }
++
++#ifdef HAVE_STATUS_SET_BYTES
++    if (err != -1 && status) MPIR_Status_set_bytes(status, datatype, err);
++#endif
++
++    if (err == -1) {
++#ifdef MPICH2
++      *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io",
++          "**io %s", strerror(errno));
++#elif defined(PRINT_ERR_MSG)
++                      *error_code = MPI_ERR_UNKNOWN;
++#else
++      *error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ADIO_ERROR,
++                            myname, "I/O Error", "%s", strerror(errno));
++      ADIOI_Error(fd, *error_code, myname);
++#endif
++    }
++    else *error_code = MPI_SUCCESS;
++}
++
++
++
++void ADIOI_LUSTRE_WriteStrided(ADIO_File fd, void *buf, int count,
++                       MPI_Datatype datatype, int file_ptr_type,
++                       ADIO_Offset offset, ADIO_Status *status, int
++                       *error_code)
++{
++    ADIOI_GEN_WriteStrided(fd, buf, count, datatype, file_ptr_type,
++                        offset, status, error_code);
++}
+diff -r -u --new-file mpich-1.2.6/romio/adio/ad_lustre/Makefile.in mpich-1.2.6/romio/adio/ad_lustre/Makefile.in
+--- mpich-1.2.6/romio/adio/ad_lustre/Makefile.in       1969-12-31 19:00:00.000000000 -0500
++++ mpich-1.2.6/romio/adio/ad_lustre/Makefile.in       2005-12-06 11:54:37.883130927 -0500
+@@ -0,0 +1,47 @@
++CC          = @CC@
++AR          = @AR@
++LIBNAME     = @LIBNAME@
++srcdir      = @srcdir@
++CC_SHL      = @CC_SHL@
++SHLIBNAME   = @SHLIBNAME@
++
++INCLUDE_DIR = -I@MPI_INCLUDE_DIR@ -I${srcdir}/../include -I../include
++CFLAGS      = @CFLAGS@ $(INCLUDE_DIR)
++
++C_COMPILE_SHL = $(CC_SHL) @CFLAGS@ $(INCLUDE_DIR)
++
++@VPATH@
++
++AD_LUSTRE_OBJECTS = ad_lustre_close.o ad_lustre_read.o \
++      ad_lustre_open.o ad_lustre_write.o ad_lustre_done.o \
++      ad_lustre_fcntl.o ad_lustre_iread.o ad_lustre_iwrite.o ad_lustre_wait.o \
++      ad_lustre_resize.o ad_lustre_hints.o \
++      ad_lustre.o
++
++
++default: $(LIBNAME)
++      @if [ "@ENABLE_SHLIB@" != "none" ] ; then \
++          $(MAKE) $(SHLIBNAME).la ;\
++      fi
++
++.SUFFIXES: $(SUFFIXES) .p .lo
++
++.c.o:
++      $(CC) $(CFLAGS) -c $<
++.c.lo:
++      $(C_COMPILE_SHL) -c $<
++      @mv -f $*.o $*.lo
++
++$(LIBNAME): $(AD_LUSTRE_OBJECTS)
++      $(AR) $(LIBNAME) $(AD_LUSTRE_OBJECTS)
++
++AD_LUSTRE_LOOBJECTS=$(AD_LUSTRE_OBJECTS:.o=.lo)
++$(SHLIBNAME).la: $(AD_LUSTRE_LOOBJECTS)
++      $(AR) $(SHLIBNAME).la $(AD_LUSTRE_LOOBJECTS)
++
++coverage:
++      -@for file in  ${AD_LUSTRE_OBJECTS:.o=.c} ; do \
++              gcov -b -f $$file ; done
++
++clean:
++      @rm -f *.o *.lo
+--- mpich-1.2.6/romio/Makefile.in      2004-01-27 18:27:35.000000000 -0500
++++ mpich-1.2.6/romio/Makefile.in      2005-12-06 11:54:38.000000000 -0500
+@@ -14,7 +14,7 @@ DIRS        = mpi-io adio/common
+ MPIO_DIRS   = mpi-io
+ EXTRA_SRC_DIRS = @EXTRA_SRC_DIRS@
+ FILE_SYS_DIRS = @FILE_SYS_DIRS@
+-ALL_DIRS    = mpi-io mpi-io/fortran mpi2-other/info mpi2-other/info/fortran mpi2-other/array mpi2-other/array/fortran adio/common adio/ad_pfs adio/ad_piofs adio/ad_nfs adio/ad_ufs adio/ad_xfs adio/ad_hfs adio/ad_sfs adio/ad_testfs adio/ad_pvfs adio/ad_pvfs2 test
++ALL_DIRS    = mpi-io mpi-io/fortran mpi2-other/info mpi2-other/info/fortran mpi2-other/array mpi2-other/array/fortran adio/common adio/ad_pfs adio/ad_piofs adio/ad_nfs adio/ad_ufs adio/ad_xfs adio/ad_hfs adio/ad_sfs adio/ad_testfs adio/ad_pvfs adio/ad_pvfs2 adio/ad_lustre test
+ SHELL       = /bin/sh
+ @VPATH@
+--- mpich-1.2.6/romio/configure.in     2004-08-02 09:37:31.000000000 -0400
++++ mpich-1.2.6/romio/configure.in     2005-12-06 11:54:38.000000000 -0500
+@@ -90,7 +90,7 @@ MPIO_REQ_REAL_POBJECTS="_iotest.o _iowai
+ #
+ have_aio=no
+ #
+-known_filesystems="nfs ufs pfs piofs pvfs pvfs2 testfs xfs hfs sfs"
++known_filesystems="nfs ufs pfs piofs pvfs pvfs2 testfs xfs hfs sfs lustre"
+ known_mpi_impls="mpich_mpi sgi_mpi hp_mpi cray_mpi lam_mpi"
+ #
+ # Defaults
+@@ -1270,6 +1270,9 @@ fi
+ if test -n "$file_system_testfs"; then
+     AC_DEFINE(ROMIO_TESTFS,1,[Define for TESTFS])
+ fi
++if test -n "$file_system_lustre"; then
++    AC_DEFINE(ROMIO_LUSTRE,1,[Define for LUSTRE])
++fi
+ if test -n "$file_system_piofs"; then
+     AC_DEFINE(PIOFS,1,[Define for PIOFS])
+     USER_CFLAGS="$USER_CFLAGS -bI:/usr/include/piofs/piofs.exp"
+@@ -1634,7 +1637,7 @@ AC_OUTPUT(Makefile localdefs mpi-io/Make
+                  adio/ad_nfs/Makefile adio/ad_ufs/Makefile \
+                  adio/ad_xfs/Makefile adio/ad_hfs/Makefile \
+                  adio/ad_sfs/Makefile adio/ad_pfs/Makefile \
+-                 adio/ad_testfs/Makefile adio/ad_pvfs/Makefile \
++                 adio/ad_testfs/Makefile adio/ad_lustre/Makefile adio/ad_pvfs/Makefile \
+                  adio/ad_pvfs2/Makefile adio/ad_piofs/Makefile \
+                    mpi-io/fortran/Makefile mpi2-other/info/fortran/Makefile \
+                    mpi2-other/array/fortran/Makefile test/fmisc.f \
+--- mpich-1.2.6/romio/configure        2004-08-04 12:08:28.000000000 -0400
++++ mpich-1.2.6/romio/configure        2005-12-06 11:54:38.000000000 -0500
+@@ -623,7 +623,7 @@ MPIO_REQ_REAL_POBJECTS="_iotest.o _iowai
+ #
+ have_aio=no
+ #
+-known_filesystems="nfs ufs pfs piofs pvfs pvfs2 testfs xfs hfs sfs"
++known_filesystems="nfs ufs pfs piofs pvfs pvfs2 testfs lustre xfs hfs sfs"
+ known_mpi_impls="mpich_mpi sgi_mpi hp_mpi cray_mpi lam_mpi"
+ #
+ # Defaults
+@@ -4022,6 +4022,13 @@ if test -n "$file_system_testfs"; then
+ EOF
+ fi
++if test -n "$file_system_lustre"; then
++    cat >> confdefs.h <<\EOF
++#define LUSTRE 1
++EOF
++
++fi
++
+ if test -n "$file_system_piofs"; then
+     cat >> confdefs.h <<\EOF
+ #define PIOFS 1
+@@ -4746,7 +4753,7 @@ trap 'rm -fr `echo "Makefile localdefs m
+                  adio/ad_xfs/Makefile adio/ad_hfs/Makefile \
+                  adio/ad_sfs/Makefile adio/ad_pfs/Makefile \
+                  adio/ad_testfs/Makefile adio/ad_pvfs/Makefile \
+-                 adio/ad_pvfs2/Makefile adio/ad_piofs/Makefile \
++                 adio/ad_pvfs2/Makefile adio/ad_piofs/Makefile adio/ad_lustre/Makefile\
+                    mpi-io/fortran/Makefile mpi2-other/info/fortran/Makefile \
+                    mpi2-other/array/fortran/Makefile test/fmisc.f \
+                    test/fcoll_test.f test/pfcoll_test.f test/fperf.f  adio/include/romioconf.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+@@ -4912,7 +4919,7 @@ CONFIG_FILES=\${CONFIG_FILES-"Makefile l
+                  adio/ad_nfs/Makefile adio/ad_ufs/Makefile \
+                  adio/ad_xfs/Makefile adio/ad_hfs/Makefile \
+                  adio/ad_sfs/Makefile adio/ad_pfs/Makefile \
+-                 adio/ad_testfs/Makefile adio/ad_pvfs/Makefile \
++                 adio/ad_testfs/Makefile adio/ad_lustre/Makefile adio/ad_pvfs/Makefile \
+                  adio/ad_pvfs2/Makefile adio/ad_piofs/Makefile \
+                    mpi-io/fortran/Makefile mpi2-other/info/fortran/Makefile \
+                    mpi2-other/array/fortran/Makefile test/fmisc.f \
+--- mpich-1.2.6/romio/adio/include/romioconf.h.in      2004-08-04 12:08:28.000000000 -0400
++++ mpich-1.2.6/romio/adio/include/romioconf.h.in      2005-12-06 11:54:38.000000000 -0500
+@@ -192,6 +192,9 @@
+ /* Define for TESTFS */
+ #undef ROMIO_TESTFS
++/* Define for LUSTRE */
++#undef LUSTRE
++
+ /* Define for PIOFS */
+ #undef PIOFS
+--- mpich-1.2.6/romio/adio/include/mpio_error.h        2002-11-15 11:26:23.000000000 -0500
++++ mpich-1.2.6/romio/adio/include/mpio_error.h        2005-12-06 11:54:38.000000000 -0500
+@@ -62,6 +62,7 @@
+ #define MPIR_ERR_FILETYPE 33 
+ #define MPIR_ERR_NO_NTFS 35
+ #define MPIR_ERR_NO_TESTFS 36
++#define MPIR_ERR_NO_LUSTRE 37
+ /* MPI_ERR_COMM */
+ #ifndef MPIR_ERR_COMM_NULL
+--- mpich-1.2.6/romio/adio/include/adioi_fs_proto.h    2003-06-24 18:48:23.000000000 -0400
++++ mpich-1.2.6/romio/adio/include/adioi_fs_proto.h    2005-12-06 11:54:38.000000000 -0500
+@@ -261,6 +261,68 @@ ADIO_Offset ADIOI_UFS_SeekIndividual(ADI
+ void ADIOI_UFS_SetInfo(ADIO_File fd, MPI_Info users_info, int *error_code);
+ #endif
++#ifdef LUSTRE
++extern struct ADIOI_Fns_struct ADIO_LUSTRE_operations;
++
++void ADIOI_LUSTRE_Open(ADIO_File fd, int *error_code);
++void ADIOI_LUSTRE_Close(ADIO_File fd, int *error_code);
++void ADIOI_LUSTRE_ReadContig(ADIO_File fd, void *buf, int count, 
++                      MPI_Datatype datatype, int file_ptr_type,
++                     ADIO_Offset offset, ADIO_Status *status, int
++                   *error_code);
++void ADIOI_LUSTRE_WriteContig(ADIO_File fd, void *buf, int count, 
++                      MPI_Datatype datatype, int file_ptr_type,
++                      ADIO_Offset offset, ADIO_Status *status, int
++                    *error_code);   
++void ADIOI_LUSTRE_IwriteContig(ADIO_File fd, void *buf, int count, 
++                      MPI_Datatype datatype, int file_ptr_type,
++                      ADIO_Offset offset, ADIO_Request *request, int
++                    *error_code);   
++void ADIOI_LUSTRE_IreadContig(ADIO_File fd, void *buf, int count, 
++                      MPI_Datatype datatype, int file_ptr_type,
++                      ADIO_Offset offset, ADIO_Request *request, int
++                    *error_code);   
++int ADIOI_LUSTRE_ReadDone(ADIO_Request *request, ADIO_Status *status, int
++                     *error_code);
++int ADIOI_LUSTRE_WriteDone(ADIO_Request *request, ADIO_Status *status, int
++                     *error_code);
++void ADIOI_LUSTRE_ReadComplete(ADIO_Request *request, ADIO_Status *status, int
++                     *error_code); 
++void ADIOI_LUSTRE_WriteComplete(ADIO_Request *request, ADIO_Status *status,
++                      int *error_code); 
++void ADIOI_LUSTRE_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, int
++              *error_code); 
++void ADIOI_LUSTRE_WriteStrided(ADIO_File fd, void *buf, int count,
++                     MPI_Datatype datatype, int file_ptr_type,
++                     ADIO_Offset offset, ADIO_Status *status, int
++                     *error_code);
++void ADIOI_LUSTRE_ReadStrided(ADIO_File fd, void *buf, int count,
++                     MPI_Datatype datatype, int file_ptr_type,
++                     ADIO_Offset offset, ADIO_Status *status, int
++                     *error_code);
++void ADIOI_LUSTRE_WriteStridedColl(ADIO_File fd, void *buf, int count,
++                     MPI_Datatype datatype, int file_ptr_type,
++                     ADIO_Offset offset, ADIO_Status *status, int
++                     *error_code);
++void ADIOI_LUSTRE_ReadStridedColl(ADIO_File fd, void *buf, int count,
++                     MPI_Datatype datatype, int file_ptr_type,
++                     ADIO_Offset offset, ADIO_Status *status, int
++                     *error_code);
++void ADIOI_LUSTRE_IreadStrided(ADIO_File fd, void *buf, int count,
++                     MPI_Datatype datatype, int file_ptr_type,
++                     ADIO_Offset offset, ADIO_Request *request, int
++                     *error_code);
++void ADIOI_LUSTRE_IwriteStrided(ADIO_File fd, void *buf, int count,
++                     MPI_Datatype datatype, int file_ptr_type,
++                     ADIO_Offset offset, ADIO_Request *request, int
++                     *error_code);
++void ADIOI_LUSTRE_Flush(ADIO_File fd, int *error_code);
++void ADIOI_LUSTRE_Resize(ADIO_File fd, ADIO_Offset size, int *error_code);
++ADIO_Offset ADIOI_LUSTRE_SeekIndividual(ADIO_File fd, ADIO_Offset offset, 
++                       int whence, int *error_code);
++void ADIOI_LUSTRE_SetInfo(ADIO_File fd, MPI_Info users_info, int *error_code);
++#endif
++
+ #ifdef ROMIO_NTFS
+ extern struct ADIOI_Fns_struct ADIO_NTFS_operations;
+--- mpich-1.2.6/romio/adio/include/adio.h      2004-06-07 13:59:57.000000000 -0400
++++ mpich-1.2.6/romio/adio/include/adio.h      2005-12-06 11:54:38.000000000 -0500
+@@ -276,6 +276,7 @@ typedef struct {
+ #define ADIO_NTFS                158   /* NTFS for Windows NT */
+ #define ADIO_TESTFS              159   /* fake file system for testing */
+ #define ADIO_PVFS2               160   /* PVFS2: 2nd generation PVFS */
++#define ADIO_LUSTRE              161   /* Lustre */
+ #define ADIO_SEEK_SET            SEEK_SET
+ #define ADIO_SEEK_CUR            SEEK_CUR
+--- mpich-1.2.6/romio/adio/common/setfn.c      2003-06-24 18:48:18.000000000 -0400
++++ mpich-1.2.6/romio/adio/common/setfn.c      2005-12-06 11:54:38.000000000 -0500
+@@ -114,6 +114,16 @@ void ADIOI_SetFunctions(ADIO_File fd)
+ #endif
+       break;
++    case ADIO_LUSTRE:
++#ifdef LUSTRE 
++        *(fd->fns) = ADIO_LUSTRE_operations;
++#else   
++        FPRINTF(stderr, "ADIOI_SetFunctions: ROMIO has not been configured to use the LUSTRE file system\n");
++        MPI_Abort(MPI_COMM_WORLD, 1);
++#endif 
++        break;
++
++
+     default:
+       FPRINTF(stderr, "ADIOI_SetFunctions: Unsupported file system type\n");
+         MPI_Abort(MPI_COMM_WORLD, 1);
+--- mpich-1.2.6/romio/adio/common/ad_fstype.c  2003-09-04 16:24:44.000000000 -0400
++++ mpich-1.2.6/romio/adio/common/ad_fstype.c  2005-12-06 11:54:38.000000000 -0500
+@@ -204,6 +204,11 @@ static void ADIO_FileSysType_fncall(char
+       }
+     }
+ #elif defined(LINUX)
++#warning use correct include
++# if defined (LUSTRE)
++#define LL_SUPER_MAGIC 0x0BD00BD0
++# endif
++
+     do {
+       err = statfs(filename, &fsbuf);
+     } while (err && (errno == ESTALE));
+@@ -218,6 +223,9 @@ static void ADIO_FileSysType_fncall(char
+     else {
+       /* FPRINTF(stderr, "%d\n", fsbuf.f_type);*/
+       if (fsbuf.f_type == NFS_SUPER_MAGIC) *fstype = ADIO_NFS;
++# if defined (LUSTRE)
++      else if (fsbuf.f_type == LL_SUPER_MAGIC) *fstype = ADIO_LUSTRE;
++#endif
+ # if defined(ROMIO_PVFS)
+       else if (fsbuf.f_type == PVFS_SUPER_MAGIC) *fstype = ADIO_PVFS;
+ # endif
+@@ -359,6 +367,11 @@ static void ADIO_FileSysType_prefix(char
+     {
+       *fstype = ADIO_TESTFS;
+     }
++    else if (!strncmp(filename, "lustre:", 7) 
++           || !strncmp(filename, "LUSTRE:", 7))
++    {
++      *fstype = ADIO_LUSTRE;
++    }
+     else {
+ #ifdef ROMIO_NTFS
+       *fstype = ADIO_NTFS;
+@@ -644,6 +657,24 @@ void ADIO_ResolveFileType(MPI_Comm comm,
+       *ops = &ADIO_TESTFS_operations;
+ #endif
+     }
++    if (file_system == ADIO_LUSTRE) {
++#ifndef LUSTRE 
++# ifdef MPICH2
++      *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**iofstypeunsupported", 0);
++      return;
++# elif defined(PRINT_ERR_MSG)
++      FPRINTF(stderr, "ADIO_ResolveFileType: ROMIO has not been configured to use the LUSTRE file system\n");
++      MPI_Abort(MPI_COMM_WORLD, 1);
++# else /* MPICH-1 */
++      myerrcode = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ERR_NO_LUSTRE,
++                                   myname, (char *) 0, (char *) 0);
++      *error_code = ADIOI_Error(MPI_FILE_NULL, myerrcode, myname);
++# endif
++      return;
++#else
++      *ops = &ADIO_LUSTRE_operations;
++#endif
++    }
+     *error_code = MPI_SUCCESS;
+     *fstype = file_system;
+     return;
index 2b214f7..1d02c60 100644 (file)
@@ -15,7 +15,7 @@ TEXEXPAND = texexpand
 SUFFIXES = .lin .lyx .pdf .ps .sgml .html .txt .tex .fig .eps .dvi
 
 if UTILS
-man_MANS = lfs.1 lmc.1 lconf.8 lctl.8
+man_MANS = lustre.7 lfs.1 mount.lustre.8 mkfs.lustre.8 tunefs.lustre.8 lctl.8 
 endif
 
 LYXFILES= $(filter-out $(patsubst %.lin,%.lyx,$(wildcard *.lin)),\
@@ -23,8 +23,8 @@ LYXFILES= $(filter-out $(patsubst %.lin,%.lyx,$(wildcard *.lin)),\
 
 CLEANFILES = *.aux *.tex *.log *.pdf
 
-EXTRA_DIST = tex2pdf $(man_MANS) \
-       $(LYXFILES) lfs.1 lmc.1 lconf.8 lctl.8  
+EXTRA_DIST = tex2pdf lustre.7 mount.lustre.8 mkfs.lustre.8 tunefs.lustre.8 \
+       $(LYXFILES) lfs.1 lctl.8        
 
 all:
 
index 6143c6b..a6ca88a 100644 (file)
@@ -4,48 +4,59 @@ lconf \- Lustre filesystem configuration utility
 .SH SYNOPSIS
 .br
 .B lconf
-[--node <node_name>] [-d,--cleanup] [--noexec] [--gdb] [--nosetup] [--nomod] [-n,--noexec] [-v,--verbose] [-h,--help] <XML-config file>
-[options] --add <objecttype> [args]
+[OPTIONS] <XML-config file>
 .br
 .SH DESCRIPTION
 .B lconf
-, when invoked configures a node following directives in the <XML-config-file>. There will be single configuration file for all the nodes in a single cluster. This file should be distributed to all the nodes in the cluster or kept in a location accessible to all the nodes. One option is to store the cluster configuration information in LDAP format on an LDAP server that can be reached from all the cluster nodes.
+, when invoked configures a node following directives in the
+<XML-config-file>.Can be used to control recovery and startup/shutdown
+. There will be single configuration file for all the nodes in a
+single cluster. This file should be distributed to all the nodes in
+the cluster or kept in a location accessible to all the nodes. The XML file must be specified. When invoked with no options, lconf will attempt to configure the resources owned by the node it is invoked on
 .PP
 The arguments that can be used for lconf are:
 .PP
 .TP
+--abort_recovery - Used to start Lustre when you are certian that
+recovery will not succeed, as when an OST or MDS is disabled. 
+.TP
+--acl Enable Access Control List support on the MDS 
+.TP
+--allow_unprivileged_port Allows connections from unprivileged ports
+.TP
+--clientoptions <options> 
+Additional options for mounting Lustre clients. Obsolete with
+zeroconfig mounting..
+.TP
 --client_uuid <uuid> 
 The failed client (required for recovery).
 .TP
---clientoptions <options> 
-Additional options for Lustre.
+--clumanager Generate a Red Hat Clumanager configuration file for this
+node.
 .TP
 --config <arg> 
-Cluster configuration name used for LDAP query
+Cluster configuration name used for LDAP query (depreciated)
 .TP
 --conn_uuid <uuid> 
 The failed connection (required for recovery).
 .TP
---d|--cleanup 
+-d|--cleanup 
 Unconfigure a node. The same config and --node argument used for configuration needs to be used for cleanup as well. This will attempt to undo all of the configuration steps done by lconf, including unloading the kernel modules.
 .TP
 --debug_path <path> 
-Path to save debug dumps.
+Path to save debug dumps.(default is /tmp/lustre-log)
 .TP
 --dump <file> 
 Dump the kernel debug log to the specified file before portals is unloaded during cleanup.
 .TP
---dump_path <arg> 
-Path to save debug dumps. Default is /tmp/lustre_log
-.TP
 --failover 
-Used to shutdown without saving state. Default is 0. This will allow the node to give up service to another node for failover purposes. This will not be a clean shutdown.
+Used to shutdown without saving state. This will allow the node to give up service to another node for failover purposes. This will not be a clean shutdown.
 .TP
---force 
-Forced unmounting and/or obd detach during cleanup. Default is 0. 
+-f|--force 
+Forced unmounting and/or obd detach during cleanup. 
 .TP
 --gdb 
-Causes lconf to print a message and pause for 5 seconds after creating a gdb module script and before doing any Lustre configuration (the gdb module script is always created, however).
+Causes lconf to create a gdb module script and pause 5 seconds before doing any Lustre configuration (the gdb module script is always created, however).
 .TP
 --gdb_script <arg> 
 Full name of gdb debug script. Default is /tmp/ogdb.
@@ -66,19 +77,29 @@ The UUID of the service to be ignored by a client mounting Lustre. Allows the cl
 Dump all ioctls to the specified file
 .TP
 --ldapurl <arg> 
-LDAP server URL 
+LDAP server URL. Depreciated
+.TP
+--lustre=src_dir 
+Specify the base directory for Lustre sources, this parameter will cause lconf to load the lustre modules from this source tree.
 .TP
 --lustre_upcall <path> 
 Set the location of the Lustre upcall scripts used by the client for recovery
 .TP
---lustre=src_dir 
-Specify the base directory for Lustre sources, this parameter will cause lconf to load the lustre modules from this soure tree.
+--make_service_scripts Create per-service symlinks for use with clumanager HA software
 .TP
 --mds_ost_conn 
 Open connections to OSTs on MDS.
 .TP
 --maxlevel <level> 
-Perform configuration of devices and services up to level given. level can take the values net, dev, svc, fs. When used in conjunction with cleanup, services are torn down up to a certain level. Default is 100.
+Perform configuration of devices and services up to level given. When
+used in conjunction with cleanup, services are torn down up to a
+certain level.
+Levels are aproximatly like:
+10 - network
+20 - device, ldlm
+30 - osd, mdd
+40 - mds, ost
+70 - mountpoint, echo_client, osc, mdc, lov
 .TP
 --minlevel <level> 
 Specify the minimum level of services to configure/cleanup. Default is 0.
@@ -101,24 +122,36 @@ Only setup devices and services, do not load modules.
 --nosetup 
 Only load modules, do not configure devices or services.
 .TP
+--old_conf Start up service even though config logs appear outdated.
+.TP
 --portals <path> 
-Specify portals source directory. If this is a relative path, then it is assumed to be relative to lustre.
+Specify portals source directory. If this is a relative path, then it
+is assumed to be relative to lustre. (Depreciated)
 .TP
 --portals_upcall <path> 
-Specify the location of the Portals upcall scripts used by the client for recovery
+Specify the location of the Portals upcall scripts used by the client
+for recovery (Depreciated)
 .TP
 --ptldebug debug-level 
 This options can be used to set the required debug level.
 .TP
+--quota 
+Enable quota support for client filesystem
+.TP
+--rawprimary <arg>  For clumanager, device of the primary quorum
+(default=/dev/raw/raw1)
+.TP
+--rawsecondary <arg>  For clumanager, device of the secondary quorum (default=/dev/raw/raw2)
+.TP
 --record 
 Write config information on mds.
 .TP
---record_log <arg> 
-Specify the name of config record log.
-.TP
 --record_device <arg> 
 Specify MDS device name that will record the config commands.
 .TP
+--record_log <arg> 
+Specify the name of config record log.
+.TP
 --recover <arg> 
 Recover a device.
 .TP
@@ -131,6 +164,11 @@ Select a particular node for a service
 --service <arg>
 Shorthand for --group <arg> --select <arg>=<hostname>
 .TP
+--service_scripts <arg>  For clumanager, directory containing per-service scripts (default=/etc/lustre/services)
+.TP
+--single_socket The socknal option. Uses only one socket instead of a
+bundle.
+.TP
 --subsystem <arg> 
 Set the portals debug subsystem.
 .TP
@@ -141,7 +179,10 @@ Specify the failed target (required for recovery).
 Set the recovery timeout period.
 .TP
 --upcall <path> 
-Set the location of both Lustre and Portals upcall scripts used by the client for recovery
+Set the location of both Lustre and Portals upcall scripts used by the
+client for recovery
+.TP
+--user_xattr Enable user_xattr support on MDS
 .TP
 --verbose,-v 
 Be verbose and show actions while going along.
index 69c6ece..2015734 100644 (file)
@@ -34,269 +34,213 @@ To get a complete listing of available commands, type help at the lctl prompt.
 
 For non-interactive single-threaded use, one uses the second invocation, which runs command after connecting to the device. 
 
-.B Network Configuration
+.SS Network Configuration
 .TP
---net <tcp/elan/myrinet> <command> 
-Indicate the network type to be used for the operation.
-.TP 
-network <tcp/elans/myrinet> 
-Indicate what kind of network applies for the configuration commands that follow.
+.BI network " <up/down>|<tcp/elan/myrinet>"
+Start or stop LNET, or select a network type for other
+.I
+lctl
+commands
+.TP
+.BI list_nids
+Print all Network Identifiers on the local node
 .TP
-interface_list 
+.BI which_nid " <nidlist>"
+From a list of nids for a remote node, show which interface communication
+will take place on.
+.TP
+.BI interface_list 
 Print the interface entries.
 .TP
-add_interface <ip> [netmask] 
+.BI add_interface " <ip> [netmask]" 
 Add an interface entry.
 .TP
-del_interface [ip] 
+.BI del_interface " [ip]" 
 Delete an interface entry.
 .TP
-peer_list 
+.BI peer_list 
 Print the peer entries.
 .TP
-add_peer <nid> <host> <port> 
+.BI add_peer " <nid> <host> <port>"
 Add a peer entry.
 .TP
-del_peer [<nid>] [<host>] [ks] 
+.BI del_peer " [<nid>] [<host>] [ks] "
 Remove a peer entry.
 .TP
-conn_list 
-Print all the connected remote nid.
-.TP 
-connect [[<hostname> <port>] | <elan id>] 
-This will establish a connection to a remote network network id given by the hostname/port combination, or the elan id.
-.TP 
-disconnect <nid> 
-Disconnect from a remote nid.
+.BI conn_list 
+Print all the connected remote nids on a network.
 .TP
-active_tx 
+.BI active_tx 
 This command should print active transmits, and it is only used for elan network type.
 .TP 
-mynid [nid] 
-Informs the socknal of the local nid. It defaults to hostname for tcp networks and is automatically setup for elan/myrinet networks.
-.TP
-shownid 
-Print the local NID.
-.TP 
-add_uuid <uuid> <nid> 
-Associate a given UUID with an nid.
-.TP 
-close_uuid <uuid> 
-Disconnect a UUID.
-.TP 
-del_uuid <uuid> 
-Delete a UUID association.
-.TP 
-add_route <gateway> <target> [target] 
+.BI add_route " <gateway> <target> [target] "
 Add an entry to the routing table for the given target.
 .TP 
-del_route <target> 
+.BI del_route " <target>" 
 Delete an entry for the target from the routing table.
 .TP
-set_route <gateway> <up/down> [<time>] 
+.BI set_route " <gateway> <up/down> [<time>] "
 Enable/disable routes via the given gateway in the protals routing table. <time> is used to tell when a gateway comes back online.
 .TP 
-route_list 
+.BI route_list 
 Print the complete routing table.
 .TP
-fail nid|_all_ [count] 
-Fail/restore communications. Omitting the count implies fail indefinitely, count of zero indicates that communication should be restored. A non-zero count indicates the number of portals messages to be dropped after which the communication is restored. The argument "nid" is used to specify the gateway, which is one peer of the communication.
+.BI fail " <nid>|_all_ [count]" 
+Fail/restore communications. Omitting the count implies fail indefinitely, count of zero indicates that communication should be restored. A non-zero count indicates the number of LNET messages to be dropped after which the communication is restored. The argument "nid" is used to specify the gateway, which is one peer of the communication.
 .PP
-.B Device Selection
+.SS Device Selection
 .TP 
-newdev 
-Create a new device.
-.TP 
-device 
+.BI device 
 This will select the specified OBD device.  All other commands depend on the device being set. 
 .TP
-cfg_device <$name> 
+.BI cfg_device " <$name>" 
 Set current device being configured to <$name>.
 .TP 
-device_list 
+.BI device_list 
 Show all the devices.
 .TP 
-lustre_build_version 
+.BI lustre_build_version 
 Print the Lustre build version.
 .PP
-.B Device Configuration
-.TP 
-attach type [name [uuid]] 
-Attach a type to the current device (which you need to set using the device command) and give that device a name and UUID.  This allows us to identify the device for use later, and also tells us what type of device we will have.
+.SS Device Configuration
 .TP 
-setup <args...> 
-Type specific device setup commands. For obdfilter, a setup command tells the driver which block device it should use for storage and what type of filesystem is on that device. 
+.BI conf_param " <device> <parameter>"
+Set a configuration parameter 
 .TP 
-cleanup 
+.BI cleanup " [force/failover]"
 Cleanup a previously setup device.
 .TP 
-detach 
+.BI detach 
 Remove driver (and name and UUID) from the current device.
-.TP 
-lov_setconfig lov-uuid stripe-count default-stripe-size offset pattern UUID1 [UUID2...] 
-Write LOV configuration to an MDS device.
-.TP 
-lov_getconfig lov-uuid 
-Read LOV configuration from an MDS device. Returns default-stripe-count, default-stripe-size, offset, pattern, and a list of OST UUID's.
-.TP
-record cfg-uuid-name 
-Record commands that follow in log.
-.TP
-endrecord 
-Stop recording.
-.TP
-parse config-uuid-name 
-Parse the log of recorded commands for this config.
-.TP
-dump_log config-uuid-name 
-Print log of recorded commands for this config to kernel debug log.
-.TP
-clear_log config-name 
-Delete current config log of recorded commands.
 .PP
-.B Device Operations
+.SS Device Operations
 .TP 
-probe [timeout] 
-Build a connection handle to a device. This command is used to suspend configuration until the lctl command has ensured that the MDS and OSC services are available. This is to avoid mount failures in a rebooting cluster.
-.TP 
-close 
-Close the connection handle
-.TP 
-getattr <objid> 
+.BI getattr " <objid>" 
 Get attributes for an OST object <objid> .
 .TP 
-setattr <objid> <mode> 
+.BI setattr " <objid> <mode>" 
 Set mode attribute for OST object <objid>.
 .TP 
-create [num [mode [verbose]]] 
+.BI create " [num [mode [verbose]]]" 
 Create the specified number <num> of OST objects with the given <mode>.
 .TP 
-destroy <num> 
+.BI destroy " <num>" 
 Starting at <objid>, destroy <num> number of objects starting from the object with object id <objid>.
 .TP 
-test_getattr <num> [verbose [[t]objid]] 
+.BI test_getattr " <num> [verbose [[t]objid]]" 
 Do <num> getattrs on OST object <objid> (objectid+1 on each thread).
 .TP 
-test_brw [t]<num> [write [verbose [npages [[t]objid]]]] 
+.BI test_brw " [t]<num> [write [verbose [npages [[t]objid]]]]" 
 Do <num> bulk read/writes on OST object <objid> (<npages> per I/O).
 .TP 
-test_ldlm 
+.BI test_ldlm 
 Perform lock manager test.
 .TP 
-ldlm_regress_start %s [numthreads [refheld [numres [numext]]]] 
+.BI ldlm_regress_start " %s [numthreads [refheld [numres [numext]]]]" 
 Start lock manager stress test.
 .TP 
-ldlm_regress_stop 
+.BI ldlm_regress_stop 
 Stop lock manager stress test.
 .TP 
-dump_ldlm 
+.BI dump_ldlm 
 Dump all lock manager state, this is very useful for debugging
 .TP 
-activate 
+.BI activate 
 Activate an import
 .TP 
-deacttivate 
+.BI deactivate 
 De-activate an import
 .TP 
-recover <connection UUID> 
+.BI recover " <connection UUID>" 
 .TP 
-lookup <directory> <file>
+.BI lookup " <directory> <file>"
 .TP 
-notransno 
+.BI notransno 
 Disable sending of committed transnumber updates
 .TP 
-readonly 
+.BI readonly 
 Disable writes to the underlying device
 .TP 
-abort_recovery 
+.BI abort_recovery 
 Abort recovery on MDS device
 .TP 
-mount_option 
-Dump mount options to a file
-.TP 
-get_stripe 
+.BI get_stripe 
 Show stripe info for an echo client object.
 .TP 
-set_stripe <objid>[ width!count[@offset] [:id:id....] 
+.BI set_stripe " <objid>[ width!count[@offset] [:id:id....] "
 Set stripe info for an echo client
 .TP 
-unset_stripe <objid> 
+.BI unset_stripe " <objid>" 
 Unset stripe info for an echo client object.
 .TP
-del_mount_option profile 
-Delete a specified profile.
-.TP
-set_timeout <secs> 
-Set the timeout(obd_timeout) for server to wait before failing recovery.
-.TP
-set_lustre_upcall </full/path/to/upcall> 
+.BI set_lustre_upcall " </full/path/to/upcall> "
 Set the lustre upcall(obd_lustre_upcall) via the lustre.upcall sysctl.
 .TP
-llog_catlist 
+.BI llog_catlist 
 List all catalog logs on current device.
 .TP
-llog_info <$logname|#oid#ogr#ogen> 
+.BI llog_info " <$logname|#oid#ogr#ogen> "
 Print log header information. 
 .TP
-llog_print <$logname|#oid#ogr#ogen> [from] [to] 
+.BI llog_print " <$logname|#oid#ogr#ogen> [from] [to] "
 Print log content information. It will print all records from index 1 by default.
 .TP
-llog_check <$logname|#oid#ogr#ogen> [from] [to] 
+.BI llog_check " <$logname|#oid#ogr#ogen> [from] [to] "
 Check log content information. It will check all records from index 1 by default.
 .TP
-llog_cancel <catalog id|catalog name> <log id> <index> 
+.BI llog_cancel " <catalog id|catalog name> <log id> <index> "
 Cancel one record in log.
 .TP
-llog_remove <catalog id|catalog name> <log id> 
+.BI llog_remove " <catalog id|catalog name> <log id> "
 Remove one log from catalog, erase it from disk.
 .PP
-.B Debug
+.SS Debug
 .TP 
-debug_daemon 
+.BI debug_daemon 
 Debug daemon control and dump to a file
 .TP 
-debug_kernel [file] [raw] 
+.BI debug_kernel " [file] [raw]" 
 Get debug buffer and dump to a fileusage.
 .TP 
-debug_file <input> [output]
+.BI debug_file " <input> [output]"
 Convert kernel-dumped debug log from binary to plain text format.
 .TP 
-clear 
+.BI clear 
 Clear kernel debug buffer.
 .TP 
-mark <text> 
+.BI mark " <text>" 
 Insert marker text in kernel debug buffer.
 .TP 
-filter <subsystem id/debug mask> 
+.BI filter " <subsystem id/debug mask>" 
 Filter message type from the kernel debug buffer.
 .TP 
-show <subsystem id/debug mask> 
+.BI show " <subsystem id/debug mask>" 
 Show specific type of messages.
 .TP 
-debug_list <subs/types> 
+.BI debug_list " <subs/types>" 
 List all the subsystem and debug types.
 .TP
-modules <path> 
+.BI modules " <path>" 
 Provide gdb-friendly module information.
 .TP 
-panic 
+.BI panic 
 Force the kernel to panic.
 .TP
-lwt start/stop [file] 
+.BI lwt " start/stop [file]" 
 Light-weight tracing.
 .TP
-memhog <page count> [<gfp flags>] 
+.BI memhog " <page count> [<gfp flags>]" 
 Memory pressure testing.
 .PP
-.B Control
+.SS Control
 .TP 
-help 
+.BI help 
 Show a complete list of commands; help <command name> can be used to get help on specific command.
 .TP 
-exit 
+.BI exit 
 Close the lctl session.
 .TP 
-quit 
+.BI quit 
 Close the lctl session.
 
 .SH OPTIONS
@@ -314,69 +258,32 @@ Ignore errors during script processing
 .B dump 
 Save ioctls to a file 
 .SH EXAMPLES
-.B attach
-
 # lctl
 .br
-lctl > newdev
+lctl > dl
+  0 UP mgc MGC192.168.0.20@tcp bfbb24e3-7deb-2ffa-eab0-44dffe00f692 5
+  1 UP ost OSS OSS_uuid 3
+  2 UP obdfilter testfs-OST0000 testfs-OST0000_UUID 3
 .br
-lctl > attach obdfilter OBDDEV OBDUUID
-
-.B connect
-
-lctl > name2dev OSCDEV 2 
-.br
-lctl > device 2
-.br
-lctl > connect
-
-.B getattr
-
-lctl > getattr 12
-.br
-id: 12
-.br
-grp: 0
-.br
-atime: 1002663714
-.br
-mtime: 1002663535
-.br
-ctime: 1002663535
-.br
-size: 10
-.br
-blocks: 8
-.br
-blksize: 4096
-.br
-mode: 100644
-.br
-uid: 0
-.br
-gid: 0
-.br
-flags: 0
-.br
-obdflags: 0
-.br
-nlink: 1
-.br
-valid: ffffffff
-.br
-inline:
-.br
-obdmd:
-.br
-lctl > disconnect 
-.br
-Finished (success)
-
-.B setup 
-
-lctl > setup /dev/loop0 ldiskfs
+lctl > dk /tmp/log
+Debug log: 87 lines, 87 kept, 0 dropped.
 .br
 lctl > quit
+.PP
+# lctl conf_param testfs-MDT0000 sys.timeout=40
 
 .SH BUGS
-None are known.
+Please report all bugs to ClusterFileSystems, support@clusterfs.com
+.SH AVAILABILITY
+.B lctl
+is part of the 
+.BR Lustre (7) 
+filesystem package and is available from CFS
+.br
+http://clusterfs.com
+.SH SEE ALSO
+.BR Lustre (7),
+.BR mkfs.lustre (8),
+.BR mount.lustre (8),
+.BR lctl (8),
+.BR lfs (1)
index b31f5ff..959d7b5 100644 (file)
@@ -5,9 +5,13 @@ lfs \- Lustre utility to create a file with specific striping pattern, find the
 .br
 .B lfs
 .br
-.B lfs find [--obd <uuid>] [--quiet | --verbose] [--recursive] <dir|file>
+.B lfs find [--atime|-A N] [--mtime|-M N] [--ctime|-C N] [--maxdepth|-D N]
+         \fB[--print0|-P] [--print|-p] [--obd|-O <uuid>] <dir/file>\fR
 .br
-.B lfs getstripe <filename> 
+.B lfs find [--quiet|-q] [--verbose|-v] [--recursive|-r] <dir|file>
+.br
+.B lfs getstripe [--obd|-O <uuid>] [--quiet|-q] [--verbose|-v] 
+              \fB[--recursive|-r] <dir/file>\fR
 .br
 .B lfs setstripe <filename> <stripe-size> <start-ost> <stripe-cnt>
 .br
@@ -19,13 +23,16 @@ lfs \- Lustre utility to create a file with specific striping pattern, find the
 .br
 .B lfs quotaoff [-ug] <filesystem>
 .br
-.B lfs setquota [-u|-g] <name> <block-softlimit> <block-hardlimit> <inode-softlimit> <inode-hardlimit> <filesystem>
+.B lfs setquota [-u|-g] <name> <block-softlimit> <block-hardlimit> 
+             \fB<inode-softlimit> <inode-hardlimit> <filesystem>\fR
 .br
 .B lfs quota [-o obd_uuid] [-u|-g] <name> <filesystem>
 .br
 .B lfs setstripe <filename> <stripe-size> <start-ost> <stripe-cnt>
 .br
 .B lfs check <mds| osts| servers>
+.br
+.B lfs df [-i] [-h] [path]
 .SH DESCRIPTION
 .B lfs
 can be used to create a new file with a specific striping pattern, determine the default striping pattern, gather the extended attributes (object numbers and 
@@ -38,10 +45,13 @@ The various options supported by lctl are listed and explained below:
 To create a new file with a specific striping pattern
 .TP
 .B find 
-To list the extended attributes for a given filename or files in a directory or recursively for all files in a directory tree. It can also be used to list the files that have objects on a specific OST. 
+To search the directory tree rooted at the given dir/file name for the files that match the given parameters: \fB--atime\fR (file was last accessed N*24 hours ago), \fB--ctime\fR (file's status was last changed N*24 hours ago), \fB--mtime\fR (file's data was last modified N*24 hours ago), \fB--obd\fR (file has an object on a specific OST). The option \fB--maxdepth\fR allows find to decend at most N levels of directory tree. The options \fB--print\fR and \fB--print0\fR print full file name, followed by a newline and null character correspondingly.  Using one of these options works in the new (filename only) mode.
+.TP
+.B find
+To list the striping info for a given filename or files in a directory or recursively for all files in a directory tree use one of the following options: \fB[--quiet|-q] [--verbose|-v] [--recursive|-r]\fR. If one of these options is given find works in old (obsolete, please use getstripe instead) filename and striping mode.
 .TP
 .B getstripe 
-To list the striping pattern for given filename
+To list the striping info for given filename or files in a directory or recursively for all files in a directory tree. It can also be used to list the files that have objects on a specific OST.
 .TP
 .B quotachown
 To change files' owner and group on OSTs of the specified filesystem
@@ -67,6 +77,9 @@ Display the status of MDS or OSTs (as specified in the command) or all the serve
 .B osts 
 List all the OSTs for the filesystem
 .TP
+.B df
+Report filesystem disk space usage or inodes usage of each MDT/OST.
+.TP
 .B help 
 Provides brief help on the various arguments
 .TP
@@ -74,45 +87,46 @@ Provides brief help on the various arguments
 Quit the interactive lfs session
 .SH EXAMPLES
 .TP
-.B $lfs setstripe /mnt/lustre/file1 131072 0 1
-This creats a file striped on one OST
+.B $ lfs setstripe /mnt/lustre/file1 131072 -1 2
+This creats a file striped on two OSTs with 128kB on each stripe.
 .TP
-.B $lfs find /mnt/lustre/file1
-Lists the extended attributes of a given file
+.B $ lfs find /mnt/lustre/file1
+Lists the object allocation of a given file
 .TP
-.B $lfs find /mnt/lustre/
-Lists the extended attributes of all files in a given directory
+.B $ lfs find /mnt/lustre/
+Lists the object allocationss of all files in a given directory
 .TP
-.B $lfs find -r /mnt/lustre/
-Recursively list the extended attributes of all files in a given directory tree
+.B $ lfs find -r /mnt/lustre/
+Recursively list the objects of all files in a given directory tree
 .TP
-.B $lfs find -r --obd OST2-UUID /mnt/lustre/
-List all the files that have objects on a specific OST
+.B $ lfs find -r --obd OST2-UUID /mnt/lustre/
+Recursively list all files in a given directory that have objects on OST2-UUID.
 .TP
-.B $lfs quotachown -i /mnt/lustre
+.B $ lfs quotachown -i /mnt/lustre
 Change file owner and group
 .TP
-.B $lfs quotacheck -ug /mnt/lustre
+.B $ lfs quotacheck -ug /mnt/lustre
 Quotacheck for user and group
 .TP
-.B $lfs quotaon -ug /mnt/lustre
+.B $ lfs quotaon -ug /mnt/lustre
 Turn quotas of user and group on
 .TP
-.B $lfs quotaoff -ug /mnt/lustre
+.B $ lfs quotaoff -ug /mnt/lustre
 Turn quotas of user and group off
 .TP
-.B $lfs setquota -u bob 0 1000000 0 10000 /mnt/lustre
+.B $ lfs setquota -u bob 0 1000000 0 10000 /mnt/lustre
 Set quotas of user `bob': 1GB block quota and 10,000 file quota
 .TP
-.B $lfs quota -u bob /mnt/lustre
+.B $ lfs quota -u bob /mnt/lustre
 List quotas of user `bob'
 .TP
-.B $ lfs find -r --obd OST2-UUID /mnt/lustre/
-.TP
-.B $lfs check servers 
-Check the status of all servers(mds, osts)
+.B $ lfs check servers 
+Check the status of all servers (MDT, OST)
 .TP
-.B $lfs osts
+.B $ lfs osts
 List all the OSTs
+.TP
+.B $ lfs df -i 
+Lists inode consumpton per OST and MDT
 .SH BUGS
 None are known.
index 8e08a86..3b4588f 100644 (file)
@@ -47,13 +47,21 @@ lfs
 
 \series bold 
 lfs\SpecialChar ~
-find [--obd <uuid>] [--quiet | --verbose] [--recursive] <dir|file>
+find [--atime|-A N] [--mtime|-M N] [--ctime|-C N] [--maxdepth|-D N] [--print0
+|-P] [--print|-p] [--obd|-O <uuid>] <dir/file>
 \layout Standard
 
 
 \series bold 
 lfs\SpecialChar ~
-getstripe <filename> 
+find [--quiet|-q] [--verbose|-v] [--recursive|-r] <dir/file>
+\layout Standard
+
+
+\series bold 
+lfs\SpecialChar ~
+getstripe [--obd|-O <uuid>] [--quiet|-q] [--verbose|-v] [--recursive|-r]
+ <dir/file>
 \layout Standard
 
 
@@ -62,6 +70,7 @@ lfs\SpecialChar ~
 setstripe <filename|dirname> <stripe_size> <start_ost> <stripe_cnt>
 \layout Standard
 
+
 \series bold 
 lfs\SpecialChar ~
 setstripe -d <dirname>
@@ -108,6 +117,18 @@ setquota [-u|-g] <name> <block-softlimit> <block-hardlimit> <inode-softlimit>
 \series bold 
 lfs\SpecialChar ~
 quota [-o obd_uuid] [-u|-g] <name> <filesystem>
+\layout Standard
+
+
+\series bold 
+lfs\SpecialChar ~
+df [-i] [-h] [path]
+\layout Standard
+
+
+\series bold 
+lfs\SpecialChar ~
+help
 \layout Subsection
 
 DESCRIPTION
@@ -134,9 +155,27 @@ setstripe
 \series bold 
 find
 \series default 
- To list the extended attributes for a given filename or files in a directory
- or recursively for all files in a directory tree.
- It can also be used to list the files that have objects on a specific OST.
+ To search the directory tree rooted at the given dir/file name for the
+ files that match the given parameters: --atime (file was last accessed
+ N*24 hours ago), --ctime (file's status was last changed N*24 hours ago),
+ --mtime (file's data was last modified N*24 hours ago), --obd (file has
+ an object on a specific OST).
+ The option --maxdepth allows find to decend at most N levels of directory
+ tree.
+ The options --print and --print0 print full file name, followed by a newline
+ and null character correspondingly.
+\layout List
+\labelwidthstring 00.00.0000
+
+
+\series bold 
+find
+\series default 
+ To list the striping info for a given filename or files in a directory
+ or recursively for all files in a directory tree use one of the following
+ options: [--quiet|-q] [--verbose|-v] [--recursive|-r].
+ If one of these options is given find works in old (obsolete, please use
+ getstripe instead) mode.
  
 \layout List
 \labelwidthstring 00.00.0000
@@ -145,7 +184,9 @@ find
 \series bold 
 getstripe
 \series default 
- To list the striping pattern for given filename
+ To list the striping info for given filename or files in a directory or
+ recursively for all files in a directory tree.
+ It can also be used to list the files that have objects on a specific OST.
 \layout List
 \labelwidthstring 00.00.0000
 
@@ -217,6 +258,14 @@ quota
 
 
 \series bold 
+df
+\series default 
+ Report filesystem disk space usage or inodes usage of each MDS/OSD.
+\layout List
+\labelwidthstring 00.00.0000
+
+
+\series bold 
 help
 \series default 
  Provides brief help on the various arguments
@@ -246,8 +295,8 @@ This creates a default stripe pattern on and existing dir for all new files
    $ lfs setstripe /mnt/lustre/dir 131072 0 1
 \layout Description
 
-This deletes a default stripe pattern on dir.  New files will use the
- default striping pattern.
+This deletes a default stripe pattern on dir.
 New files will use the default striping pattern.
  created therein.
 \layout LyX-Code
 
diff --git a/lustre/doc/llverdev.txt b/lustre/doc/llverdev.txt
new file mode 100644 (file)
index 0000000..dd0e150
--- /dev/null
@@ -0,0 +1,48 @@
+BLOCK DEVICE VERIFICATION TOOL. ( bdevt )
+==========================================
+
+Building tool: 
+       To build this tool you just need to invoke make at command prompt.
+       e.g.  $ make 
+       
+       this will compile the sources and build bdevt in this directory.
+
+Usage: 
+Syntax:
+
+./bdevt [OPTION]... <device-name> ... 
+
+[OPTION]
+        -t {seconds} for --timestamp,  set test time (default=current time())
+        -o {offset}  for --offset, offset in kB of start of test (default=0)
+        -r run test in read (verify) mode
+        -w run test in write (test-pattern) mode (default=r&w)
+        -v for verbose
+        -p for --partial, for partial check (1GB steps)
+        -l for --long, full check (default 4k)
+        -c for --chunksize, IO chunk size (default=1048576)
+        -f for --force, force test to run without confirmation
+       --help to display help.
+
+Guide lines for using this tool:
+       It is expected that bdevt tool will be run on large size devices (TB), 
+So it is always better to run bdevt tool in verbose mode, So that one can easily 
+restart device testing from the point at which it had stoped. 
+for example:
+
+       [root@tucker bdevt]# ./bdevt -v -f -w --timestamp=1009839028 /dev/hda5
+       Number of sectors: 49158837, this makes 23.441 GB
+       Timestamp: 1009839028
+       Current write offset:        5078016 kB
+
+If due to some reason sombody breaks execution at this point then one can 
+easily restart device from the same point by picking the same offset 
+displayed in by verbose as explained below.
+
+       [root@tucker bdevt]# ./bdevt -v -f -w --offset=5078016 --timestamp=1009839028 /dev/hda5
+       Number of sectors: 49158837, this makes 23.441 GB
+       Timestamp: 1009839028
+       Current write offset:        9726208 kB
+One can use similar things for read only and read write modes also.
+
diff --git a/lustre/doc/llverfs.txt b/lustre/doc/llverfs.txt
new file mode 100644 (file)
index 0000000..0321d75
--- /dev/null
@@ -0,0 +1,48 @@
+FILESYSTEM VERIFICATION TOOL. ( ext3vt )
+==========================================
+
+Building tool: 
+       To build this tool you just need to invoke make at command prompt.
+       e.g.  $ make 
+       
+       this will compile the sources and build ext3vt in this directory.
+
+Usage: 
+Syntax:
+
+./ext3vt [OPTION]... <filesystem path> ... 
+
+[OPTION]
+        -t {seconds} for --timestamp,  set test time(default=current time())
+        -o {fileOffset}  for --fileOffset, full path of file from which tests should start
+        -r run test in read (verify) mode
+        -w run test in write (test-pattern) mode (default=r&w)
+        -v for verbose
+        -p for --partial, for partial check (1MB files)
+        -l for --long, full check (4GB file with 4k blocks)
+        -c for --chunksize, IO chunk size (default=1048576)
+        -h display this help and exit
+        --help display this help and exit
+
+Guide lines for using this tool:
+       It is expected that ext3vt tool will be run on large size 
+filesystem (TB), So it is always better to run ext3vt tool in verbose mode, 
+So that one can easily restart device testing from the point at which it 
+had stoped. 
+for example:
+       
+       [root@Matrix ext3vt]# ./ext3vtnew -v -f -w --timestamp=1145009417 /mnt/store/
+       Timestamp: 1145009417
+       write File name: /mnt/store/dir00004/file005
+       
+If due to some reason sombody breaks execution at this point then one can 
+easily restart device from the same point by picking the same file offset 
+displayed in by verbose as explained below.
+
+       [root@tucker ext3vt]# ./bdevt -v -f -w --fileOffset=/home/dir00004/file005 
+                            --timestamp=1145009417 /mnt/store/
+       Timestamp: 1145009417
+       write File name: /mnt/store/dir00008/file007
+       write complete
+       [root@tucker ext3vt]#
+One can use similar things for read only and read write modes also.
index d755de8..9197ead 100644 (file)
@@ -207,7 +207,7 @@ Optional argument to mount fs. Mount options will be passed by this argument. Fo
 Optional arguement to specify the journal size for the ext3 file system. The size should be in the units expected by mkfs, so for ext3 it should be in MB. If this is option is not used, the ext3 filesystem will be configured with a journal size dependent upon how large the filesystem is.
 .PP
 .B --add mtpt 
-Creates a mount-point on the specified node. Either an LOV or OSC name can be used.
+Creates a mount-point on the specified node for the given LOV.
 .TP
 --node node 
 Node that will use the mtpt.
index e42e64b..48fcb4b 100644 (file)
@@ -504,8 +504,7 @@ mkfs
 \layout Description
 
 --add\SpecialChar ~
-mtpt Creates a mount-point on the specified node.
- Either an LOV or OSC name can be used.
+mtpt Creates a mount-point on the specified node for the given LOV.
 \begin_deeper 
 \layout Description
 
diff --git a/lustre/doc/lustre.7 b/lustre/doc/lustre.7
new file mode 100644 (file)
index 0000000..460df98
--- /dev/null
@@ -0,0 +1,76 @@
+.\" -*- nroff -*-
+.\" Copyright 2006 by Cluster FileSystems.  All Rights Reserved.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH Lustre 7 "2006 Jun 15" Lustre "A high-performance cluster file system"
+.SH NAME
+Lustre
+.SH SYNOPSIS
+A high-performance file system designed for clusters.
+.SH DESCRIPTION
+.B Lustre®
+is a high-performance, massively-scalable, POSIX-compliant network file system
+designed for the world's largest high-performance compute clusters. Lustre
+is under active development from Cluster FileSystems (http://clusterfs.com).
+
+Lustre filesystems are made up of multiple servers typically distributed
+across multiple nodes.  Lustre clients can contact these server nodes over
+multiple high-speed network fabrics via LNET, the Lustre NETworking
+system.  Clients then present the filesystem at a mount point.
+
+A filesystem is comprised of a 
+.I MDT
+, MetaData Target, which stores directory and file meta-information, and a
+series of 
+.I OSTs
+, Object Storage Targets, which hold the file data.  There is typically not
+a 1:1 mapping of a file on disk and what is presented as a file on a Lustre client.
+
+Lustre and LNET are implemented as a series of kernel modules, for both
+servers and clients. LNET networks are defined in the modprobe.conf file on
+all nodes.  Lustre and LNET make extensive use of /proc files for making
+system data available, for example
+.TP
+.B /proc/sys/lnet/nis
+to show the local LNET Network Interfaces.
+.TP
+.B /proc/fs/lustre/devices
+to show locally running Lustre objects.
+
+.SH COMMANDS
+.TP
+.B mkfs.lustre(8)
+Format a physical disk for use as a Lustre server's backend storage (aka
+target).
+.TP
+.B tunefs.lustre(8)
+Modify configuration information on a Lustre target disk.
+.TP
+.B mount.lustre(8)
+A helper program for
+.BR mount (8)
+that starts Lustre servers and clients.
+.TP
+.B lctl(8)
+A low-level interface to control various aspects of Lustre
+.TP
+.B lfs(1)
+A user-level interface to control Lustre-specific information for
+individual files. 
+.B lustre_config.sh
+Format multiple Lustre targets simultaneously from definitions in a CSV
+file.
+.SH BUGS
+Please report all bugs to Cluster FileSystems, support@clusterfs.com
+.SH AVAILABILITY
+.B The
+.BR Lustre (7) 
+filesystem package is available from CFS
+.br
+http://clusterfs.com
+.SH SEE ALSO
+.BR mkfs.lustre (8),
+.BR tunefs.lustre (8),
+.BR mount.lustre (8),
+.BR lctl (8),
+.BR lfs (1)
diff --git a/lustre/doc/mkfs.lustre.8 b/lustre/doc/mkfs.lustre.8
new file mode 100644 (file)
index 0000000..a1469e4
--- /dev/null
@@ -0,0 +1,129 @@
+.\" -*- nroff -*-
+.\" Copyright 2006 by Cluster FileSystems.  All Rights Reserved.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH mkfs.lustre 8 "2006 Jun 15" Lustre "configuration utilities"
+.SH NAME
+mkfs.lustre \- format a disk for a Lustre service
+.SH SYNOPSIS
+.br
+.B mkfs.lustre
+<target_type> [options] 
+.I device
+.br
+where
+.B <target_type>
+is one of
+.TP
+.BI \--ost
+object storage target
+.TP
+.BI \--mdt
+metadata storage target
+.TP
+.BI \--mgs
+configuration management service - one per site.  This service can be
+combined with one 
+.BI \--mdt
+service by specifying both types
+.SH DESCRIPTION
+.B mkfs.lustre
+is used to format a disk device for use as part of a Lustre
+filesystem. After formatting, a disk can be mounted to start the Lustre
+service defined by this command.
+
+.SH OPTIONS
+.TP
+.BI \--backfstype= fstype
+Force a particular format for the backing fs (ext3, ldiskfs)
+.TP
+.BI \--device-size= KB
+Set device size for loop devices
+.TP
+.BI \--failnode= nid,...  
+Set the NID(s) of a failover partner. This option can be repeated as desired.
+.TP
+.BI \--fsname= filesystem_name  
+The Lustre filesystem this service will be part of.  Default is 'lustre'
+.TP
+.BI \--index= index
+Force a particular OST or MDT index 
+.TP
+.BI \--mkfsoptions= opts
+Format options for the backing fs. For example, ext3 options could be set here.
+.TP
+.BI \--mountfsoptions= opts
+Set permanent mount options, equivalent to setting in /etc/fstab
+.TP
+.BI \--mgsnode= nid,...  
+Set the NID(s) of the MGS node, required for all targets other than the MGS.
+.TP
+.BI \--noformat 
+Only print what would be done; does not affect the disk
+.TP
+.BI \--param " key=value"
+Set permanent parameter 
+.I key 
+to value 
+.I value.
+This option can be repeated as desired.  Typical options might include:
+.RS
+.I \--param sys.timeout=40 
+.RS
+System obd timeout
+.RE
+.I \--param lov.stripe.size=2097152
+.RS
+Default stripe size
+.RE
+.I \--param lov.stripe.count=2       
+.RS
+Default stripe count
+.RE
+.I \--param failover.mode=failout    
+.RS
+Return errs instead of waiting for recovery
+.RE
+.RE
+.TP
+.BI \--quiet
+Print less information.
+.TP
+.BI \--reformat 
+Reformat an existing Lustre disk
+.TP
+.BI \--stripe-count-hint= stripes
+Used for optizing MDT inode size
+.TP
+.BI \--verbose
+Print more information.
+
+.SH EXAMPLES
+.TP
+.B mkfs.lustre --fsname=testfs --mdt --mgs /dev/sda1
+Combined MGS and MDT for filesystem 'testfs' on node e.g. cfs21
+.TP
+.B mkfs.lustre --fsname=testfs --ost --mgsnode=cfs21@tcp0 /dev/sdb
+OST for filesystem 'testfs' on any node using the above MGS.
+.TP
+.B mkfs.lustre --mgs /dev/sda1
+Standalone MGS on e.g. node cfs22
+.TP
+.B mkfs.lustre --fsname=myfs1 --mdt --mgsnode=cfs22@tcp0 /dev/sda2
+MDT for filesystem 'myfs1' on any node, using the above MGS
+
+.SH BUGS
+Please report all bugs to Cluster FileSystems, support@clusterfs.com
+.SH AVAILABILITY
+.B mkfs.lustre
+is part of the 
+.BR Lustre (7) 
+filesystem package and is available from CFS
+.br
+http://clusterfs.com
+.SH SEE ALSO
+.BR Lustre (7),
+.BR mount.lustre (8),
+.BR tunefs.lustre (8),
+.BR lctl (8),
+.BR lfs (1)
diff --git a/lustre/doc/mount.lustre.8 b/lustre/doc/mount.lustre.8
new file mode 100644 (file)
index 0000000..3e830a9
--- /dev/null
@@ -0,0 +1,105 @@
+.\" -*- nroff -*-
+.\" Copyright 2006 by Cluster FileSystems.  All Rights Reserved.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH mount.lustre 8 "2006 Jun 15" Lustre "configuration utilities"
+.SH NAME
+mount.lustre \- start a Lustre client or target service 
+.SH SYNOPSIS
+.br
+.BI "mount \-t lustre [\-o " options "] " "device dir"
+.SH DESCRIPTION
+.B mount.lustre
+is used to start a Lustre client or target service.  This program should not be
+called directly; rather it is a helper program invoked through 
+.BR mount (8)
+as above.  Lustre clients and targets are stopped by using the 
+.BR umount (8)
+command.
+.br
+
+There are two forms for the 
+.I device
+option, depending on whether a client or a target service is started:
+.TP
+.BI <mgsspec>:/<fsname>
+This is a client mount command to mount the Lustre filesystem named
+<fsname> by contacting the Management Service at <mgsspec>.  The format for
+<mgsspec> is defined below.
+.TP
+.BI <disk_device>
+This starts the target service defined by the 
+.I mkfs.lustre
+command on the physical disk <disk_device>
+.SH OPTIONS
+.TP
+.BI <mgsspec>:= <mgsnode>[:<mgsnode>]
+The mgs specification may be a colon-separated list of nodes...
+.TP
+.BI <mgsnode>:= <mgsnid>[,<mgsnid>]
+ ...and each node may be specified by a comma-separated list of NIDs.
+.PP
+In addition to the standard mount options, Lustre understands the following
+.I client-specific
+options:
+.TP
+.BI flock
+Enable flock support
+.TP
+.BI noflock
+Disable flock support
+.TP
+.BI user_xattr
+Enable get/set user xattr
+.TP
+.BI nouser_xattr
+Disable user xattr
+.TP
+.BI acl
+Enable ACL support
+.TP
+.BI noacl
+Disable ACL support
+.PP
+In addition to the standard mount options and backing disk type
+(e.g. LDISKFS) options, Lustre understands the following
+.I server-specific
+options:
+.TP
+.BI nosvc
+Only start the MGC (and MGS, if co-located) for a target service, and not the actual service.
+.TP
+.BI exclude= ostlist
+Start a client or MDT with a list of known inactive OSTs
+.TP
+.BI abort_recov
+Abort recovery (targets only)
+.SH EXAMPLES
+.TP
+.B mount -t lustre cfs21@tcp0:/testfs /mnt/myfilesystem
+Start a client for the Lustre filesystem 'testfs' at the mount point
+/mnt/myfilesystem. The Management Service is running on a node reachable
+from this client via the nid cfs21@tcp0.
+.TP
+.B mount -t lustre /dev/sda1 /mnt/test/mdt
+Start the Lustre target service on /dev/sda1.
+.TP
+.B mount -t lustre -L testfs-MDT0000 -o abort_recov /mnt/test/mdt
+Start the testfs-MDT0000 service (by using the disk label), but abort the
+recovery process.
+.SH BUGS
+Please report all bugs to Cluster FileSystems, support@clusterfs.com
+.SH AVAILABILITY
+.B mount.lustre
+is part of the 
+.BR Lustre (7) 
+filesystem package and is available from CFS
+.br
+http://clusterfs.com
+.SH SEE ALSO
+.BR Lustre (7),
+.BR mount (8),
+.BR mkfs.lustre (8),
+.BR tunefs.lustre (8),
+.BR lctl (8),
+.BR lfs (1)
diff --git a/lustre/doc/tunefs.lustre.8 b/lustre/doc/tunefs.lustre.8
new file mode 100644 (file)
index 0000000..423c8bd
--- /dev/null
@@ -0,0 +1,92 @@
+.\" -*- nroff -*-
+.\" Copyright 2006 by ClusterFileSystems.  All Rights Reserved.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH tunefs.lustre 8 "2006 Jun 15" Lustre "configuration utilities"
+.SH NAME
+tunefs.lustre \- modify the Lustre configuration information on a disk
+.SH SYNOPSIS
+.br
+.B tunefs.lustre
+[options] 
+.I device
+.br
+.SH DESCRIPTION
+.B tunefs.lustre
+is used to modify the configuration information on a Lustre target
+disk. This includes upgrading old (pre-Lustre 1.6) disks.  This does not
+reformat the disk or erase the target information, but modifying the
+configuration information can result in an unusable filesystem.  You have
+been warned.
+.br
+Changes made here will affect a filesystem only when the target is next
+mounted.
+
+.SH OPTIONS
+.TP
+.BI \--erase-params
+Remove all previous parameter info
+.TP
+.BI \--failnode= nid,...  
+Set the NID(s) of a failover partner. This option can be repeated as desired.
+.TP
+.BI \--fsname= filesystem_name  
+The Lustre filesystem this service will be part of.  Default is 'lustre'
+.TP
+.BI \--index= index
+Force a particular OST or MDT index 
+.TP
+.BI \--mountfsoptions= opts
+Set permanent mount options, equivalent to setting in /etc/fstab
+.TP
+.BI \--mgs
+add a configuration management service to this target
+.TP
+.BI \--mgsnode= nid,...  
+Set the NID(s) of the MGS node, required for all targets other than the MGS.
+.TP
+.BI \--noformat 
+Only print what would be done; does not affect the disk
+.TP
+.BI \--nomgs
+remove a configuration management service to this target
+.TP
+.BI \--quiet
+Print less information.
+.TP
+.BI \--verbose
+Print more information.
+.TP
+.BI \--writeconf
+Erase all config logs for the filesystem that this target is part of.  This
+is very dangerous.
+
+.SH EXAMPLES
+.TP
+.B tunefs.lustre --fsname=testfs --mdt --mgs /dev/sda1
+Combined MGS and MDT for filesystem 'testfs' on node e.g. cfs21
+.TP
+.B tunefs.lustre --fsname=testfs --ost --mgsnode=cfs21@tcp0 /dev/sdb
+OST for filesystem 'testfs' on any node using the above MGS.
+.TP
+.B tunefs.lustre --mgs /dev/sda1
+Standalone MGS on e.g. node cfs22
+.TP
+.B tunefs.lustre --fsname=myfs1 --mdt --mgsnode=cfs22@tcp0 /dev/sda2
+MDT for filesystem 'myfs1' on any node, using the above MGS
+
+.SH BUGS
+Please report all bugs to ClusterFileSystems, support@clusterfs.com
+.SH AVAILABILITY
+.B tunefs.lustre
+is part of the 
+.BR Lustre (7) 
+filesystem package and is available from CFS
+.br
+http://clusterfs.com
+.SH SEE ALSO
+.BR Lustre (7),
+.BR mkfs.lustre (8),
+.BR mount.lustre (8),
+.BR lctl (8),
+.BR lfs (1)
index 6d058da..2177f32 100644 (file)
@@ -362,7 +362,7 @@ static int seq_req_handle(struct ptlrpc_request *req)
 
         seq_thread_info_init(req, info);
 
-        if (req->rq_reqmsg->opc == SEQ_QUERY) {
+        if (lustre_msg_get_opc(req->rq_reqmsg) == SEQ_QUERY) {
                 if (req->rq_export != NULL) {
                         /* 
                          * no need to return error here and overwrite @rc, this
@@ -375,7 +375,8 @@ static int seq_req_handle(struct ptlrpc_request *req)
                         req->rq_status = -ENOTCONN;
                 }
         } else {
-                CERROR("Wrong opcode: %d\n", req->rq_reqmsg->opc);
+                CERROR("Wrong opcode: %d\n", 
+                       lustre_msg_get_opc(req->rq_reqmsg));
                 req->rq_status = -ENOTSUPP;
                 rc = ptlrpc_error(req);
                 GOTO(out_info, rc);
@@ -455,9 +456,9 @@ static void seq_server_proc_fini(struct lu_server_seq *seq)
 }
 #endif
 
-#define LUSTRE_MD_SEQ_NAME "md-seq"
-#define LUSTRE_CT_SEQ_NAME "ct-seq"
-#define LUSTRE_DT_SEQ_NAME "dt-seq"
+#define LUSTRE_MD_SEQ_NAME "seq-md"
+#define LUSTRE_CT_SEQ_NAME "seq-ct"
+#define LUSTRE_DT_SEQ_NAME "seq-dt"
 
 int seq_server_init(struct lu_server_seq *seq,
                     struct dt_device *dev,
@@ -533,7 +534,7 @@ int seq_server_init(struct lu_server_seq *seq,
 
         seq->lss_md_service = ptlrpc_init_svc_conf(&seq_md_conf,
                                                    seq_req_handle,
-                                                   LUSTRE_SEQ_NAME,
+                                                   LUSTRE_SEQ_NAME"_md",
                                                    seq->lss_proc_entry,
                                                    NULL);
        if (seq->lss_md_service != NULL)
@@ -550,7 +551,7 @@ int seq_server_init(struct lu_server_seq *seq,
         if (is_srv) {
                 seq->lss_dt_service =  ptlrpc_init_svc_conf(&seq_dt_conf,
                                                             seq_req_handle,
-                                                            LUSTRE_SEQ_NAME,
+                                                            LUSTRE_SEQ_NAME"_dt",
                                                             seq->lss_proc_entry,
                                                             NULL);
                 if (seq->lss_dt_service != NULL)
index 0140fb7..a18aa0e 100644 (file)
@@ -46,7 +46,7 @@ struct seq_thread_info {
         struct txn_param        sti_txn;
         struct req_capsule      sti_pill;
         struct seq_store_record sti_record;
-        int                     sti_rep_buf_size[2];
+        int                     sti_rep_buf_size[3];
 };
 
 extern struct lu_context_key seq_thread_key;
index 1283518..7b9a24a 100644 (file)
@@ -52,8 +52,10 @@ static int seq_client_rpc(struct lu_client_seq *seq,
                           __u32 opc, const char *opcname)
 {
         struct obd_export *exp = seq->lcs_exp;
-        int repsize = sizeof(struct lu_range);
-        int rc, reqsize = sizeof(__u32);
+        int repsize[2] = { sizeof(struct ptlrpc_body),
+                           sizeof(struct lu_range) };
+        int rc, reqsize[2] = { sizeof(struct ptlrpc_body),
+                               sizeof(__u32) };
         struct ptlrpc_request *req;
         struct req_capsule pill;
         struct lu_range *ran;
@@ -62,7 +64,7 @@ static int seq_client_rpc(struct lu_client_seq *seq,
 
         req = ptlrpc_prep_req(class_exp2cliimp(exp),
                              LUSTRE_MDS_VERSION,
-                              SEQ_QUERY, 1, &reqsize,
+                              SEQ_QUERY, 2, reqsize,
                               NULL);
         if (req == NULL)
                 RETURN(-ENOMEM);
@@ -74,7 +76,7 @@ static int seq_client_rpc(struct lu_client_seq *seq,
         op = req_capsule_client_get(&pill, &RMF_SEQ_OPC);
         *op = opc;
 
-        req->rq_replen = lustre_msg_size(1, &repsize);
+        ptlrpc_req_set_repsize(req, 2, repsize);
 
         if (seq->lcs_type == LUSTRE_SEQ_METADATA) {
                 req->rq_request_portal = (opc == SEQ_ALLOC_SUPER) ?
index fd0ee24..0434a1d 100644 (file)
@@ -94,9 +94,9 @@ struct fld_cache_info *fld_cache_init(int hash_size, int cache_size,
         for (i = 0; i < hash_size; i++)
                 INIT_HLIST_HEAD(&cache->fci_hash_table[i]);
 
-        CDEBUG(D_INFO|D_WARNING, "FLD cache - htable size: %d, "
-               "cache size: %d, cache threshold: %d\n",
-               hash_size, cache_size, cache_threshold);
+        CDEBUG(D_INFO|D_WARNING, "FLD cache - htable: %d, "
+               "size: %d, threshold: %d\n", hash_size,
+               cache_size, cache_threshold);
 
         RETURN(cache);
 }
index c579db5..3f8ab0b 100644 (file)
@@ -212,7 +212,7 @@ static int fld_req_handle(struct ptlrpc_request *req)
 
         fld_thread_info_init(req, info);
 
-        if (req->rq_reqmsg->opc == FLD_QUERY) {
+        if (lustre_msg_get_opc(req->rq_reqmsg) == FLD_QUERY) {
                 if (req->rq_export != NULL) {
                         site = req->rq_export->exp_obd->obd_lu_dev->ld_site;
                         LASSERT(site != NULL);
@@ -227,7 +227,8 @@ static int fld_req_handle(struct ptlrpc_request *req)
                         req->rq_status = -ENOTCONN;
                 }
         } else {
-                CERROR("Wrong opcode: %d\n", req->rq_reqmsg->opc);
+                CERROR("Wrong opcode: %d\n", 
+                       lustre_msg_get_opc(req->rq_reqmsg));
                 req->rq_status = -ENOTSUPP;
                 rc = ptlrpc_error(req);
                 GOTO(out_info, rc);
index d7ff46b..bbb2a7b 100644 (file)
@@ -54,7 +54,7 @@ extern struct lu_fld_hash fld_hash[];
 #define FLD_SERVICE_WATCHDOG_TIMEOUT (obd_timeout * 1000)
 struct fld_thread_info {
         struct req_capsule fti_pill;
-        int                fti_rep_buf_size[3];
+        int                fti_rep_buf_size[4];
         __u64              fti_key;
         __u64              fti_rec;
 };
index 038e9d5..3027f14 100644 (file)
@@ -349,19 +349,23 @@ EXPORT_SYMBOL(fld_client_fini);
 static int fld_client_rpc(struct obd_export *exp,
                           struct md_fld *mf, __u32 fld_op)
 {
-        int size[2] = {sizeof(__u32), sizeof(struct md_fld)}, rc;
-        int mf_size = sizeof(struct md_fld);
+        int reqsize[3] = { sizeof(struct ptlrpc_body),
+                           sizeof(__u32),
+                           sizeof(struct md_fld) };
+        int repsize[2] = { sizeof(struct ptlrpc_body),
+                           sizeof(struct md_fld) };
         struct ptlrpc_request *req;
         struct req_capsule pill;
         struct md_fld *pmf;
         __u32 *op;
+        int rc;
         ENTRY;
 
         LASSERT(exp != NULL);
 
         req = ptlrpc_prep_req(class_exp2cliimp(exp),
                               LUSTRE_MDS_VERSION, FLD_QUERY,
-                              2, size, NULL);
+                              3, reqsize, NULL);
         if (req == NULL)
                 RETURN(-ENOMEM);
 
@@ -375,7 +379,7 @@ static int fld_client_rpc(struct obd_export *exp,
         pmf = req_capsule_client_get(&pill, &RMF_FLD_MDFLD);
         *pmf = *mf;
 
-        req->rq_replen = lustre_msg_size(1, &mf_size);
+        ptlrpc_req_set_repsize(req, 2, repsize);
         req->rq_request_portal = FLD_REQUEST_PORTAL;
 
         rc = ptlrpc_queue_wait(req);
index bfe6275..aae009d 100644 (file)
@@ -7,8 +7,8 @@
 SUBDIRS = linux lustre
 
 EXTRA_DIST = ioctl.h liblustre.h lprocfs_status.h lustre_cfg.h         \
-            lustre_commit_confd.h lustre_debug.h lustre_dlm.h  \
-            lustre_export.h lustre_fsfilt.h lustre_ha.h        \
+            lustre_commit_confd.h lustre_debug.h lustre_disk.h \
+            lustre_dlm.h lustre_export.h lustre_fsfilt.h lustre_ha.h \
             lustre_handles.h lustre_import.h lustre_lib.h      \
             lustre_lite.h lustre_log.h lustre_mds.h lustre_mdc.h \
             lustre_net.h lustre_quota.h lustre_ucache.h lvfs.h \
index b48cac9..c8b0c07 100644 (file)
@@ -290,6 +290,8 @@ extern int ldlm_init(void);
 extern int osc_init(void);
 extern int lov_init(void);
 extern int mdc_init(void);
+extern int lmv_init(void);
+extern int mgc_init(void);
 extern int echo_client_init(void);
 
 
@@ -386,8 +388,6 @@ static inline int kmem_cache_destroy(kmem_cache_t *a)
         free(a);
         return 0;
 }
-#define kmem_cache_alloc(cache, prio) malloc(cache->size)
-#define kmem_cache_free(cache, obj) free(obj)
 
 #define PAGE_CACHE_SIZE  PAGE_SIZE
 #define PAGE_CACHE_SHIFT PAGE_SHIFT
@@ -563,6 +563,10 @@ static inline void init_MUTEX (struct semaphore *sem)
 {
         sema_init(sem, 1);
 }
+static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+{
+        sema_init(sem, 0);
+}
 
 #define init_mutex(s)   init_MUTEX(s)
 
@@ -667,6 +671,7 @@ static inline int schedule_timeout(signed long t)
                 _ret = tv.tv_sec;               \
         _ret;                                   \
 })
+#define get_jiffies_64()  (__u64)jiffies
 #define time_after(a, b) ((long)(b) - (long)(a) < 0)
 #define time_before(a, b) time_after(b,a)
 #define time_after_eq(a,b)      ((long)(a) - (long)(b) >= 0)
@@ -707,6 +712,7 @@ typedef struct { volatile int counter; } atomic_t;
 #define atomic_read(a) ((a)->counter)
 #define atomic_set(a,b) do {(a)->counter = b; } while (0)
 #define atomic_dec_and_test(a) ((--((a)->counter)) == 0)
+#define atomic_dec_and_lock(a,b) ((--((a)->counter)) == 0)
 #define atomic_inc(a)  (((a)->counter)++)
 #define atomic_dec(a)  do { (a)->counter--; } while (0)
 #define atomic_add(b,a)  do {(a)->counter += b;} while (0)
index e7caf8c..7ef8e06 100644 (file)
@@ -13,4 +13,4 @@ EXTRA_DIST = lprocfs_status.h lustre_acl.h lustre_debug.h lustre_lib.h lustre_dl
             lustre_handles.h lustre_net.h obd_class.h obd_support.h     \
             lustre_log.h lustre_compat25.h lustre_fsfilt.h lustre_mds.h \
             obd.h lvfs.h lvfs_linux.h lustre_lite.h lustre_quota.h      \
-            lustre_user.h lustre_types.h
+            lustre_user.h lustre_types.h lustre_patchless_compat.h lustre_intent.h
index ed0be5c..eb06205 100644 (file)
 
 /* ACL */
 #ifdef CONFIG_FS_POSIX_ACL
-#define LUSTRE_POSIX_ACL_MAX_ENTRIES    (32)
-#define LUSTRE_POSIX_ACL_MAX_SIZE       \
-        (sizeof(xattr_acl_header) + 32 * sizeof(xattr_acl_entry))
+#ifdef HAVE_XATTR_ACL
+#  define MDS_XATTR_NAME_ACL_ACCESS XATTR_NAME_ACL_ACCESS
+#  define mds_xattr_acl_size(entry) xattr_acl_size(entry)
+# else
+#  define MDS_XATTR_NAME_ACL_ACCESS POSIX_ACL_XATTR_ACCESS
+#  define mds_xattr_acl_size(entry) posix_acl_xattr_size(entry)
+# endif
+# define LUSTRE_POSIX_ACL_MAX_ENTRIES   (32)
+# define LUSTRE_POSIX_ACL_MAX_SIZE      \
+                (mds_xattr_acl_size(LUSTRE_POSIX_ACL_MAX_ENTRIES))
 #else
-#define LUSTRE_POSIX_ACL_MAX_SIZE       0
+# define LUSTRE_POSIX_ACL_MAX_SIZE      0
 #endif
 
-
 #endif
index 066cc20..1214b17 100644 (file)
@@ -31,6 +31,8 @@
 
 #include <libcfs/linux/portals_compat25.h>
 
+#include <linux/lustre_patchless_compat.h>
+
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
 struct ll_iattr_struct {
         struct iattr    iattr;
@@ -40,7 +42,30 @@ struct ll_iattr_struct {
 #define ll_iattr_struct iattr
 #endif
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
+#ifndef HAVE_SET_FS_PWD
+static inline void ll_set_fs_pwd(struct fs_struct *fs, struct vfsmount *mnt,
+                struct dentry *dentry)
+{
+        struct dentry *old_pwd;
+        struct vfsmount *old_pwdmnt;
+
+        write_lock(&fs->lock);
+        old_pwd = fs->pwd;
+        old_pwdmnt = fs->pwdmnt;
+        fs->pwdmnt = mntget(mnt);
+        fs->pwd = dget(dentry);
+        write_unlock(&fs->lock);
+
+        if (old_pwd) {
+                dput(old_pwd);
+                mntput(old_pwdmnt);
+        }
+}
+#else
+#define ll_set_fs_pwd set_fs_pwd
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
 #define UNLOCK_INODE_MUTEX(inode) do {mutex_unlock(&(inode)->i_mutex); } while(0)
 #define LOCK_INODE_MUTEX(inode) do {mutex_lock(&(inode)->i_mutex); } while(0)
 #define TRYLOCK_INODE_MUTEX(inode) mutex_trylock(&(inode)->i_mutex)
@@ -52,6 +77,15 @@ struct ll_iattr_struct {
 #define TRYLOCK_INODE_MUTEX(inode) (!down_trylock(&(inode)->i_sem))
 #endif
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
+#define UNLOCK_DQONOFF_MUTEX(dqopt) do {mutex_unlock(&(dqopt)->dqonoff_mutex); } while(0)
+#define LOCK_DQONOFF_MUTEX(dqopt) do {mutex_lock(&(dqopt)->dqonoff_mutex); } while(0)
+#else
+#define UNLOCK_DQONOFF_MUTEX(dqopt) do {up(&(dqopt)->dqonoff_sem); } while(0)
+#define LOCK_DQONOFF_MUTEX(dqopt) do {down(&(dqopt)->dqonoff_sem); } while(0)
+#endif
+
+
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4)
 #define NGROUPS_SMALL           NGROUPS
 #define NGROUPS_PER_BLOCK       ((int)(EXEC_PAGESIZE / sizeof(gid_t)))
@@ -177,6 +211,9 @@ static inline int cleanup_group_info(void)
 #define unlock_24kernel()       unlock_kernel()
 #define ll_kernel_locked()      (current->lock_depth >= 0)
 
+/* 2.4 kernels have HZ=100 on i386/x86_64, this should be reasonably safe */
+#define get_jiffies_64()        (__u64)jiffies
+
 #ifdef HAVE_MM_INLINE
 #include <linux/mm_inline.h>
 #endif
@@ -242,7 +279,7 @@ typedef long sector_t;
 static inline void clear_page_dirty(struct page *page)
 {
         if (PageDirty(page))
-                ClearPageDirty(page); 
+                ClearPageDirty(page);
 }
 
 static inline int clear_page_dirty_for_io(struct page *page)
@@ -326,12 +363,10 @@ static inline int page_mapped(struct page *page)
 }
 #endif /* !HAVE_PAGE_MAPPED */
 
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16))
 static inline void touch_atime(struct vfsmount *mnt, struct dentry *dentry)
 {
         update_atime(dentry->d_inode);
 }
-#endif
 
 static inline void file_accessed(struct file *file)
 {
index a96c161..a19f31a 100644 (file)
 
 #ifdef __KERNEL__
 # include <linux/proc_fs.h>
+# ifdef HAVE_BIT_SPINLOCK_H
+#  include <asm/processor.h>
+#  include <linux/bit_spinlock.h>
+# endif
 #endif
 
 #endif
index 84e9af9..fb09ce3 100644 (file)
@@ -154,16 +154,19 @@ static inline __u8 *fsfilt_uuid(struct obd_device *obd, struct super_block *sb)
 #define FSFILT_OP_JOIN          11
 #define FSFILT_OP_NOOP          15
 
-#define fsfilt_check_slow(start, timeout, msg)                          \
+#define fsfilt_check_slow(obd, start, timeout, msg)                     \
 do {                                                                    \
         if (time_before(jiffies, start + 15 * HZ))                      \
                 break;                                                  \
         else if (time_before(jiffies, start + 30 * HZ))                 \
-                CDEBUG(D_VFSTRACE,"slow %s %lus\n", msg,(jiffies-start)/HZ);\
+                CDEBUG(D_VFSTRACE, "%s: slow %s %lus\n", obd->obd_name, \
+                       msg, (jiffies-start) / HZ);                      \
         else if (time_before(jiffies, start + timeout / 2 * HZ))        \
-                CWARN("slow %s %lus\n", msg, (jiffies - start) / HZ);   \
+                CWARN("%s: slow %s %lus\n", obd->obd_name, msg,         \
+                      (jiffies - start) / HZ);                          \
         else                                                            \
-                CERROR("slow %s %lus\n", msg, (jiffies - start) / HZ);  \
+                CERROR("%s: slow %s %lus\n", obd->obd_name, msg,        \
+                       (jiffies - start) / HZ);                         \
 } while (0)
 
 static inline void *fsfilt_start_log(struct obd_device *obd,
@@ -189,7 +192,7 @@ static inline void *fsfilt_start_log(struct obd_device *obd,
                         LBUG();
                 }
         }
-        fsfilt_check_slow(now, obd_timeout, "journal start");
+        fsfilt_check_slow(obd, now, obd_timeout, "journal start");
         return handle;
 }
 
@@ -224,7 +227,7 @@ static inline void *fsfilt_brw_start_log(struct obd_device *obd, int objcount,
                         LBUG();
                 }
         }
-        fsfilt_check_slow(now, obd_timeout, "journal start");
+        fsfilt_check_slow(obd, now, obd_timeout, "journal start");
 
         return handle;
 }
@@ -244,7 +247,7 @@ static inline int fsfilt_commit(struct obd_device *obd, struct inode *inode,
         int rc = obd->obd_fsops->fs_commit(inode, handle, force_sync);
         CDEBUG(D_INFO, "committing handle %p\n", handle);
 
-        fsfilt_check_slow(now, obd_timeout, "journal start");
+        fsfilt_check_slow(obd, now, obd_timeout, "journal start");
 
         return rc;
 }
@@ -257,7 +260,7 @@ static inline int fsfilt_commit_async(struct obd_device *obd,
         int rc = obd->obd_fsops->fs_commit_async(inode, handle, wait_handle);
 
         CDEBUG(D_INFO, "committing handle %p (async)\n", *wait_handle);
-        fsfilt_check_slow(now, obd_timeout, "journal start");
+        fsfilt_check_slow(obd, now, obd_timeout, "journal start");
 
         return rc;
 }
@@ -268,7 +271,7 @@ static inline int fsfilt_commit_wait(struct obd_device *obd,
         unsigned long now = jiffies;
         int rc = obd->obd_fsops->fs_commit_wait(inode, handle);
         CDEBUG(D_INFO, "waiting for completion %p\n", handle);
-        fsfilt_check_slow(now, obd_timeout, "journal start");
+        fsfilt_check_slow(obd, now, obd_timeout, "journal start");
         return rc;
 }
 
@@ -278,7 +281,7 @@ static inline int fsfilt_setattr(struct obd_device *obd, struct dentry *dentry,
         unsigned long now = jiffies;
         int rc;
         rc = obd->obd_fsops->fs_setattr(dentry, handle, iattr, do_trunc);
-        fsfilt_check_slow(now, obd_timeout, "setattr");
+        fsfilt_check_slow(obd, now, obd_timeout, "setattr");
         return rc;
 }
 
@@ -329,15 +332,16 @@ static inline int fsfilt_add_journal_cb(struct obd_device *obd, __u64 last_rcvd,
 
 /* very similar to obd_statfs(), but caller already holds obd_osfs_lock */
 static inline int fsfilt_statfs(struct obd_device *obd, struct super_block *sb,
-                                unsigned long max_age)
+                                __u64 max_age)
 {
         int rc = 0;
 
-        CDEBUG(D_SUPER, "osfs %lu, max_age %lu\n", obd->obd_osfs_age, max_age);
-        if (time_before(obd->obd_osfs_age, max_age)) {
+        CDEBUG(D_SUPER, "osfs "LPU64", max_age "LPU64"\n",
+                obd->obd_osfs_age, max_age);
+        if (cfs_time_before_64(obd->obd_osfs_age, max_age)) {
                 rc = obd->obd_fsops->fs_statfs(sb, &obd->obd_osfs);
                 if (rc == 0) /* N.B. statfs can't really fail */
-                        obd->obd_osfs_age = jiffies;
+                        obd->obd_osfs_age = cfs_time_current_64();
         } else {
                 CDEBUG(D_SUPER, "using cached obd_statfs data\n");
         }
diff --git a/lustre/include/linux/lustre_intent.h b/lustre/include/linux/lustre_intent.h
new file mode 100644 (file)
index 0000000..3d8cb2c
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef LUSTRE_INTENT_H
+#define LUSTRE_INTENT_H
+
+#include <linux/lustre_version.h>
+
+#ifndef LUSTRE_KERNEL_VERSION
+#define IT_OPEN     (1)
+#define IT_CREAT    (1<<1)
+#define IT_READDIR  (1<<2)
+#define IT_GETATTR  (1<<3)
+#define IT_LOOKUP   (1<<4)
+#define IT_UNLINK   (1<<5)
+#define IT_TRUNC    (1<<6)
+#define IT_GETXATTR (1<<7)
+
+struct lustre_intent_data {
+        int       it_disposition;
+        int       it_status;
+        __u64     it_lock_handle;
+        void     *it_data;
+        int       it_lock_mode;
+};
+
+struct lookup_intent {
+        int     it_op;
+        int     it_flags;
+       int     it_create_mode;
+        union {
+                struct lustre_intent_data lustre;
+        } d;
+};
+
+
+#endif
+#endif
index 17f4546..c2d9311 100644 (file)
 
 #include <linux/fs.h>
 #include <linux/dcache.h>
-#include <linux/jbd.h>
-#include <linux/ext3_fs.h>
 #include <linux/proc_fs.h>
 
 #include <obd_class.h>
 #include <lustre_net.h>
-#include <lustre_mds.h>
 #include <lustre_ha.h>
 
 #include <linux/rbtree.h>
index b305234..c418603 100644 (file)
 #ifdef __KERNEL__
 # include <linux/fs.h>
 # include <linux/dcache.h>
-# include <linux/xattr_acl.h>
+# ifdef CONFIG_FS_POSIX_ACL
+#  ifdef HAVE_XATTR_ACL
+#   include <linux/xattr_acl.h>
+#  endif 
+#  ifdef HAVE_LINUX_POSIX_ACL_XATTR_H
+#   include <linux/posix_acl_xattr.h>
+#  endif
+# endif
+# ifndef LUSTRE_KERNEL_VERSION
+#  include <linux/lustre_intent.h>
+# endif
 #endif
 
 struct mds_obd;
diff --git a/lustre/include/linux/lustre_patchless_compat.h b/lustre/include/linux/lustre_patchless_compat.h
new file mode 100644 (file)
index 0000000..63cad57
--- /dev/null
@@ -0,0 +1,78 @@
+#ifndef LUSTRE_PATCHLESS_COMPAT_H
+#define LUSTRE_PATCHLESS_COMPAT_H
+
+#include <linux/lustre_version.h>
+#ifndef LUSTRE_KERNEL_VERSION
+#include <linux/fs.h>
+
+#ifndef HAVE_TRUNCATE_COMPLETE_PAGE
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/hash.h>
+
+/* XXX copy & paste from 2.6.15 kernel */
+static inline void ll_remove_from_page_cache(struct page *page)
+{
+        struct address_space *mapping = page->mapping;
+
+        BUG_ON(!PageLocked(page));
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+        write_lock_irq(&mapping->tree_lock);
+#else
+       spin_lock_irq(&mapping->tree_lock);
+#endif
+        radix_tree_delete(&mapping->page_tree, page->index);
+        page->mapping = NULL;
+        mapping->nrpages--;
+        atomic_add(-1, &nr_pagecache); // XXX pagecache_acct(-1);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+        write_unlock_irq(&mapping->tree_lock);
+#else
+       spin_unlock_irq(&mapping->tree_lock);
+#endif
+}
+
+static inline void
+truncate_complete_page(struct address_space *mapping, struct page *page)
+{
+        if (page->mapping != mapping)
+                return;
+
+        if (PagePrivate(page))
+                page->mapping->a_ops->invalidatepage(page, 0);
+
+        clear_page_dirty(page);
+        ClearPageUptodate(page);
+        ClearPageMappedToDisk(page);
+        ll_remove_from_page_cache(page);
+        page_cache_release(page);       /* pagecache ref */
+}
+#endif
+
+/* megahack */
+static inline void d_rehash_cond(struct dentry * entry, int lock)
+{
+       if (!lock)
+               spin_unlock(&dcache_lock);
+
+       d_rehash(entry);
+
+       if (!lock)
+               spin_lock(&dcache_lock);
+}
+
+#define __d_rehash(dentry, lock) d_rehash_cond(dentry, lock)
+       
+#define LUSTRE_PATCHLESS
+
+#ifndef ATTR_FROM_OPEN
+#define ATTR_FROM_OPEN 0
+#endif
+#ifndef ATTR_RAW
+#define ATTR_RAW 0
+#endif
+
+#endif /* LUSTRE_KERNEL_VERSION */
+
+#endif
index 8f724c8..351002f 100644 (file)
 #endif
 #endif
 
-#if (!defined(_LINUX_TYPES_H) && !defined(_BLKID_TYPES_H) && \
-     !defined(_EXT2_TYPES_H) && !defined(_I386_TYPES_H) && \
-     !defined(_X86_64_TYPES_H))
+#if !defined(_LINUX_TYPES_H) && !defined(_BLKID_TYPES_H) && \
+        !defined(_EXT2_TYPES_H) && !defined(_I386_TYPES_H) && \
+        !defined(_ASM_IA64_TYPES_H) && !defined(_X86_64_TYPES_H) && \
+        !defined(_PPC_TYPES_H) && !defined(_PPC64_TYPES_H)
+        /* yuck, would be nicer with _ASM_TYPES_H */
 
 typedef unsigned short umode_t;
 /*
index 7bbcca7..668d122 100644 (file)
 #if defined(__x86_64__) || defined(__ia64__) || defined(__ppc64__) || \
     defined(__craynv)
 typedef struct stat     lstat_t;
+#define lstat_f         lstat
 #define HAVE_LOV_USER_MDS_DATA
 #elif defined(__USE_LARGEFILE64) || defined(__KERNEL__)
 typedef struct stat64   lstat_t;
+#define lstat_f         lstat64
 #define HAVE_LOV_USER_MDS_DATA
 #endif
 
index 0ea6104..5c466ce 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/fs.h>
+#include <linux/namei.h>
 #include <linux/sched.h>
 
 #include <lvfs.h>
index c6b8005..c34ea2d 100644 (file)
@@ -248,8 +248,14 @@ extern int lprocfs_rd_filegroups(char *page, char **start, off_t off,
 
 extern int lprocfs_write_helper(const char *buffer, unsigned long count,
                                 int *val);
+extern int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
+                                     int *val, int mult);
+extern int lprocfs_read_frac_helper(char *buffer, unsigned long count, 
+                                    long val, int mult);
 extern int lprocfs_write_u64_helper(const char *buffer, unsigned long count,
                                     __u64 *val);
+extern int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
+                                         __u64 *val, int mult);
 int lprocfs_obd_seq_create(struct obd_device *dev, char *name, mode_t mode,
                            struct file_operations *seq_fops, void *data);
 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value);
index 08f8786..a828b35 100644 (file)
 typedef void (*llapi_cb_t)(char *obd_type_name, char *obd_name, char *obd_uuid, void *args);
 
 /* liblustreapi.c */
-extern int llapi_file_create(char *name, long stripe_size, int stripe_offset,
-                             int stripe_count, int stripe_pattern);
-extern int llapi_file_get_stripe(char *path, struct lov_user_md *lum);
-extern int llapi_find(char *path, struct obd_uuid *obduuid, int recursive,
-                      int verbose, int quiet);
+extern int llapi_file_create(const char *name, long stripe_size,
+                             int stripe_offset, int stripe_count,
+                             int stripe_pattern);
+extern int llapi_file_get_stripe(const char *path, struct lov_user_md *lum);
+#define HAVE_LLAPI_FILE_LOOKUP
+extern int llapi_file_lookup(int dirfd, const char *name);
+struct find_param {
+        unsigned int maxdepth;
+        time_t  atime;
+        time_t  mtime;
+        time_t  ctime;
+        int     asign;
+        int     csign;
+        int     msign;
+
+        int zeroend:1, recursive:1, got_uuids:1, obds_printed:1;
+
+        int     verbose;
+        int     quiet;
+
+        char   *print_fmt;
+
+        struct  obd_uuid        *obduuid;
+        int     obdindex;
+
+        int     lumlen;
+        struct  lov_user_mds_data *lmd;
+
+        /* In-precess parameters. */
+        unsigned int depth;
+        dev_t   st_dev;
+};
+
+extern int llapi_getstripe(char *path, struct find_param *param);
+extern int llapi_find(char *path, struct find_param *param);
+
 extern int llapi_obd_statfs(char *path, __u32 type, __u32 index,
                      struct obd_statfs *stat_buf,
                      struct obd_uuid *uuid_buf);
index 8b0b19d..325811b 100644 (file)
@@ -33,6 +33,8 @@
 #ifndef _LUSTRE_IDL_H_
 #define _LUSTRE_IDL_H_
 
+#include <libcfs/kp30.h>
+
 #if defined(__linux__)
 #include <linux/lustre_types.h>
 #elif defined(__APPLE__)
 #define PTL_RPC_MSG_ERR     4712
 #define PTL_RPC_MSG_REPLY   4713
 
-#define PTLRPC_MSG_MAGIC    0x0BD00BD0
+/* DON'T use swabbed values of MAGIC as magic! */
+#define LUSTRE_MSG_MAGIC_V1 0x0BD00BD0
+#define LUSTRE_MSG_MAGIC_V2 0x0BD00BD2
 
+#define LUSTRE_MSG_MAGIC_V1_SWABBED 0xD00BD00B
+#define LUSTRE_MSG_MAGIC_V2_SWABBED 0xD20BD00B
+
+#define LUSTRE_MSG_MAGIC LUSTRE_MSG_MAGIC_V2
 
 #define PTLRPC_MSG_VERSION  0x00000003
 #define LUSTRE_VERSION_MASK 0xffff0000
@@ -321,22 +329,71 @@ static inline void lustre_handle_copy(struct lustre_handle *tgt,
 
 /* we depend on this structure to be 8-byte aligned */
 /* this type is only endian-adjusted in lustre_unpack_msg() */
-struct lustre_msg {
-        struct lustre_handle handle;
-        __u32 magic;
-        __u32 type;
-        __u32 version;
-        __u32 opc;
-        __u64 last_xid;
-        __u64 last_committed;
-        __u64 transno;
-        __u32 status;
-        __u32 flags;
-        __u32 conn_cnt;
-        __u32 bufcount;
-        __u32 buflens[0];
+struct lustre_msg_v1 {
+        struct lustre_handle lm_handle;
+        __u32 lm_magic;
+        __u32 lm_type;
+        __u32 lm_version;
+        __u32 lm_opc;
+        __u64 lm_last_xid;
+        __u64 lm_last_committed;
+        __u64 lm_transno;
+        __u32 lm_status;
+        __u32 lm_flags;
+        __u32 lm_conn_cnt;
+        __u32 lm_bufcount;
+        __u32 lm_buflens[0];
 };
 
+#define lustre_msg lustre_msg_v2
+/* we depend on this structure to be 8-byte aligned */
+/* this type is only endian-adjusted in lustre_unpack_msg() */
+struct lustre_msg_v2 {
+        __u32 lm_bufcount;
+        __u32 lm_secflvr;
+        __u32 lm_magic;
+        __u32 lm_repsize;
+        __u32 lm_buflens[0];
+};
+
+/* without security, ptlrpc_body is put in the first buffer. */
+struct ptlrpc_body {
+        struct lustre_handle pb_handle;
+        __u32 pb_type;
+        __u32 pb_version;
+        __u32 pb_opc;
+        __u32 pb_status;
+        __u64 pb_last_xid;
+        __u64 pb_last_committed;
+        __u64 pb_transno;
+        __u32 pb_flags;
+        __u32 pb_op_flags;
+        __u32 pb_conn_cnt;
+        __u32 pb_paddings[3];
+};
+
+extern void lustre_swab_ptlrpc_body(struct ptlrpc_body *pb);
+
+/* message body offset for lustre_msg_v2 */
+/* ptlrpc body offset in all request/reply messages */
+#define MSG_PTLRPC_BODY_OFF             0
+
+/* normal request/reply message record offset */
+#define REQ_REC_OFF                     1
+#define REPLY_REC_OFF                   1
+
+/* ldlm request message body offset */
+#define DLM_LOCKREQ_OFF                 1 /* lockreq offset */
+#define DLM_REQ_REC_OFF                 2 /* normal dlm request record offset */
+
+/* ldlm intent lock message body offset */
+#define DLM_INTENT_IT_OFF               2 /* intent lock it offset */
+#define DLM_INTENT_REC_OFF              3 /* intent lock record offset */
+
+/* ldlm reply message body offset */
+#define DLM_LOCKREPLY_OFF               1 /* lockrep offset */
+#define DLM_REPLY_REC_OFF               2 /* reply record offset */
+
 /* Flags that are operation-specific go in the top 16 bits. */
 #define MSG_OP_FLAG_MASK   0xffff0000
 #define MSG_OP_FLAG_SHIFT  16
@@ -347,43 +404,6 @@ struct lustre_msg {
 #define MSG_RESENT             2
 #define MSG_REPLAY             4
 
-static inline int lustre_msg_get_flags(struct lustre_msg *msg)
-{
-        return (msg->flags & MSG_GEN_FLAG_MASK);
-}
-
-static inline void lustre_msg_add_flags(struct lustre_msg *msg, int flags)
-{
-        msg->flags |= MSG_GEN_FLAG_MASK & flags;
-}
-
-static inline void lustre_msg_set_flags(struct lustre_msg *msg, int flags)
-{
-        msg->flags &= ~MSG_GEN_FLAG_MASK;
-        lustre_msg_add_flags(msg, flags);
-}
-
-static inline void lustre_msg_clear_flags(struct lustre_msg *msg, int flags)
-{
-        msg->flags &= ~(MSG_GEN_FLAG_MASK & flags);
-}
-
-static inline int lustre_msg_get_op_flags(struct lustre_msg *msg)
-{
-        return (msg->flags >> MSG_OP_FLAG_SHIFT);
-}
-
-static inline void lustre_msg_add_op_flags(struct lustre_msg *msg, int flags)
-{
-        msg->flags |= ((flags & MSG_GEN_FLAG_MASK) << MSG_OP_FLAG_SHIFT);
-}
-
-static inline void lustre_msg_set_op_flags(struct lustre_msg *msg, int flags)
-{
-        msg->flags &= ~MSG_OP_FLAG_MASK;
-        lustre_msg_add_op_flags(msg, flags);
-}
-
 /*
  * Flags for all connect opcodes (MDS_CONNECT, OST_CONNECT)
  */
@@ -395,6 +415,7 @@ static inline void lustre_msg_set_op_flags(struct lustre_msg *msg, int flags)
 #define MSG_CONNECT_LIBCLIENT   0x10
 #define MSG_CONNECT_INITIAL     0x20
 #define MSG_CONNECT_ASYNC       0x40
+#define MSG_CONNECT_NEXT_VER    0x80 /* use next version of lustre_msg */
 
 /* Connect flags */
 #define OBD_CONNECT_RDONLY       0x1ULL /* client allowed read-only access */
@@ -411,18 +432,22 @@ static inline void lustre_msg_set_op_flags(struct lustre_msg *msg, int flags)
 #define OBD_CONNECT_IBITS     0x1000ULL /* support for inodebits locks */
 #define OBD_CONNECT_JOIN      0x2000ULL /* files can be concatenated */
 #define OBD_CONNECT_REAL      0x4000ULL
-#define OBD_CONNECT_NODEVOH   0x8000ULL /* No open handle for special nodes */
-#define OBD_CONNECT_EMPTY 0x80000000ULL /* fake: these are empty connect flags*/
+#define OBD_CONNECT_ATTRFID   0x8000ULL /* Server supports GetAttr By Fid */
+#define OBD_CONNECT_NODEVOH   0x10000ULL /* No open handle for special nodes */
+#define OBD_CONNECT_LCL_CLIENT 0x20000ULL /* local 1.6 client */
+#define OBD_CONNECT_RMT_CLIENT 0x40000ULL /* Remote client */
+#define OBD_CONNECT_BRW_SIZE    0x80000ULL  /* Maximum pages per RPC */
 
 /* also update obd_connect_names[] for lprocfs_rd_connect_flags() */
 
 #define MDS_CONNECT_SUPPORTED  (OBD_CONNECT_RDONLY | OBD_CONNECT_VERSION | \
                                 OBD_CONNECT_ACL | OBD_CONNECT_XATTR | \
                                 OBD_CONNECT_IBITS | OBD_CONNECT_JOIN | \
-                                OBD_CONNECT_NODEVOH)
+                                OBD_CONNECT_NODEVOH | OBD_CONNECT_ATTRFID)
 #define OST_CONNECT_SUPPORTED  (OBD_CONNECT_SRVLOCK | OBD_CONNECT_GRANT | \
                                 OBD_CONNECT_REQPORTAL | OBD_CONNECT_VERSION | \
-                                OBD_CONNECT_TRUNCLOCK | OBD_CONNECT_INDEX)
+                                OBD_CONNECT_TRUNCLOCK | OBD_CONNECT_INDEX | \
+                                OBD_CONNECT_BRW_SIZE)
 #define ECHO_CONNECT_SUPPORTED (0)
 #define MGS_CONNECT_SUPPORTED  (OBD_CONNECT_VERSION)
 
@@ -446,13 +471,14 @@ struct obd_connect_data {
         __u32 ocd_version;              /* lustre release version number */
         __u32 ocd_grant;                /* initial cache grant amount (bytes) */
         __u32 ocd_index;                /* LOV index to connect to */
-        __u32 ocd_unused;
+        __u32 ocd_brw_size;             /* Maximum BRW size in bytes */
         __u64 ocd_ibits_known;          /* inode bits this client understands */
+        __u32 ocd_nllu;                 /* non-local-lustre-user */
+        __u32 ocd_nllg;                 /* non-local-lustre-group */
+        __u64 padding1;                 /* also fix lustre_swab_connect */
         __u64 padding2;                 /* also fix lustre_swab_connect */
         __u64 padding3;                 /* also fix lustre_swab_connect */
         __u64 padding4;                 /* also fix lustre_swab_connect */
-        __u64 padding5;                 /* also fix lustre_swab_connect */
-        __u64 padding6;                 /* also fix lustre_swab_connect */
 };
 
 extern void lustre_swab_connect(struct obd_connect_data *ocd);
@@ -550,7 +576,8 @@ struct obdo {
         __u32                   o_mds;
         __u32                   o_stripe_idx;   /* holds stripe idx */
         __u32                   o_padding_1;
-        char                    o_inline[OBD_INLINESZ]; /* fid in ost writes */
+        char                    o_inline[OBD_INLINESZ];
+                                /* lustre_handle + llog_cookie */
 };
 
 #define o_dirty   o_blocks
@@ -766,14 +793,6 @@ extern void lustre_swab_ost_lvb(struct ost_lvb *);
  *   MDS REQ RECORDS
  */
 
-/* FIXME: this is different from HEAD, adjust it
- * while merge GSS */
-#define MDS_REQ_REC_OFF                 0
-
-#define MDS_REQ_INTENT_LOCKREQ_OFF      0
-#define MDS_REQ_INTENT_IT_OFF           1
-#define MDS_REQ_INTENT_REC_OFF          2
-
 /* opcodes */
 typedef enum {
         MDS_GETATTR      = 33,
@@ -816,13 +835,15 @@ typedef enum {
 } mds_reint_t, mdt_reint_t;
 
 /* the disposition of the intent outlines what was executed */
-#define DISP_IT_EXECD     0x01
-#define DISP_LOOKUP_EXECD 0x02
-#define DISP_LOOKUP_NEG   0x04
-#define DISP_LOOKUP_POS   0x08
-#define DISP_OPEN_CREATE  0x10
-#define DISP_OPEN_OPEN    0x20
-#define DISP_ENQ_COMPLETE 0x40
+#define DISP_IT_EXECD        0x00000001
+#define DISP_LOOKUP_EXECD    0x00000002
+#define DISP_LOOKUP_NEG      0x00000004
+#define DISP_LOOKUP_POS      0x00000008
+#define DISP_OPEN_CREATE     0x00000010
+#define DISP_OPEN_OPEN       0x00000020
+#define DISP_ENQ_COMPLETE    0x00400000
+#define DISP_ENQ_OPEN_REF    0x00800000
+#define DISP_ENQ_CREATE_REF  0x01000000
 
 /* INODE LOCK PARTS */
 #define MDS_INODELOCK_LOOKUP 0x000001       /* dentry, mode, owner, group */
@@ -861,6 +882,48 @@ struct mds_status_req {
 extern void lustre_swab_mds_status_req (struct mds_status_req *r);
 
 #define MDS_BFLAG_UNCOMMITTED_WRITES   0x1
+#define MDS_BFLAG_EXT_FLAGS     0x80000000 /* == EXT3_RESERVED_FL */
+
+/* these should be identical to their EXT3_*_FL counterparts, and are
+ * redefined here only to avoid dragging in ext3_fs.h */
+#define MDS_SYNC_FL             0x00000008 /* Synchronous updates */
+#define MDS_IMMUTABLE_FL        0x00000010 /* Immutable file */
+#define MDS_APPEND_FL           0x00000020 /* writes to file may only append */
+#define MDS_NOATIME_FL          0x00000080 /* do not update atime */
+#define MDS_DIRSYNC_FL          0x00010000 /* dirsync behaviour (dir only) */
+
+#ifdef __KERNEL__
+/* If MDS_BFLAG_IOC_FLAGS is set it means we requested EXT3_*_FL inode flags
+ * and we need to decode these into local S_* flags in the inode.  Otherwise
+ * we pass flags straight through (see bug 9486). */
+static inline int ll_ext_to_inode_flags(int flags)
+{
+        return (flags & MDS_BFLAG_EXT_FLAGS) ?
+               (((flags & MDS_SYNC_FL)      ? S_SYNC      : 0) |
+                ((flags & MDS_NOATIME_FL)   ? S_NOATIME   : 0) |
+                ((flags & MDS_APPEND_FL)    ? S_APPEND    : 0) |
+#if defined(S_DIRSYNC)
+                ((flags & MDS_DIRSYNC_FL)   ? S_DIRSYNC   : 0) |
+#endif
+                ((flags & MDS_IMMUTABLE_FL) ? S_IMMUTABLE : 0)) :
+               (flags & ~MDS_BFLAG_EXT_FLAGS);
+}
+
+/* If MDS_BFLAG_EXT_FLAGS is set it means we requested EXT3_*_FL inode flags
+ * and we pass these straight through.  Otherwise we need to convert from
+ * S_* flags to their EXT3_*_FL equivalents (see bug 9486). */
+static inline int ll_inode_to_ext_flags(int oflags, int iflags)
+{
+        return (oflags & MDS_BFLAG_EXT_FLAGS) ? (oflags & ~MDS_BFLAG_EXT_FLAGS):
+               (((iflags & S_SYNC)      ? MDS_SYNC_FL      : 0) |
+                ((iflags & S_NOATIME)   ? MDS_NOATIME_FL   : 0) |
+                ((iflags & S_APPEND)    ? MDS_APPEND_FL    : 0) |
+#if defined(S_DIRSYNC)
+                ((iflags & S_DIRSYNC)   ? MDS_DIRSYNC_FL   : 0) |
+#endif
+                ((iflags & S_IMMUTABLE) ? MDS_IMMUTABLE_FL : 0));
+}
+#endif
 
 struct mdt_body {
         struct lu_fid  fid1;
@@ -1015,6 +1078,7 @@ extern void lustre_swab_mdt_rec_setattr (struct mdt_rec_setattr *sa);
 #define MDS_OPEN_DELAY_CREATE  0100000000 /* delay initial object create */
 #define MDS_OPEN_OWNEROVERRIDE 0200000000 /* NFSD rw-reopen ro file for owner */
 #define MDS_OPEN_JOIN_FILE     0400000000 /* open for join file*/
+#define MDS_OPEN_LOCK         04000000000 /* This open requires open lock */
 #define MDS_OPEN_HAS_EA      010000000000 /* specify object create pattern */
 #define MDS_OPEN_HAS_OBJS    020000000000 /* Just set the EA the obj exist */
 
@@ -1230,14 +1294,15 @@ enum seq_op {
 
 #define LOV_DESC_MAGIC 0xB0CCDE5C
 
+/* LOV settings descriptor (should only contain static info) */
 struct lov_desc {
         __u32 ld_tgt_count;                /* how many OBD's */
         __u32 ld_active_tgt_count;         /* how many active */
         __u32 ld_default_stripe_count;     /* how many objects are used */
-        __u32 ld_pattern;                  /* PATTERN_RAID0, PATTERN_RAID1 */
+        __u32 ld_pattern;                  /* default PATTERN_RAID0 */
         __u64 ld_default_stripe_size;      /* in bytes */
         __u64 ld_default_stripe_offset;    /* in bytes */
-        __u32 ld_qos_threshold;            /* in MB */
+        __u32 ld_padding_0;                /* unused */
         __u32 ld_qos_maxage;               /* in second */
         __u32 ld_padding_1;                /* also fix lustre_swab_lov_desc */
         __u32 ld_padding_2;                /* also fix lustre_swab_lov_desc */
@@ -1382,24 +1447,20 @@ typedef enum {
         MGS_LAST_OPC
 } mgs_cmd_t;
 
+/* We pass this info to the MGS so it can write config logs */
 #define MTI_NAME_MAXLEN 64
-#define MTI_UUID_MAXLEN MTI_NAME_MAXLEN + 5
-/* each host can have multiple nids, and multiple failover hosts, and I don't
-   want to run out of room... */
-#define MTI_NIDS_MAX 64 /* match lustre_disk.h */
-
+#define MTI_NIDS_MAX 32
 struct mgs_target_info {
+        __u32            mti_lustre_ver;
+        __u32            mti_stripe_index;
+        __u32            mti_config_ver;
+        __u32            mti_flags;
+        __u32            mti_nid_count;
+        __u32            padding;                    /* 64 bit align */
         char             mti_fsname[MTI_NAME_MAXLEN];
         char             mti_svname[MTI_NAME_MAXLEN];
         char             mti_uuid[sizeof(struct obd_uuid)];
         lnet_nid_t       mti_nids[MTI_NIDS_MAX];     /* host nids */
-        lnet_nid_t       mti_failnids[MTI_NIDS_MAX]; /* partner nids */
-        __u16            mti_failnodes[8];  /* last nid index of each partner */
-        __u32            mti_stripe_index;
-        __u32            mti_nid_count;
-        __u32            mti_failnid_count;
-        __u32            mti_config_ver;
-        __u32            mti_flags;
         char             mti_params[2048];
 };
 
@@ -1412,12 +1473,14 @@ extern void lustre_swab_mgs_target_info(struct mgs_target_info *oinfo);
 #define CM_START_SKIP (CM_START | CM_SKIP)
 
 struct cfg_marker {
-        __u32             cm_step;  /* aka config version */
+        __u32             cm_step;       /* aka config version */
         __u32             cm_flags;
+        __u32             cm_vers;       /* lustre release version number */
+        __u32             padding;       /* 64 bit align */
         time_t            cm_createtime; /*when this record was first created */
         time_t            cm_canceltime; /*when this record is no longer valid*/
-        char              cm_svname[16];
-        char              cm_comment[40];
+        char              cm_svname[MTI_NAME_MAXLEN];
+        char              cm_comment[MTI_NAME_MAXLEN];
 };
 
 /*
@@ -1690,7 +1753,7 @@ extern void lustre_swab_llog_rec(struct llog_rec_hdr  *rec,
 struct lustre_cfg;
 extern void lustre_swab_lustre_cfg(struct lustre_cfg *lcfg);
 
-/* qutoa */
+/* quota */
 struct qunit_data {
         __u32 qd_id;    /* ID appiles to (uid, gid) */
         __u32 qd_type;  /* Quota type (USRQUOTA, GRPQUOTA) */
index 4afa860..8e748fc 100644 (file)
 
 struct obd_statfs;
 
+/* 
+ * The ioctl naming rules:
+ * LL_*     - works on the currently opened filehandle instead of parent dir
+ * *_OBD_*  - gets data for both OSC or MDC (LOV, LMV indirectly)
+ * *_MDC_*  - gets/sets data related to MDC
+ * *_LOV_*  - gets/sets data related to OSC/LOV
+ * *FILE*   - called on parent dir and passes in a filename
+ * *STRIPE* - set/get lov_user_md
+ * *INFO    - set/get lov_user_mds_data
+ */
 #define LL_IOC_GETFLAGS                 _IOR ('f', 151, long)
 #define LL_IOC_SETFLAGS                 _IOW ('f', 152, long)
 #define LL_IOC_CLRFLAGS                 _IOW ('f', 153, long)
@@ -46,15 +56,21 @@ struct obd_statfs;
 #define LL_IOC_POLL_QUOTACHECK          _IOR ('f', 161, struct if_quotacheck *)
 #define LL_IOC_QUOTACTL                 _IOWR('f', 162, struct if_quotactl *)
 #define LL_IOC_JOIN                     _IOW ('f', 163, long)
-#define LL_IOC_OBD_STATFS               _IOWR('f', 164, struct obd_statfs *)
+#define IOC_OBD_STATFS                  _IOWR('f', 164, struct obd_statfs *)
+#define IOC_LOV_GETINFO                 _IOWR('f', 165, struct lov_user_mds_data *)
 
 #define LL_STATFS_MDC           1
 #define LL_STATFS_LOV           2
 
 #define IOC_MDC_TYPE            'i'
 #define IOC_MDC_LOOKUP          _IOWR(IOC_MDC_TYPE, 20, struct obd_device *)
-#define IOC_MDC_GETSTRIPE       _IOWR(IOC_MDC_TYPE, 21, struct lov_mds_md *)
-#define IOC_MDC_GETFILEINFO     _IOWR(IOC_MDC_TYPE, 22, struct lov_mds_data *)
+#define IOC_MDC_GETFILESTRIPE   _IOWR(IOC_MDC_TYPE, 21, struct lov_user_md *)
+#define IOC_MDC_GETFILEINFO     _IOWR(IOC_MDC_TYPE, 22, struct lov_user_mds_data *)
+#define LL_IOC_MDC_GETINFO      _IOWR(IOC_MDC_TYPE, 23, struct lov_user_mds_data *)
+
+/* Keep these for backward compartability. */
+#define LL_IOC_OBD_STATFS       IOC_OBD_STATFS
+#define IOC_MDC_GETSTRIPE       IOC_MDC_GETFILESTRIPE
 
 #define O_LOV_DELAY_CREATE 0100000000  /* hopefully this does not conflict */
 #define O_JOIN_FILE        0400000000  /* hopefully this does not conflict */
@@ -132,9 +148,10 @@ static inline void obd_str2uuid(struct obd_uuid *uuid, const char *tmp)
 static inline char *obd_uuid2str(struct obd_uuid *uuid) 
 {
         if (uuid->uuid[sizeof(*uuid) - 1] != '\0') {
-                /* Obviously not safe, but for printfs, no real harm done...*/
+                /* Obviously not safe, but for printfs, no real harm done...
+                   we're always null-terminated, even in a race. */
                 static char temp[sizeof(*uuid)];
-                memcpy(temp, uuid->uuid, sizeof(*uuid));
+                memcpy(temp, uuid->uuid, sizeof(*uuid) - 1);
                 temp[sizeof(*uuid) - 1] = '\0';
                 return temp;
         }
index a04245a..f508bdf 100644 (file)
@@ -164,8 +164,12 @@ static inline char *lustre_cfg_string(struct lustre_cfg *lcfg, int index)
         if (s[lcfg->lcfg_buflens[index] - 1] != '\0') {
                 int last = min((int)lcfg->lcfg_buflens[index], 
                                size_round(lcfg->lcfg_buflens[index]) - 1);
+                char lost = s[last];
                 s[last] = '\0';
-                CWARN("Truncating buf %d to '%s'\n", index, s);
+                if (lost != '\0') {
+                        CWARN("Truncated buf %d to '%s' (lost '%c'...)\n",
+                              index, s, lost);
+                }
         }
         return s;
 }
index 9e0bd03..b2b7d48 100644 (file)
@@ -1,7 +1,7 @@
 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
  * vim:expandtab:shiftwidth=8:tabstop=8:
  *
- *  Copyright (C) 2001 Cluster File Systems, Inc. <braam@clusterfs.com>
+ *  Copyright (C) 2006 Cluster File Systems, Inc.
  *   Author: Nathan Rutman <nathan@clusterfs.com>
  *
  *   This file is part of Lustre, http://www.lustre.org.
 #ifndef _LUSTRE_DISK_H
 #define _LUSTRE_DISK_H
 
-#include <linux/types.h>
 #include <lnet/types.h>
 
+/****************** on-disk files *********************/
 
-/****************** persistent mount data *********************/
-
-/* Persistent mount data are stored on the disk in this file.
-   Used before the setup llog can be read. */
-#define MOUNT_CONFIGS_DIR "CONFIGS"
-#define MOUNT_DATA_FILE   MOUNT_CONFIGS_DIR"/mountdata"
 #define MDT_LOGS_DIR      "LOGS"  /* COMPAT_146 */
+#define MOUNT_CONFIGS_DIR "CONFIGS"
+/* Persistent mount data are stored on the disk in this file. */
+#define MOUNT_DATA_FILE    MOUNT_CONFIGS_DIR"/mountdata"
+#define LAST_RCVD         "last_rcvd"
+#define LOV_OBJID         "lov_objid"
+#define HEALTH_CHECK      "health_check"
+
+
+/****************** persistent mount data *********************/
 
 #define LDD_F_SV_TYPE_MDT   0x0001
 #define LDD_F_SV_TYPE_OST   0x0002
@@ -47,8 +50,7 @@
 #define LDD_F_REWRITE_LDD   0x0080 /* rewrite the LDD */
 #define LDD_F_WRITECONF     0x0100 /* regenerate all logs for this fs */
 #define LDD_F_UPGRADE14     0x0200 /* COMPAT_14 */
-#define MTI_F_IOCTL         0x0400 /* only used in mti  */
-
+#define LDD_F_PARAM_FNID    0x0400 /* process failover nids as params */
 
 enum ldd_mount_type {
         LDD_MT_EXT3 = 0, 
@@ -66,14 +68,9 @@ static inline char *mt_str(enum ldd_mount_type mt)
                 "smfs",
                 "reiserfs",
         };
-        //LASSERT(mt < LDD_MT_LAST);
         return mount_type_string[mt];
 }
 
-#ifndef MTI_NIDS_MAX  /* match lustre_idl.h */
-#define MTI_NIDS_MAX 64
-#endif
-
 #define LDD_INCOMPAT_SUPP 0
 #define LDD_ROCOMPAT_SUPP 0
 
@@ -146,36 +143,14 @@ struct lustre_mount_data {
         __u32     *lmd_exclude;       /* array of OSTs to ignore */
 };
 
-#define LMD_FLG_CLIENT       0x0002  /* Mounting a client only */
-#define LMD_FLG_RECOVER      0x0004  /* Allow recovery */
-#define LMD_FLG_NOSVC        0x0008  /* Only start MGS/MGC for servers, 
+#define LMD_FLG_SERVER       0x0001  /* Mounting a server */
+#define LMD_FLG_CLIENT       0x0002  /* Mounting a client */
+#define LMD_FLG_ABORT_RECOV  0x0008  /* Abort recovery */
+#define LMD_FLG_NOSVC        0x0010  /* Only start MGS/MGC for servers, 
                                         no other services */
 
 #define lmd_is_client(x) ((x)->lmd_flags & LMD_FLG_CLIENT) 
 
-/****************** mkfs command *********************/
-
-#define MO_IS_LOOP     0x01
-#define MO_FORCEFORMAT 0x02
-
-/* used to describe the options to format the lustre disk, not persistent */
-struct mkfs_opts {
-        struct lustre_disk_data mo_ldd; /* to be written in MOUNT_DATA_FILE */
-        char  mo_mount_type_string[20]; /* "ext3", "ldiskfs", ... */
-        char  mo_device[128];           /* disk device name */
-        char  mo_mkfsopts[128];         /* options to the backing-store mkfs */
-        char  mo_loopdev[128];          /* in case a loop dev is needed */
-        __u64 mo_device_sz;             /* in KB */
-        int   mo_stripe_count;
-        int   mo_flags; 
-        int   mo_mgs_failnodes;
-};
-
-/****************** on-disk files *********************/
-
-#define LAST_RCVD    "last_rcvd"
-#define LOV_OBJID    "lov_objid"
-#define HEALTH_CHECK "health_check"
 
 /****************** last_rcvd file *********************/
 
@@ -208,8 +183,8 @@ struct mkfs_opts {
    This should be common to filter_internal.h, lustre_mds.h */
 struct lr_server_data {
         __u8  lsd_uuid[40];        /* server UUID */
-        __u64 lsd_unused;          /* was fsd_last_objid - don't use for now */
         __u64 lsd_last_transno;    /* last completed transaction ID */
+        __u64 lsd_compat14;        /* reserved - compat with old last_rcvd */
         __u64 lsd_mount_count;     /* incarnation number */
         __u32 lsd_feature_compat;  /* compatible feature flags */
         __u32 lsd_feature_rocompat;/* read-only compatible feature flags */
index e45f18c..4b3cd6a 100644 (file)
@@ -114,6 +114,21 @@ typedef enum {
 /* Flags sent in AST lock_flags to be mapped into the receiving lock. */
 #define LDLM_AST_FLAGS         (LDLM_FL_DISCARD_DATA)
 
+/* completion ast to be executed */
+#define LDLM_FL_CP_REQD        0x1000000
+
+/* cleanup_resource has already handled the lock */
+#define LDLM_FL_CLEANED        0x2000000
+
+/* optimization hint: LDLM can run blocking callback from current context
+ * w/o involving separate thread. in order to decrease cs rate */
+#define LDLM_FL_ATOMIC_CB      0x4000000
+
+/* while this flag is set, the lock can't change resource */
+#define LDLM_FL_LOCK_PROTECT   0x8000000
+#define LDLM_FL_LOCK_PROTECT_BIT  27
+
+
 /* The blocking callback is overloaded to perform two functions.  These flags
  * indicate which operation should be performed. */
 #define LDLM_CB_BLOCKING    1
@@ -155,6 +170,25 @@ static inline int lockmode_compat(ldlm_mode_t exist, ldlm_mode_t new)
    -
 */
 
+/*
+ * Locking rules:
+ *
+ * lr_lock
+ *
+ * lr_lock
+ *     waiting_locks_spinlock
+ *
+ * lr_lock
+ *     led_lock
+ *
+ * lr_lock
+ *     ns_unused_lock
+ *
+ * lr_lvb_sem
+ *     lr_lock
+ *
+ */
+
 struct ldlm_lock;
 struct ldlm_resource;
 struct ldlm_namespace;
@@ -173,22 +207,24 @@ struct ldlm_namespace {
         char                  *ns_name;
         __u32                  ns_client; /* is this a client-side lock tree? */
         struct list_head      *ns_hash; /* hash table for ns */
-        cfs_waitq_t            ns_refcount_waitq; /* for cleanup */
-        atomic_t               ns_refcount; /* count of resources in the hash */
+        spinlock_t             ns_hash_lock;
+        __u32                  ns_refcount; /* count of resources in the hash */
         struct list_head       ns_root_list; /* all root resources in ns */
-        struct lustre_lock     ns_lock; /* protects hash, refcount, list */
         struct list_head       ns_list_chain; /* position in global NS list */
 
         struct list_head       ns_unused_list; /* all root resources in ns */
         int                    ns_nr_unused;
+        spinlock_t             ns_unused_lock;
+
         unsigned int           ns_max_unused;
         cfs_time_t             ns_next_dump;   /* next debug dump, jiffies */
 
-        spinlock_t             ns_counter_lock;
-        __u64                  ns_locks;
+        atomic_t               ns_locks;
+        __u64                  ns_resources;
         ldlm_res_policy        ns_policy;
         struct ldlm_valblock_ops *ns_lvbo;
-        void                    *ns_lvbp;
+        void                  *ns_lvbp;
+        cfs_waitq_t            ns_waitq;
 };
 
 /*
@@ -213,14 +249,27 @@ typedef int (*ldlm_glimpse_callback)(struct ldlm_lock *lock, void *data);
 struct ldlm_lock {
         struct portals_handle l_handle; // must be first in the structure
         atomic_t              l_refc;
+
+        /* ldlm_lock_change_resource() can change this */
         struct ldlm_resource *l_resource;
+
+        /* set once, no need to protect it */
         struct ldlm_lock     *l_parent;
+
+        /* protected by ns_hash_lock */
         struct list_head      l_children;
         struct list_head      l_childof;
+
+        /* protected by ns_hash_lock. FIXME */
         struct list_head      l_lru;
+
+        /* protected by lr_lock */
         struct list_head      l_res_link; // position in one of three res lists
+
+        /* protected by led_lock */
         struct list_head      l_export_chain; // per-export chain of locks
 
+        /* protected by lr_lock */
         ldlm_mode_t           l_req_mode;
         ldlm_mode_t           l_granted_mode;
 
@@ -230,10 +279,14 @@ struct ldlm_lock {
 
         struct obd_export    *l_export;
         struct obd_export    *l_conn_export;
+
+        /* protected by lr_lock */
         __u32                 l_flags;
+
         struct lustre_handle  l_remote_handle;
         ldlm_policy_data_t    l_policy_data;
 
+        /* protected by lr_lock */
         __u32                 l_readers;
         __u32                 l_writers;
         __u8                  l_destroyed;
@@ -254,26 +307,40 @@ struct ldlm_lock {
         void                 *l_ast_data;
 
         /* Server-side-only members */
+
+        /* protected by elt_lock */
         struct list_head      l_pending_chain;  /* callbacks pending */
         cfs_time_t            l_callback_timeout; /* jiffies */
 
         __u32                 l_pid;            /* pid which created this lock */
+        __u32                 l_pidb;           /* who holds LOCK_PROTECT_BIT */
+
+        struct list_head      l_tmp;
+
+        /* for ldlm_add_ast_work_item() */
+        struct list_head      l_bl_ast;
+        struct list_head      l_cp_ast;
+        struct ldlm_lock     *l_blocking_lock; 
+        int                   l_bl_ast_run;
 };
 
 struct ldlm_resource {
         struct ldlm_namespace *lr_namespace;
+
+        /* protected by ns_hash_lock */
         struct list_head       lr_hash;
         struct ldlm_resource  *lr_parent;   /* 0 for a root resource */
         struct list_head       lr_children; /* list head for child resources */
         struct list_head       lr_childof;  /* part of ns_root_list if root res,
                                              * part of lr_children if child */
+        spinlock_t             lr_lock;
 
+        /* protected by lr_lock */
         struct list_head       lr_granted;
         struct list_head       lr_converting;
         struct list_head       lr_waiting;
         ldlm_mode_t            lr_most_restr;
         ldlm_type_t            lr_type; /* LDLM_{PLAIN,EXTENT,FLOCK} */
-        struct ldlm_resource  *lr_root;
         struct ldlm_res_id     lr_name;
         atomic_t               lr_refcount;
 
@@ -421,7 +488,8 @@ do {                                                                          \
         CDEBUG(D_DLMTRACE, "### " format "\n" , ## a)
 
 typedef int (*ldlm_processing_policy)(struct ldlm_lock *lock, int *flags,
-                                      int first_enq, ldlm_error_t *err);
+                                      int first_enq, ldlm_error_t *err,
+                                      struct list_head *work_list);
 
 /*
  * Iterators.
@@ -441,8 +509,9 @@ int ldlm_namespace_foreach_res(struct ldlm_namespace *ns,
                                ldlm_res_iterator_t iter, void *closure);
 
 int ldlm_replay_locks(struct obd_import *imp);
-void ldlm_change_cbdata(struct ldlm_namespace *, struct ldlm_res_id *,
-                        ldlm_iterator_t iter, void *data);
+void ldlm_resource_iterate(struct ldlm_namespace *, struct ldlm_res_id *,
+                           ldlm_iterator_t iter, void *data);
+
 
 /* ldlm_flock.c */
 int ldlm_flock_completion_ast(struct ldlm_lock *lock, int flags, void *data);
@@ -461,6 +530,7 @@ int ldlm_handle_enqueue(struct ptlrpc_request *req, ldlm_completion_callback,
 int ldlm_handle_convert(struct ptlrpc_request *req);
 int ldlm_handle_cancel(struct ptlrpc_request *req);
 int ldlm_del_waiting_lock(struct ldlm_lock *lock);
+int ldlm_refresh_waiting_lock(struct ldlm_lock *lock);
 int ldlm_get_ref(void);
 void ldlm_put_ref(int force);
 
@@ -472,7 +542,7 @@ void ldlm_lock2handle(const struct ldlm_lock *lock,
 struct ldlm_lock *__ldlm_handle2lock(const struct lustre_handle *, int flags);
 void ldlm_cancel_callback(struct ldlm_lock *);
 int ldlm_lock_set_data(struct lustre_handle *, void *data);
-void ldlm_lock_remove_from_lru(struct ldlm_lock *);
+int ldlm_lock_remove_from_lru(struct ldlm_lock *);
 struct ldlm_lock *ldlm_handle2lock_ns(struct ldlm_namespace *,
                                       const struct lustre_handle *);
 
@@ -554,25 +624,31 @@ int ldlm_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
                       void *data, int flag);
 int ldlm_glimpse_ast(struct ldlm_lock *lock, void *reqp);
 int ldlm_completion_ast(struct ldlm_lock *lock, int flags, void *data);
-int ldlm_cli_enqueue(struct obd_export *exp,
-                     struct ptlrpc_request *req,
-                     struct ldlm_namespace *ns,
-                     struct ldlm_res_id,
-                     ldlm_type_t type,
-                     ldlm_policy_data_t *,
-                     ldlm_mode_t mode,
-                     int *flags,
+int ldlm_cli_enqueue(struct obd_export *exp, struct ptlrpc_request **reqp,
+                     struct ldlm_res_id res_id, 
+                     ldlm_type_t type, ldlm_policy_data_t *policy, 
+                     ldlm_mode_t mode, int *flags,
                      ldlm_blocking_callback blocking,
                      ldlm_completion_callback completion,
                      ldlm_glimpse_callback glimpse,
-                     void *data,
-                     void *lvb,
-                     __u32 lvb_len,
-                     void *lvb_swabber,
-                     struct lustre_handle *lockh);
+                     void *data, void *lvb, __u32 lvb_len, void *lvb_swabber,
+                     struct lustre_handle *lockh, int async);
 int ldlm_handle_enqueue0(struct ldlm_namespace *ns, struct ptlrpc_request *req,
                          const struct ldlm_request *dlm_req,
                          const struct ldlm_callback_suite *cbs);
+int ldlm_cli_enqueue_fini(struct obd_export *exp, struct ptlrpc_request *req,
+                          ldlm_type_t type, __u8 with_policy, ldlm_mode_t mode,
+                          int *flags, void *lvb, __u32 lvb_len,
+                          void *lvb_swabber, struct lustre_handle *lockh,
+                          int rc);
+int ldlm_cli_enqueue_local(struct ldlm_namespace *ns, struct ldlm_res_id res_id,
+                           ldlm_type_t type, ldlm_policy_data_t *policy,
+                           ldlm_mode_t mode, int *flags,
+                           ldlm_blocking_callback blocking,
+                           ldlm_completion_callback completion,
+                           ldlm_glimpse_callback glimpse,
+                           void *data, __u32 lvb_len, void *lvb_swabber,
+                           struct lustre_handle *lockh);
 int ldlm_server_ast(struct lustre_handle *lockh, struct ldlm_lock_desc *new,
                     void *data, __u32 data_len);
 int ldlm_cli_convert(struct lustre_handle *, int new_mode, int *flags);
@@ -581,8 +657,7 @@ int ldlm_handle_convert0(struct ptlrpc_request *req,
 int ldlm_cli_cancel(struct lustre_handle *lockh);
 int ldlm_cli_cancel_unused(struct ldlm_namespace *, struct ldlm_res_id *,
                            int flags, void *opaque);
-int ldlm_cli_join_lru(struct ldlm_namespace *, struct ldlm_res_id *,
-                      int join);
+int ldlm_cli_join_lru(struct ldlm_namespace *, struct ldlm_res_id *, int join);
 
 /* mds/handler.c */
 /* This has to be here because recursive inclusion sucks. */
@@ -600,4 +675,46 @@ void intent_set_disposition(struct ldlm_reply *rep, int flag);
 #define IOC_LDLM_REGRESS_STOP           _IOWR('f', 43, long)
 #define IOC_LDLM_MAX_NR                 43
 
+static inline void lock_res(struct ldlm_resource *res)
+{
+        spin_lock(&res->lr_lock);
+}
+
+static inline void unlock_res(struct ldlm_resource *res)
+{
+        spin_unlock(&res->lr_lock);
+}
+
+static inline void check_res_locked(struct ldlm_resource *res)
+{
+        LASSERT_SPIN_LOCKED(&res->lr_lock);
+}
+#ifdef __KERNEL__
+static inline void lock_bitlock(struct ldlm_lock *lock)
+{
+        bit_spin_lock(LDLM_FL_LOCK_PROTECT_BIT, (void *) &lock->l_flags);
+        LASSERT(lock->l_pidb == 0);
+        lock->l_pidb = current->pid;
+}
+
+static inline void unlock_bitlock(struct ldlm_lock *lock)
+{
+        LASSERT(lock->l_pidb == current->pid);
+        lock->l_pidb = 0;
+        bit_spin_unlock(LDLM_FL_LOCK_PROTECT_BIT, (void *) &lock->l_flags);
+}
+#else
+static inline void lock_bitlock(struct ldlm_lock *lock)
+{
+        lock->l_flags |= 1 << LDLM_FL_LOCK_PROTECT_BIT;
+}
+
+static inline void unlock_bitlock(struct ldlm_lock *lock)
+{
+        lock->l_flags &= ~(1 << LDLM_FL_LOCK_PROTECT_BIT);
+}
+#endif
+struct ldlm_resource * lock_res_and_lock(struct ldlm_lock *lock);
+void unlock_res_and_lock(struct ldlm_lock *lock);
+
 #endif
index 9801d8a..511ba12 100644 (file)
@@ -44,6 +44,7 @@ struct osc_creator {
 
 struct ldlm_export_data {
         struct list_head       led_held_locks; /* protected by namespace lock */
+        spinlock_t             led_lock;
 };
 
 struct ec_export_data { /* echo client */
@@ -59,6 +60,8 @@ struct filter_export_data {
         int                        fed_lr_idx;
         long                       fed_dirty;    /* in bytes */
         long                       fed_grant;    /* in bytes */
+        struct list_head           fed_mod_list; /* files being modified */
+        int                        fed_mod_count;/* items in fed_writing list */
         long                       fed_pending;  /* bytes just being written */
 };
 
index ff74277..0639d79 100644 (file)
@@ -45,7 +45,7 @@ struct obd_import_conn {
         struct list_head          oic_item;
         struct ptlrpc_connection *oic_conn;
         struct obd_uuid           oic_uuid;
-        cfs_time_t                oic_last_attempt; /* in cfs_time_t */
+        __u64                     oic_last_attempt; /* jiffies, 64-bit */
 };
 
 struct obd_import {
@@ -77,6 +77,7 @@ struct obd_import {
         __u64                     imp_last_transno_checked;
         struct lustre_handle      imp_remote_handle;
         cfs_time_t                imp_next_ping;   /* jiffies */
+        __u64                     imp_last_success_conn;   /* jiffies, 64-bit */
 
         /* all available obd_import_conn linked here */
         struct list_head          imp_conn_list;
@@ -86,21 +87,24 @@ struct obd_import {
         spinlock_t                imp_lock;
 
         /* flags */
-        unsigned int             
-                imp_invalid:1,          /* evicted */
-                imp_replayable:1,       /* try to recover the import */
-                imp_dlm_fake:1,         /* don't run recovery (timeout instead) */
-                imp_server_timeout:1,   /* use 1/2 timeout on MDS' OSCs */
-                imp_initial_recov:1,    /* retry the initial connection */  
-                imp_initial_recov_bk:1, /* turn off init_recov after trying all failover nids */
-                imp_force_verify:1,     /* force an immidiate ping */
-                imp_pingable:1,         /* pingable */
-                imp_resend_replay:1,    /* resend for replay */
-                imp_deactive:1;         /* administratively disabled */
+        unsigned int              imp_invalid:1,          /* evicted */
+                                  imp_deactive:1,         /* administratively disabled */
+                                  imp_replayable:1,       /* try to recover the import */
+                                  imp_dlm_fake:1,         /* don't run recovery (timeout instead) */
+                                  imp_server_timeout:1,   /* use 1/2 timeout on MDS' OSCs */
+                                  imp_initial_recov:1,    /* retry the initial connection */  
+                                  imp_initial_recov_bk:1, /* turn off init_recov after trying all failover nids */
+                                  imp_force_verify:1,     /* force an immidiate ping */
+                                  imp_pingable:1,         /* pingable */
+                                  imp_resend_replay:1,    /* resend for replay */
+                                  imp_recon_bk:1,         /* turn off reconnect if all failovers fail */
+                                  imp_last_recon:1;       /* internally used by above */
         __u32                     imp_connect_op;
         struct obd_connect_data   imp_connect_data;
         __u64                     imp_connect_flags_orig;
 
+        __u32                     imp_msg_magic;
+
         struct ptlrpc_request_pool *imp_rq_pool; /* emergency request pool */
 };
 
index 5c0f95f..77e1f0e 100644 (file)
@@ -588,13 +588,13 @@ struct l_wait_info {
         .lwi_interval   = interval                      \
 })
 
-#define LWI_TIMEOUT_INTR(time, time_cb, sig_cb, data)                          \
-((struct l_wait_info) {                                                        \
-        .lwi_timeout    = time,                                                \
-        .lwi_on_timeout = time_cb,                                             \
-        .lwi_on_signal = (sig_cb == NULL) ? LWI_ON_SIGNAL_NOOP : sig_cb,       \
-        .lwi_cb_data    = data,                                                \
-        .lwi_interval    = 0                                                   \
+#define LWI_TIMEOUT_INTR(time, time_cb, sig_cb, data)   \
+((struct l_wait_info) {                                 \
+        .lwi_timeout    = time,                         \
+        .lwi_on_timeout = time_cb,                      \
+        .lwi_on_signal = sig_cb,                        \
+        .lwi_cb_data    = data,                         \
+        .lwi_interval    = 0                            \
 })
 
 #define LWI_INTR(cb, data)  LWI_TIMEOUT_INTR(0, NULL, cb, data)
index 09c9e7a..599666d 100644 (file)
@@ -18,7 +18,6 @@
 #include <obd_class.h>
 #include <obd_ost.h>
 #include <lustre_net.h>
-#include <lustre_mds.h>
 #include <lustre_ha.h>
 
 #ifdef __KERNEL__
index 3173cf4..a061942 100644 (file)
@@ -32,6 +32,7 @@ struct obd_device;
 
 /* mdc/mdc_locks.c */
 int it_disposition(struct lookup_intent *it, int flag);
+void it_clear_disposition(struct lookup_intent *it, int flag);
 void it_set_disposition(struct lookup_intent *it, int flag);
 int it_open_error(int phase, struct lookup_intent *it);
 #endif
index 33a90ee..f6328f0 100644 (file)
@@ -68,31 +68,22 @@ struct mds_file_data {
         struct dentry        *mfd_dentry;
 };
 
-
 /* mds/mds_reint.c */
 struct inode;
 
 int mds_reint_rec(struct mds_update_record *r, int offset,
                   struct ptlrpc_request *req, struct lustre_handle *);
 
-int md_lov_connect(struct obd_device *obd, struct md_lov_info *mli,
-                   char *lov_name, struct obd_uuid *uuid,
-                   struct md_lov_ops *mlo, const void *ctxt);
-int md_lov_notity_pre(struct obd_device *obd, struct md_lov_info *mli,
-                      struct obd_device *watched, enum obd_notify_event ev,
-                      void *data);
-int md_lov_start_synchronize(struct obd_device *obd, struct md_lov_info *mli,
-                             struct obd_device *watched,
-                             void *data, int nonblock, const void *ctxt);
-int mds_log_op_unlink(struct obd_device *obd, struct inode *inode,
+int mds_osc_setattr_async(struct obd_device *obd, __u32 uid, __u32 gid,
+                          struct lov_mds_md *lmm, int lmm_size,
+                          struct llog_cookie *logcookies, __u64 id, __u32 gen);
+
+int mds_log_op_unlink(struct obd_device *obd,
                       struct lov_mds_md *lmm, int lmm_size,
                       struct llog_cookie *logcookies, int cookies_size);
 int mds_log_op_setattr(struct obd_device *obd, struct inode *inode,
                       struct lov_mds_md *lmm, int lmm_size,
                       struct llog_cookie *logcookies, int cookies_size);
-int mds_osc_setattr_async(struct obd_device *obd, __u32 uid, __u32 gid,
-                          struct lov_mds_md *lmm, int lmm_size,
-                          struct llog_cookie *logcookies, __u64 id, __u32 gen);
 
 /* ioctls for trying requests */
 #define IOC_REQUEST_TYPE                   'f'
index 6c45cfb..8fa6dbd 100644 (file)
 #define MDS_MAXREQSIZE  (5 * 1024)
 #define MDS_MAXREPSIZE  max(9 * 1024, 280 + LOV_MAX_STRIPE_COUNT * 56)
 
-/* FLD_MAXREQSIZE == lustre_msg + __u32 padding + opc + md_fld */
-#define FLD_MAXREQSIZE  (96)
+/* FLD_MAXREQSIZE == lustre_msg + __u32 padding + ptlrpc_body + opc + md_fld */
+#define FLD_MAXREQSIZE  (168)
 
-/* FLD_MAXREPSIZE == lustre_msg + __u32 padding + md_fld */
-#define FLD_MAXREPSIZE  (88)
+/* FLD_MAXREPSIZE == lustre_msg + __u32 padding + ptlrpc_body + md_fld */
+#define FLD_MAXREPSIZE  (160)
 
-/* SEQ_MAXREQSIZE == lustre_msg + __u32 padding + opc + __u32 padding */
-#define SEQ_MAXREQSIZE  (80)
+/* SEQ_MAXREQSIZE == lustre_msg + __u32 padding + opc + ptlrpc_body + __u32 padding */
+#define SEQ_MAXREQSIZE  (152)
 
-/* SEQ_MAXREPSIZE == lustre_msg + __u32 padding + lu_range */
-#define SEQ_MAXREPSIZE  (88)
+/* SEQ_MAXREPSIZE == lustre_msg + __u32 padding + ptlrpc_body + lu_range */
+#define SEQ_MAXREPSIZE  (160)
 
 /* FIXME fix all constants here.  Andreas suggests dyamically adding threads. */
 #define MGS_MAX_THREADS 8UL
@@ -186,26 +186,27 @@ struct ptlrpc_client {
 /* unpacking: assert idx not unpacked already */
 #define LASSERT_REQSWAB(rq, idx)                                \
 do {                                                            \
-        LASSERT ((idx) < sizeof ((rq)->rq_req_swab_mask) * 8);  \
-        LASSERT (((rq)->rq_req_swab_mask & (1 << (idx))) == 0); \
+        LASSERT((idx) < sizeof((rq)->rq_req_swab_mask) * 8);    \
+        LASSERT(((rq)->rq_req_swab_mask & (1 << (idx))) == 0);  \
         (rq)->rq_req_swab_mask |= (1 << (idx));                 \
 } while (0)
 
 #define LASSERT_REPSWAB(rq, idx)                                \
 do {                                                            \
-        LASSERT ((idx) < sizeof ((rq)->rq_rep_swab_mask) * 8);  \
-        LASSERT (((rq)->rq_rep_swab_mask & (1 << (idx))) == 0); \
+        LASSERT((idx) < sizeof((rq)->rq_rep_swab_mask) * 8);    \
+        LASSERT(((rq)->rq_rep_swab_mask & (1 << (idx))) == 0);  \
         (rq)->rq_rep_swab_mask |= (1 << (idx));                 \
 } while (0)
 
 /* just looking: assert idx already unpacked */
-#define LASSERT_REQSWABBED(rq, idx)                     \
-LASSERT ((idx) < sizeof ((rq)->rq_req_swab_mask) * 8 && \
-         ((rq)->rq_req_swab_mask & (1 << (idx))) != 0)
+#define LASSERT_REQSWABBED(rq, idx)                             \
+LASSERT((idx) < sizeof((rq)->rq_req_swab_mask) * 8 &&           \
+        ((rq)->rq_req_swab_mask & (1 << (idx))) != 0);          \
+
+#define LASSERT_REPSWABBED(rq, idx)                             \
+LASSERT((idx) < sizeof((rq)->rq_rep_swab_mask) * 8 &&           \
+        ((rq)->rq_rep_swab_mask & (1 << (idx))) != 0);          \
 
-#define LASSERT_REPSWABBED(rq, idx)                     \
-LASSERT ((idx) < sizeof ((rq)->rq_rep_swab_mask) * 8 && \
-         ((rq)->rq_rep_swab_mask & (1 << (idx))) != 0)
 #else
 #define LASSERT_REQSWAB(rq, idx)
 #define LASSERT_REPSWAB(rq, idx)
@@ -281,7 +282,7 @@ struct ptlrpc_reply_state {
         struct lustre_handle   rs_locks[RS_MAX_LOCKS];
         ldlm_mode_t            rs_modes[RS_MAX_LOCKS];
         /* last member: variable sized reply message */
-        struct lustre_msg      rs_msg;
+        struct lustre_msg     *rs_msg;
 };
 
 struct ptlrpc_thread;
@@ -428,18 +429,21 @@ CDEB_TYPE(level, "@@@ " fmt                                                    \
        " req@%p x"LPD64"/t"LPD64" o%d->%s@%s:%d lens %d/%d ref %d fl "         \
        REQ_FLAGS_FMT"/%x/%x rc %d/%d\n" , ## args, req, req->rq_xid,           \
        req->rq_transno,                                                        \
-       req->rq_reqmsg ? req->rq_reqmsg->opc : -1,                              \
-       req->rq_import ? obd2cli_tgt(req->rq_import->imp_obd) : "<?>",  \
+       req->rq_reqmsg ? lustre_msg_get_opc(req->rq_reqmsg) : -1,               \
+       req->rq_import ? obd2cli_tgt(req->rq_import->imp_obd) :                 \
+          req->rq_export ? (char*)req->rq_export->exp_client_uuid.uuid : "<?>",\
        req->rq_import ?                                                        \
-          (char *)req->rq_import->imp_connection->c_remote_uuid.uuid : "<?>",  \
+          (char *)req->rq_import->imp_connection->c_remote_uuid.uuid :         \
+          req->rq_export ?                                                     \
+          (char *)req->rq_export->exp_connection->c_remote_uuid.uuid :  "<?>", \
        (req->rq_import && req->rq_import->imp_client) ?                        \
            req->rq_import->imp_client->cli_request_portal : -1,                \
        req->rq_reqlen, req->rq_replen,                                         \
        atomic_read(&req->rq_refcount),                                         \
        DEBUG_REQ_FLAGS(req),                                                   \
-       req->rq_reqmsg ? req->rq_reqmsg->flags : 0,                             \
-       req->rq_repmsg ? req->rq_repmsg->flags : 0,                             \
-       req->rq_status, req->rq_repmsg ? req->rq_repmsg->status : 0)
+       req->rq_reqmsg ? lustre_msg_get_flags(req->rq_reqmsg) : 0,              \
+       req->rq_repmsg ? lustre_msg_get_flags(req->rq_repmsg) : 0,              \
+       req->rq_status, req->rq_repmsg ? lustre_msg_get_status(req->rq_repmsg) : 0)
 
 /* for most callers (level is a constant) this is resolved at compile time */
 #define DEBUG_REQ(level, req, fmt, args...)                                    \
@@ -450,14 +454,6 @@ do {                                                                           \
             __DEBUG_REQ(CDEBUG, level, req, fmt, ## args);                     \
 } while (0)
 
-#define DEBUG_REQ_EX(level, req, fmt, args...)                          \
-do {                                                                    \
-        if ((level) & (D_ERROR | D_WARNING))                            \
-            __DEBUG_REQ(CDEBUG_LIMIT, D_ERROR, req, fmt, ## args);      \
-        else                                                            \
-            __DEBUG_REQ(CDEBUG_EX, level, req, fmt, ## args);           \
-} while (0)
-
 struct ptlrpc_bulk_page {
         struct list_head bp_link;
         int bp_buflen;
@@ -632,12 +628,11 @@ void ptlrpc_unregister_bulk (struct ptlrpc_request *req);
 
 static inline int ptlrpc_bulk_active (struct ptlrpc_bulk_desc *desc)
 {
-        unsigned long flags;
         int           rc;
 
-        spin_lock_irqsave (&desc->bd_lock, flags);
+        spin_lock(&desc->bd_lock);
         rc = desc->bd_network_rw;
-        spin_unlock_irqrestore (&desc->bd_lock, flags);
+        spin_unlock(&desc->bd_lock);
         return (rc);
 }
 
@@ -657,24 +652,22 @@ struct ptlrpc_connection *ptlrpc_uuid_to_connection(struct obd_uuid *uuid);
 static inline int
 ptlrpc_client_receiving_reply (struct ptlrpc_request *req)
 {
-        unsigned long flags;
         int           rc;
 
-        spin_lock_irqsave(&req->rq_lock, flags);
+        spin_lock(&req->rq_lock);
         rc = req->rq_receiving_reply;
-        spin_unlock_irqrestore(&req->rq_lock, flags);
+        spin_unlock(&req->rq_lock);
         return (rc);
 }
 
 static inline int
 ptlrpc_client_replied (struct ptlrpc_request *req)
 {
-        unsigned long flags;
         int           rc;
 
-        spin_lock_irqsave(&req->rq_lock, flags);
+        spin_lock(&req->rq_lock);
         rc = req->rq_replied;
-        spin_unlock_irqrestore(&req->rq_lock, flags);
+        spin_unlock(&req->rq_lock);
         return (rc);
 }
 
@@ -710,11 +703,11 @@ void ptlrpc_add_rqs_to_pool(struct ptlrpc_request_pool *pool, int num_rq);
 struct ptlrpc_request_pool *ptlrpc_init_rq_pool(int, int,
                                                 void (*populate_pool)(struct ptlrpc_request_pool *, int));
 struct ptlrpc_request *ptlrpc_prep_req(struct obd_import *imp, __u32 version,
-                                       int opcode, int count,
-                                       int *lengths, char **bufs);
-struct ptlrpc_request *ptlrpc_prep_req_pool(struct obd_import *imp, __u32 version,
-                                            int opcode, int count, int *lengths,
-                                            char **bufs,
+                                       int opcode, int count, int *lengths,
+                                       char **bufs);
+struct ptlrpc_request *ptlrpc_prep_req_pool(struct obd_import *imp,
+                                             __u32 version, int opcode,
+                                            int count, int *lengths, char **bufs,
                                             struct ptlrpc_request_pool *pool);
 void ptlrpc_free_req(struct ptlrpc_request *request);
 void ptlrpc_req_finished(struct ptlrpc_request *request);
@@ -791,23 +784,52 @@ int ptlrpc_import_recovery_state_machine(struct obd_import *imp);
 /* ptlrpc/pack_generic.c */
 int lustre_msg_swabbed(struct lustre_msg *msg);
 int lustre_msg_check_version(struct lustre_msg *msg, __u32 version);
-int lustre_pack_request(struct ptlrpc_request *, int count, const int *lens,
-                        char **bufs);
-int lustre_pack_reply(struct ptlrpc_request *, int count, const int *lens,
+int lustre_pack_request(struct ptlrpc_request *, __u32 magic, int count,
+                        int *lens, char **bufs);
+int lustre_pack_reply(struct ptlrpc_request *, int count, int *lens,
                       char **bufs);
-void lustre_shrink_reply(struct ptlrpc_request *req,
-                         int segment, unsigned int newlen, int move_data);
+void lustre_shrink_reply(struct ptlrpc_request *req, int segment,
+                         unsigned int newlen, int move_data);
 void lustre_free_reply_state(struct ptlrpc_reply_state *rs);
-int lustre_msg_size(int count, const int *lengths);
+int lustre_msg_size(__u32 magic, int count, int *lengths);
 int lustre_unpack_msg(struct lustre_msg *m, int len);
+int lustre_unpack_ptlrpc_body(struct lustre_msg *m);
 void *lustre_msg_buf(struct lustre_msg *m, int n, int minlen);
 int lustre_msg_buflen(struct lustre_msg *m, int n);
+void lustre_msg_set_buflen(struct lustre_msg *m, int n, int len);
+int lustre_msg_bufcount(struct lustre_msg *m);
 char *lustre_msg_string (struct lustre_msg *m, int n, int max_len);
 void *lustre_swab_buf(struct lustre_msg *, int n, int minlen, void *swabber);
-void *lustre_swab_reqbuf (struct ptlrpc_request *req, int n, int minlen,
-                          void *swabber);
-void *lustre_swab_repbuf (struct ptlrpc_request *req, int n, int minlen,
-                          void *swabber);
+void *lustre_swab_reqbuf(struct ptlrpc_request *req, int n, int minlen,
+                         void *swabber);
+void *lustre_swab_repbuf(struct ptlrpc_request *req, int n, int minlen,
+                         void *swabber);
+__u32 lustre_msg_get_flags(struct lustre_msg *msg);
+void lustre_msg_add_flags(struct lustre_msg *msg, int flags);
+void lustre_msg_set_flags(struct lustre_msg *msg, int flags);
+void lustre_msg_clear_flags(struct lustre_msg *msg, int flags);
+__u32 lustre_msg_get_op_flags(struct lustre_msg *msg);
+void lustre_msg_add_op_flags(struct lustre_msg *msg, int flags);
+void lustre_msg_set_op_flags(struct lustre_msg *msg, int flags);
+struct lustre_handle *lustre_msg_get_handle(struct lustre_msg *msg);
+__u32 lustre_msg_get_type(struct lustre_msg *msg);
+__u32 lustre_msg_get_version(struct lustre_msg *msg);
+void lustre_msg_add_version(struct lustre_msg *msg, int version);
+__u32 lustre_msg_get_opc(struct lustre_msg *msg);
+__u64 lustre_msg_get_last_xid(struct lustre_msg *msg);
+__u64 lustre_msg_get_last_committed(struct lustre_msg *msg);
+__u64 lustre_msg_get_transno(struct lustre_msg *msg);
+__u32 lustre_msg_get_status(struct lustre_msg *msg);
+__u32 lustre_msg_get_conn_cnt(struct lustre_msg *msg);
+__u32 lustre_msg_get_magic(struct lustre_msg *msg);
+void lustre_msg_set_handle(struct lustre_msg *msg,struct lustre_handle *handle);
+void lustre_msg_set_type(struct lustre_msg *msg, __u32 type);
+void lustre_msg_set_opc(struct lustre_msg *msg, __u32 opc);
+void lustre_msg_set_last_xid(struct lustre_msg *msg, __u64 last_xid);
+void lustre_msg_set_last_committed(struct lustre_msg *msg,__u64 last_committed);
+void lustre_msg_set_transno(struct lustre_msg *msg, __u64 transno);
+void lustre_msg_set_status(struct lustre_msg *msg, __u32 status);
+void lustre_msg_set_conn_cnt(struct lustre_msg *msg, __u32 conn_cnt);
 
 static inline void
 ptlrpc_rs_addref(struct ptlrpc_reply_state *rs)
@@ -824,6 +846,34 @@ ptlrpc_rs_decref(struct ptlrpc_reply_state *rs)
                 lustre_free_reply_state(rs);
 }
 
+static inline __u32 lustre_request_magic(struct ptlrpc_request *req)
+{
+        return lustre_msg_get_magic(req->rq_reqmsg);
+}
+
+static inline int ptlrpc_req_get_repsize(struct ptlrpc_request *req)
+{
+        switch (req->rq_reqmsg->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+                CERROR("function not supported for lustre_msg V1!\n");
+                return -ENOTSUPP;
+        case LUSTRE_MSG_MAGIC_V2:
+                return req->rq_reqmsg->lm_repsize;
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n",
+                         req->rq_reqmsg->lm_magic);
+                return -EFAULT;
+        }
+}
+
+static inline void
+ptlrpc_req_set_repsize(struct ptlrpc_request *req, int count, int *lens)
+{
+        req->rq_replen = lustre_msg_size(req->rq_reqmsg->lm_magic, count, lens);
+        if (req->rq_reqmsg->lm_magic == LUSTRE_MSG_MAGIC_V2)
+                req->rq_reqmsg->lm_repsize = req->rq_replen;
+}
+
 /* ldlm/ldlm_lib.c */
 int client_obd_setup(struct obd_device *obddev, struct lustre_cfg *lcfg);
 int client_obd_cleanup(struct obd_device *obddev);
index 142c1f1..427973d 100644 (file)
 #ifndef _LUSTRE_PARAM_H
 #define _LUSTRE_PARAM_H
 
-/* obd_mount.c */
+/* obd_config.c */
 int class_find_param(char *buf, char *key, char **valp);
 int class_match_param(char *buf, char *key, char **valp);
 int class_parse_nid(char *buf, lnet_nid_t *nid, char **endh);
+/* obd_mount.c */
+int do_lcfg(char *cfgname, lnet_nid_t nid, int cmd,
+            char *s1, char *s2, char *s3, char *s4);
+
 
 
 /****************** User-settable parameter keys *********************/
 
-#define PARAM_MGSNODE          "mgsnode="
-#define PARAM_FAILNODE         "failnode="
-#define PARAM_OBD_TIMEOUT      "obd_timeout="
-#define PARAM_DEFAULT_STRIPE   "default_stripe_"
-#define PARAM_D_STRIPE_SIZE    PARAM_DEFAULT_STRIPE"size"
-#define PARAM_D_STRIPE_COUNT   PARAM_DEFAULT_STRIPE"count"
-#define PARAM_D_STRIPE_OFFSET  PARAM_DEFAULT_STRIPE"offset"
-#define PARAM_D_STRIPE_PATTERN PARAM_DEFAULT_STRIPE"pattern"
+#define PARAM_SYS_TIMEOUT          "sys.timeout="
+#define PARAM_MGSNODE              "mgsnode="
+#define PARAM_FAILNODE             "failover.node="
+#define PARAM_FAILMODE             "failover.mode="
+#define PARAM_OST                  "ost."
+#define PARAM_OSC                  "osc."
+#define PARAM_MDT                  "mdt."
+#define PARAM_MDC                  "mdc."
+#define PARAM_LLITE                "llite."
+#define PARAM_LOV                  "lov."
+/* LOV_STRIPE_* aren't settable in proc. But match the proc names. */
+#define PARAM_LOV_STRIPE_SIZE      PARAM_LOV"stripesize="
+#define PARAM_LOV_STRIPE_COUNT     PARAM_LOV"stripecount="
+#define PARAM_LOV_STRIPE_OFFSET    PARAM_LOV"stripeoffset="
+#define PARAM_LOV_STRIPE_PATTERN   PARAM_LOV"stripetype="
 
 #endif // _LUSTRE_PARAM_H
index 4ddc09e..15bc66b 100644 (file)
@@ -120,6 +120,7 @@ extern const struct req_format RQF_LDLM_INTENT_OPEN;
 extern const struct req_format RQF_LDLM_INTENT_CREATE;
 extern const struct req_format RQF_LDLM_INTENT_UNLINK;
 
+extern const struct req_msg_field RMF_PTLRPC_BODY;
 extern const struct req_msg_field RMF_MDT_BODY;
 extern const struct req_msg_field RMF_OBD_STATFS;
 extern const struct req_msg_field RMF_NAME;
index 24b423b..327ea0b 100644 (file)
@@ -23,7 +23,7 @@
 #define IOC_MDC_TYPE         'i'
 #define IOC_MDC_MIN_NR       20
 /* Moved to lustre_user.h
-#define IOC_MDC_LOOKUP       _IOWR(IOC_MDC_TYPE, 20, struct obd_device *)
+#define IOC_MDC_LOOKUP       _IOWR(IOC_MDC_TYPE, 20, struct obd_ioctl_data *)
 #define IOC_MDC_GETSTRIPE    _IOWR(IOC_MDC_TYPE, 21, struct lov_mds_md *) */
 #define IOC_MDC_MAX_NR       50
 
@@ -37,9 +37,9 @@
 /* this is really local to the OSC */
 struct loi_oap_pages {
         struct list_head        lop_pending;
-        int                     lop_num_pending;
         struct list_head        lop_urgent;
         struct list_head        lop_pending_group;
+        int                     lop_num_pending;
 };
 
 struct osc_async_rc {
@@ -105,7 +105,6 @@ struct lov_stripe_md {
                 __u64 lw_object_id;        /* lov object id */
                 __u64 lw_object_gr;        /* lov object group */
                 __u64 lw_maxbytes;         /* maximum possible file size */
-                unsigned long lw_xfersize; /* optimal transfer size */
 
                 /* LOV-private members start here -- only for use in lov/. */
                 __u32 lw_magic;
@@ -121,12 +120,55 @@ struct lov_stripe_md {
 #define lsm_object_id    lsm_wire.lw_object_id
 #define lsm_object_gr    lsm_wire.lw_object_gr
 #define lsm_maxbytes     lsm_wire.lw_maxbytes
-#define lsm_xfersize     lsm_wire.lw_xfersize
 #define lsm_magic        lsm_wire.lw_magic
 #define lsm_stripe_size  lsm_wire.lw_stripe_size
 #define lsm_pattern      lsm_wire.lw_pattern
 #define lsm_stripe_count lsm_wire.lw_stripe_count
 
+struct obd_info;
+
+typedef int (*obd_enqueue_update_f)(struct obd_info *oinfo, int rc);
+
+/* obd_enqueue parameters common for all levels (lov, osc). */
+struct obd_enqueue_info {
+        /* Flags used while lock handling. */
+        int   ei_flags;
+        /* Type of the lock being enqueued. */
+        __u32 ei_type;
+        /* Mode of the lock being enqueued. */
+        __u32 ei_mode;
+        /* Different callbacks for lock handling (blocking, completion,
+           glimpse */
+        void *ei_cb_bl;
+        void *ei_cb_cp;
+        void *ei_cb_gl;
+        /* Data to be passed into callbacks. */
+        void *ei_cbdata;
+        /* Request set for OSC async requests. */
+        struct ptlrpc_request_set *ei_rqset;
+};
+
+/* obd info for a particular level (lov, osc). */
+struct obd_info {
+        /* Lock policy. It keeps an extent which is specific for a particular
+         * OSC. (e.g. lov_prep_enqueue_set initialises extent of the policy,
+         * and osc_enqueue passes it into ldlm_lock_match & ldlm_cli_enqueue. */
+        ldlm_policy_data_t      oi_policy;
+        /* Lock handle specific for every OSC lock. */
+        struct lustre_handle   *oi_lockh;
+        /* lsm data specific for every OSC. */
+        struct lov_stripe_md   *oi_md;
+        /* obdo data specific for every OSC, if needed at all. */
+        struct obdo            *oi_oa;
+        /* statfs data specific for every OSC, if needed at all. */
+        struct obd_statfs      *oi_osfs;
+        /* An update callback which is called to update some data on upper
+         * level. E.g. it is used for update lsm->lsm_oinfo at every recieved
+         * request in osc level for enqueue requests. It is also possible to
+         * update some caller data from LOV layer if needed. */
+        obd_enqueue_update_f     oi_cb_up;
+};
+
 /* compare all relevant fields. */
 static inline int lov_stripe_md_cmp(struct lov_stripe_md *m1,
                                     struct lov_stripe_md *m2)
@@ -149,6 +191,7 @@ struct obd_type {
         char *typ_name;
         int  typ_refcnt;
         struct lu_device_type *typ_lu;
+        spinlock_t obd_type_lock;
 };
 
 struct brw_page {
@@ -175,7 +218,9 @@ struct obd_async_page_ops {
         int  (*ap_make_ready)(void *data, int cmd);
         int  (*ap_refresh_count)(void *data, int cmd);
         void (*ap_fill_obdo)(void *data, int cmd, struct obdo *oa);
-        void (*ap_completion)(void *data, int cmd, struct obdo *oa, int rc);
+        void (*ap_update_obdo)(void *data, int cmd, struct obdo *oa,
+                               obd_valid valid);
+        int  (*ap_completion)(void *data, int cmd, struct obdo *oa, int rc);
 };
 
 /* the `oig' is passed down from a caller of obd rw methods.  the callee
@@ -264,9 +309,8 @@ struct filter_obd {
 
         struct semaphore     fo_alloc_lock;
 
-        spinlock_t fo_stats_lock;
-        int fo_r_in_flight; /* protected by fo_stats_lock */
-        int fo_w_in_flight; /* protected by fo_stats_lock */
+        atomic_t             fo_r_in_flight;
+        atomic_t             fo_w_in_flight;
 
         /*
          * per-filter pool of kiobuf's allocated by filter_common_setup() and
@@ -295,10 +339,15 @@ struct filter_obd {
         struct obd_histogram     fo_w_discont_blocks;
         struct obd_histogram     fo_r_disk_iosize;
         struct obd_histogram     fo_w_disk_iosize;
+        struct obd_histogram     fo_r_dio_frags;
+        struct obd_histogram     fo_w_dio_frags;
 
         struct lustre_quota_ctxt fo_quota_ctxt;
         spinlock_t               fo_quotacheck_lock;
         atomic_t                 fo_quotachecking;
+
+        int                      fo_fmd_max_num; /* per exp filter_mod_data */
+        int                      fo_fmd_max_age; /* jiffies to fmd expiry */
 };
 
 #define OSC_MAX_RIF_DEFAULT       8
@@ -306,6 +355,9 @@ struct filter_obd {
 #define OSC_MAX_DIRTY_DEFAULT  (OSC_MAX_RIF_DEFAULT * 4)
 #define OSC_MAX_DIRTY_MB_MAX   2048     /* totally arbitrary */
 
+#define MDC_MAX_RIF_DEFAULT       8
+#define MDC_MAX_RIF_MAX         512
+
 struct mdc_rpc_lock;
 struct obd_import;
 struct client_obd {
@@ -368,6 +420,7 @@ struct client_obd {
 
         struct mdc_rpc_lock     *cl_rpc_lock;
         struct mdc_rpc_lock     *cl_setattr_lock;
+        struct mdc_rpc_lock     *cl_close_lock;
         struct osc_creator       cl_oscc;
 
         /* mgc datastruct */
@@ -403,20 +456,6 @@ struct mgs_obd {
         struct semaphore                 mgs_sem;
 };
 
-struct md_lov_info;
-
-struct md_lov_ops {
-        int (*ml_read_objids)(struct obd_device *obd, struct md_lov_info *mli,
-                              const void *ctxt);
-        int (*ml_write_objids)(struct obd_device *obd, struct md_lov_info *mli,
-                               const void *ctxt);
-        int (*ml_read_catlist)(struct obd_device *obd, void *idarray, int size,
-                               const void *ctxt);
-        int (*ml_write_catlist)(struct obd_device *obd, void *idarray, int size,
-                               const void *ctxt);
-
-};
-
 struct mds_obd {
         /* NB this field MUST be first */
         struct obd_device_target         mds_obt;
@@ -487,28 +526,63 @@ struct echo_client_obd {
         __u64                ec_unique;
 };
 
+struct lov_qos_oss {
+        struct obd_uuid     lqo_uuid;       /* ptlrpc's c_remote_uuid */
+        struct list_head    lqo_oss_list;   /* link to lov_qos */
+        __u32               lqo_ost_count;  /* number of osts on this oss */
+        __u64               lqo_bavail;     /* total bytes avail on OSS */
+        __u64               lqo_penalty;    /* current penalty */
+        __u64               lqo_penalty_per_obj; /* penalty decrease every obj*/
+};
+
+struct ltd_qos {
+        struct lov_qos_oss *ltq_oss;         /* oss info */
+        __u64               ltq_penalty;     /* current penalty */
+        __u64               ltq_penalty_per_obj; /* penalty decrease every obj*/
+        __u64               ltq_weight;      /* net weighting */
+        unsigned int        ltq_usable:1;    /* usable for striping */
+};
+
+struct lov_qos {
+        struct list_head    lq_oss_list;    /* list of OSSs that targets use */
+        struct rw_semaphore lq_rw_sem;
+        __u32               lq_active_oss_count;
+        __u32              *lq_rr_array;    /* round-robin optimized list */
+        unsigned int        lq_rr_size;     /* rr array size */
+        unsigned int        lq_prio_free;   /* priority for free space */
+        unsigned int        lq_dirty:1,     /* recalc qos data */
+                            lq_dirty_rr:1,  /* recalc round-robin list */
+                            lq_same_space:1,/* the ost's all have approx.
+                                               the same space avail */
+                            lq_reset:1;     /* zero current penalties */
+};
+
 struct lov_tgt_desc {
-        struct obd_uuid          uuid;
-        __u32                    ltd_gen;
-        struct obd_export       *ltd_exp;
-        unsigned int             active:1, /* is this target up for requests */
-                                 reap:1;   /* should this target be deleted */
-        int                      index;  /* index of target array in lov_obd */
-        struct list_head         qos_bavail_list; /* link entry to lov_obd */
+        struct obd_uuid     ltd_uuid;
+        struct obd_export  *ltd_exp;
+        struct ltd_qos      ltd_qos;     /* qos info per target */
+        __u32               ltd_gen;
+        __u32               ltd_index;   /* index in lov_obd->tgts */
+        unsigned int        ltd_active:1,/* is this target up for requests */
+                            ltd_activate:1,/* should this target be activated */
+                            ltd_reap:1;  /* should this target be deleted */
 };
 
 struct lov_obd {
-        struct semaphore lov_lock;
-        atomic_t refcount;
-        struct lov_desc desc;
-        struct obd_connect_data ocd;
-        int bufsize;
-        int connects;
-        int death_row;      /* Do we have tgts scheduled to be deleted?
-                               (Make this a linked list?) */
-        struct list_head qos_bavail_list; /* tgts list, sorted by available
-                                             space, protected by lov_lock */
-        struct lov_tgt_desc *tgts;
+        struct lov_desc         desc;
+        struct lov_tgt_desc   **lov_tgts;
+        struct semaphore        lov_lock;
+        struct obd_connect_data lov_ocd;
+        struct lov_qos          lov_qos;               /* qos info per lov */
+        atomic_t                lov_refcount;
+        __u32                   lov_tgt_count;         /* how many OBD's */
+        __u32                   lov_active_tgt_count;  /* how many active */
+        __u32                   lov_death_row;/* tgts scheduled to be deleted */
+        __u32                   lov_tgt_size;   /* size of tgts array */
+        __u32                   lov_start_idx;  /* start index of new inode */
+        __u32                   lov_offset_idx; /* aliasing for start_idx  */
+        int                     lov_start_count;/* reseed counter */
+        int                     lov_connects;
 };
 
 struct lmv_tgt_desc {
@@ -598,6 +672,9 @@ struct lu_placement_hint {
 #define LUSTRE_ECHO_NAME        "obdecho"
 #define LUSTRE_ECHO_CLIENT_NAME "echo_client"
 
+/* Constant obd names (post-rename) */
+#define LUSTRE_MDS_OBDNAME "MDS"
+#define LUSTRE_OSS_OBDNAME "OSS"
 #define LUSTRE_MGS_OBDNAME "MGS"
 #define LUSTRE_MGC_OBDNAME "MGC"
 
@@ -606,6 +683,7 @@ struct lu_placement_hint {
 
 struct obd_trans_info {
         __u64                    oti_transno;
+        __u64                    oti_xid;
         __u64                   *oti_objid;
         /* Only used on the server side for tracking acks. */
         struct oti_req_ack_lock {
@@ -619,6 +697,7 @@ struct obd_trans_info {
 
         /* initial thread handling transaction */
         int                      oti_thread_id;
+        __u32                    oti_conn_cnt;
 };
 
 static inline void oti_init(struct obd_trans_info *oti,
@@ -631,9 +710,12 @@ static inline void oti_init(struct obd_trans_info *oti,
         if (req == NULL)
                 return;
 
+        oti->oti_xid = req->rq_xid;
+
         if (req->rq_repmsg && req->rq_reqmsg != 0)
-                oti->oti_transno = req->rq_repmsg->transno;
+                oti->oti_transno = lustre_msg_get_transno(req->rq_repmsg);
         oti->oti_thread_id = req->rq_svc_thread ? req->rq_svc_thread->t_id : -1;
+        oti->oti_conn_cnt = lustre_msg_get_conn_cnt(req->rq_reqmsg);
 }
 
 static inline void oti_alloc_cookies(struct obd_trans_info *oti,int num_cookies)
@@ -711,33 +793,46 @@ struct obd_notify_upcall {
 };
 
 /* corresponds to one of the obd's */
+#define MAX_OBD_NAME 128
+#define OBD_DEVICE_MAGIC        0XAB5CD6EF
 struct obd_device {
         struct obd_type        *obd_type;
+        __u32                   obd_magic;
+
         /* common and UUID name of this device */
-        char                   *obd_name;
+        char                    obd_name[MAX_OBD_NAME];
         struct obd_uuid         obd_uuid;
 
         struct lu_device       *obd_lu_dev;
 
         int                     obd_minor;
-        unsigned int obd_attached:1, obd_set_up:1, obd_recovering:1,
-                obd_abort_recovery:1, obd_replayable:1, obd_no_transno:1,
-                obd_no_recov:1, obd_stopping:1, obd_starting:1,
-                obd_force:1, obd_fail:1, obd_async_recov:1;
+        unsigned int obd_attached:1,      /* finished attach */
+                     obd_set_up:1,        /* finished setup */
+                     obd_recovering:1,    /* there are recoverable clients */
+                     obd_abort_recovery:1,/* somebody ioctl'ed us to abort */ 
+                     obd_replayable:1,    /* recovery is enabled; inform clients */
+                     obd_no_transno:1,    /* no committed-transno notification */
+                     obd_no_recov:1,      /* fail instead of retry messages */
+                     obd_stopping:1,      /* started cleanup */
+                     obd_starting:1,      /* started setup */
+                     obd_force:1,         /* cleanup with > 0 obd refcount */
+                     obd_fail:1,          /* cleanup with failover */
+                     obd_async_recov:1;   /* allow asyncronous orphan cleanup */
         atomic_t obd_refcount;
         cfs_waitq_t             obd_refcount_waitq;
-        cfs_proc_dir_entry_t  *obd_proc_entry;
+        cfs_proc_dir_entry_t   *obd_proc_entry;
         struct list_head        obd_exports;
         int                     obd_num_exports;
         struct ldlm_namespace  *obd_namespace;
         struct ptlrpc_client    obd_ldlm_client; /* XXX OST/MDS only */
         /* a spinlock is OK for what we do now, may need a semaphore later */
         spinlock_t              obd_dev_lock;
+        struct semaphore        obd_dev_sem;
         __u64                   obd_last_committed;
         struct fsfilt_operations *obd_fsops;
         spinlock_t              obd_osfs_lock;
         struct obd_statfs       obd_osfs;       /* locked by obd_osfs_lock */
-        cfs_time_t              obd_osfs_age;
+        __u64                   obd_osfs_age;
         struct lvfs_run_ctxt    obd_lvfs_ctxt;
         struct llog_ctxt        *obd_llog_ctxt[LLOG_MAX_CTXTS];
         struct obd_device       *obd_observer;
@@ -752,7 +847,7 @@ struct obd_device {
         int                              obd_max_recoverable_clients;
         int                              obd_connected_clients;
         int                              obd_recoverable_clients;
-        spinlock_t                       obd_processing_task_lock;
+        spinlock_t                       obd_processing_task_lock; /* BH lock (timer) */
         pid_t                            obd_processing_task;
         __u64                            obd_next_recovery_transno;
         int                              obd_replayed_requests;
@@ -860,7 +955,9 @@ struct obd_ops {
         int (*o_fid_delete)(struct obd_export *exp, struct lu_fid *fid);
 
         int (*o_statfs)(struct obd_device *obd, struct obd_statfs *osfs,
-                        unsigned long max_age);
+                        __u64 max_age);
+        int (*o_statfs_async)(struct obd_device *obd, struct obd_info *oinfo,
+                              __u64 max_age, struct ptlrpc_request_set *set);
         int (*o_packmd)(struct obd_export *exp, struct lov_mds_md **disk_tgt,
                         struct lov_stripe_md *mem_src);
         int (*o_unpackmd)(struct obd_export *exp,struct lov_stripe_md **mem_tgt,
@@ -874,22 +971,21 @@ struct obd_ops {
         int (*o_destroy)(struct obd_export *exp, struct obdo *oa,
                          struct lov_stripe_md *ea, struct obd_trans_info *oti,
                          struct obd_export *md_exp);
-        int (*o_setattr)(struct obd_export *exp, struct obdo *oa,
-                         struct lov_stripe_md *ea, struct obd_trans_info *oti);
-        int (*o_setattr_async)(struct obd_export *exp, struct obdo *oa,
-                         struct lov_stripe_md *ea, struct obd_trans_info *oti);
-        int (*o_getattr)(struct obd_export *exp, struct obdo *oa,
-                         struct lov_stripe_md *ea);
-        int (*o_getattr_async)(struct obd_export *exp, struct obdo *oa,
-                               struct lov_stripe_md *ea,
+        int (*o_setattr)(struct obd_export *exp, struct obd_info *oinfo,
+                         struct obd_trans_info *oti);
+        int (*o_setattr_async)(struct obd_export *exp, struct obd_info *oinfo,
+                               struct obd_trans_info *oti,
+                               struct ptlrpc_request_set *rqset);
+        int (*o_getattr)(struct obd_export *exp, struct obd_info *oinfo);
+        int (*o_getattr_async)(struct obd_export *exp, struct obd_info *oinfo,
                                struct ptlrpc_request_set *set);
-        int (*o_brw)(int rw, struct obd_export *exp, struct obdo *oa,
-                     struct lov_stripe_md *ea, obd_count oa_bufs,
-                     struct brw_page *pgarr, struct obd_trans_info *oti);
-        int (*o_brw_async)(int rw, struct obd_export *exp, struct obdo *oa,
-                           struct lov_stripe_md *ea, obd_count oa_bufs,
-                           struct brw_page *pgarr, struct ptlrpc_request_set *,
-                           struct obd_trans_info *oti);
+        int (*o_brw)(int rw, struct obd_export *exp, struct obd_info *oinfo,
+                     obd_count oa_bufs, struct brw_page *pgarr,
+                     struct obd_trans_info *oti);
+        int (*o_brw_async)(int rw, struct obd_export *exp,
+                           struct obd_info *oinfo, obd_count oa_bufs,
+                           struct brw_page *pgarr, struct obd_trans_info *oti,
+                           struct ptlrpc_request_set *);
         int (*o_prep_async_page)(struct obd_export *exp,
                                  struct lov_stripe_md *lsm,
                                  struct lov_oinfo *loi,
@@ -922,9 +1018,9 @@ struct obd_ops {
                            struct ost_lvb *lvb, int kms_only);
         int (*o_adjust_kms)(struct obd_export *exp, struct lov_stripe_md *lsm,
                             obd_off size, int shrink);
-        int (*o_punch)(struct obd_export *exp, struct obdo *oa,
-                       struct lov_stripe_md *ea, obd_size start,
-                       obd_size end, struct obd_trans_info *oti);
+        int (*o_punch)(struct obd_export *exp, struct obd_info *oinfo,
+                       struct obd_trans_info *oti,
+                       struct ptlrpc_request_set *rqset);
         int (*o_sync)(struct obd_export *exp, struct obdo *oa,
                       struct lov_stripe_md *ea, obd_size start, obd_size end);
         int (*o_migrate)(struct lustre_handle *conn, struct lov_stripe_md *dst,
@@ -944,11 +1040,8 @@ struct obd_ops {
                           int objcount, struct obd_ioobj *obj,
                           int niocount, struct niobuf_local *local,
                           struct obd_trans_info *oti, int rc);
-        int (*o_enqueue)(struct obd_export *, struct lov_stripe_md *,
-                         __u32 type, ldlm_policy_data_t *, __u32 mode,
-                         int *flags, void *bl_cb, void *cp_cb, void *gl_cb,
-                         void *data, __u32 lvb_len, void *lvb_swabber,
-                         struct lustre_handle *lockh);
+        int (*o_enqueue)(struct obd_export *, struct obd_info *oinfo,
+                         struct obd_enqueue_info *einfo);
         int (*o_match)(struct obd_export *, struct lov_stripe_md *, __u32 type,
                        ldlm_policy_data_t *, __u32 mode, int *flags, void *data,
                        struct lustre_handle *lockh);
@@ -966,6 +1059,8 @@ struct obd_ops {
                             struct niobuf_remote *remote);
         int (*o_init_export)(struct obd_export *exp);
         int (*o_destroy_export)(struct obd_export *exp);
+        int (*o_extent_calc)(struct obd_export *, struct lov_stripe_md *,
+                             int cmd, obd_off *);
 
         /* llog related obd_methods */
         int (*o_llog_init)(struct obd_device *obd, struct obd_device *disk_obd,
@@ -989,15 +1084,11 @@ struct obd_ops {
         int (*o_quotacheck)(struct obd_export *, struct obd_quotactl *);
         int (*o_quotactl)(struct obd_export *, struct obd_quotactl *);
 
+        int (*o_ping)(struct obd_export *exp);
         /*
          * NOTE: If adding ops, add another LPROCFS_OBD_OP_INIT() line
          * to lprocfs_alloc_obd_stats() in obdclass/lprocfs_status.c.
-         * Also, add a wrapper function in include/linux/obd_class.h.
-         *
-         * Also note that if you add it to the END, you also have to change
-         * the num_stats calculation.
-         *
-         */
+         * Also, add a wrapper function in include/linux/obd_class.h. */
 };
 
 struct md_ops {
@@ -1108,6 +1199,10 @@ static inline struct lsm_operations *lsm_op_find(int magic)
 
 int lvfs_check_io_health(struct obd_device *obd, struct file *file);
 
+/* Requests for obd_extent_calc() */
+#define OBD_CALC_STRIPE_START   1
+#define OBD_CALC_STRIPE_END     2
+
 static inline void obd_transno_commit_cb(struct obd_device *obd, __u64 transno,
                                          int error)
 {
index d22bc67..2f2bddc 100644 (file)
@@ -42,8 +42,8 @@
 #endif
 
 /* OBD Device Declarations */
-#define MAX_OBD_DEVICES 520
-extern struct obd_device obd_dev[MAX_OBD_DEVICES];
+#define MAX_OBD_DEVICES 2048
+extern struct obd_device *obd_devs[MAX_OBD_DEVICES];
 extern spinlock_t obd_dev_lock;
 
 /* OBD Operations Declarations */
@@ -59,7 +59,7 @@ int class_register_type(struct obd_ops *, struct md_ops *,
                         struct lu_device_type *ldt);
 int class_unregister_type(const char *nm);
 
-struct obd_device *class_newdev(struct obd_type *type, char *name);
+struct obd_device *class_newdev(const char *type_name, const char *name);
 void class_release_dev(struct obd_device *obd);
 
 int class_name2dev(const char *name);
@@ -74,10 +74,10 @@ struct obd_device * class_find_client_notype(struct obd_uuid *tgt_uuid,
                                              struct obd_uuid *grp_uuid);
 struct obd_device * class_devices_in_group(struct obd_uuid *grp_uuid,
                                            int *next);
+struct obd_device * class_num2obd(int num);
 
 int oig_init(struct obd_io_group **oig);
-void oig_add_one(struct obd_io_group *oig,
-                  struct oig_callback_context *occ);
+int oig_add_one(struct obd_io_group *oig, struct oig_callback_context *occ);
 void oig_complete_one(struct obd_io_group *oig,
                       struct oig_callback_context *occ, int rc);
 void oig_release(struct obd_io_group *oig);
@@ -90,6 +90,8 @@ int obd_export_evict_by_uuid(struct obd_device *obd, const char *uuid);
 
 /* obd_config.c */
 int class_process_config(struct lustre_cfg *lcfg);
+int class_process_proc_param(char *prefix, struct lprocfs_vars *lvars, 
+                             struct lustre_cfg *lcfg, void *data);
 int class_attach(struct lustre_cfg *lcfg);
 int class_setup(struct obd_device *obd, struct lustre_cfg *lcfg);
 int class_cleanup(struct obd_device *obd, struct lustre_cfg *lcfg);
@@ -100,10 +102,9 @@ void class_decref(struct obd_device *obd);
 #define CFG_F_START     0x01   /* Set when we start updating from a log */
 #define CFG_F_MARKER    0x02   /* We are within a maker */
 #define CFG_F_SKIP      0x04   /* We should ignore this cfg command */
-#define CFG_F_COMPAT146 0x08   /* Translation to new obd names required */
+#define CFG_F_COMPAT146 0x08   /* Using old-style log */
 #define CFG_F_EXCLUDE   0x10   /* OST exclusion list */
 
-
 /* Passed as data param to class_config_parse_llog */
 struct config_llog_instance {
         char *              cfg_instance;
@@ -124,18 +125,20 @@ struct config_llog_data {
         struct config_llog_instance cld_cfg;
         struct list_head    cld_list_chain;
         atomic_t            cld_refcount;
+        struct obd_export  *cld_mgcexp;
         unsigned int        cld_stopping:1;
 };
 
 struct lustre_profile {
         struct list_head lp_list;
-        char lp_profile;
-        char * lp_osc;
-        char * lp_mdc;
+        char            *lp_profile;
+        char            *lp_dt;
+        char            *lp_md;
 };
 
 struct lustre_profile *class_get_profile(const char * prof);
 void class_del_profile(const char *prof);
+void class_del_profiles(void);
 
 /* genops.c */
 #define class_export_get(exp)                                                  \
@@ -310,6 +313,11 @@ do {                                                            \
         }                                                       \
 } while (0)
 
+static inline int class_devno_max(void)
+{
+        return MAX_OBD_DEVICES;
+}
+
 static inline int obd_get_info(struct obd_export *exp, __u32 keylen,
                                void *key, __u32 *vallen, void *val)
 {
@@ -606,8 +614,7 @@ static inline int obd_destroy(struct obd_export *exp, struct obdo *obdo,
         RETURN(rc);
 }
 
-static inline int obd_getattr(struct obd_export *exp, struct obdo *obdo,
-                              struct lov_stripe_md *ea)
+static inline int obd_getattr(struct obd_export *exp, struct obd_info *oinfo)
 {
         int rc;
         ENTRY;
@@ -615,26 +622,25 @@ static inline int obd_getattr(struct obd_export *exp, struct obdo *obdo,
         EXP_CHECK_DT_OP(exp, getattr);
         OBD_COUNTER_INCREMENT(exp->exp_obd, getattr);
 
-        rc = OBP(exp->exp_obd, getattr)(exp, obdo, ea);
+        rc = OBP(exp->exp_obd, getattr)(exp, oinfo);
         RETURN(rc);
 }
 
 static inline int obd_getattr_async(struct obd_export *exp,
-                                    struct obdo *obdo, struct lov_stripe_md *ea,
+                                    struct obd_info *oinfo,
                                     struct ptlrpc_request_set *set)
 {
         int rc;
         ENTRY;
 
-        EXP_CHECK_DT_OP(exp, getattr);
-        OBD_COUNTER_INCREMENT(exp->exp_obd, getattr);
+        EXP_CHECK_DT_OP(exp, getattr_async);
+        OBD_COUNTER_INCREMENT(exp->exp_obd, getattr_async);
 
-        rc = OBP(exp->exp_obd, getattr_async)(exp, obdo, ea, set);
+        rc = OBP(exp->exp_obd, getattr_async)(exp, oinfo, set);
         RETURN(rc);
 }
 
-static inline int obd_setattr(struct obd_export *exp, struct obdo *obdo,
-                              struct lov_stripe_md *ea,
+static inline int obd_setattr(struct obd_export *exp, struct obd_info *oinfo,
                               struct obd_trans_info *oti)
 {
         int rc;
@@ -643,22 +649,47 @@ static inline int obd_setattr(struct obd_export *exp, struct obdo *obdo,
         EXP_CHECK_DT_OP(exp, setattr);
         OBD_COUNTER_INCREMENT(exp->exp_obd, setattr);
 
-        rc = OBP(exp->exp_obd, setattr)(exp, obdo, ea, oti);
+        rc = OBP(exp->exp_obd, setattr)(exp, oinfo, oti);
         RETURN(rc);
 }
 
-static inline int obd_setattr_async(struct obd_export *exp,
-                                    struct obdo *obdo,
-                                    struct lov_stripe_md *ea,
+/* This performs all the requests set init/wait/destroy actions. */
+static inline int obd_setattr_rqset(struct obd_export *exp,
+                                    struct obd_info *oinfo,
                                     struct obd_trans_info *oti)
 {
+        struct ptlrpc_request_set *set = NULL;
+        int rc;
+        ENTRY;
+
+        EXP_CHECK_DT_OP(exp, setattr_async);
+        OBD_COUNTER_INCREMENT(exp->exp_obd, setattr_async);
+
+        set =  ptlrpc_prep_set();
+        if (set == NULL)
+                RETURN(-ENOMEM);
+
+        rc = OBP(exp->exp_obd, setattr_async)(exp, oinfo, oti, set);
+        if (rc == 0)
+                rc = ptlrpc_set_wait(set);
+        ptlrpc_set_destroy(set);
+        RETURN(rc);
+}
+
+/* This adds all the requests into @set if @set != NULL, otherwise
+   all requests are sent asynchronously without waiting for response. */
+static inline int obd_setattr_async(struct obd_export *exp,
+                                    struct obd_info *oinfo,
+                                    struct obd_trans_info *oti,
+                                    struct ptlrpc_request_set *set)
+{
         int rc;
         ENTRY;
 
         EXP_CHECK_DT_OP(exp, setattr_async);
         OBD_COUNTER_INCREMENT(exp->exp_obd, setattr_async);
 
-        rc = OBP(exp->exp_obd, setattr_async)(exp, obdo, ea, oti);
+        rc = OBP(exp->exp_obd, setattr_async)(exp, oinfo, oti, set);
         RETURN(rc);
 }
 
@@ -801,6 +832,18 @@ static inline int obd_fid_delete(struct obd_export *exp,
         RETURN(rc);
 }
 
+static inline int obd_ping(struct obd_export *exp)
+{
+        int rc;
+        ENTRY;
+
+        OBD_CHECK_DT_OP(exp->exp_obd, ping, 0);
+        OBD_COUNTER_INCREMENT(exp->exp_obd, ping);
+
+        rc = OBP(exp->exp_obd, ping)(exp);
+        RETURN(rc);
+}
+
 static inline int obd_init_export(struct obd_export *exp)
 {
         int rc = 0;
@@ -821,6 +864,17 @@ static inline int obd_destroy_export(struct obd_export *exp)
         RETURN(0);
 }
 
+static inline int obd_extent_calc(struct obd_export *exp,
+                                  struct lov_stripe_md *md,
+                                  int cmd, obd_off *offset)
+{
+        int rc;
+        ENTRY;
+        EXP_CHECK_DT_OP(exp, extent_calc);
+        rc = OBP(exp->exp_obd, extent_calc)(exp, md, cmd, offset);
+        RETURN(rc);
+}
+
 static inline struct dentry *
 obd_lvfs_fid2dentry(struct obd_export *exp, __u64 id_ino, __u32 gen, __u64 gr)
 {
@@ -848,9 +902,61 @@ obd_lvfs_open_llog(struct obd_export *exp, __u64 id_ino, struct dentry *dentry)
 
 /* @max_age is the oldest time in jiffies that we accept using a cached data.
  * If the cache is older than @max_age we will get a new value from the
- * target.  Use a value of "jiffies + HZ" to guarantee freshness. */
+ * target.  Use a value of "cfs_time_current() + HZ" to guarantee freshness. */
+static inline int obd_statfs_async(struct obd_device *obd,
+                                   struct obd_info *oinfo,
+                                   __u64 max_age,
+                                   struct ptlrpc_request_set *rqset)
+{
+        int rc = 0;
+        ENTRY;
+
+        if (obd == NULL)
+                RETURN(-EINVAL);
+
+        OBD_CHECK_DT_OP(obd, statfs, -EOPNOTSUPP);
+        OBD_COUNTER_INCREMENT(obd, statfs);
+
+        CDEBUG(D_SUPER, "osfs "LPU64", max_age "LPU64"\n",
+               obd->obd_osfs_age, max_age);
+        if (cfs_time_before_64(obd->obd_osfs_age, max_age)) {
+                rc = OBP(obd, statfs_async)(obd, oinfo, max_age, rqset);
+        } else {
+                CDEBUG(D_SUPER, "using cached obd_statfs data\n");
+                spin_lock(&obd->obd_osfs_lock);
+                memcpy(oinfo->oi_osfs, &obd->obd_osfs, sizeof(*oinfo->oi_osfs));
+                spin_unlock(&obd->obd_osfs_lock);
+                if (oinfo->oi_cb_up)
+                        oinfo->oi_cb_up(oinfo, 0);
+        }
+        RETURN(rc);
+}
+
+static inline int obd_statfs_rqset(struct obd_device *obd,
+                                   struct obd_statfs *osfs, __u64 max_age)
+{
+        struct ptlrpc_request_set *set = NULL;
+        struct obd_info oinfo = { { { 0 } } };
+        int rc = 0;
+        ENTRY;
+
+        set =  ptlrpc_prep_set();
+        if (set == NULL)
+                RETURN(-ENOMEM);
+
+        oinfo.oi_osfs = osfs;
+        rc = obd_statfs_async(obd, &oinfo, max_age, set);
+        if (rc == 0)
+                rc = ptlrpc_set_wait(set);
+        ptlrpc_set_destroy(set);
+        RETURN(rc);
+}
+
+/* @max_age is the oldest time in jiffies that we accept using a cached data.
+ * If the cache is older than @max_age we will get a new value from the
+ * target.  Use a value of "cfs_time_current() + HZ" to guarantee freshness. */
 static inline int obd_statfs(struct obd_device *obd, struct obd_statfs *osfs,
-                             unsigned long max_age)
+                             __u64 max_age)
 {
         int rc = 0;
         ENTRY;
@@ -861,13 +967,14 @@ static inline int obd_statfs(struct obd_device *obd, struct obd_statfs *osfs,
         OBD_CHECK_DT_OP(obd, statfs, -EOPNOTSUPP);
         OBD_COUNTER_INCREMENT(obd, statfs);
 
-        CDEBUG(D_SUPER, "osfs %lu, max_age %lu\n", obd->obd_osfs_age, max_age);
-        if (time_before(obd->obd_osfs_age, max_age)) {
+        CDEBUG(D_SUPER, "osfs "LPU64", max_age "LPU64"\n",
+               obd->obd_osfs_age, max_age);
+        if (cfs_time_before_64(obd->obd_osfs_age, max_age)) {
                 rc = OBP(obd, statfs)(obd, osfs, max_age);
                 if (rc == 0) {
                         spin_lock(&obd->obd_osfs_lock);
                         memcpy(&obd->obd_osfs, osfs, sizeof(obd->obd_osfs));
-                        obd->obd_osfs_age = jiffies;
+                        obd->obd_osfs_age = cfs_time_current_64();
                         spin_unlock(&obd->obd_osfs_lock);
                 }
         } else {
@@ -893,22 +1000,44 @@ static inline int obd_sync(struct obd_export *exp, struct obdo *oa,
         RETURN(rc);
 }
 
-static inline int obd_punch(struct obd_export *exp, struct obdo *oa,
-                            struct lov_stripe_md *ea, obd_size start,
-                            obd_size end, struct obd_trans_info *oti)
+static inline int obd_punch_rqset(struct obd_export *exp,
+                                  struct obd_info *oinfo,
+                                  struct obd_trans_info *oti)
 {
+        struct ptlrpc_request_set *set = NULL;
         int rc;
         ENTRY;
 
         EXP_CHECK_DT_OP(exp, punch);
         OBD_COUNTER_INCREMENT(exp->exp_obd, punch);
 
-        rc = OBP(exp->exp_obd, punch)(exp, oa, ea, start, end, oti);
+        set =  ptlrpc_prep_set();
+        if (set == NULL)
+                RETURN(-ENOMEM);
+
+        rc = OBP(exp->exp_obd, punch)(exp, oinfo, oti, set);
+        if (rc == 0)
+                rc = ptlrpc_set_wait(set);
+        ptlrpc_set_destroy(set);
+        RETURN(rc);
+}
+
+static inline int obd_punch(struct obd_export *exp, struct obd_info *oinfo,
+                            struct obd_trans_info *oti,
+                            struct ptlrpc_request_set *rqset)
+{
+        int rc;
+        ENTRY;
+
+        EXP_CHECK_DT_OP(exp, punch);
+        OBD_COUNTER_INCREMENT(exp->exp_obd, punch);
+
+        rc = OBP(exp->exp_obd, punch)(exp, oinfo, oti, rqset);
         RETURN(rc);
 }
 
-static inline int obd_brw(int cmd, struct obd_export *exp, struct obdo *oa,
-                          struct lov_stripe_md *ea, obd_count oa_bufs,
+static inline int obd_brw(int cmd, struct obd_export *exp,
+                          struct obd_info *oinfo, obd_count oa_bufs,
                           struct brw_page *pg, struct obd_trans_info *oti)
 {
         int rc;
@@ -923,15 +1052,14 @@ static inline int obd_brw(int cmd, struct obd_export *exp, struct obdo *oa,
                 LBUG();
         }
 
-        rc = OBP(exp->exp_obd, brw)(cmd, exp, oa, ea, oa_bufs, pg, oti);
+        rc = OBP(exp->exp_obd, brw)(cmd, exp, oinfo, oa_bufs, pg, oti);
         RETURN(rc);
 }
 
 static inline int obd_brw_async(int cmd, struct obd_export *exp,
-                                struct obdo *oa, struct lov_stripe_md *ea,
-                                obd_count oa_bufs, struct brw_page *pg,
-                                struct ptlrpc_request_set *set,
-                                struct obd_trans_info *oti)
+                                struct obd_info *oinfo, obd_count oa_bufs,
+                                struct brw_page *pg, struct obd_trans_info *oti,
+                                struct ptlrpc_request_set *set)
 {
         int rc;
         ENTRY;
@@ -944,8 +1072,35 @@ static inline int obd_brw_async(int cmd, struct obd_export *exp,
                 LBUG();
         }
 
-        rc = OBP(exp->exp_obd, brw_async)(cmd, exp, oa, ea, oa_bufs, pg, set,
-                                          oti);
+        rc = OBP(exp->exp_obd, brw_async)(cmd, exp, oinfo, oa_bufs, pg,oti,set);
+        RETURN(rc);
+}
+
+static inline int obd_brw_rqset(int cmd, struct obd_export *exp,
+                                struct obdo *oa, struct lov_stripe_md *lsm,
+                                obd_count oa_bufs, struct brw_page *pg,
+                                struct obd_trans_info *oti)
+{
+        struct ptlrpc_request_set *set = NULL;
+        struct obd_info oinfo = { { { 0 } } };
+        int rc = 0;
+        ENTRY;
+
+        set =  ptlrpc_prep_set();
+        if (set == NULL)
+                RETURN(-ENOMEM);
+
+        oinfo.oi_oa = oa;
+        oinfo.oi_md = lsm;
+        rc = obd_brw_async(cmd, exp, &oinfo, oa_bufs, pg, oti, set);
+        if (rc == 0) {
+                rc = ptlrpc_set_wait(set);
+                if (rc)
+                        CERROR("error from callback: rc = %d\n", rc);
+        } else {
+                CDEBUG(D_INODE, "error from obd_brw_async: rc = %d\n", rc);
+        }
+        ptlrpc_set_destroy(set);
         RETURN(rc);
 }
 
@@ -1124,11 +1279,32 @@ static inline int obd_iocontrol(unsigned int cmd, struct obd_export *exp,
         RETURN(rc);
 }
 
-static inline int obd_enqueue(struct obd_export *exp, struct lov_stripe_md *ea,
-                              __u32 type, ldlm_policy_data_t *policy,
-                              __u32 mode, int *flags, void *bl_cb, void *cp_cb,
-                              void *gl_cb, void *data, __u32 lvb_len,
-                              void *lvb_swabber, struct lustre_handle *lockh)
+static inline int obd_enqueue_rqset(struct obd_export *exp,
+                                    struct obd_info *oinfo,
+                                    struct obd_enqueue_info *einfo)
+{
+        int rc;
+        ENTRY;
+
+        EXP_CHECK_DT_OP(exp, enqueue);
+        OBD_COUNTER_INCREMENT(exp->exp_obd, enqueue);
+
+        einfo->ei_rqset =  ptlrpc_prep_set();
+        if (einfo->ei_rqset == NULL)
+                RETURN(-ENOMEM);
+
+        rc = OBP(exp->exp_obd, enqueue)(exp, oinfo, einfo);
+        if (rc == 0)
+                rc = ptlrpc_set_wait(einfo->ei_rqset);
+        ptlrpc_set_destroy(einfo->ei_rqset);
+        einfo->ei_rqset = NULL;
+
+        RETURN(rc);
+}
+
+static inline int obd_enqueue(struct obd_export *exp,
+                              struct obd_info *oinfo,
+                              struct obd_enqueue_info *einfo)
 {
         int rc;
         ENTRY;
@@ -1136,9 +1312,7 @@ static inline int obd_enqueue(struct obd_export *exp, struct lov_stripe_md *ea,
         EXP_CHECK_DT_OP(exp, enqueue);
         OBD_COUNTER_INCREMENT(exp->exp_obd, enqueue);
 
-        rc = OBP(exp->exp_obd, enqueue)(exp, ea, type, policy, mode, flags,
-                                        bl_cb, cp_cb, gl_cb, data, lvb_len,
-                                        lvb_swabber, lockh);
+        rc = OBP(exp->exp_obd, enqueue)(exp, oinfo, einfo);
         RETURN(rc);
 }
 
@@ -1357,7 +1531,7 @@ static inline int obd_health_check(struct obd_device *obd)
         int rc;
         ENTRY;
 
-        /* don't use EXP_CHECK_OP, because NULL method is normal here */
+        /* don't use EXP_CHECK_DT_OP, because NULL method is normal here */
         if (obd == NULL || !OBT(obd)) {
                 CERROR("cleaned up obd\n");
                 RETURN(-EOPNOTSUPP);
index 50aace7..48526ad 100644 (file)
@@ -18,13 +18,19 @@ struct osc_brw_async_args {
         int              aa_requested_nob;
         int              aa_nio_count;
         obd_count        aa_page_count;
-        struct brw_page *aa_pga;
+        struct brw_page **aa_ppga;
         struct client_obd *aa_cli;
         struct list_head aa_oaps;
 };
 
-struct osc_getattr_async_args {
-        struct obdo     *aa_oa;
+struct osc_async_args {
+        struct obd_info   *aa_oi;
+};
+
+struct osc_enqueue_args {
+        struct obd_export       *oa_exp;
+        struct obd_info         *oa_oi;
+        struct obd_enqueue_info *oa_ei;
 };
 
 #endif
index 87c27e4..40e57cd 100644 (file)
@@ -37,6 +37,7 @@ extern unsigned int ldlm_timeout;
 extern unsigned int obd_health_check_timeout;
 extern char obd_lustre_upcall[128];
 extern cfs_waitq_t obd_race_waitq;
+extern int obd_race_state;
 
 #define OBD_FAIL_MDS                     0x100
 #define OBD_FAIL_MDS_HANDLE_UNPACK       0x101
@@ -118,6 +119,7 @@ extern cfs_waitq_t obd_race_waitq;
 #define OBD_FAIL_OST_ENOENT              0x217
 #define OBD_FAIL_OST_QUOTACHECK_NET      0x218
 #define OBD_FAIL_OST_QUOTACTL_NET        0x219
+#define OBD_FAIL_OST_BRW_SIZE            0x21a
 
 #define OBD_FAIL_LDLM                    0x300
 #define OBD_FAIL_LDLM_NAMESPACE_NEW      0x301
@@ -169,6 +171,7 @@ extern cfs_waitq_t obd_race_waitq;
 #define OBD_FAIL_MGS                     0x900
 #define OBD_FAIL_MGS_ALL_REQUEST_NET     0x901
 #define OBD_FAIL_MGS_ALL_REPLY_NET       0x902
+#define OBD_FAIL_MGC_PROCESS_LOG         0x903
 
 #define OBD_FAIL_SEQ                     0x1000
 #define OBD_FAIL_SEQ_ALL_REQUEST_NET     0x1001
@@ -183,8 +186,6 @@ extern cfs_waitq_t obd_race_waitq;
 #define OBD_FAIL_MASK_LOC    (0x000000FF | OBD_FAIL_MASK_SYS)
 #define OBD_FAIL_ONCE        0x80000000
 #define OBD_FAILED           0x40000000
-#define OBD_FAIL_MDS_ALL_NET 0x01000000
-#define OBD_FAIL_OST_ALL_NET 0x02000000
 
 #define OBD_FAIL_CHECK(id)   (((obd_fail_loc & OBD_FAIL_MASK_LOC) ==           \
                               ((id) & OBD_FAIL_MASK_LOC)) &&                   \
@@ -228,8 +229,8 @@ do {                                                                         \
  * first thread that calls this with a matching fail_loc is put to
  * sleep. The next thread that calls with the same fail_loc wakes up
  * the first and continues. */
-#define OBD_RACE(id)                                            \
-do {                                                            \
+#define OBD_RACE(id)                                                           \
+do {                                                                           \
         if  (OBD_FAIL_CHECK_ONCE(id)) {                         \
                 CERROR("obd_race id %x sleeping\n", (id));      \
                 OBD_SLEEP_ON(&obd_race_waitq);        \
index 6d1a75b..21c0c0b 100644 (file)
@@ -622,6 +622,7 @@ CONFIG_SCSI_IN2000=m
 CONFIG_SCSI_AM53C974=m
 CONFIG_SCSI_MEGARAID=m
 CONFIG_SCSI_MEGARAID2=m
+CONFIG_SCSI_MEGARAID_SAS=m
 CONFIG_SCSI_SATA=y
 CONFIG_SCSI_SATA_AHCI=m
 CONFIG_SCSI_SATA_SVW=m
@@ -714,7 +715,7 @@ CONFIG_PCMCIA_QLOGIC=m
 CONFIG_FUSION=m
 # CONFIG_FUSION_BOOT is not set
 CONFIG_FUSION_MAX_SGE=40
-# CONFIG_FUSION_ISENSE is not set
+CONFIG_FUSION_ISENSE=m
 CONFIG_FUSION_CTL=m
 CONFIG_FUSION_LAN=m
 CONFIG_NET_FC=y
@@ -872,6 +873,7 @@ CONFIG_YELLOWFIN=m
 CONFIG_R8169=m
 CONFIG_SK98LIN=m
 CONFIG_TIGON3=m
+CONFIG_BNX2=m
 
 #
 # Quadrics QsNet device support
@@ -2053,6 +2055,8 @@ CONFIG_FC_QLA2300=m
 CONFIG_SCSI_ISCSI=m
 # CONFIG_SCSI_IPR is not set
 CONFIG_SCSI_LPFC=m
+CONFIG_FUSION_ISENSE=m
+CONFIG_DELL_RBU=m
 
 #
 # Bluetooth support
index 6d1a75b..658522a 100644 (file)
@@ -622,6 +622,7 @@ CONFIG_SCSI_IN2000=m
 CONFIG_SCSI_AM53C974=m
 CONFIG_SCSI_MEGARAID=m
 CONFIG_SCSI_MEGARAID2=m
+CONFIG_SCSI_MEGARAID_SAS=m
 CONFIG_SCSI_SATA=y
 CONFIG_SCSI_SATA_AHCI=m
 CONFIG_SCSI_SATA_SVW=m
@@ -872,6 +873,7 @@ CONFIG_YELLOWFIN=m
 CONFIG_R8169=m
 CONFIG_SK98LIN=m
 CONFIG_TIGON3=m
+CONFIG_BNX2=m
 
 #
 # Quadrics QsNet device support
@@ -2053,6 +2055,8 @@ CONFIG_FC_QLA2300=m
 CONFIG_SCSI_ISCSI=m
 # CONFIG_SCSI_IPR is not set
 CONFIG_SCSI_LPFC=m
+# CONFIG_FUSION_ISENSE is not set
+CONFIG_DELL_RBU=m
 
 #
 # Bluetooth support
index 4fb3337..a43b807 100644 (file)
@@ -570,6 +570,7 @@ CONFIG_AIC7XXX_OLD_PROC_STATS=y
 # CONFIG_SCSI_AM53C974 is not set
 CONFIG_SCSI_MEGARAID=m
 CONFIG_SCSI_MEGARAID2=m
+CONFIG_SCSI_MEGARAID_SAS=m
 CONFIG_SCSI_SATA=y
 CONFIG_SCSI_SATA_AHCI=m
 CONFIG_SCSI_SATA_SVW=m
@@ -721,6 +722,7 @@ CONFIG_YELLOWFIN=m
 CONFIG_R8169=m
 CONFIG_SK98LIN=m
 CONFIG_TIGON3=m
+CONFIG_BNX2=m
 
 #
 # Quadrics QsNet device support
@@ -1426,6 +1428,8 @@ CONFIG_FC_QLA2300=m
 CONFIG_SCSI_ISCSI=m
 # CONFIG_SCSI_IPR is not set
 CONFIG_SCSI_LPFC=m
+# CONFIG_FUSION_ISENSE is not set
+CONFIG_DELL_RBU=m
 
 #
 # Kernel hacking
index 4fb3337..a43b807 100644 (file)
@@ -570,6 +570,7 @@ CONFIG_AIC7XXX_OLD_PROC_STATS=y
 # CONFIG_SCSI_AM53C974 is not set
 CONFIG_SCSI_MEGARAID=m
 CONFIG_SCSI_MEGARAID2=m
+CONFIG_SCSI_MEGARAID_SAS=m
 CONFIG_SCSI_SATA=y
 CONFIG_SCSI_SATA_AHCI=m
 CONFIG_SCSI_SATA_SVW=m
@@ -721,6 +722,7 @@ CONFIG_YELLOWFIN=m
 CONFIG_R8169=m
 CONFIG_SK98LIN=m
 CONFIG_TIGON3=m
+CONFIG_BNX2=m
 
 #
 # Quadrics QsNet device support
@@ -1426,6 +1428,8 @@ CONFIG_FC_QLA2300=m
 CONFIG_SCSI_ISCSI=m
 # CONFIG_SCSI_IPR is not set
 CONFIG_SCSI_LPFC=m
+# CONFIG_FUSION_ISENSE is not set
+CONFIG_DELL_RBU=m
 
 #
 # Kernel hacking
index 9b1c043..03230c2 100644 (file)
@@ -26,7 +26,7 @@ CONFIG_KMOD=y
 #
 # Processor type and features
 #
-# CONFIG_MK8
+# CONFIG_MK8 is not set
 # CONFIG_IA32E is not set
 CONFIG_GENERIC_CPU=y
 CONFIG_X86_L1_CACHE_BYTES=64
@@ -116,6 +116,7 @@ CONFIG_ACPI_THERMAL=m
 # CONFIG_ACPI_ASUS is not set
 # CONFIG_ACPI_TOSHIBA is not set
 # CONFIG_ACPI_DEBUG is not set
+# CONFIG_ACPI_PMTMR is not set
 
 #
 # Memory Technology Devices (MTD)
@@ -576,6 +577,7 @@ CONFIG_AIC7XXX_OLD_PROC_STATS=y
 # CONFIG_SCSI_AM53C974 is not set
 CONFIG_SCSI_MEGARAID=m
 CONFIG_SCSI_MEGARAID2=m
+CONFIG_SCSI_MEGARAID_SAS=m
 CONFIG_SCSI_SATA=y
 CONFIG_SCSI_SATA_AHCI=m
 CONFIG_SCSI_SATA_SVW=m
@@ -781,6 +783,7 @@ CONFIG_YELLOWFIN=m
 CONFIG_R8169=m
 CONFIG_SK98LIN=m
 CONFIG_TIGON3=m
+CONFIG_BNX2=m
 
 #
 # Quadrics QsNet device support
@@ -1755,6 +1758,8 @@ CONFIG_FC_QLA2300=m
 CONFIG_SCSI_ISCSI=m
 # CONFIG_SCSI_IPR is not set
 CONFIG_SCSI_LPFC=m
+# CONFIG_FUSION_ISENSE is not set
+CONFIG_DELL_RBU=m
 
 #
 # Kernel hacking
index ea03f03..03230c2 100644 (file)
@@ -116,6 +116,7 @@ CONFIG_ACPI_THERMAL=m
 # CONFIG_ACPI_ASUS is not set
 # CONFIG_ACPI_TOSHIBA is not set
 # CONFIG_ACPI_DEBUG is not set
+# CONFIG_ACPI_PMTMR is not set
 
 #
 # Memory Technology Devices (MTD)
@@ -576,6 +577,7 @@ CONFIG_AIC7XXX_OLD_PROC_STATS=y
 # CONFIG_SCSI_AM53C974 is not set
 CONFIG_SCSI_MEGARAID=m
 CONFIG_SCSI_MEGARAID2=m
+CONFIG_SCSI_MEGARAID_SAS=m
 CONFIG_SCSI_SATA=y
 CONFIG_SCSI_SATA_AHCI=m
 CONFIG_SCSI_SATA_SVW=m
@@ -781,6 +783,7 @@ CONFIG_YELLOWFIN=m
 CONFIG_R8169=m
 CONFIG_SK98LIN=m
 CONFIG_TIGON3=m
+CONFIG_BNX2=m
 
 #
 # Quadrics QsNet device support
@@ -1755,6 +1758,8 @@ CONFIG_FC_QLA2300=m
 CONFIG_SCSI_ISCSI=m
 # CONFIG_SCSI_IPR is not set
 CONFIG_SCSI_LPFC=m
+# CONFIG_FUSION_ISENSE is not set
+CONFIG_DELL_RBU=m
 
 #
 # Kernel hacking
@@ -1777,4 +1782,3 @@ CONFIG_CRC32=m
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
 CONFIG_QSORT=y
-CONFIG_IEEE1394_PCILYNX=m
index a041ccf..d8c0697 100644 (file)
@@ -24,8 +24,8 @@ CONFIG_KMOD=y
 #
 # Processor type and features
 #
-CONFIG_MK8=y
-# CONFIG_GENERIC_CPU is not set
+# CONFIG_MK8 is not set
+CONFIG_GENERIC_CPU=y
 CONFIG_X86_L1_CACHE_BYTES=64
 CONFIG_X86_L1_CACHE_SHIFT=6
 CONFIG_X86_TSC=y
diff --git a/lustre/kernel_patches/kernel_configs/kernel-2.6.15-2.6-fc5-i686-smp.config b/lustre/kernel_patches/kernel_configs/kernel-2.6.15-2.6-fc5-i686-smp.config
new file mode 100644 (file)
index 0000000..403b327
--- /dev/null
@@ -0,0 +1,1598 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.15-prep
+# Wed May 31 10:45:28 2006
+#
+CONFIG_X86_32=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_X86=y
+CONFIG_MMU=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_DMI=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_CPUSETS is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_VM86=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Processor type and features
+#
+CONFIG_X86_PC=y
+# CONFIG_X86_XEN is not set
+# CONFIG_X86_ELAN is not set
+# CONFIG_X86_VOYAGER is not set
+# CONFIG_X86_NUMAQ is not set
+# CONFIG_X86_SUMMIT is not set
+# CONFIG_X86_BIGSMP is not set
+# CONFIG_X86_VISWS is not set
+# CONFIG_X86_GENERICARCH is not set
+# CONFIG_X86_ES7000 is not set
+# CONFIG_M386 is not set
+# CONFIG_M486 is not set
+# CONFIG_M586 is not set
+# CONFIG_M586TSC is not set
+# CONFIG_M586MMX is not set
+# CONFIG_M686 is not set
+# CONFIG_MPENTIUMII is not set
+# CONFIG_MPENTIUMIII is not set
+# CONFIG_MPENTIUMM is not set
+CONFIG_MPENTIUM4=y
+# CONFIG_MK6 is not set
+# CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
+# CONFIG_MCRUSOE is not set
+# CONFIG_MEFFICEON is not set
+# CONFIG_MWINCHIPC6 is not set
+# CONFIG_MWINCHIP2 is not set
+# CONFIG_MWINCHIP3D is not set
+# CONFIG_MGEODEGX1 is not set
+# CONFIG_MGEODE_LX is not set
+# CONFIG_MCYRIXIII is not set
+# CONFIG_MVIAC3_2 is not set
+CONFIG_X86_GENERIC=y
+CONFIG_X86_CMPXCHG=y
+CONFIG_X86_XADD=y
+CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_X86_WP_WORKS_OK=y
+CONFIG_X86_INVLPG=y
+CONFIG_X86_BSWAP=y
+CONFIG_X86_POPAD_OK=y
+CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_GOOD_APIC=y
+CONFIG_X86_INTEL_USERCOPY=y
+CONFIG_X86_USE_PPRO_CHECKSUM=y
+CONFIG_X86_TSC=y
+CONFIG_HPET_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
+CONFIG_SMP=y
+# CONFIG_SMP_ALTERNATIVES is not set
+CONFIG_NR_CPUS=8
+# CONFIG_SCHED_SMT is not set
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_BKL=y
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_X86_IO_APIC=y
+CONFIG_X86_MCE=y
+# CONFIG_X86_MCE_NONFATAL is not set
+# CONFIG_X86_MCE_P4THERMAL is not set
+# CONFIG_TOSHIBA is not set
+# CONFIG_I8K is not set
+# CONFIG_X86_REBOOTFIXUPS is not set
+# CONFIG_MICROCODE is not set
+# CONFIG_X86_MSR is not set
+# CONFIG_X86_CPUID is not set
+# CONFIG_SWIOTLB is not set
+
+#
+# Firmware Drivers
+#
+# CONFIG_EDD is not set
+# CONFIG_DELL_RBU is not set
+# CONFIG_DCDBAS is not set
+# CONFIG_NOHIGHMEM is not set
+CONFIG_HIGHMEM4G=y
+# CONFIG_HIGHMEM64G is not set
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_STATIC=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HIGHPTE is not set
+# CONFIG_MATH_EMULATION is not set
+CONFIG_MTRR=y
+# CONFIG_EFI is not set
+CONFIG_IRQBALANCE=y
+# CONFIG_REGPARM is not set
+CONFIG_SECCOMP=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_PHYSICAL_START=0x100000
+# CONFIG_HOTPLUG_CPU is not set
+CONFIG_DOUBLEFAULT=y
+
+#
+# Power management options (ACPI, APM)
+#
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+CONFIG_ACPI=y
+CONFIG_ACPI_AC=m
+CONFIG_ACPI_BATTERY=m
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_VIDEO=y
+# CONFIG_ACPI_HOTKEY is not set
+CONFIG_ACPI_FAN=m
+CONFIG_ACPI_PROCESSOR=m
+CONFIG_ACPI_THERMAL=m
+CONFIG_ACPI_ASUS=m
+# CONFIG_ACPI_IBM is not set
+CONFIG_ACPI_TOSHIBA=m
+CONFIG_ACPI_BLACKLIST_YEAR=0
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_EC=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_SYSTEM=y
+CONFIG_X86_PM_TIMER=y
+# CONFIG_ACPI_CONTAINER is not set
+
+#
+# APM (Advanced Power Management) BIOS Support
+#
+# CONFIG_APM is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+CONFIG_PCI=y
+# CONFIG_PCI_GOBIOS is not set
+# CONFIG_PCI_GOMMCONFIG is not set
+# CONFIG_PCI_GODIRECT is not set
+# CONFIG_PCI_GOXEN_FE is not set
+CONFIG_PCI_GOANY=y
+CONFIG_PCI_BIOS=y
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_MMCONFIG=y
+# CONFIG_PCIEPORTBUS is not set
+# CONFIG_PCI_MSI is not set
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_DEBUG is not set
+CONFIG_ISA_DMA_API=y
+CONFIG_ISA=y
+# CONFIG_EISA is not set
+# CONFIG_MCA is not set
+# CONFIG_SCx200 is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+CONFIG_TUX=y
+
+#
+# TUX options
+#
+CONFIG_TUX_EXTCGI=y
+# CONFIG_TUX_EXTENDED_LOG is not set
+# CONFIG_TUX_DEBUG is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_DISKDUMP is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_CMD640 is not set
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_RZ1000=y
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+CONFIG_BLK_DEV_AMD74XX=y
+CONFIG_BLK_DEV_ATIIXP=y
+CONFIG_BLK_DEV_CMD64X=y
+CONFIG_BLK_DEV_TRIFLEX=y
+CONFIG_BLK_DEV_CY82C693=y
+CONFIG_BLK_DEV_CS5520=y
+CONFIG_BLK_DEV_CS5530=y
+# CONFIG_BLK_DEV_CS5535 is not set
+CONFIG_BLK_DEV_HPT34X=y
+# CONFIG_HPT34X_AUTODMA is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=y
+# CONFIG_PDC202XX_BURST is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+CONFIG_BLK_DEV_SVWKS=y
+CONFIG_BLK_DEV_SIIMAGE=y
+CONFIG_BLK_DEV_SIS5513=y
+CONFIG_BLK_DEV_SLC90E66=y
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_SD_IOSTATS=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+CONFIG_SCSI_BUSLOGIC=m
+# CONFIG_SCSI_OMIT_FLASHPOINT is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_ULTRASTOR is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=128
+# CONFIG_FUSION_CTL is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+CONFIG_LANCE=m
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=m
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+CONFIG_8139TOO_PIO=y
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_KEYBOARD_XTKBD=y
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_INPORT is not set
+CONFIG_MOUSE_LOGIBM=m
+CONFIG_MOUSE_PC110PAD=m
+CONFIG_MOUSE_VSXXXAA=m
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PCSPKR=m
+# CONFIG_INPUT_WISTRON_BTNS is not set
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+CONFIG_ROCKETPORT=m
+# CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_ESPSERIAL is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+# CONFIG_SYNCLINK_GT is not set
+CONFIG_N_HDLC=m
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+CONFIG_STALDRV=y
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_ACPI is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_CRASH is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_ACQUIRE_WDT=m
+CONFIG_ADVANTECH_WDT=m
+CONFIG_ALIM1535_WDT=m
+CONFIG_ALIM7101_WDT=m
+CONFIG_SC520_WDT=m
+CONFIG_EUROTECH_WDT=m
+CONFIG_IB700_WDT=m
+# CONFIG_IBMASR is not set
+CONFIG_WAFER_WDT=m
+# CONFIG_I6300ESB_WDT is not set
+CONFIG_I8XX_TCO=m
+CONFIG_SC1200_WDT=m
+# CONFIG_60XX_WDT is not set
+# CONFIG_SBC8360_WDT is not set
+CONFIG_CPU5_WDT=m
+CONFIG_W83627HF_WDT=m
+CONFIG_W83877F_WDT=m
+# CONFIG_W83977F_WDT is not set
+CONFIG_MACHZ_WDT=m
+# CONFIG_SBC_EPX_C3_WATCHDOG is not set
+
+#
+# ISA-based Watchdog Cards
+#
+CONFIG_PCWATCHDOG=m
+# CONFIG_MIXCOMWD is not set
+CONFIG_WDT=m
+# CONFIG_WDT_501 is not set
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_SONYPI is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=y
+CONFIG_AGP_ALI=y
+CONFIG_AGP_ATI=y
+CONFIG_AGP_AMD=y
+CONFIG_AGP_AMD64=y
+CONFIG_AGP_INTEL=y
+CONFIG_AGP_NVIDIA=y
+CONFIG_AGP_SIS=y
+CONFIG_AGP_SWORKS=y
+CONFIG_AGP_VIA=y
+CONFIG_AGP_EFFICEON=y
+# CONFIG_DRM is not set
+# CONFIG_MWAVE is not set
+# CONFIG_CS5535_GPIO is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HPET is not set
+CONFIG_HANGCHECK_TIMER=m
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+CONFIG_I2C_AMD8111=m
+# CONFIG_I2C_I801 is not set
+CONFIG_I2C_I810=m
+CONFIG_I2C_PIIX4=m
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_RTC_X1205_I2C is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_HDAPS is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+# CONFIG_IBM_ASM is not set
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+
+#
+# Video For Linux
+#
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_SAA7134 is not set
+# CONFIG_VIDEO_MXB is not set
+# CONFIG_VIDEO_DPC is not set
+# CONFIG_VIDEO_HEXIUM_ORION is not set
+# CONFIG_VIDEO_HEXIUM_GEMINI is not set
+# CONFIG_VIDEO_CX88 is not set
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_OVCAMCHIP is not set
+# CONFIG_VIDEO_AUDIO_DECODER is not set
+# CONFIG_VIDEO_DECODER is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_ZOLTRIX is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ARC is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+CONFIG_FB_VGA16=m
+CONFIG_FB_VESA=y
+CONFIG_VIDEO_SELECT=y
+# CONFIG_FB_HGA is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_I810 is not set
+# CONFIG_FB_INTEL is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_CYBLA is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_GEODE is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_MDA_CONSOLE=m
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_ET61X251 is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_KONICAWC is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_SN9C102 is not set
+# CONFIG_USB_STV680 is not set
+# CONFIG_USB_PWC is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+# CONFIG_EDAC is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+# CONFIG_KPROBES is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+CONFIG_DEBUG_SLAB=y
+# CONFIG_DEBUG_SLAB_LEAK is not set
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_HIGHMEM is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_BOOT_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_EARLY_PRINTK=y
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_DEBUG_STACK_USAGE=y
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_DEBUG_RODATA is not set
+# CONFIG_4KSTACKS is not set
+CONFIG_X86_FIND_SMP_CONFIG=y
+CONFIG_X86_MPPARSE=y
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_AES_586 is not set
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO_SIGNATURE is not set
+# CONFIG_CRYPTO_MPILIB is not set
+
+#
+# Hardware crypto devices
+#
+# CONFIG_CRYPTO_DEV_PADLOCK is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
+CONFIG_X86_SMP=y
+CONFIG_X86_HT=y
+CONFIG_X86_BIOS_REBOOT=y
+CONFIG_X86_TRAMPOLINE=y
+CONFIG_X86_SYSENTER=y
+CONFIG_KTIME_SCALAR=y
diff --git a/lustre/kernel_patches/kernel_configs/kernel-2.6.15-2.6-fc5-i686.config b/lustre/kernel_patches/kernel_configs/kernel-2.6.15-2.6-fc5-i686.config
new file mode 100644 (file)
index 0000000..691606a
--- /dev/null
@@ -0,0 +1,1591 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.15-prep
+# Wed May 31 14:11:18 2006
+#
+CONFIG_X86_32=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_X86=y
+CONFIG_MMU=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_DMI=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_VM86=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Processor type and features
+#
+CONFIG_X86_PC=y
+# CONFIG_X86_XEN is not set
+# CONFIG_X86_ELAN is not set
+# CONFIG_X86_VOYAGER is not set
+# CONFIG_X86_NUMAQ is not set
+# CONFIG_X86_SUMMIT is not set
+# CONFIG_X86_BIGSMP is not set
+# CONFIG_X86_VISWS is not set
+# CONFIG_X86_GENERICARCH is not set
+# CONFIG_X86_ES7000 is not set
+# CONFIG_M386 is not set
+# CONFIG_M486 is not set
+# CONFIG_M586 is not set
+# CONFIG_M586TSC is not set
+# CONFIG_M586MMX is not set
+# CONFIG_M686 is not set
+# CONFIG_MPENTIUMII is not set
+# CONFIG_MPENTIUMIII is not set
+# CONFIG_MPENTIUMM is not set
+CONFIG_MPENTIUM4=y
+# CONFIG_MK6 is not set
+# CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
+# CONFIG_MCRUSOE is not set
+# CONFIG_MEFFICEON is not set
+# CONFIG_MWINCHIPC6 is not set
+# CONFIG_MWINCHIP2 is not set
+# CONFIG_MWINCHIP3D is not set
+# CONFIG_MGEODEGX1 is not set
+# CONFIG_MGEODE_LX is not set
+# CONFIG_MCYRIXIII is not set
+# CONFIG_MVIAC3_2 is not set
+CONFIG_X86_GENERIC=y
+CONFIG_X86_CMPXCHG=y
+CONFIG_X86_XADD=y
+CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_X86_WP_WORKS_OK=y
+CONFIG_X86_INVLPG=y
+CONFIG_X86_BSWAP=y
+CONFIG_X86_POPAD_OK=y
+CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_GOOD_APIC=y
+CONFIG_X86_INTEL_USERCOPY=y
+CONFIG_X86_USE_PPRO_CHECKSUM=y
+CONFIG_X86_TSC=y
+CONFIG_HPET_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+# CONFIG_X86_UP_APIC is not set
+CONFIG_X86_MCE=y
+# CONFIG_X86_MCE_NONFATAL is not set
+# CONFIG_TOSHIBA is not set
+# CONFIG_I8K is not set
+# CONFIG_X86_REBOOTFIXUPS is not set
+# CONFIG_MICROCODE is not set
+# CONFIG_X86_MSR is not set
+# CONFIG_X86_CPUID is not set
+# CONFIG_SWIOTLB is not set
+
+#
+# Firmware Drivers
+#
+# CONFIG_EDD is not set
+# CONFIG_DELL_RBU is not set
+# CONFIG_DCDBAS is not set
+# CONFIG_NOHIGHMEM is not set
+CONFIG_HIGHMEM4G=y
+# CONFIG_HIGHMEM64G is not set
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_STATIC=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HIGHPTE is not set
+# CONFIG_MATH_EMULATION is not set
+CONFIG_MTRR=y
+# CONFIG_EFI is not set
+# CONFIG_REGPARM is not set
+CONFIG_SECCOMP=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_PHYSICAL_START=0x100000
+CONFIG_DOUBLEFAULT=y
+
+#
+# Power management options (ACPI, APM)
+#
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_SOFTWARE_SUSPEND is not set
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+CONFIG_ACPI=y
+CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_SLEEP_PROC_FS=y
+# CONFIG_ACPI_SLEEP_PROC_SLEEP is not set
+CONFIG_ACPI_AC=m
+CONFIG_ACPI_BATTERY=m
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_VIDEO=y
+# CONFIG_ACPI_HOTKEY is not set
+CONFIG_ACPI_FAN=m
+CONFIG_ACPI_PROCESSOR=m
+CONFIG_ACPI_THERMAL=m
+CONFIG_ACPI_ASUS=m
+# CONFIG_ACPI_IBM is not set
+CONFIG_ACPI_TOSHIBA=m
+CONFIG_ACPI_BLACKLIST_YEAR=0
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_EC=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_SYSTEM=y
+CONFIG_X86_PM_TIMER=y
+# CONFIG_ACPI_CONTAINER is not set
+
+#
+# APM (Advanced Power Management) BIOS Support
+#
+# CONFIG_APM is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+CONFIG_PCI=y
+# CONFIG_PCI_GOBIOS is not set
+# CONFIG_PCI_GOMMCONFIG is not set
+# CONFIG_PCI_GODIRECT is not set
+# CONFIG_PCI_GOXEN_FE is not set
+CONFIG_PCI_GOANY=y
+CONFIG_PCI_BIOS=y
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_MMCONFIG=y
+# CONFIG_PCIEPORTBUS is not set
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_DEBUG is not set
+CONFIG_ISA_DMA_API=y
+CONFIG_ISA=y
+# CONFIG_EISA is not set
+# CONFIG_MCA is not set
+# CONFIG_SCx200 is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+CONFIG_TUX=y
+
+#
+# TUX options
+#
+CONFIG_TUX_EXTCGI=y
+# CONFIG_TUX_EXTENDED_LOG is not set
+# CONFIG_TUX_DEBUG is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_DISKDUMP is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_CMD640 is not set
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_RZ1000=y
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+CONFIG_BLK_DEV_AMD74XX=y
+CONFIG_BLK_DEV_ATIIXP=y
+CONFIG_BLK_DEV_CMD64X=y
+CONFIG_BLK_DEV_TRIFLEX=y
+CONFIG_BLK_DEV_CY82C693=y
+CONFIG_BLK_DEV_CS5520=y
+CONFIG_BLK_DEV_CS5530=y
+# CONFIG_BLK_DEV_CS5535 is not set
+CONFIG_BLK_DEV_HPT34X=y
+# CONFIG_HPT34X_AUTODMA is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=y
+# CONFIG_PDC202XX_BURST is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+CONFIG_BLK_DEV_SVWKS=y
+CONFIG_BLK_DEV_SIIMAGE=y
+CONFIG_BLK_DEV_SIS5513=y
+CONFIG_BLK_DEV_SLC90E66=y
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_SD_IOSTATS=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+CONFIG_SCSI_BUSLOGIC=m
+# CONFIG_SCSI_OMIT_FLASHPOINT is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_ULTRASTOR is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=128
+# CONFIG_FUSION_CTL is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+CONFIG_LANCE=m
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=m
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+CONFIG_8139TOO_PIO=y
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_KEYBOARD_XTKBD=y
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_INPORT is not set
+CONFIG_MOUSE_LOGIBM=m
+CONFIG_MOUSE_PC110PAD=m
+CONFIG_MOUSE_VSXXXAA=m
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PCSPKR=m
+# CONFIG_INPUT_WISTRON_BTNS is not set
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+CONFIG_ROCKETPORT=m
+# CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_ESPSERIAL is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+# CONFIG_SYNCLINK_GT is not set
+CONFIG_N_HDLC=m
+# CONFIG_RISCOM8 is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+CONFIG_STALDRV=y
+# CONFIG_STALLION is not set
+# CONFIG_ISTALLION is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_ACPI is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_CRASH is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_ACQUIRE_WDT=m
+CONFIG_ADVANTECH_WDT=m
+CONFIG_ALIM1535_WDT=m
+CONFIG_ALIM7101_WDT=m
+CONFIG_SC520_WDT=m
+CONFIG_EUROTECH_WDT=m
+CONFIG_IB700_WDT=m
+# CONFIG_IBMASR is not set
+CONFIG_WAFER_WDT=m
+# CONFIG_I6300ESB_WDT is not set
+CONFIG_I8XX_TCO=m
+CONFIG_SC1200_WDT=m
+# CONFIG_60XX_WDT is not set
+# CONFIG_SBC8360_WDT is not set
+CONFIG_CPU5_WDT=m
+CONFIG_W83627HF_WDT=m
+CONFIG_W83877F_WDT=m
+# CONFIG_W83977F_WDT is not set
+CONFIG_MACHZ_WDT=m
+# CONFIG_SBC_EPX_C3_WATCHDOG is not set
+
+#
+# ISA-based Watchdog Cards
+#
+CONFIG_PCWATCHDOG=m
+# CONFIG_MIXCOMWD is not set
+CONFIG_WDT=m
+# CONFIG_WDT_501 is not set
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_SONYPI is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+CONFIG_AGP=y
+CONFIG_AGP_ALI=y
+CONFIG_AGP_ATI=y
+CONFIG_AGP_AMD=y
+CONFIG_AGP_AMD64=y
+CONFIG_AGP_INTEL=y
+CONFIG_AGP_NVIDIA=y
+CONFIG_AGP_SIS=y
+CONFIG_AGP_SWORKS=y
+CONFIG_AGP_VIA=y
+CONFIG_AGP_EFFICEON=y
+# CONFIG_DRM is not set
+# CONFIG_MWAVE is not set
+# CONFIG_CS5535_GPIO is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HPET is not set
+CONFIG_HANGCHECK_TIMER=m
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+CONFIG_I2C_AMD8111=m
+# CONFIG_I2C_ELEKTOR is not set
+# CONFIG_I2C_I801 is not set
+CONFIG_I2C_I810=m
+CONFIG_I2C_PIIX4=m
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_RTC_X1205_I2C is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_HDAPS is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+# CONFIG_IBM_ASM is not set
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+
+#
+# Video For Linux
+#
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_SAA7134 is not set
+# CONFIG_VIDEO_MXB is not set
+# CONFIG_VIDEO_DPC is not set
+# CONFIG_VIDEO_HEXIUM_ORION is not set
+# CONFIG_VIDEO_HEXIUM_GEMINI is not set
+# CONFIG_VIDEO_CX88 is not set
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_OVCAMCHIP is not set
+# CONFIG_VIDEO_AUDIO_DECODER is not set
+# CONFIG_VIDEO_DECODER is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_ZOLTRIX is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ARC is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+CONFIG_FB_VGA16=m
+CONFIG_FB_VESA=y
+CONFIG_VIDEO_SELECT=y
+# CONFIG_FB_HGA is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_I810 is not set
+# CONFIG_FB_INTEL is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_CYBLA is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_GEODE is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_MDA_CONSOLE=m
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_ET61X251 is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_KONICAWC is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_SN9C102 is not set
+# CONFIG_USB_STV680 is not set
+# CONFIG_USB_PWC is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+# CONFIG_EDAC is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+# CONFIG_KPROBES is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+CONFIG_DEBUG_SLAB=y
+# CONFIG_DEBUG_SLAB_LEAK is not set
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_HIGHMEM is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_BOOT_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_EARLY_PRINTK=y
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_DEBUG_STACK_USAGE=y
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_DEBUG_RODATA is not set
+# CONFIG_4KSTACKS is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_AES_586 is not set
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO_SIGNATURE is not set
+# CONFIG_CRYPTO_MPILIB is not set
+
+#
+# Hardware crypto devices
+#
+# CONFIG_CRYPTO_DEV_PADLOCK is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_X86_BIOS_REBOOT=y
+CONFIG_X86_SYSENTER=y
+CONFIG_KTIME_SCALAR=y
diff --git a/lustre/kernel_patches/kernel_configs/kernel-2.6.15-fc5-i686.config b/lustre/kernel_patches/kernel_configs/kernel-2.6.15-fc5-i686.config
new file mode 100644 (file)
index 0000000..403b327
--- /dev/null
@@ -0,0 +1,1598 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.15-prep
+# Wed May 31 10:45:28 2006
+#
+CONFIG_X86_32=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_X86=y
+CONFIG_MMU=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_DMI=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_CPUSETS is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_VM86=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Processor type and features
+#
+CONFIG_X86_PC=y
+# CONFIG_X86_XEN is not set
+# CONFIG_X86_ELAN is not set
+# CONFIG_X86_VOYAGER is not set
+# CONFIG_X86_NUMAQ is not set
+# CONFIG_X86_SUMMIT is not set
+# CONFIG_X86_BIGSMP is not set
+# CONFIG_X86_VISWS is not set
+# CONFIG_X86_GENERICARCH is not set
+# CONFIG_X86_ES7000 is not set
+# CONFIG_M386 is not set
+# CONFIG_M486 is not set
+# CONFIG_M586 is not set
+# CONFIG_M586TSC is not set
+# CONFIG_M586MMX is not set
+# CONFIG_M686 is not set
+# CONFIG_MPENTIUMII is not set
+# CONFIG_MPENTIUMIII is not set
+# CONFIG_MPENTIUMM is not set
+CONFIG_MPENTIUM4=y
+# CONFIG_MK6 is not set
+# CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
+# CONFIG_MCRUSOE is not set
+# CONFIG_MEFFICEON is not set
+# CONFIG_MWINCHIPC6 is not set
+# CONFIG_MWINCHIP2 is not set
+# CONFIG_MWINCHIP3D is not set
+# CONFIG_MGEODEGX1 is not set
+# CONFIG_MGEODE_LX is not set
+# CONFIG_MCYRIXIII is not set
+# CONFIG_MVIAC3_2 is not set
+CONFIG_X86_GENERIC=y
+CONFIG_X86_CMPXCHG=y
+CONFIG_X86_XADD=y
+CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_X86_WP_WORKS_OK=y
+CONFIG_X86_INVLPG=y
+CONFIG_X86_BSWAP=y
+CONFIG_X86_POPAD_OK=y
+CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_GOOD_APIC=y
+CONFIG_X86_INTEL_USERCOPY=y
+CONFIG_X86_USE_PPRO_CHECKSUM=y
+CONFIG_X86_TSC=y
+CONFIG_HPET_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
+CONFIG_SMP=y
+# CONFIG_SMP_ALTERNATIVES is not set
+CONFIG_NR_CPUS=8
+# CONFIG_SCHED_SMT is not set
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_BKL=y
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_X86_IO_APIC=y
+CONFIG_X86_MCE=y
+# CONFIG_X86_MCE_NONFATAL is not set
+# CONFIG_X86_MCE_P4THERMAL is not set
+# CONFIG_TOSHIBA is not set
+# CONFIG_I8K is not set
+# CONFIG_X86_REBOOTFIXUPS is not set
+# CONFIG_MICROCODE is not set
+# CONFIG_X86_MSR is not set
+# CONFIG_X86_CPUID is not set
+# CONFIG_SWIOTLB is not set
+
+#
+# Firmware Drivers
+#
+# CONFIG_EDD is not set
+# CONFIG_DELL_RBU is not set
+# CONFIG_DCDBAS is not set
+# CONFIG_NOHIGHMEM is not set
+CONFIG_HIGHMEM4G=y
+# CONFIG_HIGHMEM64G is not set
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_STATIC=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HIGHPTE is not set
+# CONFIG_MATH_EMULATION is not set
+CONFIG_MTRR=y
+# CONFIG_EFI is not set
+CONFIG_IRQBALANCE=y
+# CONFIG_REGPARM is not set
+CONFIG_SECCOMP=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_PHYSICAL_START=0x100000
+# CONFIG_HOTPLUG_CPU is not set
+CONFIG_DOUBLEFAULT=y
+
+#
+# Power management options (ACPI, APM)
+#
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+CONFIG_ACPI=y
+CONFIG_ACPI_AC=m
+CONFIG_ACPI_BATTERY=m
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_VIDEO=y
+# CONFIG_ACPI_HOTKEY is not set
+CONFIG_ACPI_FAN=m
+CONFIG_ACPI_PROCESSOR=m
+CONFIG_ACPI_THERMAL=m
+CONFIG_ACPI_ASUS=m
+# CONFIG_ACPI_IBM is not set
+CONFIG_ACPI_TOSHIBA=m
+CONFIG_ACPI_BLACKLIST_YEAR=0
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_EC=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_SYSTEM=y
+CONFIG_X86_PM_TIMER=y
+# CONFIG_ACPI_CONTAINER is not set
+
+#
+# APM (Advanced Power Management) BIOS Support
+#
+# CONFIG_APM is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+CONFIG_PCI=y
+# CONFIG_PCI_GOBIOS is not set
+# CONFIG_PCI_GOMMCONFIG is not set
+# CONFIG_PCI_GODIRECT is not set
+# CONFIG_PCI_GOXEN_FE is not set
+CONFIG_PCI_GOANY=y
+CONFIG_PCI_BIOS=y
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_MMCONFIG=y
+# CONFIG_PCIEPORTBUS is not set
+# CONFIG_PCI_MSI is not set
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_DEBUG is not set
+CONFIG_ISA_DMA_API=y
+CONFIG_ISA=y
+# CONFIG_EISA is not set
+# CONFIG_MCA is not set
+# CONFIG_SCx200 is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+CONFIG_TUX=y
+
+#
+# TUX options
+#
+CONFIG_TUX_EXTCGI=y
+# CONFIG_TUX_EXTENDED_LOG is not set
+# CONFIG_TUX_DEBUG is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_DISKDUMP is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_CMD640 is not set
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_RZ1000=y
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+CONFIG_BLK_DEV_AMD74XX=y
+CONFIG_BLK_DEV_ATIIXP=y
+CONFIG_BLK_DEV_CMD64X=y
+CONFIG_BLK_DEV_TRIFLEX=y
+CONFIG_BLK_DEV_CY82C693=y
+CONFIG_BLK_DEV_CS5520=y
+CONFIG_BLK_DEV_CS5530=y
+# CONFIG_BLK_DEV_CS5535 is not set
+CONFIG_BLK_DEV_HPT34X=y
+# CONFIG_HPT34X_AUTODMA is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=y
+# CONFIG_PDC202XX_BURST is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+CONFIG_BLK_DEV_SVWKS=y
+CONFIG_BLK_DEV_SIIMAGE=y
+CONFIG_BLK_DEV_SIS5513=y
+CONFIG_BLK_DEV_SLC90E66=y
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_SD_IOSTATS=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+CONFIG_SCSI_BUSLOGIC=m
+# CONFIG_SCSI_OMIT_FLASHPOINT is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_ULTRASTOR is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=128
+# CONFIG_FUSION_CTL is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+CONFIG_LANCE=m
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=m
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+CONFIG_8139TOO_PIO=y
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_KEYBOARD_XTKBD=y
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_INPORT is not set
+CONFIG_MOUSE_LOGIBM=m
+CONFIG_MOUSE_PC110PAD=m
+CONFIG_MOUSE_VSXXXAA=m
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PCSPKR=m
+# CONFIG_INPUT_WISTRON_BTNS is not set
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+CONFIG_ROCKETPORT=m
+# CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_ESPSERIAL is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+# CONFIG_SYNCLINK_GT is not set
+CONFIG_N_HDLC=m
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+CONFIG_STALDRV=y
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_ACPI is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_CRASH is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_ACQUIRE_WDT=m
+CONFIG_ADVANTECH_WDT=m
+CONFIG_ALIM1535_WDT=m
+CONFIG_ALIM7101_WDT=m
+CONFIG_SC520_WDT=m
+CONFIG_EUROTECH_WDT=m
+CONFIG_IB700_WDT=m
+# CONFIG_IBMASR is not set
+CONFIG_WAFER_WDT=m
+# CONFIG_I6300ESB_WDT is not set
+CONFIG_I8XX_TCO=m
+CONFIG_SC1200_WDT=m
+# CONFIG_60XX_WDT is not set
+# CONFIG_SBC8360_WDT is not set
+CONFIG_CPU5_WDT=m
+CONFIG_W83627HF_WDT=m
+CONFIG_W83877F_WDT=m
+# CONFIG_W83977F_WDT is not set
+CONFIG_MACHZ_WDT=m
+# CONFIG_SBC_EPX_C3_WATCHDOG is not set
+
+#
+# ISA-based Watchdog Cards
+#
+CONFIG_PCWATCHDOG=m
+# CONFIG_MIXCOMWD is not set
+CONFIG_WDT=m
+# CONFIG_WDT_501 is not set
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_SONYPI is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=y
+CONFIG_AGP_ALI=y
+CONFIG_AGP_ATI=y
+CONFIG_AGP_AMD=y
+CONFIG_AGP_AMD64=y
+CONFIG_AGP_INTEL=y
+CONFIG_AGP_NVIDIA=y
+CONFIG_AGP_SIS=y
+CONFIG_AGP_SWORKS=y
+CONFIG_AGP_VIA=y
+CONFIG_AGP_EFFICEON=y
+# CONFIG_DRM is not set
+# CONFIG_MWAVE is not set
+# CONFIG_CS5535_GPIO is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HPET is not set
+CONFIG_HANGCHECK_TIMER=m
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+CONFIG_I2C_AMD8111=m
+# CONFIG_I2C_I801 is not set
+CONFIG_I2C_I810=m
+CONFIG_I2C_PIIX4=m
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_RTC_X1205_I2C is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_HDAPS is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+# CONFIG_IBM_ASM is not set
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+
+#
+# Video For Linux
+#
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_SAA7134 is not set
+# CONFIG_VIDEO_MXB is not set
+# CONFIG_VIDEO_DPC is not set
+# CONFIG_VIDEO_HEXIUM_ORION is not set
+# CONFIG_VIDEO_HEXIUM_GEMINI is not set
+# CONFIG_VIDEO_CX88 is not set
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_OVCAMCHIP is not set
+# CONFIG_VIDEO_AUDIO_DECODER is not set
+# CONFIG_VIDEO_DECODER is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_ZOLTRIX is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ARC is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+CONFIG_FB_VGA16=m
+CONFIG_FB_VESA=y
+CONFIG_VIDEO_SELECT=y
+# CONFIG_FB_HGA is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_I810 is not set
+# CONFIG_FB_INTEL is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_CYBLA is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_GEODE is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_MDA_CONSOLE=m
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_ET61X251 is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_KONICAWC is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_SN9C102 is not set
+# CONFIG_USB_STV680 is not set
+# CONFIG_USB_PWC is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+# CONFIG_EDAC is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+# CONFIG_KPROBES is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+CONFIG_DEBUG_SLAB=y
+# CONFIG_DEBUG_SLAB_LEAK is not set
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_HIGHMEM is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_BOOT_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_EARLY_PRINTK=y
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_DEBUG_STACK_USAGE=y
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_DEBUG_RODATA is not set
+# CONFIG_4KSTACKS is not set
+CONFIG_X86_FIND_SMP_CONFIG=y
+CONFIG_X86_MPPARSE=y
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_AES_586 is not set
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO_SIGNATURE is not set
+# CONFIG_CRYPTO_MPILIB is not set
+
+#
+# Hardware crypto devices
+#
+# CONFIG_CRYPTO_DEV_PADLOCK is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
+CONFIG_X86_SMP=y
+CONFIG_X86_HT=y
+CONFIG_X86_BIOS_REBOOT=y
+CONFIG_X86_TRAMPOLINE=y
+CONFIG_X86_SYSENTER=y
+CONFIG_KTIME_SCALAR=y
diff --git a/lustre/kernel_patches/kernel_configs/kernel-2.6.16-2.6-patchless-i686-smp.config b/lustre/kernel_patches/kernel_configs/kernel-2.6.16-2.6-patchless-i686-smp.config
new file mode 100644 (file)
index 0000000..935b78e
--- /dev/null
@@ -0,0 +1,1617 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.16.22
+# Thu Jul 13 14:19:50 2006
+#
+CONFIG_X86_32=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_X86=y
+CONFIG_MMU=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_DMI=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_CPUSETS is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_VM86=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Processor type and features
+#
+CONFIG_X86_PC=y
+# CONFIG_X86_ELAN is not set
+# CONFIG_X86_VOYAGER is not set
+# CONFIG_X86_NUMAQ is not set
+# CONFIG_X86_SUMMIT is not set
+# CONFIG_X86_BIGSMP is not set
+# CONFIG_X86_VISWS is not set
+# CONFIG_X86_GENERICARCH is not set
+# CONFIG_X86_ES7000 is not set
+# CONFIG_M386 is not set
+# CONFIG_M486 is not set
+# CONFIG_M586 is not set
+# CONFIG_M586TSC is not set
+# CONFIG_M586MMX is not set
+CONFIG_M686=y
+# CONFIG_MPENTIUMII is not set
+# CONFIG_MPENTIUMIII is not set
+# CONFIG_MPENTIUMM is not set
+# CONFIG_MPENTIUM4 is not set
+# CONFIG_MK6 is not set
+# CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
+# CONFIG_MCRUSOE is not set
+# CONFIG_MEFFICEON is not set
+# CONFIG_MWINCHIPC6 is not set
+# CONFIG_MWINCHIP2 is not set
+# CONFIG_MWINCHIP3D is not set
+# CONFIG_MGEODEGX1 is not set
+# CONFIG_MGEODE_LX is not set
+# CONFIG_MCYRIXIII is not set
+# CONFIG_MVIAC3_2 is not set
+CONFIG_X86_GENERIC=y
+CONFIG_X86_CMPXCHG=y
+CONFIG_X86_XADD=y
+CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_X86_PPRO_FENCE=y
+CONFIG_X86_WP_WORKS_OK=y
+CONFIG_X86_INVLPG=y
+CONFIG_X86_BSWAP=y
+CONFIG_X86_POPAD_OK=y
+CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_GOOD_APIC=y
+CONFIG_X86_INTEL_USERCOPY=y
+CONFIG_X86_USE_PPRO_CHECKSUM=y
+CONFIG_X86_TSC=y
+CONFIG_HPET_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=8
+# CONFIG_SCHED_SMT is not set
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_BKL=y
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_X86_IO_APIC=y
+CONFIG_X86_MCE=y
+# CONFIG_X86_MCE_NONFATAL is not set
+# CONFIG_X86_MCE_P4THERMAL is not set
+# CONFIG_TOSHIBA is not set
+# CONFIG_I8K is not set
+# CONFIG_X86_REBOOTFIXUPS is not set
+# CONFIG_MICROCODE is not set
+# CONFIG_X86_MSR is not set
+# CONFIG_X86_CPUID is not set
+
+#
+# Firmware Drivers
+#
+# CONFIG_EDD is not set
+# CONFIG_DELL_RBU is not set
+# CONFIG_DCDBAS is not set
+# CONFIG_NOHIGHMEM is not set
+CONFIG_HIGHMEM4G=y
+# CONFIG_HIGHMEM64G is not set
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_STATIC=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HIGHPTE is not set
+# CONFIG_MATH_EMULATION is not set
+CONFIG_MTRR=y
+# CONFIG_EFI is not set
+CONFIG_IRQBALANCE=y
+# CONFIG_REGPARM is not set
+CONFIG_SECCOMP=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_PHYSICAL_START=0x100000
+# CONFIG_HOTPLUG_CPU is not set
+CONFIG_DOUBLEFAULT=y
+
+#
+# Power management options (ACPI, APM)
+#
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+CONFIG_ACPI=y
+CONFIG_ACPI_AC=m
+CONFIG_ACPI_BATTERY=m
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_VIDEO=y
+# CONFIG_ACPI_HOTKEY is not set
+CONFIG_ACPI_FAN=m
+CONFIG_ACPI_PROCESSOR=m
+CONFIG_ACPI_THERMAL=m
+CONFIG_ACPI_ASUS=m
+# CONFIG_ACPI_IBM is not set
+CONFIG_ACPI_TOSHIBA=m
+CONFIG_ACPI_BLACKLIST_YEAR=0
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_EC=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_SYSTEM=y
+CONFIG_X86_PM_TIMER=y
+# CONFIG_ACPI_CONTAINER is not set
+
+#
+# APM (Advanced Power Management) BIOS Support
+#
+# CONFIG_APM is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+CONFIG_PCI=y
+# CONFIG_PCI_GOBIOS is not set
+# CONFIG_PCI_GOMMCONFIG is not set
+# CONFIG_PCI_GODIRECT is not set
+CONFIG_PCI_GOANY=y
+CONFIG_PCI_BIOS=y
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_MMCONFIG=y
+# CONFIG_PCIEPORTBUS is not set
+# CONFIG_PCI_MSI is not set
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_DEBUG is not set
+CONFIG_ISA_DMA_API=y
+CONFIG_ISA=y
+# CONFIG_EISA is not set
+# CONFIG_MCA is not set
+# CONFIG_SCx200 is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_CMD640 is not set
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_RZ1000=y
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+CONFIG_BLK_DEV_AMD74XX=y
+CONFIG_BLK_DEV_ATIIXP=y
+CONFIG_BLK_DEV_CMD64X=y
+CONFIG_BLK_DEV_TRIFLEX=y
+CONFIG_BLK_DEV_CY82C693=y
+CONFIG_BLK_DEV_CS5520=y
+CONFIG_BLK_DEV_CS5530=y
+# CONFIG_BLK_DEV_CS5535 is not set
+CONFIG_BLK_DEV_HPT34X=y
+# CONFIG_HPT34X_AUTODMA is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=y
+# CONFIG_PDC202XX_BURST is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+CONFIG_BLK_DEV_SVWKS=y
+CONFIG_BLK_DEV_SIIMAGE=y
+CONFIG_BLK_DEV_SIS5513=y
+CONFIG_BLK_DEV_SLC90E66=y
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+CONFIG_SCSI_BUSLOGIC=m
+# CONFIG_SCSI_OMIT_FLASHPOINT is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_ULTRASTOR is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=128
+# CONFIG_FUSION_CTL is not set
+CONFIG_FUSION_LAN=m
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+# CONFIG_CASSINI is not set
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_EL1=m
+CONFIG_EL2=m
+CONFIG_ELPLUS=m
+CONFIG_EL16=m
+CONFIG_EL3=m
+CONFIG_3C515=m
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+# CONFIG_LANCE is not set
+CONFIG_NET_VENDOR_SMC=y
+CONFIG_WD80x3=m
+CONFIG_ULTRA=m
+CONFIG_SMC9194=m
+CONFIG_NET_VENDOR_RACAL=y
+CONFIG_NI52=m
+CONFIG_NI65=m
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+CONFIG_TULIP_NAPI=y
+# CONFIG_TULIP_NAPI_HW_MITIGATION is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+CONFIG_HP100=m
+# CONFIG_NET_ISA is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+# CONFIG_AC3200 is not set
+CONFIG_APRICOT=m
+CONFIG_B44=m
+CONFIG_FORCEDETH=m
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=m
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+CONFIG_8139TOO_PIO=y
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+# CONFIG_SUNDANCE is not set
+CONFIG_TLAN=m
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+CONFIG_NS83820=m
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+CONFIG_SKY2=m
+CONFIG_SK98LIN=m
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_KEYBOARD_XTKBD=y
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_INPORT is not set
+CONFIG_MOUSE_LOGIBM=m
+CONFIG_MOUSE_PC110PAD=m
+CONFIG_MOUSE_VSXXXAA=m
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PCSPKR=m
+# CONFIG_INPUT_WISTRON_BTNS is not set
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+CONFIG_ROCKETPORT=m
+# CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_ESPSERIAL is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+# CONFIG_SYNCLINK_GT is not set
+CONFIG_N_HDLC=m
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+CONFIG_STALDRV=y
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_ACPI is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_ACQUIRE_WDT=m
+CONFIG_ADVANTECH_WDT=m
+CONFIG_ALIM1535_WDT=m
+CONFIG_ALIM7101_WDT=m
+CONFIG_SC520_WDT=m
+CONFIG_EUROTECH_WDT=m
+CONFIG_IB700_WDT=m
+# CONFIG_IBMASR is not set
+CONFIG_WAFER_WDT=m
+# CONFIG_I6300ESB_WDT is not set
+CONFIG_I8XX_TCO=m
+CONFIG_SC1200_WDT=m
+# CONFIG_60XX_WDT is not set
+# CONFIG_SBC8360_WDT is not set
+CONFIG_CPU5_WDT=m
+CONFIG_W83627HF_WDT=m
+CONFIG_W83877F_WDT=m
+# CONFIG_W83977F_WDT is not set
+CONFIG_MACHZ_WDT=m
+# CONFIG_SBC_EPX_C3_WATCHDOG is not set
+
+#
+# ISA-based Watchdog Cards
+#
+CONFIG_PCWATCHDOG=m
+# CONFIG_MIXCOMWD is not set
+CONFIG_WDT=m
+# CONFIG_WDT_501 is not set
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_SONYPI is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=y
+CONFIG_AGP_ALI=y
+CONFIG_AGP_ATI=y
+CONFIG_AGP_AMD=y
+CONFIG_AGP_AMD64=y
+CONFIG_AGP_INTEL=y
+CONFIG_AGP_NVIDIA=y
+CONFIG_AGP_SIS=y
+CONFIG_AGP_SWORKS=y
+CONFIG_AGP_VIA=y
+CONFIG_AGP_EFFICEON=y
+# CONFIG_DRM is not set
+# CONFIG_MWAVE is not set
+# CONFIG_CS5535_GPIO is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HPET is not set
+CONFIG_HANGCHECK_TIMER=m
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+CONFIG_I2C_AMD8111=m
+# CONFIG_I2C_I801 is not set
+CONFIG_I2C_I810=m
+CONFIG_I2C_PIIX4=m
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_RTC_X1205_I2C is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_HDAPS is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+# CONFIG_IBM_ASM is not set
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+
+#
+# Video For Linux
+#
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_SAA7134 is not set
+# CONFIG_VIDEO_MXB is not set
+# CONFIG_VIDEO_DPC is not set
+# CONFIG_VIDEO_HEXIUM_ORION is not set
+# CONFIG_VIDEO_HEXIUM_GEMINI is not set
+# CONFIG_VIDEO_CX88 is not set
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_OVCAMCHIP is not set
+# CONFIG_VIDEO_AUDIO_DECODER is not set
+# CONFIG_VIDEO_DECODER is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_ZOLTRIX is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ARC is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+CONFIG_FB_VGA16=m
+CONFIG_FB_VESA=y
+CONFIG_VIDEO_SELECT=y
+# CONFIG_FB_HGA is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_I810 is not set
+# CONFIG_FB_INTEL is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_CYBLA is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_GEODE is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_MDA_CONSOLE=m
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_ET61X251 is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_KONICAWC is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_SN9C102 is not set
+# CONFIG_USB_STV680 is not set
+# CONFIG_USB_PWC is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+# CONFIG_EDAC is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+# CONFIG_KPROBES is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+CONFIG_DEBUG_SLAB=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_HIGHMEM is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_EARLY_PRINTK=y
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_DEBUG_STACK_USAGE=y
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_DEBUG_RODATA is not set
+# CONFIG_4KSTACKS is not set
+CONFIG_X86_FIND_SMP_CONFIG=y
+CONFIG_X86_MPPARSE=y
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_AES_586=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+# CONFIG_CRYPTO_DEV_PADLOCK is not set
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
+CONFIG_X86_SMP=y
+CONFIG_X86_HT=y
+CONFIG_X86_BIOS_REBOOT=y
+CONFIG_X86_TRAMPOLINE=y
+CONFIG_KTIME_SCALAR=y
diff --git a/lustre/kernel_patches/kernel_configs/kernel-2.6.16-2.6-patchless-i686.config b/lustre/kernel_patches/kernel_configs/kernel-2.6.16-2.6-patchless-i686.config
new file mode 100644 (file)
index 0000000..285c6a5
--- /dev/null
@@ -0,0 +1,1613 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.16.22
+# Thu Jul 13 14:08:44 2006
+#
+CONFIG_X86_32=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_X86=y
+CONFIG_MMU=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_DMI=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_VM86=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Processor type and features
+#
+CONFIG_X86_PC=y
+# CONFIG_X86_ELAN is not set
+# CONFIG_X86_VOYAGER is not set
+# CONFIG_X86_NUMAQ is not set
+# CONFIG_X86_SUMMIT is not set
+# CONFIG_X86_BIGSMP is not set
+# CONFIG_X86_VISWS is not set
+# CONFIG_X86_GENERICARCH is not set
+# CONFIG_X86_ES7000 is not set
+# CONFIG_M386 is not set
+# CONFIG_M486 is not set
+# CONFIG_M586 is not set
+# CONFIG_M586TSC is not set
+# CONFIG_M586MMX is not set
+CONFIG_M686=y
+# CONFIG_MPENTIUMII is not set
+# CONFIG_MPENTIUMIII is not set
+# CONFIG_MPENTIUMM is not set
+# CONFIG_MPENTIUM4 is not set
+# CONFIG_MK6 is not set
+# CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
+# CONFIG_MCRUSOE is not set
+# CONFIG_MEFFICEON is not set
+# CONFIG_MWINCHIPC6 is not set
+# CONFIG_MWINCHIP2 is not set
+# CONFIG_MWINCHIP3D is not set
+# CONFIG_MGEODEGX1 is not set
+# CONFIG_MGEODE_LX is not set
+# CONFIG_MCYRIXIII is not set
+# CONFIG_MVIAC3_2 is not set
+CONFIG_X86_GENERIC=y
+CONFIG_X86_CMPXCHG=y
+CONFIG_X86_XADD=y
+CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_X86_PPRO_FENCE=y
+CONFIG_X86_WP_WORKS_OK=y
+CONFIG_X86_INVLPG=y
+CONFIG_X86_BSWAP=y
+CONFIG_X86_POPAD_OK=y
+CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_GOOD_APIC=y
+CONFIG_X86_INTEL_USERCOPY=y
+CONFIG_X86_USE_PPRO_CHECKSUM=y
+CONFIG_X86_TSC=y
+CONFIG_HPET_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+# CONFIG_X86_UP_APIC is not set
+CONFIG_X86_MCE=y
+# CONFIG_X86_MCE_NONFATAL is not set
+# CONFIG_TOSHIBA is not set
+# CONFIG_I8K is not set
+# CONFIG_X86_REBOOTFIXUPS is not set
+# CONFIG_MICROCODE is not set
+# CONFIG_X86_MSR is not set
+# CONFIG_X86_CPUID is not set
+
+#
+# Firmware Drivers
+#
+# CONFIG_EDD is not set
+# CONFIG_DELL_RBU is not set
+# CONFIG_DCDBAS is not set
+# CONFIG_NOHIGHMEM is not set
+CONFIG_HIGHMEM4G=y
+# CONFIG_HIGHMEM64G is not set
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_STATIC=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HIGHPTE is not set
+# CONFIG_MATH_EMULATION is not set
+CONFIG_MTRR=y
+# CONFIG_EFI is not set
+# CONFIG_REGPARM is not set
+CONFIG_SECCOMP=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_PHYSICAL_START=0x100000
+CONFIG_DOUBLEFAULT=y
+
+#
+# Power management options (ACPI, APM)
+#
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_SOFTWARE_SUSPEND is not set
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+CONFIG_ACPI=y
+CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_SLEEP_PROC_FS=y
+# CONFIG_ACPI_SLEEP_PROC_SLEEP is not set
+CONFIG_ACPI_AC=m
+CONFIG_ACPI_BATTERY=m
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_VIDEO=y
+# CONFIG_ACPI_HOTKEY is not set
+CONFIG_ACPI_FAN=m
+CONFIG_ACPI_PROCESSOR=m
+CONFIG_ACPI_THERMAL=m
+CONFIG_ACPI_ASUS=m
+# CONFIG_ACPI_IBM is not set
+CONFIG_ACPI_TOSHIBA=m
+CONFIG_ACPI_BLACKLIST_YEAR=0
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_EC=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_SYSTEM=y
+CONFIG_X86_PM_TIMER=y
+# CONFIG_ACPI_CONTAINER is not set
+
+#
+# APM (Advanced Power Management) BIOS Support
+#
+# CONFIG_APM is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+CONFIG_PCI=y
+# CONFIG_PCI_GOBIOS is not set
+# CONFIG_PCI_GOMMCONFIG is not set
+# CONFIG_PCI_GODIRECT is not set
+CONFIG_PCI_GOANY=y
+CONFIG_PCI_BIOS=y
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_MMCONFIG=y
+# CONFIG_PCIEPORTBUS is not set
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_DEBUG is not set
+CONFIG_ISA_DMA_API=y
+CONFIG_ISA=y
+# CONFIG_EISA is not set
+# CONFIG_MCA is not set
+# CONFIG_SCx200 is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_CMD640 is not set
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_RZ1000=y
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+CONFIG_BLK_DEV_AMD74XX=y
+CONFIG_BLK_DEV_ATIIXP=y
+CONFIG_BLK_DEV_CMD64X=y
+CONFIG_BLK_DEV_TRIFLEX=y
+CONFIG_BLK_DEV_CY82C693=y
+CONFIG_BLK_DEV_CS5520=y
+CONFIG_BLK_DEV_CS5530=y
+# CONFIG_BLK_DEV_CS5535 is not set
+CONFIG_BLK_DEV_HPT34X=y
+# CONFIG_HPT34X_AUTODMA is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=y
+# CONFIG_PDC202XX_BURST is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+CONFIG_BLK_DEV_SVWKS=y
+CONFIG_BLK_DEV_SIIMAGE=y
+CONFIG_BLK_DEV_SIS5513=y
+CONFIG_BLK_DEV_SLC90E66=y
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+CONFIG_SCSI_BUSLOGIC=m
+# CONFIG_SCSI_OMIT_FLASHPOINT is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_ULTRASTOR is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=128
+# CONFIG_FUSION_CTL is not set
+CONFIG_FUSION_LAN=m
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+# CONFIG_CASSINI is not set
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_EL1=m
+CONFIG_EL2=m
+CONFIG_ELPLUS=m
+CONFIG_EL16=m
+CONFIG_EL3=m
+CONFIG_3C515=m
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+# CONFIG_LANCE is not set
+CONFIG_NET_VENDOR_SMC=y
+CONFIG_WD80x3=m
+CONFIG_ULTRA=m
+CONFIG_SMC9194=m
+CONFIG_NET_VENDOR_RACAL=y
+CONFIG_NI5010=m
+CONFIG_NI52=m
+CONFIG_NI65=m
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+CONFIG_TULIP_NAPI=y
+# CONFIG_TULIP_NAPI_HW_MITIGATION is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+CONFIG_HP100=m
+# CONFIG_NET_ISA is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+# CONFIG_AC3200 is not set
+CONFIG_APRICOT=m
+CONFIG_B44=m
+CONFIG_FORCEDETH=m
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=m
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+CONFIG_8139TOO_PIO=y
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+# CONFIG_SUNDANCE is not set
+CONFIG_TLAN=m
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+CONFIG_NS83820=m
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+CONFIG_SKY2=m
+CONFIG_SK98LIN=m
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_KEYBOARD_XTKBD=y
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_INPORT is not set
+CONFIG_MOUSE_LOGIBM=m
+CONFIG_MOUSE_PC110PAD=m
+CONFIG_MOUSE_VSXXXAA=m
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PCSPKR=m
+# CONFIG_INPUT_WISTRON_BTNS is not set
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+CONFIG_ROCKETPORT=m
+# CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_ESPSERIAL is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+# CONFIG_SYNCLINK_GT is not set
+CONFIG_N_HDLC=m
+# CONFIG_RISCOM8 is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+CONFIG_RIO=m
+# CONFIG_RIO_OLDPCI is not set
+CONFIG_STALDRV=y
+CONFIG_STALLION=m
+CONFIG_ISTALLION=m
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_ACPI is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_ACQUIRE_WDT=m
+CONFIG_ADVANTECH_WDT=m
+CONFIG_ALIM1535_WDT=m
+CONFIG_ALIM7101_WDT=m
+CONFIG_SC520_WDT=m
+CONFIG_EUROTECH_WDT=m
+CONFIG_IB700_WDT=m
+# CONFIG_IBMASR is not set
+CONFIG_WAFER_WDT=m
+# CONFIG_I6300ESB_WDT is not set
+CONFIG_I8XX_TCO=m
+CONFIG_SC1200_WDT=m
+# CONFIG_60XX_WDT is not set
+# CONFIG_SBC8360_WDT is not set
+CONFIG_CPU5_WDT=m
+CONFIG_W83627HF_WDT=m
+CONFIG_W83877F_WDT=m
+# CONFIG_W83977F_WDT is not set
+CONFIG_MACHZ_WDT=m
+# CONFIG_SBC_EPX_C3_WATCHDOG is not set
+
+#
+# ISA-based Watchdog Cards
+#
+CONFIG_PCWATCHDOG=m
+# CONFIG_MIXCOMWD is not set
+CONFIG_WDT=m
+# CONFIG_WDT_501 is not set
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_SONYPI is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+CONFIG_AGP=y
+CONFIG_AGP_ALI=y
+CONFIG_AGP_ATI=y
+CONFIG_AGP_AMD=y
+CONFIG_AGP_AMD64=y
+CONFIG_AGP_INTEL=y
+CONFIG_AGP_NVIDIA=y
+CONFIG_AGP_SIS=y
+CONFIG_AGP_SWORKS=y
+CONFIG_AGP_VIA=y
+CONFIG_AGP_EFFICEON=y
+# CONFIG_DRM is not set
+# CONFIG_MWAVE is not set
+# CONFIG_CS5535_GPIO is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HPET is not set
+CONFIG_HANGCHECK_TIMER=m
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+CONFIG_I2C_AMD8111=m
+# CONFIG_I2C_ELEKTOR is not set
+# CONFIG_I2C_I801 is not set
+CONFIG_I2C_I810=m
+CONFIG_I2C_PIIX4=m
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_RTC_X1205_I2C is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_HDAPS is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+# CONFIG_IBM_ASM is not set
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+
+#
+# Video For Linux
+#
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_SAA7134 is not set
+# CONFIG_VIDEO_MXB is not set
+# CONFIG_VIDEO_DPC is not set
+# CONFIG_VIDEO_HEXIUM_ORION is not set
+# CONFIG_VIDEO_HEXIUM_GEMINI is not set
+# CONFIG_VIDEO_CX88 is not set
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_OVCAMCHIP is not set
+# CONFIG_VIDEO_AUDIO_DECODER is not set
+# CONFIG_VIDEO_DECODER is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_ZOLTRIX is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ARC is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+CONFIG_FB_VGA16=m
+CONFIG_FB_VESA=y
+CONFIG_VIDEO_SELECT=y
+# CONFIG_FB_HGA is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_I810 is not set
+# CONFIG_FB_INTEL is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_CYBLA is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_GEODE is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_MDA_CONSOLE=m
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_ET61X251 is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_KONICAWC is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_SN9C102 is not set
+# CONFIG_USB_STV680 is not set
+# CONFIG_USB_PWC is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+# CONFIG_EDAC is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+# CONFIG_KPROBES is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+CONFIG_DEBUG_SLAB=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_HIGHMEM is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_EARLY_PRINTK=y
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_DEBUG_STACK_USAGE=y
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_DEBUG_RODATA is not set
+# CONFIG_4KSTACKS is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_AES_586=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+# CONFIG_CRYPTO_DEV_PADLOCK is not set
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_X86_BIOS_REBOOT=y
+CONFIG_KTIME_SCALAR=y
diff --git a/lustre/kernel_patches/kernel_configs/kernel-2.6.16-2.6-patchless-ia64-smp.config b/lustre/kernel_patches/kernel_configs/kernel-2.6.16-2.6-patchless-ia64-smp.config
new file mode 100644 (file)
index 0000000..0fd1a95
--- /dev/null
@@ -0,0 +1,1419 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.16.22
+# Thu Jul 13 14:28:18 2006
+#
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_CPUSETS is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Block layer
+#
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Processor type and features
+#
+CONFIG_IA64=y
+CONFIG_64BIT=y
+CONFIG_MMU=y
+CONFIG_SWIOTLB=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_TIME_INTERPOLATION=y
+CONFIG_EFI=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_IA64_UNCACHED_ALLOCATOR=y
+CONFIG_DMA_IS_DMA32=y
+CONFIG_IA64_GENERIC=y
+# CONFIG_IA64_DIG is not set
+# CONFIG_IA64_HP_ZX1 is not set
+# CONFIG_IA64_HP_ZX1_SWIOTLB is not set
+# CONFIG_IA64_SGI_SN2 is not set
+# CONFIG_IA64_HP_SIM is not set
+# CONFIG_ITANIUM is not set
+CONFIG_MCKINLEY=y
+# CONFIG_IA64_PAGE_SIZE_4KB is not set
+# CONFIG_IA64_PAGE_SIZE_8KB is not set
+CONFIG_IA64_PAGE_SIZE_16KB=y
+# CONFIG_IA64_PAGE_SIZE_64KB is not set
+CONFIG_PGTABLE_3=y
+# CONFIG_PGTABLE_4 is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_IA64_L1_CACHE_SHIFT=7
+CONFIG_IA64_CYCLONE=y
+CONFIG_IOSAPIC=y
+CONFIG_IA64_SGI_SN_XP=m
+CONFIG_FORCE_MAX_ZONEORDER=17
+CONFIG_SMP=y
+CONFIG_NR_CPUS=8
+# CONFIG_HOTPLUG_CPU is not set
+# CONFIG_SCHED_SMT is not set
+# CONFIG_PREEMPT is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_NEED_MULTIPLE_NODES=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y
+CONFIG_NUMA=y
+CONFIG_VIRTUAL_MEM_MAP=y
+CONFIG_HOLES_IN_ZONE=y
+CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
+# CONFIG_IA32_SUPPORT is not set
+CONFIG_IA64_MCA_RECOVERY=m
+CONFIG_PERFMON=y
+CONFIG_IA64_PALINFO=y
+CONFIG_SGI_SN=y
+
+#
+# Firmware Drivers
+#
+CONFIG_EFI_VARS=y
+CONFIG_EFI_PCDP=y
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management and ACPI
+#
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+CONFIG_ACPI=y
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_FAN=m
+CONFIG_ACPI_PROCESSOR=m
+CONFIG_ACPI_THERMAL=m
+CONFIG_ACPI_NUMA=y
+CONFIG_ACPI_BLACKLIST_YEAR=0
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_EC=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_SYSTEM=y
+# CONFIG_ACPI_CONTAINER is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Bus options (PCI, PCMCIA)
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_MSI is not set
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+CONFIG_BLK_DEV_AMD74XX=y
+CONFIG_BLK_DEV_CMD64X=y
+CONFIG_BLK_DEV_TRIFLEX=y
+CONFIG_BLK_DEV_CY82C693=y
+CONFIG_BLK_DEV_CS5520=y
+CONFIG_BLK_DEV_CS5530=y
+CONFIG_BLK_DEV_HPT34X=y
+# CONFIG_HPT34X_AUTODMA is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=y
+# CONFIG_PDC202XX_BURST is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+CONFIG_BLK_DEV_SVWKS=y
+CONFIG_BLK_DEV_SGIIOC4=m
+CONFIG_BLK_DEV_SIIMAGE=y
+CONFIG_BLK_DEV_SLC90E66=y
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=128
+# CONFIG_FUSION_CTL is not set
+CONFIG_FUSION_LAN=m
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+# CONFIG_CASSINI is not set
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+CONFIG_TULIP_NAPI=y
+# CONFIG_TULIP_NAPI_HW_MITIGATION is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_HP100=m
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+CONFIG_B44=m
+CONFIG_FORCEDETH=m
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=m
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+CONFIG_8139TOO_PIO=y
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+# CONFIG_SUNDANCE is not set
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+CONFIG_NS83820=m
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+CONFIG_SKY2=m
+CONFIG_SK98LIN=m
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_KEYBOARD_XTKBD=y
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+CONFIG_MOUSE_VSXXXAA=m
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+CONFIG_ROCKETPORT=m
+# CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+CONFIG_SYNCLINKMP=m
+# CONFIG_SYNCLINK_GT is not set
+CONFIG_N_HDLC=m
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+CONFIG_STALDRV=y
+CONFIG_SGI_SNSC=y
+# CONFIG_SGI_TIOCX is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_ACPI is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_SGI_L1_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_SERIAL_SGI_IOC4=m
+CONFIG_SERIAL_SGI_IOC3=m
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_I8XX_TCO=m
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+# CONFIG_HW_RANDOM is not set
+CONFIG_EFI_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=y
+CONFIG_AGP_I460=y
+CONFIG_AGP_HP_ZX1=y
+CONFIG_AGP_SGI_TIOCA=m
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HPET is not set
+CONFIG_HANGCHECK_TIMER=m
+CONFIG_MMTIMER=m
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+CONFIG_I2C_AMD8111=m
+# CONFIG_I2C_I801 is not set
+CONFIG_I2C_I810=m
+CONFIG_I2C_PIIX4=m
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_RTC_X1205_I2C is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+
+#
+# Video For Linux
+#
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_SAA7134 is not set
+# CONFIG_VIDEO_MXB is not set
+# CONFIG_VIDEO_DPC is not set
+# CONFIG_VIDEO_HEXIUM_ORION is not set
+# CONFIG_VIDEO_HEXIUM_GEMINI is not set
+# CONFIG_VIDEO_CX88 is not set
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_OVCAMCHIP is not set
+# CONFIG_VIDEO_AUDIO_DECODER is not set
+# CONFIG_VIDEO_DECODER is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_ET61X251 is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_KONICAWC is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_SN9C102 is not set
+# CONFIG_USB_STV680 is not set
+# CONFIG_USB_PWC is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+CONFIG_SGI_IOC4=m
+CONFIG_SGI_IOC3=m
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
+
+#
+# HP Simulator drivers
+#
+# CONFIG_HP_SIMETH is not set
+# CONFIG_HP_SIMSERIAL is not set
+# CONFIG_HP_SIMSCSI is not set
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+# CONFIG_KPROBES is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+CONFIG_DEBUG_SLAB=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_IA64_GRANULE_16MB=y
+# CONFIG_IA64_GRANULE_64MB is not set
+# CONFIG_IA64_PRINT_HAZARDS is not set
+# CONFIG_DISABLE_VHPT is not set
+# CONFIG_IA64_DEBUG_CMPXCHG is not set
+# CONFIG_IA64_DEBUG_IRQ is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/lustre/kernel_patches/kernel_configs/kernel-2.6.16-2.6-patchless-ia64.config b/lustre/kernel_patches/kernel_configs/kernel-2.6.16-2.6-patchless-ia64.config
new file mode 100644 (file)
index 0000000..c892fde
--- /dev/null
@@ -0,0 +1,1416 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.16.22
+# Thu Jul 13 14:36:16 2006
+#
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Processor type and features
+#
+CONFIG_IA64=y
+CONFIG_64BIT=y
+CONFIG_MMU=y
+CONFIG_SWIOTLB=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_TIME_INTERPOLATION=y
+CONFIG_EFI=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_IA64_UNCACHED_ALLOCATOR=y
+CONFIG_DMA_IS_DMA32=y
+CONFIG_IA64_GENERIC=y
+# CONFIG_IA64_DIG is not set
+# CONFIG_IA64_HP_ZX1 is not set
+# CONFIG_IA64_HP_ZX1_SWIOTLB is not set
+# CONFIG_IA64_SGI_SN2 is not set
+# CONFIG_IA64_HP_SIM is not set
+# CONFIG_ITANIUM is not set
+CONFIG_MCKINLEY=y
+# CONFIG_IA64_PAGE_SIZE_4KB is not set
+# CONFIG_IA64_PAGE_SIZE_8KB is not set
+CONFIG_IA64_PAGE_SIZE_16KB=y
+# CONFIG_IA64_PAGE_SIZE_64KB is not set
+CONFIG_PGTABLE_3=y
+# CONFIG_PGTABLE_4 is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_IA64_L1_CACHE_SHIFT=7
+CONFIG_IA64_CYCLONE=y
+CONFIG_IOSAPIC=y
+CONFIG_IA64_SGI_SN_XP=m
+CONFIG_FORCE_MAX_ZONEORDER=17
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_NEED_MULTIPLE_NODES=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y
+CONFIG_NUMA=y
+CONFIG_VIRTUAL_MEM_MAP=y
+CONFIG_HOLES_IN_ZONE=y
+CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
+# CONFIG_IA32_SUPPORT is not set
+CONFIG_IA64_MCA_RECOVERY=m
+CONFIG_PERFMON=y
+CONFIG_IA64_PALINFO=y
+CONFIG_SGI_SN=y
+
+#
+# Firmware Drivers
+#
+CONFIG_EFI_VARS=y
+CONFIG_EFI_PCDP=y
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management and ACPI
+#
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+CONFIG_ACPI=y
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_FAN=m
+CONFIG_ACPI_PROCESSOR=m
+CONFIG_ACPI_THERMAL=m
+CONFIG_ACPI_NUMA=y
+CONFIG_ACPI_BLACKLIST_YEAR=0
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_EC=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_SYSTEM=y
+# CONFIG_ACPI_CONTAINER is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Bus options (PCI, PCMCIA)
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_MSI is not set
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+CONFIG_BLK_DEV_AMD74XX=y
+CONFIG_BLK_DEV_CMD64X=y
+CONFIG_BLK_DEV_TRIFLEX=y
+CONFIG_BLK_DEV_CY82C693=y
+CONFIG_BLK_DEV_CS5520=y
+CONFIG_BLK_DEV_CS5530=y
+CONFIG_BLK_DEV_HPT34X=y
+# CONFIG_HPT34X_AUTODMA is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=y
+# CONFIG_PDC202XX_BURST is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+CONFIG_BLK_DEV_SVWKS=y
+CONFIG_BLK_DEV_SGIIOC4=m
+CONFIG_BLK_DEV_SIIMAGE=y
+CONFIG_BLK_DEV_SLC90E66=y
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=128
+# CONFIG_FUSION_CTL is not set
+CONFIG_FUSION_LAN=m
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+# CONFIG_CASSINI is not set
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+CONFIG_TULIP_NAPI=y
+# CONFIG_TULIP_NAPI_HW_MITIGATION is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_HP100=m
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+CONFIG_B44=m
+CONFIG_FORCEDETH=m
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=m
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+CONFIG_8139TOO_PIO=y
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+# CONFIG_SUNDANCE is not set
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+CONFIG_NS83820=m
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+CONFIG_SKY2=m
+CONFIG_SK98LIN=m
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_KEYBOARD_XTKBD=y
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+CONFIG_MOUSE_VSXXXAA=m
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+CONFIG_ROCKETPORT=m
+# CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+CONFIG_SYNCLINKMP=m
+# CONFIG_SYNCLINK_GT is not set
+CONFIG_N_HDLC=m
+# CONFIG_RISCOM8 is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+CONFIG_STALDRV=y
+CONFIG_STALLION=m
+CONFIG_ISTALLION=m
+CONFIG_SGI_SNSC=y
+# CONFIG_SGI_TIOCX is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_ACPI is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_SGI_L1_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_SERIAL_SGI_IOC4=m
+CONFIG_SERIAL_SGI_IOC3=m
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_I8XX_TCO=m
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+# CONFIG_HW_RANDOM is not set
+CONFIG_EFI_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=y
+CONFIG_AGP_I460=y
+CONFIG_AGP_HP_ZX1=y
+CONFIG_AGP_SGI_TIOCA=m
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HPET is not set
+CONFIG_HANGCHECK_TIMER=m
+CONFIG_MMTIMER=m
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+CONFIG_I2C_AMD8111=m
+# CONFIG_I2C_I801 is not set
+CONFIG_I2C_I810=m
+CONFIG_I2C_PIIX4=m
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_RTC_X1205_I2C is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+
+#
+# Video For Linux
+#
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_SAA7134 is not set
+# CONFIG_VIDEO_MXB is not set
+# CONFIG_VIDEO_DPC is not set
+# CONFIG_VIDEO_HEXIUM_ORION is not set
+# CONFIG_VIDEO_HEXIUM_GEMINI is not set
+# CONFIG_VIDEO_CX88 is not set
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_OVCAMCHIP is not set
+# CONFIG_VIDEO_AUDIO_DECODER is not set
+# CONFIG_VIDEO_DECODER is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_ET61X251 is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_KONICAWC is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_SN9C102 is not set
+# CONFIG_USB_STV680 is not set
+# CONFIG_USB_PWC is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+CONFIG_SGI_IOC4=m
+CONFIG_SGI_IOC3=m
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+
+#
+# HP Simulator drivers
+#
+# CONFIG_HP_SIMETH is not set
+# CONFIG_HP_SIMSERIAL is not set
+# CONFIG_HP_SIMSCSI is not set
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+# CONFIG_KPROBES is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+CONFIG_DEBUG_SLAB=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_IA64_GRANULE_16MB=y
+# CONFIG_IA64_GRANULE_64MB is not set
+# CONFIG_IA64_PRINT_HAZARDS is not set
+# CONFIG_DISABLE_VHPT is not set
+# CONFIG_IA64_DEBUG_CMPXCHG is not set
+# CONFIG_IA64_DEBUG_IRQ is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/lustre/kernel_patches/kernel_configs/kernel-2.6.16-2.6-patchless-x86_64-smp.config b/lustre/kernel_patches/kernel_configs/kernel-2.6.16-2.6-patchless-x86_64-smp.config
new file mode 100644 (file)
index 0000000..050b155
--- /dev/null
@@ -0,0 +1,1460 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.16.22
+# Thu Jul 13 14:24:34 2006
+#
+CONFIG_X86_64=y
+CONFIG_64BIT=y
+CONFIG_X86=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_X86_CMPXCHG=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_DMI=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_CPUSETS is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_VM86=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Processor type and features
+#
+CONFIG_X86_PC=y
+# CONFIG_X86_VSMP is not set
+# CONFIG_MK8 is not set
+# CONFIG_MPSC is not set
+CONFIG_GENERIC_CPU=y
+CONFIG_X86_L1_CACHE_BYTES=128
+CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_X86_TSC=y
+CONFIG_X86_GOOD_APIC=y
+# CONFIG_MICROCODE is not set
+# CONFIG_X86_MSR is not set
+# CONFIG_X86_CPUID is not set
+CONFIG_X86_HT=y
+CONFIG_X86_IO_APIC=y
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_MTRR=y
+CONFIG_SMP=y
+# CONFIG_SCHED_SMT is not set
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_BKL=y
+# CONFIG_NUMA is not set
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_NR_CPUS=8
+# CONFIG_HOTPLUG_CPU is not set
+CONFIG_HPET_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
+CONFIG_GART_IOMMU=y
+CONFIG_SWIOTLB=y
+CONFIG_X86_MCE=y
+# CONFIG_X86_MCE_INTEL is not set
+# CONFIG_X86_MCE_AMD is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_PHYSICAL_START=0x100000
+CONFIG_SECCOMP=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ISA_DMA_API=y
+CONFIG_GENERIC_PENDING_IRQ=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+CONFIG_ACPI=y
+CONFIG_ACPI_AC=m
+CONFIG_ACPI_BATTERY=m
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_VIDEO=y
+# CONFIG_ACPI_HOTKEY is not set
+CONFIG_ACPI_FAN=m
+CONFIG_ACPI_PROCESSOR=m
+CONFIG_ACPI_THERMAL=m
+CONFIG_ACPI_ASUS=m
+# CONFIG_ACPI_IBM is not set
+CONFIG_ACPI_TOSHIBA=m
+CONFIG_ACPI_BLACKLIST_YEAR=0
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_EC=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_SYSTEM=y
+CONFIG_X86_PM_TIMER=y
+# CONFIG_ACPI_CONTAINER is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Bus options (PCI etc.)
+#
+CONFIG_PCI=y
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_MMCONFIG=y
+# CONFIG_UNORDERED_IO is not set
+# CONFIG_PCIEPORTBUS is not set
+# CONFIG_PCI_MSI is not set
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats / Emulations
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_IA32_EMULATION=y
+# CONFIG_IA32_AOUT is not set
+CONFIG_COMPAT=y
+CONFIG_SYSVIPC_COMPAT=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_CMD640 is not set
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_RZ1000=y
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+CONFIG_BLK_DEV_AMD74XX=y
+CONFIG_BLK_DEV_ATIIXP=y
+CONFIG_BLK_DEV_CMD64X=y
+CONFIG_BLK_DEV_TRIFLEX=y
+CONFIG_BLK_DEV_CY82C693=y
+CONFIG_BLK_DEV_CS5520=y
+CONFIG_BLK_DEV_CS5530=y
+CONFIG_BLK_DEV_HPT34X=y
+# CONFIG_HPT34X_AUTODMA is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=y
+# CONFIG_PDC202XX_BURST is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+CONFIG_BLK_DEV_SVWKS=y
+CONFIG_BLK_DEV_SIIMAGE=y
+CONFIG_BLK_DEV_SIS5513=y
+CONFIG_BLK_DEV_SLC90E66=y
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+CONFIG_SCSI_BUSLOGIC=m
+# CONFIG_SCSI_OMIT_FLASHPOINT is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=128
+# CONFIG_FUSION_CTL is not set
+CONFIG_FUSION_LAN=m
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+# CONFIG_CASSINI is not set
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+CONFIG_TULIP_NAPI=y
+# CONFIG_TULIP_NAPI_HW_MITIGATION is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_HP100=m
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+CONFIG_B44=m
+CONFIG_FORCEDETH=m
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=m
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+CONFIG_8139TOO_PIO=y
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+# CONFIG_SUNDANCE is not set
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+CONFIG_NS83820=m
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+CONFIG_SKY2=m
+CONFIG_SK98LIN=m
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_KEYBOARD_XTKBD=y
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+CONFIG_MOUSE_VSXXXAA=m
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PCSPKR=m
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+CONFIG_ROCKETPORT=m
+# CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+# CONFIG_SYNCLINK_GT is not set
+CONFIG_N_HDLC=m
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+CONFIG_STALDRV=y
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_ACPI is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_ACQUIRE_WDT=m
+CONFIG_ADVANTECH_WDT=m
+CONFIG_ALIM1535_WDT=m
+CONFIG_ALIM7101_WDT=m
+CONFIG_SC520_WDT=m
+CONFIG_EUROTECH_WDT=m
+CONFIG_IB700_WDT=m
+# CONFIG_IBMASR is not set
+CONFIG_WAFER_WDT=m
+# CONFIG_I6300ESB_WDT is not set
+CONFIG_I8XX_TCO=m
+CONFIG_SC1200_WDT=m
+# CONFIG_60XX_WDT is not set
+# CONFIG_SBC8360_WDT is not set
+CONFIG_CPU5_WDT=m
+CONFIG_W83627HF_WDT=m
+CONFIG_W83877F_WDT=m
+# CONFIG_W83977F_WDT is not set
+CONFIG_MACHZ_WDT=m
+# CONFIG_SBC_EPX_C3_WATCHDOG is not set
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=y
+CONFIG_AGP_AMD64=y
+CONFIG_AGP_INTEL=y
+# CONFIG_DRM is not set
+# CONFIG_MWAVE is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HPET is not set
+CONFIG_HANGCHECK_TIMER=m
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+CONFIG_I2C_AMD8111=m
+# CONFIG_I2C_I801 is not set
+CONFIG_I2C_I810=m
+CONFIG_I2C_PIIX4=m
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_RTC_X1205_I2C is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_HDAPS is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+# CONFIG_IBM_ASM is not set
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+
+#
+# Video For Linux
+#
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_SAA7134 is not set
+# CONFIG_VIDEO_MXB is not set
+# CONFIG_VIDEO_DPC is not set
+# CONFIG_VIDEO_HEXIUM_ORION is not set
+# CONFIG_VIDEO_HEXIUM_GEMINI is not set
+# CONFIG_VIDEO_CX88 is not set
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_OVCAMCHIP is not set
+# CONFIG_VIDEO_AUDIO_DECODER is not set
+# CONFIG_VIDEO_DECODER is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ARC is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+CONFIG_FB_VGA16=m
+CONFIG_FB_VESA=y
+CONFIG_VIDEO_SELECT=y
+# CONFIG_FB_HGA is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_GEODE is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_ET61X251 is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_KONICAWC is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_SN9C102 is not set
+# CONFIG_USB_STV680 is not set
+# CONFIG_USB_PWC is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+# CONFIG_EDAC is not set
+
+#
+# Firmware Drivers
+#
+# CONFIG_EDD is not set
+# CONFIG_DELL_RBU is not set
+# CONFIG_DCDBAS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+# CONFIG_KPROBES is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+CONFIG_DEBUG_SLAB=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUG_RODATA is not set
+# CONFIG_IOMMU_DEBUG is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_AES_X86_64=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
diff --git a/lustre/kernel_patches/kernel_configs/kernel-2.6.16-2.6-patchless-x86_64.config b/lustre/kernel_patches/kernel_configs/kernel-2.6.16-2.6-patchless-x86_64.config
new file mode 100644 (file)
index 0000000..06405e8
--- /dev/null
@@ -0,0 +1,1459 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.16.22
+# Thu Jul 13 14:30:26 2006
+#
+CONFIG_X86_64=y
+CONFIG_64BIT=y
+CONFIG_X86=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_X86_CMPXCHG=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_DMI=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_VM86=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Processor type and features
+#
+CONFIG_X86_PC=y
+# CONFIG_X86_VSMP is not set
+# CONFIG_MK8 is not set
+# CONFIG_MPSC is not set
+CONFIG_GENERIC_CPU=y
+CONFIG_X86_L1_CACHE_BYTES=128
+CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_X86_TSC=y
+CONFIG_X86_GOOD_APIC=y
+# CONFIG_MICROCODE is not set
+# CONFIG_X86_MSR is not set
+# CONFIG_X86_CPUID is not set
+CONFIG_X86_IO_APIC=y
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_MTRR=y
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_HPET_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
+CONFIG_GART_IOMMU=y
+CONFIG_SWIOTLB=y
+CONFIG_X86_MCE=y
+# CONFIG_X86_MCE_INTEL is not set
+# CONFIG_X86_MCE_AMD is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_PHYSICAL_START=0x100000
+CONFIG_SECCOMP=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_SOFTWARE_SUSPEND is not set
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+CONFIG_ACPI=y
+CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_SLEEP_PROC_FS=y
+# CONFIG_ACPI_SLEEP_PROC_SLEEP is not set
+CONFIG_ACPI_AC=m
+CONFIG_ACPI_BATTERY=m
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_VIDEO=y
+# CONFIG_ACPI_HOTKEY is not set
+CONFIG_ACPI_FAN=m
+CONFIG_ACPI_PROCESSOR=m
+CONFIG_ACPI_THERMAL=m
+CONFIG_ACPI_ASUS=m
+# CONFIG_ACPI_IBM is not set
+CONFIG_ACPI_TOSHIBA=m
+CONFIG_ACPI_BLACKLIST_YEAR=0
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_EC=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_SYSTEM=y
+CONFIG_X86_PM_TIMER=y
+# CONFIG_ACPI_CONTAINER is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Bus options (PCI etc.)
+#
+CONFIG_PCI=y
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_MMCONFIG=y
+# CONFIG_UNORDERED_IO is not set
+# CONFIG_PCIEPORTBUS is not set
+# CONFIG_PCI_MSI is not set
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats / Emulations
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_IA32_EMULATION=y
+# CONFIG_IA32_AOUT is not set
+CONFIG_COMPAT=y
+CONFIG_SYSVIPC_COMPAT=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_CMD640 is not set
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_RZ1000=y
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+CONFIG_BLK_DEV_AMD74XX=y
+CONFIG_BLK_DEV_ATIIXP=y
+CONFIG_BLK_DEV_CMD64X=y
+CONFIG_BLK_DEV_TRIFLEX=y
+CONFIG_BLK_DEV_CY82C693=y
+CONFIG_BLK_DEV_CS5520=y
+CONFIG_BLK_DEV_CS5530=y
+CONFIG_BLK_DEV_HPT34X=y
+# CONFIG_HPT34X_AUTODMA is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=y
+# CONFIG_PDC202XX_BURST is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+CONFIG_BLK_DEV_SVWKS=y
+CONFIG_BLK_DEV_SIIMAGE=y
+CONFIG_BLK_DEV_SIS5513=y
+CONFIG_BLK_DEV_SLC90E66=y
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+CONFIG_SCSI_BUSLOGIC=m
+# CONFIG_SCSI_OMIT_FLASHPOINT is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=128
+# CONFIG_FUSION_CTL is not set
+CONFIG_FUSION_LAN=m
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+# CONFIG_CASSINI is not set
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+CONFIG_TULIP_NAPI=y
+# CONFIG_TULIP_NAPI_HW_MITIGATION is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_HP100=m
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+CONFIG_B44=m
+CONFIG_FORCEDETH=m
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=m
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+CONFIG_8139TOO_PIO=y
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+# CONFIG_SUNDANCE is not set
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+CONFIG_NS83820=m
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+CONFIG_SKY2=m
+CONFIG_SK98LIN=m
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_KEYBOARD_XTKBD=y
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+CONFIG_MOUSE_VSXXXAA=m
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PCSPKR=m
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+CONFIG_ROCKETPORT=m
+# CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+# CONFIG_SYNCLINK_GT is not set
+CONFIG_N_HDLC=m
+# CONFIG_RISCOM8 is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+CONFIG_STALDRV=y
+CONFIG_STALLION=m
+CONFIG_ISTALLION=m
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_ACPI is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_ACQUIRE_WDT=m
+CONFIG_ADVANTECH_WDT=m
+CONFIG_ALIM1535_WDT=m
+CONFIG_ALIM7101_WDT=m
+CONFIG_SC520_WDT=m
+CONFIG_EUROTECH_WDT=m
+CONFIG_IB700_WDT=m
+# CONFIG_IBMASR is not set
+CONFIG_WAFER_WDT=m
+# CONFIG_I6300ESB_WDT is not set
+CONFIG_I8XX_TCO=m
+CONFIG_SC1200_WDT=m
+# CONFIG_60XX_WDT is not set
+# CONFIG_SBC8360_WDT is not set
+CONFIG_CPU5_WDT=m
+CONFIG_W83627HF_WDT=m
+CONFIG_W83877F_WDT=m
+# CONFIG_W83977F_WDT is not set
+CONFIG_MACHZ_WDT=m
+# CONFIG_SBC_EPX_C3_WATCHDOG is not set
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+CONFIG_AGP=y
+CONFIG_AGP_AMD64=y
+CONFIG_AGP_INTEL=y
+# CONFIG_DRM is not set
+# CONFIG_MWAVE is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HPET is not set
+CONFIG_HANGCHECK_TIMER=m
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+CONFIG_I2C_AMD8111=m
+# CONFIG_I2C_I801 is not set
+CONFIG_I2C_I810=m
+CONFIG_I2C_PIIX4=m
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_RTC_X1205_I2C is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_HDAPS is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+# CONFIG_IBM_ASM is not set
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+
+#
+# Video For Linux
+#
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_SAA7134 is not set
+# CONFIG_VIDEO_MXB is not set
+# CONFIG_VIDEO_DPC is not set
+# CONFIG_VIDEO_HEXIUM_ORION is not set
+# CONFIG_VIDEO_HEXIUM_GEMINI is not set
+# CONFIG_VIDEO_CX88 is not set
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_OVCAMCHIP is not set
+# CONFIG_VIDEO_AUDIO_DECODER is not set
+# CONFIG_VIDEO_DECODER is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ARC is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+CONFIG_FB_VGA16=m
+CONFIG_FB_VESA=y
+CONFIG_VIDEO_SELECT=y
+# CONFIG_FB_HGA is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_GEODE is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_ET61X251 is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_KONICAWC is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_SN9C102 is not set
+# CONFIG_USB_STV680 is not set
+# CONFIG_USB_PWC is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+# CONFIG_EDAC is not set
+
+#
+# Firmware Drivers
+#
+# CONFIG_EDD is not set
+# CONFIG_DELL_RBU is not set
+# CONFIG_DCDBAS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+# CONFIG_KPROBES is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+CONFIG_DEBUG_SLAB=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUG_RODATA is not set
+# CONFIG_IOMMU_DEBUG is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_AES_X86_64=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
index 8676e89..9cc9638 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.9-prep.qp2.2.5.11.3qsnet
-# Sat Mar 11 23:36:27 2006
+# Mon Jul 31 19:27:58 2006
 #
 CONFIG_X86=y
 CONFIG_MMU=y
@@ -114,6 +114,7 @@ CONFIG_HPET_EMULATE_RTC=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=32
 CONFIG_SCHED_SMT=y
+CONFIG_SCHED_MC=y
 # CONFIG_PREEMPT is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_X86_LOCAL_APIC=y
@@ -133,6 +134,7 @@ CONFIG_X86_CPUID=m
 #
 CONFIG_EDD=m
 CONFIG_DELL_RBU=m
+CONFIG_DCDBAS=m
 # CONFIG_NOHIGHMEM is not set
 # CONFIG_HIGHMEM4G is not set
 CONFIG_HIGHMEM64G=y
@@ -429,6 +431,8 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=16384
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_LBD=y
+CONFIG_CCISS_DUMP=y
+CONFIG_CCISS_DUMP_GLUE=m
 CONFIG_DISKDUMP=m
 
 #
@@ -450,6 +454,7 @@ CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 CONFIG_BLK_DEV_IDEFLOPPY=y
 CONFIG_BLK_DEV_IDESCSI=m
+CONFIG_BLK_DEV_IDEDUMP=m
 # CONFIG_IDE_TASK_IOCTL is not set
 # CONFIG_IDE_TASKFILE_IO is not set
 
@@ -534,8 +539,6 @@ CONFIG_SCSI_LOGGING=y
 CONFIG_SCSI_SPI_ATTRS=m
 CONFIG_SCSI_FC_ATTRS=m
 CONFIG_SCSI_ISCSI_ATTRS=m
-CONFIG_SAS_CLASS=m
-# CONFIG_SAS_DEBUG is not set
 
 #
 # SCSI low-level drivers
@@ -553,7 +556,7 @@ CONFIG_AIC7XXX_RESET_DELAY_MS=15000
 # CONFIG_AIC7XXX_DEBUG_ENABLE is not set
 CONFIG_AIC7XXX_DEBUG_MASK=0
 # CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
-# CONFIG_SCSI_AIC94XX is not set
+CONFIG_SCSI_ADP94XX=m
 CONFIG_SCSI_AIC7XXX_OLD=m
 CONFIG_SCSI_AIC79XX=m
 CONFIG_AIC79XX_CMDS_PER_DEVICE=4
@@ -572,13 +575,19 @@ CONFIG_SCSI_SATA=y
 CONFIG_SCSI_SATA_AHCI=m
 CONFIG_SCSI_SATA_SVW=m
 CONFIG_SCSI_ATA_PIIX=m
+CONFIG_SCSI_SATA_MV=m
 CONFIG_SCSI_SATA_NV=m
+CONFIG_SCSI_PDC_ADMA=m
+CONFIG_SCSI_SATA_QSTOR=m
 CONFIG_SCSI_SATA_PROMISE=m
 CONFIG_SCSI_SATA_SX4=m
 CONFIG_SCSI_SATA_SIL=m
+CONFIG_SCSI_SATA_SIL24=m
 CONFIG_SCSI_SATA_SIS=m
+CONFIG_SCSI_SATA_ULI=m
 CONFIG_SCSI_SATA_VIA=m
 CONFIG_SCSI_SATA_VITESSE=m
+CONFIG_SCSI_SATA_INTEL_COMBINED=y
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_DTC3280 is not set
@@ -605,12 +614,14 @@ CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
 # CONFIG_SCSI_IPR is not set
 # CONFIG_SCSI_PAS16 is not set
+CONFIG_SCSI_PROMISE_STEX=m
 # CONFIG_SCSI_PSI240I is not set
 # CONFIG_SCSI_QLOGIC_FAS is not set
 # CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 CONFIG_SCSI_QLOGIC_1280=m
 CONFIG_SCSI_QLA2XXX=m
+CONFIG_QLA_IOCTLMOD=m
 CONFIG_SCSI_QLA21XX=m
 CONFIG_SCSI_QLA22XX=m
 CONFIG_SCSI_QLA2300=m
@@ -1119,6 +1130,7 @@ CONFIG_NS83820=m
 # CONFIG_YELLOWFIN is not set
 CONFIG_R8169=m
 CONFIG_R8169_NAPI=y
+CONFIG_SKGE=m
 CONFIG_SKY2=m
 CONFIG_SK98LIN=m
 CONFIG_VIA_VELOCITY=m
@@ -1183,14 +1195,16 @@ CONFIG_PCMCIA_NETWAVE=m
 #
 CONFIG_IEEE80211=m
 # CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT=m
-CONFIG_IEEE80211_WPA=m
+CONFIG_IEEE80211_CRYPT_WEP=m
 CONFIG_IEEE80211_CRYPT_CCMP=m
 CONFIG_IEEE80211_CRYPT_TKIP=m
 CONFIG_IPW2100=m
-CONFIG_IPW2100_PROMISC=y
-# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2100_MONITOR=y
+# CONFIG_IPW2100_DEBUG is not set
 CONFIG_IPW2200=m
+CONFIG_IPW2200_MONITOR=y
+# CONFIG_IPW_QOS is not set
+# CONFIG_IPW2200_DEBUG is not set
 CONFIG_AIRO=m
 CONFIG_HERMES=m
 CONFIG_PLX_HERMES=m
@@ -1706,6 +1720,15 @@ CONFIG_SENSORS_RTC8564=m
 # CONFIG_I2C_DEBUG_CHIP is not set
 
 #
+# Hardware Monitoring support
+#
+CONFIG_HWMON=m
+CONFIG_HWMON_VID=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_LM87=m
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
@@ -2138,13 +2161,18 @@ CONFIG_USB_SPEEDTOUCH=m
 CONFIG_INFINIBAND=m
 CONFIG_INFINIBAND_USER_MAD=m
 CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_ADDR_TRANS=y
 CONFIG_INFINIBAND_MTHCA=m
-# CONFIG_INFINIBAND_MTHCA_DEBUG is not set
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
 CONFIG_INFINIBAND_IPOIB=m
-# CONFIG_INFINIBAND_IPOIB_DEBUG is not set
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+# CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set
 CONFIG_INFINIBAND_SDP=m
 # CONFIG_INFINIBAND_SDP_DEBUG is not set
 CONFIG_INFINIBAND_SRP=m
+# CONFIG_INFINIBAND_ISER is not set
+CONFIG_INFINIBAND_RDS=m
+# CONFIG_INFINIBAND_RDS_DEBUG is not set
 
 #
 # EDAC - error detection and reporting (RAS)
@@ -2411,6 +2439,7 @@ CONFIG_CRYPTO_DES=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_AES_586=m
 CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST6=m
index 336345d..aec4d8c 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.9-prep.qp2.2.5.11.3qsnet
-# Sat Mar 11 23:44:45 2006
+# Mon Jul 31 19:31:40 2006
 #
 CONFIG_X86=y
 CONFIG_MMU=y
@@ -127,6 +127,7 @@ CONFIG_X86_CPUID=m
 #
 CONFIG_EDD=m
 CONFIG_DELL_RBU=m
+CONFIG_DCDBAS=m
 # CONFIG_NOHIGHMEM is not set
 CONFIG_HIGHMEM4G=y
 # CONFIG_HIGHMEM64G is not set
@@ -417,6 +418,8 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=16384
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_LBD=y
+CONFIG_CCISS_DUMP=y
+CONFIG_CCISS_DUMP_GLUE=m
 CONFIG_DISKDUMP=m
 
 #
@@ -438,6 +441,7 @@ CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 CONFIG_BLK_DEV_IDEFLOPPY=y
 CONFIG_BLK_DEV_IDESCSI=m
+CONFIG_BLK_DEV_IDEDUMP=m
 # CONFIG_IDE_TASK_IOCTL is not set
 # CONFIG_IDE_TASKFILE_IO is not set
 
@@ -522,8 +526,6 @@ CONFIG_SCSI_LOGGING=y
 CONFIG_SCSI_SPI_ATTRS=m
 CONFIG_SCSI_FC_ATTRS=m
 CONFIG_SCSI_ISCSI_ATTRS=m
-CONFIG_SAS_CLASS=m
-# CONFIG_SAS_DEBUG is not set
 
 #
 # SCSI low-level drivers
@@ -541,7 +543,7 @@ CONFIG_AIC7XXX_RESET_DELAY_MS=15000
 # CONFIG_AIC7XXX_DEBUG_ENABLE is not set
 CONFIG_AIC7XXX_DEBUG_MASK=0
 # CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
-# CONFIG_SCSI_AIC94XX is not set
+CONFIG_SCSI_ADP94XX=m
 CONFIG_SCSI_AIC7XXX_OLD=m
 CONFIG_SCSI_AIC79XX=m
 CONFIG_AIC79XX_CMDS_PER_DEVICE=4
@@ -560,13 +562,19 @@ CONFIG_SCSI_SATA=y
 CONFIG_SCSI_SATA_AHCI=m
 CONFIG_SCSI_SATA_SVW=m
 CONFIG_SCSI_ATA_PIIX=m
+CONFIG_SCSI_SATA_MV=m
 CONFIG_SCSI_SATA_NV=m
+CONFIG_SCSI_PDC_ADMA=m
+CONFIG_SCSI_SATA_QSTOR=m
 CONFIG_SCSI_SATA_PROMISE=m
 CONFIG_SCSI_SATA_SX4=m
 CONFIG_SCSI_SATA_SIL=m
+CONFIG_SCSI_SATA_SIL24=m
 CONFIG_SCSI_SATA_SIS=m
+CONFIG_SCSI_SATA_ULI=m
 CONFIG_SCSI_SATA_VIA=m
 CONFIG_SCSI_SATA_VITESSE=m
+CONFIG_SCSI_SATA_INTEL_COMBINED=y
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_DTC3280 is not set
@@ -593,12 +601,14 @@ CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
 # CONFIG_SCSI_IPR is not set
 # CONFIG_SCSI_PAS16 is not set
+CONFIG_SCSI_PROMISE_STEX=m
 # CONFIG_SCSI_PSI240I is not set
 # CONFIG_SCSI_QLOGIC_FAS is not set
 # CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 CONFIG_SCSI_QLOGIC_1280=m
 CONFIG_SCSI_QLA2XXX=m
+CONFIG_QLA_IOCTLMOD=m
 CONFIG_SCSI_QLA21XX=m
 CONFIG_SCSI_QLA22XX=m
 CONFIG_SCSI_QLA2300=m
@@ -1109,6 +1119,7 @@ CONFIG_NS83820=m
 # CONFIG_YELLOWFIN is not set
 CONFIG_R8169=m
 CONFIG_R8169_NAPI=y
+CONFIG_SKGE=m
 CONFIG_SKY2=m
 CONFIG_SK98LIN=m
 CONFIG_VIA_VELOCITY=m
@@ -1173,14 +1184,16 @@ CONFIG_PCMCIA_NETWAVE=m
 #
 CONFIG_IEEE80211=m
 # CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT=m
-CONFIG_IEEE80211_WPA=m
+CONFIG_IEEE80211_CRYPT_WEP=m
 CONFIG_IEEE80211_CRYPT_CCMP=m
 CONFIG_IEEE80211_CRYPT_TKIP=m
 CONFIG_IPW2100=m
-CONFIG_IPW2100_PROMISC=y
-# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2100_MONITOR=y
+# CONFIG_IPW2100_DEBUG is not set
 CONFIG_IPW2200=m
+CONFIG_IPW2200_MONITOR=y
+# CONFIG_IPW_QOS is not set
+# CONFIG_IPW2200_DEBUG is not set
 CONFIG_AIRO=m
 CONFIG_HERMES=m
 CONFIG_PLX_HERMES=m
@@ -1714,6 +1727,15 @@ CONFIG_SENSORS_RTC8564=m
 # CONFIG_I2C_DEBUG_CHIP is not set
 
 #
+# Hardware Monitoring support
+#
+CONFIG_HWMON=m
+CONFIG_HWMON_VID=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_LM87=m
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
@@ -2148,13 +2170,18 @@ CONFIG_USB_SPEEDTOUCH=m
 CONFIG_INFINIBAND=m
 CONFIG_INFINIBAND_USER_MAD=m
 CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_ADDR_TRANS=y
 CONFIG_INFINIBAND_MTHCA=m
-# CONFIG_INFINIBAND_MTHCA_DEBUG is not set
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
 CONFIG_INFINIBAND_IPOIB=m
-# CONFIG_INFINIBAND_IPOIB_DEBUG is not set
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+# CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set
 CONFIG_INFINIBAND_SDP=m
 # CONFIG_INFINIBAND_SDP_DEBUG is not set
 CONFIG_INFINIBAND_SRP=m
+# CONFIG_INFINIBAND_ISER is not set
+CONFIG_INFINIBAND_RDS=m
+# CONFIG_INFINIBAND_RDS_DEBUG is not set
 
 #
 # EDAC - error detection and reporting (RAS)
@@ -2419,6 +2446,7 @@ CONFIG_CRYPTO_DES=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_AES_586=m
 CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST6=m
index 53a883f..5d1c5b7 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.9-prep.qp2.2.5.11.3qsnet
-# Thu Oct 27 17:05:00 2005
+# Mon Jul 31 19:41:42 2006
 #
 
 #
@@ -84,6 +84,7 @@ CONFIG_FORCE_MAX_ZONEORDER=18
 CONFIG_SMP=y
 CONFIG_NR_CPUS=64
 # CONFIG_HOTPLUG_CPU is not set
+CONFIG_SCHED_SMT=y
 # CONFIG_PREEMPT is not set
 CONFIG_HAVE_DEC_LOCK=y
 # CONFIG_IA32_SUPPORT is not set
@@ -98,6 +99,7 @@ CONFIG_PTRACK=y
 #
 CONFIG_EFI_VARS=y
 CONFIG_EFI_PCDP=y
+CONFIG_DELL_RBU=m
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=y
 
@@ -208,6 +210,8 @@ CONFIG_BLK_DEV_SX8=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=16384
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_CCISS_DUMP=y
+CONFIG_CCISS_DUMP_GLUE=m
 CONFIG_DISKDUMP=m
 
 #
@@ -228,6 +232,7 @@ CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 CONFIG_BLK_DEV_IDEFLOPPY=y
 CONFIG_BLK_DEV_IDESCSI=m
+CONFIG_BLK_DEV_IDEDUMP=m
 # CONFIG_IDE_TASK_IOCTL is not set
 # CONFIG_IDE_TASKFILE_IO is not set
 
@@ -321,6 +326,7 @@ CONFIG_AIC7XXX_RESET_DELAY_MS=15000
 # CONFIG_AIC7XXX_DEBUG_ENABLE is not set
 CONFIG_AIC7XXX_DEBUG_MASK=0
 # CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+CONFIG_SCSI_ADP94XX=m
 CONFIG_SCSI_AIC7XXX_OLD=m
 CONFIG_SCSI_AIC79XX=m
 CONFIG_AIC79XX_CMDS_PER_DEVICE=4
@@ -332,17 +338,24 @@ CONFIG_AIC79XX_DEBUG_MASK=0
 CONFIG_MEGARAID_NEWGEN=y
 CONFIG_MEGARAID_MM=m
 CONFIG_MEGARAID_MAILBOX=m
+CONFIG_MEGARAID_SAS=m
 CONFIG_SCSI_SATA=y
 CONFIG_SCSI_SATA_AHCI=m
 CONFIG_SCSI_SATA_SVW=m
 CONFIG_SCSI_ATA_PIIX=m
+CONFIG_SCSI_SATA_MV=m
 CONFIG_SCSI_SATA_NV=m
+CONFIG_SCSI_PDC_ADMA=m
+CONFIG_SCSI_SATA_QSTOR=m
 CONFIG_SCSI_SATA_PROMISE=m
 CONFIG_SCSI_SATA_SX4=m
 CONFIG_SCSI_SATA_SIL=m
+CONFIG_SCSI_SATA_SIL24=m
 CONFIG_SCSI_SATA_SIS=m
+CONFIG_SCSI_SATA_ULI=m
 CONFIG_SCSI_SATA_VIA=m
 CONFIG_SCSI_SATA_VITESSE=m
+CONFIG_SCSI_SATA_INTEL_COMBINED=y
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
@@ -364,10 +377,12 @@ CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
 # CONFIG_SCSI_IPR is not set
+CONFIG_SCSI_PROMISE_STEX=m
 # CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 CONFIG_SCSI_QLOGIC_1280=m
 CONFIG_SCSI_QLA2XXX=m
+CONFIG_QLA_IOCTLMOD=m
 CONFIG_SCSI_QLA21XX=m
 CONFIG_SCSI_QLA22XX=m
 CONFIG_SCSI_QLA2300=m
@@ -408,10 +423,14 @@ CONFIG_DM_MULTIPATH_EMC=m
 #
 # Fusion MPT device support
 #
-CONFIG_FUSION=m
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
 CONFIG_FUSION_MAX_SGE=40
 CONFIG_FUSION_CTL=m
 CONFIG_FUSION_LAN=m
+CONFIG_FUSION_OLD_MODULE_COMPAT=m
 
 #
 # IEEE 1394 (FireWire) support
@@ -830,9 +849,12 @@ CONFIG_NS83820=m
 # CONFIG_YELLOWFIN is not set
 CONFIG_R8169=m
 CONFIG_R8169_NAPI=y
+CONFIG_SKGE=m
+CONFIG_SKY2=m
 CONFIG_SK98LIN=m
 CONFIG_VIA_VELOCITY=m
 CONFIG_TIGON3=m
+CONFIG_BNX2=m
 
 #
 # Ethernet (10000 Mbit)
@@ -884,6 +906,8 @@ CONFIG_PCMCIA_NETWAVE=m
 # Wireless 802.11b ISA/PCI cards support
 #
 # CONFIG_IEEE80211 is not set
+# CONFIG_IPW2100 is not set
+# CONFIG_IPW2200 is not set
 CONFIG_HERMES=m
 CONFIG_PLX_HERMES=m
 CONFIG_TMD_HERMES=m
@@ -1070,6 +1094,12 @@ CONFIG_ISDN_CAPI_CAPIDRV=m
 # Active AVM cards
 #
 CONFIG_CAPI_AVM=y
+CONFIG_ISDN_DRV_AVMB1_B1PCI=m
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
+CONFIG_ISDN_DRV_AVMB1_T1PCI=m
+CONFIG_ISDN_DRV_AVMB1_C4=m
 
 #
 # Active Eicon DIVA Server cards
@@ -1154,6 +1184,8 @@ CONFIG_SERIAL_NONSTANDARD=y
 CONFIG_N_HDLC=m
 CONFIG_STALDRV=y
 CONFIG_SGI_SNSC=y
+CONFIG_SGI_TIOCX=y
+# CONFIG_SGI_MBCS is not set
 
 #
 # Serial drivers
@@ -1175,6 +1207,7 @@ CONFIG_SERIAL_8250_RSA=y
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_SGI_L1_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_CRASH is not set
@@ -1242,7 +1275,8 @@ CONFIG_DRM_MGA=m
 CONFIG_RAW_DRIVER=y
 # CONFIG_HPET is not set
 CONFIG_MAX_RAW_DEVS=8192
-# CONFIG_MMTIMER is not set
+CONFIG_HANGCHECK_TIMER=m
+CONFIG_MMTIMER=m
 
 #
 # I2C support
@@ -1321,6 +1355,15 @@ CONFIG_SENSORS_RTC8564=m
 # CONFIG_I2C_DEBUG_CHIP is not set
 
 #
+# Hardware Monitoring support
+#
+CONFIG_HWMON=m
+CONFIG_HWMON_VID=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_LM87=m
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
@@ -1698,6 +1741,31 @@ CONFIG_USB_SPEEDTOUCH=m
 # CONFIG_USB_GADGET is not set
 
 #
+# InfiniBand support
+#
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_ADDR_TRANS=y
+# CONFIG_IPATH_CORE is not set
+CONFIG_INFINIBAND_MTHCA=m
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
+CONFIG_INFINIBAND_IPOIB=m
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+# CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set
+CONFIG_INFINIBAND_SDP=m
+# CONFIG_INFINIBAND_SDP_DEBUG is not set
+CONFIG_INFINIBAND_SRP=m
+# CONFIG_INFINIBAND_ISER is not set
+CONFIG_INFINIBAND_RDS=m
+# CONFIG_INFINIBAND_RDS_DEBUG is not set
+
+#
+# EDAC - error detection and reporting (RAS)
+#
+# CONFIG_EDAC is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1783,15 +1851,20 @@ CONFIG_VXFS_FS=m
 #
 CONFIG_NFS_FS=m
 CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
 CONFIG_NFS_V4=y
 CONFIG_NFS_DIRECTIO=y
 CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
 CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
 CONFIG_NFSD_V4=y
 CONFIG_NFSD_TCP=y
 CONFIG_LOCKD=m
 CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=m
 CONFIG_SUNRPC_GSS=m
 CONFIG_RPCSEC_GSS_KRB5=m
index 606bdbb..27ac5c1 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.9-prep.qp2.2.5.11.3qsnet
-# Thu Oct 27 17:04:10 2005
+# Mon Jul 31 19:44:37 2006
 #
 
 #
@@ -84,6 +84,7 @@ CONFIG_FORCE_MAX_ZONEORDER=18
 CONFIG_SMP=y
 CONFIG_NR_CPUS=64
 # CONFIG_HOTPLUG_CPU is not set
+CONFIG_SCHED_SMT=y
 # CONFIG_PREEMPT is not set
 CONFIG_HAVE_DEC_LOCK=y
 # CONFIG_IA32_SUPPORT is not set
@@ -98,6 +99,7 @@ CONFIG_PTRACK=y
 #
 CONFIG_EFI_VARS=y
 CONFIG_EFI_PCDP=y
+CONFIG_DELL_RBU=m
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=y
 
@@ -208,6 +210,8 @@ CONFIG_BLK_DEV_SX8=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=16384
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_CCISS_DUMP=y
+CONFIG_CCISS_DUMP_GLUE=m
 CONFIG_DISKDUMP=m
 
 #
@@ -228,6 +232,7 @@ CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 CONFIG_BLK_DEV_IDEFLOPPY=y
 CONFIG_BLK_DEV_IDESCSI=m
+CONFIG_BLK_DEV_IDEDUMP=m
 # CONFIG_IDE_TASK_IOCTL is not set
 # CONFIG_IDE_TASKFILE_IO is not set
 
@@ -321,6 +326,7 @@ CONFIG_AIC7XXX_RESET_DELAY_MS=15000
 # CONFIG_AIC7XXX_DEBUG_ENABLE is not set
 CONFIG_AIC7XXX_DEBUG_MASK=0
 # CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+CONFIG_SCSI_ADP94XX=m
 CONFIG_SCSI_AIC7XXX_OLD=m
 CONFIG_SCSI_AIC79XX=m
 CONFIG_AIC79XX_CMDS_PER_DEVICE=4
@@ -332,17 +338,24 @@ CONFIG_AIC79XX_DEBUG_MASK=0
 CONFIG_MEGARAID_NEWGEN=y
 CONFIG_MEGARAID_MM=m
 CONFIG_MEGARAID_MAILBOX=m
+CONFIG_MEGARAID_SAS=m
 CONFIG_SCSI_SATA=y
 CONFIG_SCSI_SATA_AHCI=m
 CONFIG_SCSI_SATA_SVW=m
 CONFIG_SCSI_ATA_PIIX=m
+CONFIG_SCSI_SATA_MV=m
 CONFIG_SCSI_SATA_NV=m
+CONFIG_SCSI_PDC_ADMA=m
+CONFIG_SCSI_SATA_QSTOR=m
 CONFIG_SCSI_SATA_PROMISE=m
 CONFIG_SCSI_SATA_SX4=m
 CONFIG_SCSI_SATA_SIL=m
+CONFIG_SCSI_SATA_SIL24=m
 CONFIG_SCSI_SATA_SIS=m
+CONFIG_SCSI_SATA_ULI=m
 CONFIG_SCSI_SATA_VIA=m
 CONFIG_SCSI_SATA_VITESSE=m
+CONFIG_SCSI_SATA_INTEL_COMBINED=y
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
@@ -364,10 +377,12 @@ CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
 # CONFIG_SCSI_IPR is not set
+CONFIG_SCSI_PROMISE_STEX=m
 # CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 CONFIG_SCSI_QLOGIC_1280=m
 CONFIG_SCSI_QLA2XXX=m
+CONFIG_QLA_IOCTLMOD=m
 CONFIG_SCSI_QLA21XX=m
 CONFIG_SCSI_QLA22XX=m
 CONFIG_SCSI_QLA2300=m
@@ -408,10 +423,14 @@ CONFIG_DM_MULTIPATH_EMC=m
 #
 # Fusion MPT device support
 #
-CONFIG_FUSION=m
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
 CONFIG_FUSION_MAX_SGE=40
 CONFIG_FUSION_CTL=m
 CONFIG_FUSION_LAN=m
+CONFIG_FUSION_OLD_MODULE_COMPAT=m
 
 #
 # IEEE 1394 (FireWire) support
@@ -830,9 +849,12 @@ CONFIG_NS83820=m
 # CONFIG_YELLOWFIN is not set
 CONFIG_R8169=m
 CONFIG_R8169_NAPI=y
+CONFIG_SKGE=m
+CONFIG_SKY2=m
 CONFIG_SK98LIN=m
 CONFIG_VIA_VELOCITY=m
 CONFIG_TIGON3=m
+CONFIG_BNX2=m
 
 #
 # Ethernet (10000 Mbit)
@@ -884,6 +906,8 @@ CONFIG_PCMCIA_NETWAVE=m
 # Wireless 802.11b ISA/PCI cards support
 #
 # CONFIG_IEEE80211 is not set
+# CONFIG_IPW2100 is not set
+# CONFIG_IPW2200 is not set
 CONFIG_HERMES=m
 CONFIG_PLX_HERMES=m
 CONFIG_TMD_HERMES=m
@@ -1070,6 +1094,12 @@ CONFIG_ISDN_CAPI_CAPIDRV=m
 # Active AVM cards
 #
 CONFIG_CAPI_AVM=y
+CONFIG_ISDN_DRV_AVMB1_B1PCI=m
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
+CONFIG_ISDN_DRV_AVMB1_T1PCI=m
+CONFIG_ISDN_DRV_AVMB1_C4=m
 
 #
 # Active Eicon DIVA Server cards
@@ -1154,6 +1184,8 @@ CONFIG_SERIAL_NONSTANDARD=y
 CONFIG_N_HDLC=m
 CONFIG_STALDRV=y
 CONFIG_SGI_SNSC=y
+CONFIG_SGI_TIOCX=y
+# CONFIG_SGI_MBCS is not set
 
 #
 # Serial drivers
@@ -1175,6 +1207,7 @@ CONFIG_SERIAL_8250_RSA=y
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_SGI_L1_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_CRASH is not set
@@ -1242,7 +1275,8 @@ CONFIG_DRM_MGA=m
 CONFIG_RAW_DRIVER=y
 # CONFIG_HPET is not set
 CONFIG_MAX_RAW_DEVS=8192
-# CONFIG_MMTIMER is not set
+CONFIG_HANGCHECK_TIMER=m
+CONFIG_MMTIMER=m
 
 #
 # I2C support
@@ -1321,6 +1355,15 @@ CONFIG_SENSORS_RTC8564=m
 # CONFIG_I2C_DEBUG_CHIP is not set
 
 #
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+CONFIG_HWMON_VID=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_LM87=m
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
@@ -1698,6 +1741,31 @@ CONFIG_USB_SPEEDTOUCH=m
 # CONFIG_USB_GADGET is not set
 
 #
+# InfiniBand support
+#
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_ADDR_TRANS=y
+# CONFIG_IPATH_CORE is not set
+CONFIG_INFINIBAND_MTHCA=m
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
+CONFIG_INFINIBAND_IPOIB=m
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+# CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set
+CONFIG_INFINIBAND_SDP=m
+# CONFIG_INFINIBAND_SDP_DEBUG is not set
+CONFIG_INFINIBAND_SRP=m
+# CONFIG_INFINIBAND_ISER is not set
+CONFIG_INFINIBAND_RDS=m
+# CONFIG_INFINIBAND_RDS_DEBUG is not set
+
+#
+# EDAC - error detection and reporting (RAS)
+#
+# CONFIG_EDAC is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1783,15 +1851,20 @@ CONFIG_VXFS_FS=m
 #
 CONFIG_NFS_FS=m
 CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
 CONFIG_NFS_V4=y
 CONFIG_NFS_DIRECTIO=y
 CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
 CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
 CONFIG_NFSD_V4=y
 CONFIG_NFSD_TCP=y
 CONFIG_LOCKD=m
 CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=m
 CONFIG_SUNRPC_GSS=m
 CONFIG_RPCSEC_GSS_KRB5=m
index bb5f7b2..4645f03 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.9-prep.qp2.2.5.11.3qsnet
-# Thu Oct 27 17:06:20 2005
+# Mon Jul 31 19:52:59 2006
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
@@ -71,6 +71,7 @@ CONFIG_STOP_MACHINE=y
 # CONFIG_MK8 is not set
 # CONFIG_MPSC is not set
 CONFIG_GENERIC_CPU=y
+# CONFIG_MEM_MIRROR is not set
 CONFIG_X86_L1_CACHE_BYTES=128
 CONFIG_X86_L1_CACHE_SHIFT=7
 CONFIG_X86_TSC=y
@@ -85,6 +86,7 @@ CONFIG_MTRR=y
 CONFIG_SMP=y
 # CONFIG_PREEMPT is not set
 CONFIG_SCHED_SMT=y
+CONFIG_SCHED_MC=y
 CONFIG_K8_NUMA=y
 CONFIG_DISCONTIGMEM=y
 CONFIG_NUMA=y
@@ -93,6 +95,7 @@ CONFIG_NR_CPUS=8
 CONFIG_GART_IOMMU=y
 CONFIG_SWIOTLB=y
 CONFIG_X86_MCE=y
+CONFIG_X86_MCE_AMD=y
 CONFIG_IOPROC=y
 CONFIG_PTRACK=y
 
@@ -335,6 +338,8 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=16384
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_LBD=y
+CONFIG_CCISS_DUMP=y
+CONFIG_CCISS_DUMP_GLUE=m
 CONFIG_DISKDUMP=m
 
 #
@@ -356,6 +361,7 @@ CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 CONFIG_BLK_DEV_IDEFLOPPY=y
 CONFIG_BLK_DEV_IDESCSI=m
+CONFIG_BLK_DEV_IDEDUMP=m
 # CONFIG_IDE_TASK_IOCTL is not set
 # CONFIG_IDE_TASKFILE_IO is not set
 
@@ -438,8 +444,6 @@ CONFIG_SCSI_LOGGING=y
 CONFIG_SCSI_SPI_ATTRS=m
 CONFIG_SCSI_FC_ATTRS=m
 CONFIG_SCSI_ISCSI_ATTRS=m
-CONFIG_SAS_CLASS=m
-# CONFIG_SAS_DEBUG is not set
 
 #
 # SCSI low-level drivers
@@ -454,7 +458,7 @@ CONFIG_AIC7XXX_RESET_DELAY_MS=15000
 # CONFIG_AIC7XXX_DEBUG_ENABLE is not set
 CONFIG_AIC7XXX_DEBUG_MASK=0
 # CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
-# CONFIG_SCSI_AIC94XX is not set
+CONFIG_SCSI_ADP94XX=m
 CONFIG_SCSI_AIC7XXX_OLD=m
 CONFIG_SCSI_AIC79XX=m
 CONFIG_AIC79XX_CMDS_PER_DEVICE=4
@@ -471,13 +475,19 @@ CONFIG_SCSI_SATA=y
 CONFIG_SCSI_SATA_AHCI=m
 CONFIG_SCSI_SATA_SVW=m
 CONFIG_SCSI_ATA_PIIX=m
+CONFIG_SCSI_SATA_MV=m
 CONFIG_SCSI_SATA_NV=m
+CONFIG_SCSI_PDC_ADMA=m
+CONFIG_SCSI_SATA_QSTOR=m
 CONFIG_SCSI_SATA_PROMISE=m
 CONFIG_SCSI_SATA_SX4=m
 CONFIG_SCSI_SATA_SIL=m
+CONFIG_SCSI_SATA_SIL24=m
 CONFIG_SCSI_SATA_SIS=m
+CONFIG_SCSI_SATA_ULI=m
 CONFIG_SCSI_SATA_VIA=m
 CONFIG_SCSI_SATA_VITESSE=m
+CONFIG_SCSI_SATA_INTEL_COMBINED=y
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
@@ -499,10 +509,12 @@ CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
 # CONFIG_SCSI_IPR is not set
+CONFIG_SCSI_PROMISE_STEX=m
 # CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 CONFIG_SCSI_QLOGIC_1280=m
 CONFIG_SCSI_QLA2XXX=m
+CONFIG_QLA_IOCTLMOD=m
 CONFIG_SCSI_QLA21XX=m
 CONFIG_SCSI_QLA22XX=m
 CONFIG_SCSI_QLA2300=m
@@ -973,6 +985,7 @@ CONFIG_NS83820=m
 # CONFIG_YELLOWFIN is not set
 CONFIG_R8169=m
 CONFIG_R8169_NAPI=y
+CONFIG_SKGE=m
 CONFIG_SKY2=m
 CONFIG_SK98LIN=m
 CONFIG_VIA_VELOCITY=m
@@ -1030,13 +1043,16 @@ CONFIG_PCMCIA_NETWAVE=m
 #
 CONFIG_IEEE80211=m
 # CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT=m
-CONFIG_IEEE80211_WPA=m
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
 CONFIG_IEEE80211_CRYPT_TKIP=m
 CONFIG_IPW2100=m
-CONFIG_IPW2100_PROMISC=y
-# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2100_MONITOR=y
+# CONFIG_IPW2100_DEBUG is not set
 CONFIG_IPW2200=m
+CONFIG_IPW2200_MONITOR=y
+# CONFIG_IPW_QOS is not set
+# CONFIG_IPW2200_DEBUG is not set
 CONFIG_HERMES=m
 CONFIG_PLX_HERMES=m
 CONFIG_TMD_HERMES=m
@@ -1403,11 +1419,15 @@ CONFIG_DTLK=m
 #
 CONFIG_AGP=y
 CONFIG_AGP_AMD64=y
+CONFIG_AGP_INTEL=y
 CONFIG_AGP_INTEL_MCH=y
 CONFIG_DRM=y
 # CONFIG_DRM_TDFX is not set
 CONFIG_DRM_R128=m
 CONFIG_DRM_RADEON=m
+CONFIG_DRM_I810=m
+CONFIG_DRM_I830=m
+CONFIG_DRM_I915=m
 CONFIG_DRM_MGA=m
 # CONFIG_DRM_SIS is not set
 
@@ -1498,6 +1518,15 @@ CONFIG_SENSORS_RTC8564=m
 # CONFIG_I2C_DEBUG_CHIP is not set
 
 #
+# Hardware Monitoring support
+#
+CONFIG_HWMON=m
+CONFIG_HWMON_VID=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_LM87=m
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
@@ -1885,6 +1914,7 @@ CONFIG_USB_SPEEDTOUCH=m
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
+CONFIG_IPATH_CORE=m
 
 #
 # EDAC - error detection and reporting (RAS)
@@ -1896,6 +1926,7 @@ CONFIG_USB_SPEEDTOUCH=m
 #
 CONFIG_EDD=m
 CONFIG_DELL_RBU=m
+CONFIG_DCDBAS=m
 
 #
 # File systems
@@ -1991,15 +2022,19 @@ CONFIG_VXFS_FS=m
 #
 CONFIG_NFS_FS=m
 CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
 CONFIG_NFS_V4=y
 CONFIG_NFS_DIRECTIO=y
 CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
 CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
 CONFIG_NFSD_V4=y
 CONFIG_NFSD_TCP=y
 CONFIG_LOCKD=m
 CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=m
 CONFIG_SUNRPC_GSS=m
index a00f767..2a145a6 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.9-prep.qp2.2.5.11.3qsnet
-# Thu Oct 27 17:05:31 2005
+# Mon Jul 31 19:51:03 2006
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
@@ -71,6 +71,7 @@ CONFIG_STOP_MACHINE=y
 # CONFIG_MK8 is not set
 # CONFIG_MPSC is not set
 CONFIG_GENERIC_CPU=y
+# CONFIG_MEM_MIRROR is not set
 CONFIG_X86_L1_CACHE_BYTES=128
 CONFIG_X86_L1_CACHE_SHIFT=7
 CONFIG_X86_TSC=y
@@ -85,6 +86,7 @@ CONFIG_MTRR=y
 CONFIG_SMP=y
 # CONFIG_PREEMPT is not set
 CONFIG_SCHED_SMT=y
+CONFIG_SCHED_MC=y
 CONFIG_K8_NUMA=y
 CONFIG_DISCONTIGMEM=y
 CONFIG_NUMA=y
@@ -93,6 +95,7 @@ CONFIG_NR_CPUS=8
 CONFIG_GART_IOMMU=y
 CONFIG_SWIOTLB=y
 CONFIG_X86_MCE=y
+CONFIG_X86_MCE_AMD=y
 CONFIG_IOPROC=y
 CONFIG_PTRACK=y
 
@@ -335,6 +338,8 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=16384
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_LBD=y
+CONFIG_CCISS_DUMP=y
+CONFIG_CCISS_DUMP_GLUE=m
 CONFIG_DISKDUMP=m
 
 #
@@ -356,6 +361,7 @@ CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 CONFIG_BLK_DEV_IDEFLOPPY=y
 CONFIG_BLK_DEV_IDESCSI=m
+CONFIG_BLK_DEV_IDEDUMP=m
 # CONFIG_IDE_TASK_IOCTL is not set
 # CONFIG_IDE_TASKFILE_IO is not set
 
@@ -452,6 +458,7 @@ CONFIG_AIC7XXX_RESET_DELAY_MS=15000
 # CONFIG_AIC7XXX_DEBUG_ENABLE is not set
 CONFIG_AIC7XXX_DEBUG_MASK=0
 # CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+CONFIG_SCSI_ADP94XX=m
 CONFIG_SCSI_AIC7XXX_OLD=m
 CONFIG_SCSI_AIC79XX=m
 CONFIG_AIC79XX_CMDS_PER_DEVICE=4
@@ -463,17 +470,24 @@ CONFIG_AIC79XX_DEBUG_MASK=0
 CONFIG_MEGARAID_NEWGEN=y
 CONFIG_MEGARAID_MM=m
 CONFIG_MEGARAID_MAILBOX=m
+CONFIG_MEGARAID_SAS=m
 CONFIG_SCSI_SATA=y
 CONFIG_SCSI_SATA_AHCI=m
 CONFIG_SCSI_SATA_SVW=m
 CONFIG_SCSI_ATA_PIIX=m
+CONFIG_SCSI_SATA_MV=m
 CONFIG_SCSI_SATA_NV=m
+CONFIG_SCSI_PDC_ADMA=m
+CONFIG_SCSI_SATA_QSTOR=m
 CONFIG_SCSI_SATA_PROMISE=m
 CONFIG_SCSI_SATA_SX4=m
 CONFIG_SCSI_SATA_SIL=m
+CONFIG_SCSI_SATA_SIL24=m
 CONFIG_SCSI_SATA_SIS=m
+CONFIG_SCSI_SATA_ULI=m
 CONFIG_SCSI_SATA_VIA=m
 CONFIG_SCSI_SATA_VITESSE=m
+CONFIG_SCSI_SATA_INTEL_COMBINED=y
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
@@ -495,10 +509,12 @@ CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
 # CONFIG_SCSI_IPR is not set
+CONFIG_SCSI_PROMISE_STEX=m
 # CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 CONFIG_SCSI_QLOGIC_1280=m
 CONFIG_SCSI_QLA2XXX=m
+CONFIG_QLA_IOCTLMOD=m
 CONFIG_SCSI_QLA21XX=m
 CONFIG_SCSI_QLA22XX=m
 CONFIG_SCSI_QLA2300=m
@@ -539,10 +555,14 @@ CONFIG_DM_MULTIPATH_EMC=m
 #
 # Fusion MPT device support
 #
-CONFIG_FUSION=m
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
 CONFIG_FUSION_MAX_SGE=40
 CONFIG_FUSION_CTL=m
 CONFIG_FUSION_LAN=m
+CONFIG_FUSION_OLD_MODULE_COMPAT=m
 
 #
 # IEEE 1394 (FireWire) support
@@ -561,7 +581,7 @@ CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
 # Device Drivers
 #
 CONFIG_IEEE1394_PCILYNX=m
-CONFIG_IEEE1394_OHCI1394=y
+CONFIG_IEEE1394_OHCI1394=m
 
 #
 # Protocol Drivers
@@ -965,9 +985,12 @@ CONFIG_NS83820=m
 # CONFIG_YELLOWFIN is not set
 CONFIG_R8169=m
 CONFIG_R8169_NAPI=y
+CONFIG_SKGE=m
+CONFIG_SKY2=m
 CONFIG_SK98LIN=m
 CONFIG_VIA_VELOCITY=m
 CONFIG_TIGON3=m
+CONFIG_BNX2=m
 
 #
 # Ethernet (10000 Mbit)
@@ -1020,13 +1043,16 @@ CONFIG_PCMCIA_NETWAVE=m
 #
 CONFIG_IEEE80211=m
 # CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT=m
-CONFIG_IEEE80211_WPA=m
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
 CONFIG_IEEE80211_CRYPT_TKIP=m
 CONFIG_IPW2100=m
-CONFIG_IPW2100_PROMISC=y
-# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2100_MONITOR=y
+# CONFIG_IPW2100_DEBUG is not set
 CONFIG_IPW2200=m
+CONFIG_IPW2200_MONITOR=y
+# CONFIG_IPW_QOS is not set
+# CONFIG_IPW2200_DEBUG is not set
 CONFIG_HERMES=m
 CONFIG_PLX_HERMES=m
 CONFIG_TMD_HERMES=m
@@ -1213,6 +1239,12 @@ CONFIG_ISDN_CAPI_CAPIDRV=m
 # Active AVM cards
 #
 CONFIG_CAPI_AVM=y
+CONFIG_ISDN_DRV_AVMB1_B1PCI=m
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
+CONFIG_ISDN_DRV_AVMB1_T1PCI=m
+CONFIG_ISDN_DRV_AVMB1_C4=m
 
 #
 # Active Eicon DIVA Server cards
@@ -1318,6 +1350,7 @@ CONFIG_SERIAL_8250_RSA=y
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_CRASH=m
@@ -1386,11 +1419,15 @@ CONFIG_DTLK=m
 #
 CONFIG_AGP=y
 CONFIG_AGP_AMD64=y
+CONFIG_AGP_INTEL=y
 CONFIG_AGP_INTEL_MCH=y
 CONFIG_DRM=y
 # CONFIG_DRM_TDFX is not set
 CONFIG_DRM_R128=m
 CONFIG_DRM_RADEON=m
+CONFIG_DRM_I810=m
+CONFIG_DRM_I830=m
+CONFIG_DRM_I915=m
 CONFIG_DRM_MGA=m
 # CONFIG_DRM_SIS is not set
 
@@ -1481,6 +1518,15 @@ CONFIG_SENSORS_RTC8564=m
 # CONFIG_I2C_DEBUG_CHIP is not set
 
 #
+# Hardware Monitoring support
+#
+CONFIG_HWMON=m
+CONFIG_HWMON_VID=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_LM87=m
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
@@ -1865,9 +1911,50 @@ CONFIG_USB_SPEEDTOUCH=m
 # CONFIG_USB_GADGET is not set
 
 #
+# InfiniBand support
+#
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_ADDR_TRANS=y
+CONFIG_IPATH_CORE=m
+CONFIG_INFINIBAND_IPATH=m
+CONFIG_INFINIBAND_MTHCA=m
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
+CONFIG_INFINIBAND_IPOIB=m
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+# CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set
+CONFIG_INFINIBAND_SDP=m
+# CONFIG_INFINIBAND_SDP_DEBUG is not set
+CONFIG_INFINIBAND_SRP=m
+# CONFIG_INFINIBAND_ISER is not set
+CONFIG_INFINIBAND_RDS=m
+# CONFIG_INFINIBAND_RDS_DEBUG is not set
+
+#
+# EDAC - error detection and reporting (RAS)
+#
+CONFIG_EDAC=m
+
+#
+# Reporting subsystems
+#
+# CONFIG_EDAC_DEBUG is not set
+CONFIG_EDAC_MM_EDAC=m
+CONFIG_EDAC_AMD76X=m
+CONFIG_EDAC_E7XXX=m
+CONFIG_EDAC_E752X=m
+CONFIG_EDAC_I82875P=m
+CONFIG_EDAC_I82860=m
+CONFIG_EDAC_R82600=m
+CONFIG_EDAC_POLL=y
+
+#
 # Firmware Drivers
 #
 CONFIG_EDD=m
+CONFIG_DELL_RBU=m
+CONFIG_DCDBAS=m
 
 #
 # File systems
@@ -1963,15 +2050,20 @@ CONFIG_VXFS_FS=m
 #
 CONFIG_NFS_FS=m
 CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
 CONFIG_NFS_V4=y
 CONFIG_NFS_DIRECTIO=y
 CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
 CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
 CONFIG_NFSD_V4=y
 CONFIG_NFSD_TCP=y
 CONFIG_LOCKD=m
 CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=m
 CONFIG_SUNRPC_GSS=m
 CONFIG_RPCSEC_GSS_KRB5=m
index 7c370d9..dae8a47 100644 (file)
@@ -1,8 +1,7 @@
-Index: linux-2.4.21/drivers/i2c/i2c-ali1535.c
-===================================================================
---- linux-2.4.21.orig/drivers/i2c/i2c-ali1535.c        2004-09-11 10:16:33.000000000 -0400
-+++ linux-2.4.21/drivers/i2c/i2c-ali1535.c     2004-11-03 17:40:31.000000000 -0500
-@@ -672,8 +672,8 @@
+diff -X dontdiff -urp kern_oldest/drivers/i2c/i2c-ali1535.c kern_fix/drivers/i2c/i2c-ali1535.c
+--- kern_oldest/drivers/i2c/i2c-ali1535.c      2006-05-01 11:55:43.000000000 -0700
++++ kern_fix/drivers/i2c/i2c-ali1535.c 2006-05-01 15:25:34.000000000 -0700
+@@ -672,8 +672,8 @@ EXPORT_NO_SYMBOLS;
  #ifdef MODULE
  
  MODULE_AUTHOR
@@ -13,30 +12,26 @@ Index: linux-2.4.21/drivers/i2c/i2c-ali1535.c
  MODULE_DESCRIPTION("ALI1535 SMBus driver");
  
  int init_module(void)
-Index: linux-2.4.21/drivers/sensors/lm87.c
-===================================================================
---- linux-2.4.21.orig/drivers/sensors/lm87.c   2004-09-11 10:16:33.000000000 -0400
-+++ linux-2.4.21/drivers/sensors/lm87.c        2004-11-03 17:40:31.000000000 -0500
-@@ -1060,10 +1060,10 @@
- #endif
- MODULE_AUTHOR
--    ("Frodo Looijaard <frodol@dds.nl>,
--      Philip Edelbrock <phil@netroedge.com>, 
--      Mark Studebaker <mdsxyz123@yahoo.com>,
--      and Stephen Rousset <stephen.rousset@rocketlogix.com>");
-+    ("Frodo Looijaard <frodol@dds.nl>, "
-+      "Philip Edelbrock <phil@netroedge.com>, "
-+      "Mark Studebaker <mdsxyz123@yahoo.com>, "
-+      "and Stephen Rousset <stephen.rousset@rocketlogix.com>");
- MODULE_DESCRIPTION("LM87 driver");
-Index: linux-2.4.21/drivers/net/wan/sbni.c
-===================================================================
---- linux-2.4.21.orig/drivers/net/wan/sbni.c   2002-11-28 18:53:14.000000000 -0500
-+++ linux-2.4.21/drivers/net/wan/sbni.c        2004-11-03 17:40:31.000000000 -0500
-@@ -1552,13 +1552,13 @@
+diff -X dontdiff -urp kern_oldest/drivers/net/pcmcia/wvlan_cs.c kern_fix/drivers/net/pcmcia/wvlan_cs.c
+--- kern_oldest/drivers/net/pcmcia/wvlan_cs.c  2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/net/pcmcia/wvlan_cs.c     2006-05-01 15:25:34.000000000 -0700
+@@ -1084,9 +1084,9 @@ static int wvlan_hw_config (struct net_d
+                       /* This is a PrismII card. It is is *very* similar
+                        * to the Lucent, and the driver work 95%,
+                        * therefore, we attempt to support it... */
+-                      printk(KERN_NOTICE "%s: This is a PrismII card, not a Wavelan IEEE card :-(
+-You may want report firmare revision (0x%X) and what the card support.
+-I will try to make it work, but you should look for a better driver.\n", dev_info, firmware);
++                      printk(KERN_NOTICE "%s: This is a PrismII card, not a Wavelan IEEE card :-(\n"
++"You may want report firmare revision (0x%X) and what the card support.\n"
++"I will try to make it work, but you should look for a better driver.\n", dev_info, firmware);
+                       local->has_port3  = 1;
+                       local->has_ibssid = 0;
+                       local->has_mwo    = 0;
+diff -X dontdiff -urp kern_oldest/drivers/net/wan/sbni.c kern_fix/drivers/net/wan/sbni.c
+--- kern_oldest/drivers/net/wan/sbni.c 2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/net/wan/sbni.c    2006-05-01 15:25:34.000000000 -0700
+@@ -1552,13 +1552,13 @@ __setup( "sbni=", sbni_setup );
  static u32
  calc_crc32( u32  crc,  u8  *p,  u32  len )
  {
@@ -53,7 +48,7 @@ Index: linux-2.4.21/drivers/net/wan/sbni.c
                "movl   $crc32tab, %%edi\n"
                "shrl   $2, %%ecx\n"
                "jz     1f\n"
-@@ -1594,7 +1594,7 @@
+@@ -1594,7 +1594,7 @@ calc_crc32( u32  crc,  u8  *p,  u32  len
                "jnz    0b\n"
  
        "1:\n"
@@ -62,7 +57,7 @@ Index: linux-2.4.21/drivers/net/wan/sbni.c
                "andl   $3, %%ecx\n"
                "jz     2f\n"
  
-@@ -1619,9 +1619,9 @@
+@@ -1619,9 +1619,9 @@ calc_crc32( u32  crc,  u8  *p,  u32  len
                "xorb   2(%%esi), %%bl\n"
                "xorl   (%%edi,%%ebx,4), %%eax\n"
        "2:\n"
@@ -75,33 +70,21 @@ Index: linux-2.4.21/drivers/net/wan/sbni.c
        );
  
        return  _crc;
-Index: linux-2.4.21/drivers/net/pcmcia/wvlan_cs.c
-===================================================================
---- linux-2.4.21.orig/drivers/net/pcmcia/wvlan_cs.c    2004-09-11 10:16:39.000000000 -0400
-+++ linux-2.4.21/drivers/net/pcmcia/wvlan_cs.c 2004-11-03 17:40:31.000000000 -0500
-@@ -1084,9 +1084,9 @@
-                       /* This is a PrismII card. It is is *very* similar
-                        * to the Lucent, and the driver work 95%,
-                        * therefore, we attempt to support it... */
--                      printk(KERN_NOTICE "%s: This is a PrismII card, not a Wavelan IEEE card :-(
--You may want report firmare revision (0x%X) and what the card support.
--I will try to make it work, but you should look for a better driver.\n", dev_info, firmware);
-+                      printk(KERN_NOTICE "%s: This is a PrismII card, not a Wavelan IEEE card :-(\n"
-+"You may want report firmare revision (0x%X) and what the card support.\n"
-+"I will try to make it work, but you should look for a better driver.\n", dev_info, firmware);
-                       local->has_port3  = 1;
-                       local->has_ibssid = 0;
-                       local->has_mwo    = 0;
-Index: linux-2.4.21/Makefile
-===================================================================
---- linux-2.4.21.orig/Makefile 2004-09-11 10:16:39.000000000 -0400
-+++ linux-2.4.21/Makefile      2004-11-03 17:41:35.000000000 -0500
-@@ -539,7 +539,7 @@
- ifdef CONFIG_MODVERSIONS
-       $(MAKE) update-modverfile
- endif
--      scripts/mkdep -- `find $(FINDHPATH) \( -name SCCS -o -name .svn \) -prune -o -follow -name \*.h ! -name modversions.h -print` > .hdepend
-+      find $(FINDHPATH) \( -name SCCS -o -name .svn \) -prune -o -follow -name \*.h ! -name modversions.h -print | xargs scripts/mkdep --  > .hdepend
-       scripts/mkdep -- init/*.c > .depend
-       (find $(TOPDIR) \( -name .depend -o -name .hdepend \) -print | xargs $(AWK) -f scripts/include_deps) > tmp_include_depends
-       sed -ne 's/^\([^ ].*\):.*/  \1 \\/p' tmp_include_depends > tmp_include_depends_1
+diff -X dontdiff -urp kern_oldest/drivers/sensors/lm87.c kern_fix/drivers/sensors/lm87.c
+--- kern_oldest/drivers/sensors/lm87.c 2006-05-01 11:55:44.000000000 -0700
++++ kern_fix/drivers/sensors/lm87.c    2006-05-01 15:25:34.000000000 -0700
+@@ -1060,10 +1060,10 @@ MODULE_LICENSE("GPL");
+ #endif
+ MODULE_AUTHOR
+-    ("Frodo Looijaard <frodol@dds.nl>,
+-      Philip Edelbrock <phil@netroedge.com>, 
+-      Mark Studebaker <mdsxyz123@yahoo.com>,
+-      and Stephen Rousset <stephen.rousset@rocketlogix.com>");
++    ("Frodo Looijaard <frodol@dds.nl>, "
++      "Philip Edelbrock <phil@netroedge.com>, "
++      "Mark Studebaker <mdsxyz123@yahoo.com>, "
++      "and Stephen Rousset <stephen.rousset@rocketlogix.com>");
+ MODULE_DESCRIPTION("LM87 driver");
diff --git a/lustre/kernel_patches/patches/dev_read_only-2.6-fc5.patch b/lustre/kernel_patches/patches/dev_read_only-2.6-fc5.patch
new file mode 100644 (file)
index 0000000..808f0b7
--- /dev/null
@@ -0,0 +1,145 @@
+Index: linux-2.6.16.i686/fs/block_dev.c
+===================================================================
+--- linux-2.6.16.i686.orig/fs/block_dev.c      2006-03-20 13:53:29.000000000 +0800
++++ linux-2.6.16.i686/fs/block_dev.c   2006-05-30 21:15:22.000000000 +0800
+@@ -747,6 +747,7 @@
+       }
+       unlock_kernel();
+       up(&bdev->bd_sem);
++      dev_clear_rdonly(bdev);
+       bdput(bdev);
+       return ret;
+ }
+Index: linux-2.6.16.i686/block/ll_rw_blk.c
+===================================================================
+--- linux-2.6.16.i686.orig/block/ll_rw_blk.c   2006-05-30 15:47:03.000000000 +0800
++++ linux-2.6.16.i686/block/ll_rw_blk.c        2006-05-30 21:18:49.000000000 +0800
+@@ -2940,6 +2940,8 @@
+       set_bit(BIO_EOF, &bio->bi_flags);
+ }
++int dev_check_rdonly(struct block_device *bdev);
++
+ /**
+  * generic_make_request: hand a buffer to its device driver for I/O
+  * @bio:  The bio describing the location in memory and on the device.
+@@ -3020,6 +3022,12 @@
+               if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
+                       goto end_io;
++              /* this is cfs's dev_rdonly check */
++              if (bio->bi_rw == WRITE &&
++                              dev_check_rdonly(bio->bi_bdev)) {
++                      bio_endio(bio, bio->bi_size, 0);
++                      break;
++              }
+               /*
+                * If this device has partitions, remap block n
+@@ -3593,6 +3601,91 @@
+       *ioc2 = temp;
+ }
+ EXPORT_SYMBOL(swap_io_context);
++ /*
++ * Debug code for turning block devices "read-only" (will discard writes
++ * silently).  This is for filesystem crash/recovery testing.
++ */
++struct deventry {
++      dev_t dev;
++      struct deventry *next;
++};
++
++static struct deventry *devlist = NULL;
++static spinlock_t devlock = SPIN_LOCK_UNLOCKED; 
++
++int dev_check_rdonly(struct block_device *bdev) 
++{
++      struct deventry *cur;
++      if (!bdev) return 0;
++      spin_lock(&devlock);
++      cur = devlist;
++      while(cur) {
++              if (bdev->bd_dev == cur->dev) {
++                      spin_unlock(&devlock);
++                      return 1;
++      }
++              cur = cur->next;
++      }
++      spin_unlock(&devlock);
++      return 0;
++}
++
++void dev_set_rdonly(struct block_device *bdev)
++{
++      struct deventry *newdev, *cur;
++
++      if (!bdev) 
++              return;
++      newdev = kmalloc(sizeof(struct deventry), GFP_KERNEL);
++      if (!newdev) 
++              return;
++      
++      spin_lock(&devlock);
++      cur = devlist;
++      while(cur) {
++              if (bdev->bd_dev == cur->dev) {
++                      spin_unlock(&devlock);
++                      kfree(newdev);
++                      return;
++              }
++              cur = cur->next;
++      }
++      newdev->dev = bdev->bd_dev;
++      newdev->next = devlist;
++      devlist = newdev;
++      spin_unlock(&devlock);
++      printk(KERN_WARNING "Turning device %s (%#x) read-only\n",
++             bdev->bd_disk ? bdev->bd_disk->disk_name : "", bdev->bd_dev);
++}
++
++void dev_clear_rdonly(struct block_device *bdev) 
++{
++      struct deventry *cur, *last = NULL;
++      if (!bdev) return;
++      spin_lock(&devlock);
++      cur = devlist;
++      while(cur) {
++              if (bdev->bd_dev == cur->dev) {
++                      if (last) 
++                              last->next = cur->next;
++                      else
++                              devlist = cur->next;
++                      spin_unlock(&devlock);
++                      kfree(cur);
++                      printk(KERN_WARNING "Removing read-only on %s (%#x)\n",
++                             bdev->bd_disk ? bdev->bd_disk->disk_name :
++                                             "unknown block", bdev->bd_dev);
++                      return;
++              }
++              last = cur;
++              cur = cur->next;
++      }
++      spin_unlock(&devlock);
++}
++
++EXPORT_SYMBOL(dev_set_rdonly);
++EXPORT_SYMBOL(dev_clear_rdonly);
++EXPORT_SYMBOL(dev_check_rdonly);
+ /*
+  * sysfs parts below
+Index: linux-2.6.16.i686/include/linux/fs.h
+===================================================================
+--- linux-2.6.16.i686.orig/include/linux/fs.h  2006-05-30 21:12:27.000000000 +0800
++++ linux-2.6.16.i686/include/linux/fs.h       2006-05-30 21:15:22.000000000 +0800
+@@ -1558,6 +1558,10 @@
+ struct bio;
+ extern void submit_bio(int, struct bio *);
+ extern int bdev_read_only(struct block_device *);
++#define HAVE_CLEAR_RDONLY_ON_PUT
++void dev_set_rdonly(struct block_device *bdev);
++int dev_check_rdonly(struct block_device *bdev);
++void dev_clear_rdonly(struct block_device *bdev);
+ extern int set_blocksize(struct block_device *, int);
+ extern int sb_set_blocksize(struct super_block *, int);
+ extern int sb_min_blocksize(struct super_block *, int);
diff --git a/lustre/kernel_patches/patches/dev_read_only-2.6.18-vanilla.patch b/lustre/kernel_patches/patches/dev_read_only-2.6.18-vanilla.patch
new file mode 100644 (file)
index 0000000..253efb8
--- /dev/null
@@ -0,0 +1,145 @@
+Index: linux-2.6/fs/block_dev.c
+===================================================================
+--- linux-2.6.orig/fs/block_dev.c      2006-07-06 23:41:48.000000000 +0800
++++ linux-2.6/fs/block_dev.c   2006-07-15 16:20:25.000000000 +0800
+@@ -1118,6 +1118,7 @@ static int __blkdev_put(struct block_dev
+       }
+       unlock_kernel();
+       mutex_unlock(&bdev->bd_mutex);
++      dev_clear_rdonly(bdev);
+       bdput(bdev);
+       return ret;
+ }
+Index: linux-2.6/block/ll_rw_blk.c
+===================================================================
+--- linux-2.6.orig/block/ll_rw_blk.c   2006-07-10 22:30:08.000000000 +0800
++++ linux-2.6/block/ll_rw_blk.c        2006-07-15 16:15:14.000000000 +0800
+@@ -2993,6 +2993,8 @@ static void handle_bad_sector(struct bio
+       set_bit(BIO_EOF, &bio->bi_flags);
+ }
++int dev_check_rdonly(struct block_device *bdev);
++
+ /**
+  * generic_make_request: hand a buffer to its device driver for I/O
+  * @bio:  The bio describing the location in memory and on the device.
+@@ -3076,6 +3078,12 @@ end_io:
+               if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
+                       goto end_io;
++              /* this is cfs's dev_rdonly check */
++              if (bio->bi_rw == WRITE &&
++                              dev_check_rdonly(bio->bi_bdev)) {
++                      bio_endio(bio, bio->bi_size, 0);
++                      break;
++              }
+               /*
+                * If this device has partitions, remap block n
+@@ -3673,6 +3681,91 @@ void swap_io_context(struct io_context *
+       *ioc2 = temp;
+ }
+ EXPORT_SYMBOL(swap_io_context);
++ /*
++ * Debug code for turning block devices "read-only" (will discard writes
++ * silently).  This is for filesystem crash/recovery testing.
++ */
++struct deventry {
++      dev_t dev;
++      struct deventry *next;
++};
++
++static struct deventry *devlist = NULL;
++static spinlock_t devlock = SPIN_LOCK_UNLOCKED; 
++
++int dev_check_rdonly(struct block_device *bdev) 
++{
++      struct deventry *cur;
++      if (!bdev) return 0;
++      spin_lock(&devlock);
++      cur = devlist;
++      while(cur) {
++              if (bdev->bd_dev == cur->dev) {
++                      spin_unlock(&devlock);
++                      return 1;
++      }
++              cur = cur->next;
++      }
++      spin_unlock(&devlock);
++      return 0;
++}
++
++void dev_set_rdonly(struct block_device *bdev)
++{
++      struct deventry *newdev, *cur;
++
++      if (!bdev) 
++              return;
++      newdev = kmalloc(sizeof(struct deventry), GFP_KERNEL);
++      if (!newdev) 
++              return;
++      
++      spin_lock(&devlock);
++      cur = devlist;
++      while(cur) {
++              if (bdev->bd_dev == cur->dev) {
++                      spin_unlock(&devlock);
++                      kfree(newdev);
++                      return;
++              }
++              cur = cur->next;
++      }
++      newdev->dev = bdev->bd_dev;
++      newdev->next = devlist;
++      devlist = newdev;
++      spin_unlock(&devlock);
++      printk(KERN_WARNING "Turning device %s (%#x) read-only\n",
++             bdev->bd_disk ? bdev->bd_disk->disk_name : "", bdev->bd_dev);
++}
++
++void dev_clear_rdonly(struct block_device *bdev) 
++{
++      struct deventry *cur, *last = NULL;
++      if (!bdev) return;
++      spin_lock(&devlock);
++      cur = devlist;
++      while(cur) {
++              if (bdev->bd_dev == cur->dev) {
++                      if (last) 
++                              last->next = cur->next;
++                      else
++                              devlist = cur->next;
++                      spin_unlock(&devlock);
++                      kfree(cur);
++                      printk(KERN_WARNING "Removing read-only on %s (%#x)\n",
++                             bdev->bd_disk ? bdev->bd_disk->disk_name :
++                                             "unknown block", bdev->bd_dev);
++                      return;
++              }
++              last = cur;
++              cur = cur->next;
++      }
++      spin_unlock(&devlock);
++}
++
++EXPORT_SYMBOL(dev_set_rdonly);
++EXPORT_SYMBOL(dev_clear_rdonly);
++EXPORT_SYMBOL(dev_check_rdonly);
+ /*
+  * sysfs parts below
+Index: linux-2.6/include/linux/fs.h
+===================================================================
+--- linux-2.6.orig/include/linux/fs.h  2006-07-15 16:14:58.000000000 +0800
++++ linux-2.6/include/linux/fs.h       2006-07-15 16:15:14.000000000 +0800
+@@ -1648,6 +1648,10 @@ extern void file_kill(struct file *f);
+ struct bio;
+ extern void submit_bio(int, struct bio *);
+ extern int bdev_read_only(struct block_device *);
++#define HAVE_CLEAR_RDONLY_ON_PUT
++void dev_set_rdonly(struct block_device *bdev);
++int dev_check_rdonly(struct block_device *bdev);
++void dev_clear_rdonly(struct block_device *bdev);
+ extern int set_blocksize(struct block_device *, int);
+ extern int sb_set_blocksize(struct super_block *, int);
+ extern int sb_min_blocksize(struct super_block *, int);
diff --git a/lustre/kernel_patches/patches/export-2.6-fc5.patch b/lustre/kernel_patches/patches/export-2.6-fc5.patch
new file mode 100644 (file)
index 0000000..3eb7817
--- /dev/null
@@ -0,0 +1,24 @@
+Index: linux-2.6.16.i686/fs/open.c
+===================================================================
+--- linux-2.6.16.i686.orig/fs/open.c   2006-05-30 22:10:15.000000000 +0800
++++ linux-2.6.16.i686/fs/open.c        2006-05-30 22:17:45.000000000 +0800
+@@ -811,7 +811,6 @@
+       return error;
+ }
+-
+ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group)
+ {
+       struct file * file;
+Index: linux-2.6.16.i686/fs/jbd/journal.c
+===================================================================
+--- linux-2.6.16.i686.orig/fs/jbd/journal.c    2006-05-30 22:10:16.000000000 +0800
++++ linux-2.6.16.i686/fs/jbd/journal.c 2006-05-30 22:17:26.000000000 +0800
+@@ -71,6 +71,7 @@
+ EXPORT_SYMBOL(journal_errno);
+ EXPORT_SYMBOL(journal_ack_err);
+ EXPORT_SYMBOL(journal_clear_err);
++EXPORT_SYMBOL(log_start_commit);
+ EXPORT_SYMBOL(log_wait_commit);
+ EXPORT_SYMBOL(journal_start_commit);
+ EXPORT_SYMBOL(journal_force_commit_nested);
diff --git a/lustre/kernel_patches/patches/export-2.6.18-vanilla.patch b/lustre/kernel_patches/patches/export-2.6.18-vanilla.patch
new file mode 100644 (file)
index 0000000..a6813e6
--- /dev/null
@@ -0,0 +1,24 @@
+Index: linux-2.6/fs/open.c
+===================================================================
+--- linux-2.6.orig/fs/open.c   2006-07-15 16:10:37.000000000 +0800
++++ linux-2.6/fs/open.c        2006-07-15 16:22:04.000000000 +0800
+@@ -808,7 +808,6 @@ asmlinkage long sys_lchown(const char __
+       return error;
+ }
+-
+ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group)
+ {
+       struct file * file;
+Index: linux-2.6/fs/jbd/journal.c
+===================================================================
+--- linux-2.6.orig/fs/jbd/journal.c    2006-07-15 16:13:50.000000000 +0800
++++ linux-2.6/fs/jbd/journal.c 2006-07-15 16:22:04.000000000 +0800
+@@ -74,6 +74,7 @@ EXPORT_SYMBOL(journal_abort);
+ EXPORT_SYMBOL(journal_errno);
+ EXPORT_SYMBOL(journal_ack_err);
+ EXPORT_SYMBOL(journal_clear_err);
++EXPORT_SYMBOL(log_start_commit);
+ EXPORT_SYMBOL(log_wait_commit);
+ EXPORT_SYMBOL(journal_start_commit);
+ EXPORT_SYMBOL(journal_force_commit_nested);
diff --git a/lustre/kernel_patches/patches/export-show_task-2.6-fc5.patch b/lustre/kernel_patches/patches/export-show_task-2.6-fc5.patch
new file mode 100644 (file)
index 0000000..855c359
--- /dev/null
@@ -0,0 +1,25 @@
+Index: linux-2.6.16.i686/kernel/sched.c
+===================================================================
+--- linux-2.6.16.i686.orig/kernel/sched.c      2006-05-30 15:47:15.000000000 +0800
++++ linux-2.6.16.i686/kernel/sched.c   2006-05-30 21:21:07.000000000 +0800
+@@ -4240,7 +4240,7 @@
+       return list_entry(p->sibling.next,struct task_struct,sibling);
+ }
+-static void show_task(task_t *p)
++void show_task(task_t *p)
+ {
+       task_t *relative;
+       unsigned state;
+@@ -4290,9 +4290,10 @@
+       else
+               printk(" (NOTLB)\n");
+-      if (state != TASK_RUNNING)
++      if (state != TASK_RUNNING || p == current)
+               show_stack(p, NULL);
+ }
++EXPORT_SYMBOL(show_task);
+ void show_state(void)
+ {
diff --git a/lustre/kernel_patches/patches/export-show_task-2.6.18-vanilla.patch b/lustre/kernel_patches/patches/export-show_task-2.6.18-vanilla.patch
new file mode 100644 (file)
index 0000000..834c886
--- /dev/null
@@ -0,0 +1,25 @@
+Index: linux-2.6/kernel/sched.c
+===================================================================
+--- linux-2.6.orig/kernel/sched.c      2006-07-15 11:51:46.000000000 +0800
++++ linux-2.6/kernel/sched.c   2006-07-15 16:24:35.000000000 +0800
+@@ -4652,7 +4652,7 @@ static inline struct task_struct *younge
+ static const char stat_nam[] = "RSDTtZX";
+-static void show_task(struct task_struct *p)
++void show_task(struct task_struct *p)
+ {
+       struct task_struct *relative;
+       unsigned long free = 0;
+@@ -4698,9 +4698,10 @@ static void show_task(struct task_struct
+       else
+               printk(" (NOTLB)\n");
+-      if (state != TASK_RUNNING)
++      if (state != TASK_RUNNING || p == current)
+               show_stack(p, NULL);
+ }
++EXPORT_SYMBOL(show_task);
+ void show_state(void)
+ {
diff --git a/lustre/kernel_patches/patches/export-truncate-2.6.18-vanilla.patch b/lustre/kernel_patches/patches/export-truncate-2.6.18-vanilla.patch
new file mode 100644 (file)
index 0000000..f956ef4
--- /dev/null
@@ -0,0 +1,39 @@
+ include/linux/mm.h |    2 ++
+ mm/truncate.c      |    4 ++--
+ 2 files changed, 4 insertions(+), 2 deletions(-)
+
+Index: linux-2.6/include/linux/mm.h
+===================================================================
+--- linux-2.6.orig/include/linux/mm.h  2006-07-06 23:41:48.000000000 +0800
++++ linux-2.6/include/linux/mm.h       2006-07-15 12:55:07.000000000 +0800
+@@ -529,6 +529,8 @@ static __always_inline void *lowmem_page
+ {
+       return __va(page_to_pfn(page) << PAGE_SHIFT);
+ }
++/* truncate.c */
++extern void truncate_complete_page(struct address_space *mapping,struct page *);
+ #if defined(CONFIG_HIGHMEM) && !defined(WANT_PAGE_VIRTUAL)
+ #define HASHED_PAGE_VIRTUAL
+Index: linux-2.6/mm/truncate.c
+===================================================================
+--- linux-2.6.orig/mm/truncate.c       2006-06-24 14:22:39.000000000 +0800
++++ linux-2.6/mm/truncate.c    2006-07-15 12:55:07.000000000 +0800
+@@ -33,7 +33,7 @@ static inline void truncate_partial_page
+  * its lock, b) when a concurrent invalidate_inode_pages got there first and
+  * c) when tmpfs swizzles a page between a tmpfs inode and swapper_space.
+  */
+-static void
++void
+ truncate_complete_page(struct address_space *mapping, struct page *page)
+ {
+       if (page->mapping != mapping)
+@@ -48,7 +48,7 @@ truncate_complete_page(struct address_sp
+       remove_from_page_cache(page);
+       page_cache_release(page);       /* pagecache ref */
+ }
+-
++EXPORT_SYMBOL_GPL(truncate_complete_page);
+ /*
+  * This is for invalidate_inode_pages().  That function can be called at
+  * any time, and is not supposed to throw away dirty pages.  But pages can
diff --git a/lustre/kernel_patches/patches/export_symbol_numa-2.6-fc5.patch b/lustre/kernel_patches/patches/export_symbol_numa-2.6-fc5.patch
new file mode 100644 (file)
index 0000000..095c1de
--- /dev/null
@@ -0,0 +1,12 @@
+Index: linux-2.6.16.i686/arch/i386/kernel/smpboot.c
+===================================================================
+--- linux-2.6.16.i686.orig/arch/i386/kernel/smpboot.c  2006-05-30 15:47:03.000000000 +0800
++++ linux-2.6.16.i686/arch/i386/kernel/smpboot.c       2006-05-30 21:22:02.000000000 +0800
+@@ -579,6 +579,7 @@
+ /* which logical CPUs are on which nodes */
+ cpumask_t node_2_cpu_mask[MAX_NUMNODES] __read_mostly =
+                               { [0 ... MAX_NUMNODES-1] = CPU_MASK_NONE };
++EXPORT_SYMBOL(node_2_cpu_mask);
+ /* which node each logical CPU is on */
+ int cpu_2_node[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = 0 };
+ EXPORT_SYMBOL(cpu_2_node);
diff --git a/lustre/kernel_patches/patches/export_symbols-2.6.18-vanilla.patch b/lustre/kernel_patches/patches/export_symbols-2.6.18-vanilla.patch
new file mode 100644 (file)
index 0000000..18a9815
--- /dev/null
@@ -0,0 +1,64 @@
+Index: linux-2.6/fs/filesystems.c
+===================================================================
+--- linux-2.6.orig/fs/filesystems.c    2006-07-15 16:08:35.000000000 +0800
++++ linux-2.6/fs/filesystems.c 2006-07-15 16:14:19.000000000 +0800
+@@ -29,7 +29,9 @@
+  */
+ static struct file_system_type *file_systems;
+-static DEFINE_RWLOCK(file_systems_lock);
++DEFINE_RWLOCK(file_systems_lock);
++
++EXPORT_SYMBOL(file_systems_lock);
+ /* WARNING: This can be used only if we _already_ own a reference */
+ void get_filesystem(struct file_system_type *fs)
+Index: linux-2.6/include/linux/fs.h
+===================================================================
+--- linux-2.6.orig/include/linux/fs.h  2006-07-15 16:10:37.000000000 +0800
++++ linux-2.6/include/linux/fs.h       2006-07-15 16:14:19.000000000 +0800
+@@ -1768,6 +1768,7 @@ static inline ssize_t blockdev_direct_IO
+ extern const struct file_operations generic_ro_fops;
++extern rwlock_t file_systems_lock;
+ #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
+ extern int vfs_readlink(struct dentry *, char __user *, int, const char *);
+Index: linux-2.6/fs/namespace.c
+===================================================================
+--- linux-2.6.orig/fs/namespace.c      2006-07-15 16:10:33.000000000 +0800
++++ linux-2.6/fs/namespace.c   2006-07-15 16:14:19.000000000 +0800
+@@ -1641,6 +1641,7 @@ void set_fs_pwd(struct fs_struct *fs, st
+               mntput(old_pwdmnt);
+       }
+ }
++EXPORT_SYMBOL(set_fs_pwd);
+ static void chroot_fs_refs(struct nameidata *old_nd, struct nameidata *new_nd)
+ {
+Index: linux-2.6/kernel/exit.c
+===================================================================
+--- linux-2.6.orig/kernel/exit.c       2006-07-15 16:08:34.000000000 +0800
++++ linux-2.6/kernel/exit.c    2006-07-15 16:14:19.000000000 +0800
+@@ -305,6 +305,8 @@ static void reparent_to_init(void)
+       switch_uid(INIT_USER);
+ }
++EXPORT_SYMBOL(reparent_to_init);
++
+ void __set_special_pids(pid_t session, pid_t pgrp)
+ {
+       struct task_struct *curr = current->group_leader;
+Index: linux-2.6/fs/dcache.c
+===================================================================
+--- linux-2.6.orig/fs/dcache.c 2006-07-15 16:14:00.000000000 +0800
++++ linux-2.6/fs/dcache.c      2006-07-15 16:14:19.000000000 +0800
+@@ -1628,6 +1628,7 @@ int is_subdir(struct dentry * new_dentry
+       return result;
+ }
++EXPORT_SYMBOL(is_subdir);
+ void d_genocide(struct dentry *root)
+ {
diff --git a/lustre/kernel_patches/patches/ext3-check-jbd-errors-2.6.5.patch b/lustre/kernel_patches/patches/ext3-check-jbd-errors-2.6.5.patch
new file mode 100644 (file)
index 0000000..dca4676
--- /dev/null
@@ -0,0 +1,101 @@
+Index: linux-2.6.5-7.201/fs/ext3/super.c
+===================================================================
+--- linux-2.6.5-7.201.orig/fs/ext3/super.c     2006-06-20 19:40:44.000000000 +0400
++++ linux-2.6.5-7.201/fs/ext3/super.c  2006-06-20 19:42:08.000000000 +0400
+@@ -39,7 +39,7 @@
+ static int ext3_load_journal(struct super_block *, struct ext3_super_block *);
+ static int ext3_create_journal(struct super_block *, struct ext3_super_block *,
+                              int);
+-static void ext3_commit_super (struct super_block * sb,
++void ext3_commit_super (struct super_block * sb,
+                              struct ext3_super_block * es,
+                              int sync);
+ static void ext3_mark_recovery_complete(struct super_block * sb,
+@@ -1781,7 +1781,7 @@ static int ext3_create_journal(struct su
+       return 0;
+ }
+-static void ext3_commit_super (struct super_block * sb,
++void ext3_commit_super (struct super_block * sb,
+                              struct ext3_super_block * es,
+                              int sync)
+ {
+Index: linux-2.6.5-7.201/fs/ext3/namei.c
+===================================================================
+--- linux-2.6.5-7.201.orig/fs/ext3/namei.c     2006-06-20 19:40:44.000000000 +0400
++++ linux-2.6.5-7.201/fs/ext3/namei.c  2006-06-20 19:42:08.000000000 +0400
+@@ -1598,7 +1598,7 @@ static int ext3_delete_entry (handle_t *
+                             struct buffer_head * bh)
+ {
+       struct ext3_dir_entry_2 * de, * pde;
+-      int i;
++      int i, err;
+       i = 0;
+       pde = NULL;
+@@ -1608,7 +1608,9 @@ static int ext3_delete_entry (handle_t *
+                       return -EIO;
+               if (de == de_del)  {
+                       BUFFER_TRACE(bh, "get_write_access");
+-                      ext3_journal_get_write_access(handle, bh);
++                      err = ext3_journal_get_write_access(handle, bh);
++                      if (err)
++                              return err;
+                       if (pde)
+                               pde->rec_len =
+                                       cpu_to_le16(le16_to_cpu(pde->rec_len) +
+Index: linux-2.6.5-7.201/fs/ext3/xattr.c
+===================================================================
+--- linux-2.6.5-7.201.orig/fs/ext3/xattr.c     2006-06-20 19:40:44.000000000 +0400
++++ linux-2.6.5-7.201/fs/ext3/xattr.c  2006-06-20 19:42:30.000000000 +0400
+@@ -107,7 +107,7 @@ ext3_xattr_register(int name_index, stru
+ {
+       int error = -EINVAL;
+-      if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) {
++      if (name_index > 0 && name_index < EXT3_XATTR_INDEX_MAX) {
+               write_lock(&ext3_handler_lock);
+               if (!ext3_xattr_handlers[name_index-1]) {
+                       ext3_xattr_handlers[name_index-1] = handler;
+Index: linux-2.6.5-7.201/fs/ext3/inode.c
+===================================================================
+--- linux-2.6.5-7.201.orig/fs/ext3/inode.c     2006-06-20 19:40:44.000000000 +0400
++++ linux-2.6.5-7.201/fs/ext3/inode.c  2006-06-20 19:42:08.000000000 +0400
+@@ -1517,9 +1517,14 @@ out_stop:
+                       if (end > inode->i_size) {
+                               ei->i_disksize = end;
+                               i_size_write(inode, end);
+-                              err = ext3_mark_inode_dirty(handle, inode);
+-                              if (!ret) 
+-                                      ret = err;
++                              /*
++                               * We're going to return a positive `ret'
++                               * here due to non-zero-length I/O, so there's
++                               * no way of reporting error returns from
++                               * ext3_mark_inode_dirty() to userspace.  So
++                               * ignore it.
++                               */
++                              ext3_mark_inode_dirty(handle, inode);
+                       }
+               }
+               err = ext3_journal_stop(handle);
+@@ -1811,8 +1816,18 @@ ext3_clear_blocks(handle_t *handle, stru
+               ext3_mark_inode_dirty(handle, inode);
+               ext3_journal_test_restart(handle, inode);
+               if (bh) {
++                      int err;
+                       BUFFER_TRACE(bh, "retaking write access");
+-                      ext3_journal_get_write_access(handle, bh);
++                      err = ext3_journal_get_write_access(handle, bh);
++                      if (err) {
++                              struct super_block *sb = inode->i_sb;
++                              struct ext3_super_block *es = EXT3_SB(sb)->s_es;
++                              printk (KERN_CRIT"EXT3-fs: can't continue truncate\n");
++                              EXT3_SB(sb)->s_mount_state |= EXT3_ERROR_FS;
++                              es->s_state |= cpu_to_le16(EXT3_ERROR_FS);
++                              ext3_commit_super(sb, es, 1);
++                              return;
++                      }
+               }
+       }
diff --git a/lustre/kernel_patches/patches/ext3-check-jbd-errors-2.6.9.patch b/lustre/kernel_patches/patches/ext3-check-jbd-errors-2.6.9.patch
new file mode 100644 (file)
index 0000000..df3d2ea
--- /dev/null
@@ -0,0 +1,101 @@
+Index: linux-2.6.9-full/fs/ext3/super.c
+===================================================================
+--- linux-2.6.9-full.orig/fs/ext3/super.c      2006-06-02 23:37:51.000000000 +0400
++++ linux-2.6.9-full/fs/ext3/super.c   2006-06-02 23:56:29.000000000 +0400
+@@ -43,7 +43,7 @@ static int ext3_load_journal(struct supe
+                            unsigned long journal_devnum);
+ static int ext3_create_journal(struct super_block *, struct ext3_super_block *,
+                              int);
+-static void ext3_commit_super (struct super_block * sb,
++void ext3_commit_super (struct super_block * sb,
+                              struct ext3_super_block * es,
+                              int sync);
+ static void ext3_mark_recovery_complete(struct super_block * sb,
+@@ -1991,7 +1991,7 @@ static int ext3_create_journal(struct su
+       return 0;
+ }
+-static void ext3_commit_super (struct super_block * sb,
++void ext3_commit_super (struct super_block * sb,
+                              struct ext3_super_block * es,
+                              int sync)
+ {
+Index: linux-2.6.9-full/fs/ext3/namei.c
+===================================================================
+--- linux-2.6.9-full.orig/fs/ext3/namei.c      2006-06-02 23:37:49.000000000 +0400
++++ linux-2.6.9-full/fs/ext3/namei.c   2006-06-02 23:43:31.000000000 +0400
+@@ -1599,7 +1599,7 @@ static int ext3_delete_entry (handle_t *
+                             struct buffer_head * bh)
+ {
+       struct ext3_dir_entry_2 * de, * pde;
+-      int i;
++      int i, err;
+       i = 0;
+       pde = NULL;
+@@ -1609,7 +1609,9 @@ static int ext3_delete_entry (handle_t *
+                       return -EIO;
+               if (de == de_del)  {
+                       BUFFER_TRACE(bh, "get_write_access");
+-                      ext3_journal_get_write_access(handle, bh);
++                      err = ext3_journal_get_write_access(handle, bh);
++                      if (err)
++                              return err;
+                       if (pde)
+                               pde->rec_len =
+                                       cpu_to_le16(le16_to_cpu(pde->rec_len) +
+Index: linux-2.6.9-full/fs/ext3/xattr.c
+===================================================================
+--- linux-2.6.9-full.orig/fs/ext3/xattr.c      2006-06-01 14:58:48.000000000 +0400
++++ linux-2.6.9-full/fs/ext3/xattr.c   2006-06-03 00:02:00.000000000 +0400
+@@ -132,7 +132,7 @@ ext3_xattr_handler(int name_index)
+ {
+       struct xattr_handler *handler = NULL;
+-      if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX)
++      if (name_index > 0 && name_index < EXT3_XATTR_INDEX_MAX)
+               handler = ext3_xattr_handler_map[name_index];
+       return handler;
+ }
+Index: linux-2.6.9-full/fs/ext3/inode.c
+===================================================================
+--- linux-2.6.9-full.orig/fs/ext3/inode.c      2006-06-02 23:37:38.000000000 +0400
++++ linux-2.6.9-full/fs/ext3/inode.c   2006-06-03 00:27:41.000000000 +0400
+@@ -1513,9 +1513,14 @@ out_stop:
+                       if (end > inode->i_size) {
+                               ei->i_disksize = end;
+                               i_size_write(inode, end);
+-                              err = ext3_mark_inode_dirty(handle, inode);
+-                              if (!ret) 
+-                                      ret = err;
++                              /*
++                               * We're going to return a positive `ret'
++                               * here due to non-zero-length I/O, so there's
++                               * no way of reporting error returns from
++                               * ext3_mark_inode_dirty() to userspace.  So
++                               * ignore it.
++                               */
++                              ext3_mark_inode_dirty(handle, inode);
+                       }
+               }
+               err = ext3_journal_stop(handle);
+@@ -1807,8 +1812,18 @@ ext3_clear_blocks(handle_t *handle, stru
+               ext3_mark_inode_dirty(handle, inode);
+               ext3_journal_test_restart(handle, inode);
+               if (bh) {
++                      int err;
+                       BUFFER_TRACE(bh, "retaking write access");
+-                      ext3_journal_get_write_access(handle, bh);
++                      err = ext3_journal_get_write_access(handle, bh);
++                      if (err) {
++                              struct super_block *sb = inode->i_sb;
++                              struct ext3_super_block *es = EXT3_SB(sb)->s_es;
++                              printk (KERN_CRIT"EXT3-fs: can't continue truncate\n");
++                              EXT3_SB(sb)->s_mount_state |= EXT3_ERROR_FS;
++                              es->s_state |= cpu_to_le16(EXT3_ERROR_FS);
++                              ext3_commit_super(sb, es, 1);
++                              return;
++                      }
+               }
+       }
index 731a826..0e93ced 100644 (file)
@@ -8,19 +8,17 @@
 
 --- linux-2.4.20/fs/ext3/ialloc.c~ext3-ea-in-inode-2.4.20      2003-10-08 23:18:08.000000000 +0400
 +++ linux-2.4.20-alexey/fs/ext3/ialloc.c       2003-10-12 16:25:21.000000000 +0400
-@@ -577,6 +577,12 @@ repeat:
-       insert_inode_hash(inode);
+@@ -577,6 +577,10 @@ repeat:
        inode->i_generation = sb->u.ext3_sb.s_next_generation++;
  
-+      if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) {
-+              inode->u.ext3_i.i_extra_isize = sizeof(__u16)   /* i_extra_isize */
-+                              + sizeof(__u16);        /* i_pad1 */
-+      } else
-+              inode->u.ext3_i.i_extra_isize = 0;
-+
        inode->u.ext3_i.i_state = EXT3_STATE_NEW;
++      inode->u.ext3_i.i_extra_isize =
++              (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) ?
++              sizeof(struct ext3_inode) - EXT3_GOOD_OLD_INODE_SIZE : 0;
++
        err = ext3_get_inode_loc_new(inode, &iloc, 1);
        if (err) goto fail;
+       BUFFER_TRACE(iloc->bh, "get_write_access");
 --- linux-2.4.20/fs/ext3/inode.c~ext3-ea-in-inode-2.4.20       2003-10-08 23:18:08.000000000 +0400
 +++ linux-2.4.20-alexey/fs/ext3/inode.c        2003-10-12 16:25:21.000000000 +0400
 @@ -2209,6 +2209,12 @@ void ext3_read_inode(struct inode * inod
index aaf543f..491a2df 100644 (file)
@@ -10,19 +10,17 @@ Index: linux-2.4.21-chaos/fs/ext3/ialloc.c
 ===================================================================
 --- linux-2.4.21-chaos.orig/fs/ext3/ialloc.c   2003-12-12 17:39:10.000000000 +0300
 +++ linux-2.4.21-chaos/fs/ext3/ialloc.c        2003-12-12 17:39:55.000000000 +0300
-@@ -580,6 +580,12 @@
-       insert_inode_hash(inode);
+@@ -580,6 +580,10 @@
        inode->i_generation = sbi->s_next_generation++;
  
-+      if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) {
-+              EXT3_I(inode)->i_extra_isize = sizeof(__u16)    /* i_extra_isize */
-+                              + sizeof(__u16);        /* i_pad1 */
-+      } else
-+              EXT3_I(inode)->i_extra_isize = 0;
-+
        ei->i_state = EXT3_STATE_NEW;
++      ei->i_extra_isize =
++              (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) ?
++              sizeof(struct ext3_inode) - EXT3_GOOD_OLD_INODE_SIZE : 0;
++
        err = ext3_get_inode_loc_new(inode, &iloc, 1);
        if (err) goto fail;
+       BUFFER_TRACE(iloc->bh, "get_write_access");
 Index: linux-2.4.21-chaos/fs/ext3/inode.c
 ===================================================================
 --- linux-2.4.21-chaos.orig/fs/ext3/inode.c    2003-12-12 17:39:11.000000000 +0300
index 5980fd9..90ff24a 100644 (file)
@@ -10,19 +10,17 @@ Index: linux-2.4.21-chaos/fs/ext3/ialloc.c
 ===================================================================
 --- linux-2.4.21-chaos.orig/fs/ext3/ialloc.c   2003-12-12 17:39:10.000000000 +0300
 +++ linux-2.4.21-chaos/fs/ext3/ialloc.c        2003-12-12 17:39:55.000000000 +0300
-@@ -580,6 +580,12 @@
-       insert_inode_hash(inode);
+@@ -580,6 +580,10 @@
        inode->i_generation = sbi->s_next_generation++;
  
-+      if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) {
-+              EXT3_I(inode)->i_extra_isize = sizeof(__u16)    /* i_extra_isize */
-+                              + sizeof(__u16);        /* i_pad1 */
-+      } else
-+              EXT3_I(inode)->i_extra_isize = 0;
-+
        inode->u.ext3_i.i_state = EXT3_STATE_NEW;
++      inode->u.ext3_i.i_extra_isize =
++              (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) ?
++              sizeof(struct ext3_inode) - EXT3_GOOD_OLD_INODE_SIZE : 0;
++
        err = ext3_get_inode_loc_new(inode, &iloc, 1);
        if (err) goto fail;
+       BUFFER_TRACE(iloc->bh, "get_write_access");
 Index: linux-2.4.21-chaos/fs/ext3/inode.c
 ===================================================================
 --- linux-2.4.21-chaos.orig/fs/ext3/inode.c    2003-12-12 17:39:11.000000000 +0300
index 5b118ae..6b22a71 100644 (file)
@@ -8,19 +8,17 @@
 
 --- linux-2.4.22-ac1/fs/ext3/ialloc.c~ext3-ea-in-inode-2.4.22-rh       2003-10-08 13:57:56.000000000 +0400
 +++ linux-2.4.22-ac1-alexey/fs/ext3/ialloc.c   2003-10-08 15:13:31.000000000 +0400
-@@ -715,6 +715,12 @@ have_bit_and_group:
-       insert_inode_hash(inode);
+@@ -715,6 +715,10 @@ have_bit_and_group:
        inode->i_generation = sb->u.ext3_sb.s_next_generation++;
  
-+      if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) {
-+              inode->u.ext3_i.i_extra_isize = sizeof(__u16)   /* i_extra_isize */
-+                              + sizeof(__u16);        /* i_pad1 */
-+      } else
-+              inode->u.ext3_i.i_extra_isize = 0;
-+
        inode->u.ext3_i.i_state = EXT3_STATE_NEW;
++      inode->u.ext3_i.i_extra_isize =
++              (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) ?
++              sizeof(struct ext3_inode) - EXT3_GOOD_OLD_INODE_SIZE : 0;
++
        err = ext3_get_inode_loc_new(inode, &iloc, 1);
        if (err) goto fail;
+       BUFFER_TRACE(iloc->bh, "get_write_access");
 --- linux-2.4.22-ac1/fs/ext3/inode.c~ext3-ea-in-inode-2.4.22-rh        2003-10-08 13:57:57.000000000 +0400
 +++ linux-2.4.22-ac1-alexey/fs/ext3/inode.c    2003-10-08 15:14:57.000000000 +0400
 @@ -2229,6 +2229,12 @@ void ext3_read_inode(struct inode * inod
index f4832af..2376ffa 100644 (file)
@@ -2,19 +2,17 @@ Index: linux-2.4.29/fs/ext3/ialloc.c
 ===================================================================
 --- linux-2.4.29.orig/fs/ext3/ialloc.c 2005-05-03 15:56:43.831530296 +0300
 +++ linux-2.4.29/fs/ext3/ialloc.c      2005-05-03 16:07:32.990843080 +0300
-@@ -576,6 +576,12 @@
-       insert_inode_hash(inode);
+@@ -576,6 +576,10 @@
        inode->i_generation = sb->u.ext3_sb.s_next_generation++;
  
-+      if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) {
-+              inode->u.ext3_i.i_extra_isize = sizeof(__u16)   /* i_extra_isize */
-+                              + sizeof(__u16);        /* i_pad1 */
-+      } else
-+              inode->u.ext3_i.i_extra_isize = 0;
-+
        inode->u.ext3_i.i_state = EXT3_STATE_NEW;
++      inode->u.ext3_i.i_extra_isize =
++              (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) ?
++              sizeof(struct ext3_inode) - EXT3_GOOD_OLD_INODE_SIZE : 0;
++
        err = ext3_get_inode_loc_new(inode, &iloc, 1);
        if (err) goto fail;
+       BUFFER_TRACE(iloc->bh, "get_write_access");
 Index: linux-2.4.29/fs/ext3/inode.c
 ===================================================================
 --- linux-2.4.29.orig/fs/ext3/inode.c  2005-05-03 15:58:30.758274960 +0300
index 3f5687b..89cc1b5 100644 (file)
@@ -2,15 +2,13 @@ Index: linux-stage/fs/ext3/ialloc.c
 ===================================================================
 --- linux-stage.orig/fs/ext3/ialloc.c  2005-10-04 16:53:24.000000000 -0600
 +++ linux-stage/fs/ext3/ialloc.c       2005-10-04 17:07:25.000000000 -0600
-@@ -629,6 +629,11 @@
+@@ -629,6 +629,9 @@
        spin_unlock(&sbi->s_next_gen_lock);
  
        ei->i_state = EXT3_STATE_NEW;
-+      if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) {
-+              ei->i_extra_isize = sizeof(__u16)       /* i_extra_isize */
-+                              + sizeof(__u16);        /* i_pad1 */
-+      } else
-+              ei->i_extra_isize = 0;
++      ei->i_extra_isize =
++              (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) ?
++              sizeof(struct ext3_inode) - EXT3_GOOD_OLD_INODE_SIZE : 0;
  
        ret = inode;
        if(DQUOT_ALLOC_INODE(inode)) {
index 19f153d..72c25a4 100644 (file)
@@ -3,15 +3,13 @@ Index: linux-2.6.0/fs/ext3/ialloc.c
 ===================================================================
 --- linux-2.6.0.orig/fs/ext3/ialloc.c  2004-01-14 18:54:11.000000000 +0300
 +++ linux-2.6.0/fs/ext3/ialloc.c       2004-01-14 18:54:12.000000000 +0300
-@@ -627,6 +627,11 @@
+@@ -627,6 +627,9 @@
        inode->i_generation = EXT3_SB(sb)->s_next_generation++;
  
        ei->i_state = EXT3_STATE_NEW;
-+      if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) {
-+              ei->i_extra_isize = sizeof(__u16)       /* i_extra_isize */
-+                              + sizeof(__u16);        /* i_pad1 */
-+      } else
-+              ei->i_extra_isize = 0;
++      ei->i_extra_isize =
++              (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) ?
++              sizeof(struct ext3_inode) - EXT3_GOOD_OLD_INODE_SIZE : 0;
  
        ret = inode;
        if(DQUOT_ALLOC_INODE(inode)) {
index 72f5dd5..e1bb92c 100644 (file)
@@ -2,7 +2,7 @@ Index: linux-2.4.21-rhel/fs/ext3/extents.c
 ===================================================================
 --- linux-2.4.21-rhel.orig/fs/ext3/extents.c   2005-03-02 22:42:20.659360368 +0300
 +++ linux-2.4.21-rhel/fs/ext3/extents.c        2005-03-04 02:34:52.000000000 +0300
-@@ -0,0 +1,2318 @@
+@@ -0,0 +1,2324 @@
 +/*
 + * Copyright(c) 2003, 2004, 2005, Cluster File Systems, Inc, info@clusterfs.com
 + * Written by Alex Tomas <alex@clusterfs.com>
@@ -181,7 +181,7 @@ Index: linux-2.4.21-rhel/fs/ext3/extents.c
 +{
 +      struct ext3_extent_header *neh = EXT_ROOT_HDR(tree);
 +      neh->eh_generation = ((EXT_FLAGS(neh) & ~EXT_FLAGS_CLR_UNKNOWN) << 24) |
-+                           (EXT_GENERATION(neh) + 1);
++                           (EXT_HDR_GEN(neh) + 1);
 +}
 +
 +static inline int ext3_ext_space_block(struct ext3_extents_tree *tree)
@@ -557,6 +557,7 @@ Index: linux-2.4.21-rhel/fs/ext3/extents.c
 +
 +      ix->ei_block = logical;
 +      ix->ei_leaf = ptr;
++      ix->ei_leaf_hi = ix->ei_unused = 0;
 +      curp->p_hdr->eh_entries++;
 +
 +      EXT_ASSERT(curp->p_hdr->eh_entries <= curp->p_hdr->eh_max);
@@ -719,6 +720,7 @@ Index: linux-2.4.21-rhel/fs/ext3/extents.c
 +              fidx = EXT_FIRST_INDEX(neh);
 +              fidx->ei_block = border;
 +              fidx->ei_leaf = oldblock;
++              fidx->ei_leaf_hi = fidx->ei_unused = 0;
 +
 +              ext_debug(tree, "int.index at %d (block %lu): %lu -> %lu\n",
 +                        i, newblock, border, oldblock);
@@ -852,6 +854,7 @@ Index: linux-2.4.21-rhel/fs/ext3/extents.c
 +      /* FIXME: it works, but actually path[0] can be index */
 +      curp->p_idx->ei_block = EXT_FIRST_EXTENT(path[0].p_hdr)->ee_block;
 +      curp->p_idx->ei_leaf = newblock;
++      curp->p_idx->ei_leaf_hi = curp->p_idx->ei_unused = 0;
 +
 +      neh = EXT_ROOT_HDR(tree);
 +      fidx = EXT_FIRST_INDEX(neh);
@@ -1400,6 +1403,7 @@ Index: linux-2.4.21-rhel/fs/ext3/extents.c
 +      if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) {
 +              ex->ee_block = cex->ec_block;
 +              ex->ee_start = cex->ec_start;
++              ex->ee_start_hi = 0;
 +              ex->ee_len = cex->ec_len;
 +              ext_debug(tree, "%lu cached by %lu:%lu:%lu\n",
 +                        (unsigned long) block,
@@ -1621,7 +1625,7 @@ Index: linux-2.4.21-rhel/fs/ext3/extents.c
 +
 +              if (num == 0) {
 +                      /* this extent is removed entirely mark slot unused */
-+                      ex->ee_start = 0;
++                      ex->ee_start = ex->ee_start_hi = 0;
 +                      eh->eh_entries--;
 +                      fu = ex;
 +              }
@@ -1643,7 +1647,7 @@ Index: linux-2.4.21-rhel/fs/ext3/extents.c
 +              while (lu < le) {
 +                      if (lu->ee_start) {
 +                              *fu = *lu;
-+                              lu->ee_start = 0;
++                              lu->ee_start = lu->ee_start_hi = 0;
 +                              fu++;
 +                      }
 +                      lu++;
@@ -1969,6 +1973,7 @@ Index: linux-2.4.21-rhel/fs/ext3/extents.c
 +              goal = ext3_ext_find_goal(inode, path, ex->ee_block);
 +              lock_kernel();
 +              ex->ee_start = ext3_new_block(handle, inode, goal, 0, 0, err);
++              ex->ee_start_hi = 0;
 +              unlock_kernel();
 +              if (ex->ee_start == 0) {
 +                      /* error occured: restore old extent */
@@ -2086,6 +2091,7 @@ Index: linux-2.4.21-rhel/fs/ext3/extents.c
 +      /* try to insert new extent into found leaf and return */
 +      newex.ee_block = iblock;
 +      newex.ee_start = newblock;
++      newex.ee_start_hi = 0;
 +      newex.ee_len = 1;
 +      err = ext3_ext_insert_extent(handle, &tree, path, &newex);
 +      if (err)
@@ -2478,12 +2484,14 @@ Index: linux-2.4.21-rhel/fs/ext3/super.c
        ext3_xattr_put_super(sb);
        journal_destroy(sbi->s_journal);
        if (!(sb->s_flags & MS_RDONLY)) {
-@@ -755,6 +756,10 @@
+@@ -755,6 +756,12 @@
                                return 0;
                        }
                }
 +              else if (!strcmp (this_char, "extents"))
 +                      set_opt (*mount_options, EXTENTS);
++              else if (!strcmp (this_char, "noextents"))
++                      clear_opt (*mount_options, EXTENTS);
 +              else if (!strcmp (this_char, "extdebug"))
 +                      set_opt (*mount_options, EXTDEBUG);
                else if (!strcmp (this_char, "grpid") ||
@@ -2561,12 +2569,13 @@ Index: linux-2.4.21-rhel/include/linux/ext3_fs.h
  #define EXT3_FEATURE_RO_COMPAT_SUPP   (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
                                         EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \
                                         EXT3_FEATURE_RO_COMPAT_BTREE_DIR)
-@@ -689,6 +697,8 @@
+@@ -689,6 +697,9 @@
  extern unsigned long ext3_count_free (struct buffer_head *, unsigned);
  
  /* inode.c */
 +extern int ext3_block_truncate_page(handle_t *, struct address_space *, loff_t,
 +                                  struct page *, unsigned);
++extern int ext3_writepage_trans_blocks(struct inode *inode);
  extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int);
  extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
  extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
@@ -2790,14 +2799,14 @@ Index: linux-2.4.21-rhel/include/linux/ext3_extents.h
 +      (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_max - 1)
 +#define EXT_MAX_INDEX(__hdr__) \
 +      (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_max - 1)
-+#define EXT_GENERATION(__hdr__) ((__hdr__)->eh_generation & 0x00ffffff)
++#define EXT_HDR_GEN(__hdr__)  ((__hdr__)->eh_generation & 0x00ffffff)
 +#define EXT_FLAGS(__hdr__)    ((__hdr__)->eh_generation >> 24)
 +#define EXT_FLAGS_CLR_UNKNOWN 0x7     /* Flags cleared on modification */
 +
 +#define EXT_BLOCK_HDR(__bh__)         ((struct ext3_extent_header *)(__bh__)->b_data)
 +#define EXT_ROOT_HDR(__tree__)        ((struct ext3_extent_header *)(__tree__)->root)
 +#define EXT_DEPTH(__tree__)   (EXT_ROOT_HDR(__tree__)->eh_depth)
-+
++#define EXT_GENERATION(__tree__) EXT_HDR_GEN(EXT_ROOT_HDR(__tree__))
 +
 +#define EXT_ASSERT(__x__) if (!(__x__)) BUG();
 +
index 940b916..34a0b9d 100644 (file)
@@ -2,7 +2,7 @@ Index: linux-2.4.21-suse2/fs/ext3/extents.c
 ===================================================================
 --- linux-2.4.21-suse2.orig/fs/ext3/extents.c  2003-01-30 13:24:37.000000000 +0300
 +++ linux-2.4.21-suse2/fs/ext3/extents.c       2004-11-03 00:34:45.404241880 +0300
-@@ -0,0 +1,2309 @@
+@@ -0,0 +1,2315 @@
 +/*
 + * Copyright(c) 2003, 2004, 2005, Cluster File Systems, Inc, info@clusterfs.com
 + * Written by Alex Tomas <alex@clusterfs.com>
@@ -181,7 +181,7 @@ Index: linux-2.4.21-suse2/fs/ext3/extents.c
 +{
 +      struct ext3_extent_header *neh = EXT_ROOT_HDR(tree);
 +      neh->eh_generation = ((EXT_FLAGS(neh) & ~EXT_FLAGS_CLR_UNKNOWN) << 24) |
-+                           (EXT_GENERATION(neh) + 1);
++                           (EXT_HDR_GEN(neh) + 1);
 +}
 +
 +static inline int ext3_ext_space_block(struct ext3_extents_tree *tree)
@@ -557,6 +557,7 @@ Index: linux-2.4.21-suse2/fs/ext3/extents.c
 +
 +      ix->ei_block = logical;
 +      ix->ei_leaf = ptr;
++      ix->ei_leaf_hi = ix->ei_unused = 0;
 +      curp->p_hdr->eh_entries++;
 +
 +      EXT_ASSERT(curp->p_hdr->eh_entries <= curp->p_hdr->eh_max);
@@ -719,6 +720,7 @@ Index: linux-2.4.21-suse2/fs/ext3/extents.c
 +              fidx = EXT_FIRST_INDEX(neh);
 +              fidx->ei_block = border;
 +              fidx->ei_leaf = oldblock;
++              fidx->ei_leaf_hi = fidx->ei_unused = 0;
 +
 +              ext_debug(tree, "int.index at %d (block %lu): %lu -> %lu\n",
 +                        i, newblock, border, oldblock);
@@ -852,6 +854,7 @@ Index: linux-2.4.21-suse2/fs/ext3/extents.c
 +      /* FIXME: it works, but actually path[0] can be index */
 +      curp->p_idx->ei_block = EXT_FIRST_EXTENT(path[0].p_hdr)->ee_block;
 +      curp->p_idx->ei_leaf = newblock;
++      curp->p_idx->ei_leaf_hi = curp->p_idx->ei_unused = 0;
 +
 +      neh = EXT_ROOT_HDR(tree);
 +      fidx = EXT_FIRST_INDEX(neh);
@@ -1400,6 +1403,7 @@ Index: linux-2.4.21-suse2/fs/ext3/extents.c
 +      if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) {
 +              ex->ee_block = cex->ec_block;
 +              ex->ee_start = cex->ec_start;
++              ex->ee_start_hi = 0;
 +              ex->ee_len = cex->ec_len;
 +              ext_debug(tree, "%lu cached by %lu:%lu:%lu\n",
 +                        (unsigned long) block,
@@ -1621,7 +1625,7 @@ Index: linux-2.4.21-suse2/fs/ext3/extents.c
 +
 +              if (num == 0) {
 +                      /* this extent is removed entirely mark slot unused */
-+                      ex->ee_start = 0;
++                      ex->ee_start = ex->ee_start_hi = 0;
 +                      eh->eh_entries--;
 +                      fu = ex;
 +              }
@@ -1643,7 +1647,7 @@ Index: linux-2.4.21-suse2/fs/ext3/extents.c
 +              while (lu < le) {
 +                      if (lu->ee_start) {
 +                              *fu = *lu;
-+                              lu->ee_start = 0;
++                              lu->ee_start = lu->ee_start_hi = 0;
 +                              fu++;
 +                      }
 +                      lu++;
@@ -1969,6 +1973,7 @@ Index: linux-2.4.21-suse2/fs/ext3/extents.c
 +              goal = ext3_ext_find_goal(inode, path, ex->ee_block);
 +              lock_kernel();
 +              ex->ee_start = ext3_new_block(handle, inode, goal, 0, 0, err);
++              ex->ee_start_hi = 0;
 +              unlock_kernel();
 +              if (ex->ee_start == 0) {
 +                      /* error occured: restore old extent */
@@ -2086,6 +2091,7 @@ Index: linux-2.4.21-suse2/fs/ext3/extents.c
 +      /* try to insert new extent into found leaf and return */
 +      newex.ee_block = iblock;
 +      newex.ee_start = newblock;
++      newex.ee_start_hi = 0;
 +      newex.ee_len = 1;
 +      err = ext3_ext_insert_extent(handle, &tree, path, &newex);
 +      if (err)
@@ -2477,12 +2483,14 @@ Index: linux-2.4.21-suse2/fs/ext3/super.c
        ext3_xattr_put_super(sb);
        journal_destroy(sbi->s_journal);
        if (!(sb->s_flags & MS_RDONLY)) {
-@@ -733,6 +734,10 @@
+@@ -733,6 +734,12 @@
                                return 0;
                        }
                }
 +              else if (!strcmp (this_char, "extents"))
 +                      set_opt (*mount_options, EXTENTS);
++              else if (!strcmp (this_char, "noextents"))
++                      clear_opt (*mount_options, EXTENTS);
 +              else if (!strcmp (this_char, "extdebug"))
 +                      set_opt (*mount_options, EXTDEBUG);
                else if (!strcmp (this_char, "grpid") ||
@@ -2560,11 +2568,12 @@ Index: linux-2.4.21-suse2/include/linux/ext3_fs.h
  #define EXT3_FEATURE_RO_COMPAT_SUPP   (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
                                         EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \
                                         EXT3_FEATURE_RO_COMPAT_BTREE_DIR)
-@@ -689,6 +697,7 @@
+@@ -689,6 +697,8 @@
  extern unsigned long ext3_count_free (struct buffer_head *, unsigned);
  
  /* inode.c */
 +extern int ext3_block_truncate_page(handle_t *, struct address_space *, loff_t);
++extern int ext3_writepage_trans_blocks(struct inode *inode);
  extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int);
  extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
  extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
@@ -2788,14 +2797,14 @@ Index: linux-2.4.21-suse2/include/linux/ext3_extents.h
 +      (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_max - 1)
 +#define EXT_MAX_INDEX(__hdr__) \
 +      (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_max - 1)
-+#define EXT_GENERATION(__hdr__) ((__hdr__)->eh_generation & 0x00ffffff)
++#define EXT_HDR_GEN(__hdr__)  ((__hdr__)->eh_generation & 0x00ffffff)
 +#define EXT_FLAGS(__hdr__)    ((__hdr__)->eh_generation >> 24)
 +#define EXT_FLAGS_CLR_UNKNOWN 0x7     /* Flags cleared on modification */
 +
 +#define EXT_BLOCK_HDR(__bh__)         ((struct ext3_extent_header *)(__bh__)->b_data)
 +#define EXT_ROOT_HDR(__tree__)        ((struct ext3_extent_header *)(__tree__)->root)
 +#define EXT_DEPTH(__tree__)   (EXT_ROOT_HDR(__tree__)->eh_depth)
-+
++#define EXT_GENERATION(__tree__) EXT_HDR_GEN(EXT_ROOT_HDR(__tree__))
 +
 +#define EXT_ASSERT(__x__) if (!(__x__)) BUG();
 +
index 571fb0f..067e6df 100644 (file)
@@ -2,7 +2,7 @@ Index: linux-2.4.24/fs/ext3/extents.c
 ===================================================================
 --- linux-2.4.24.orig/fs/ext3/extents.c        2003-01-30 13:24:37.000000000 +0300
 +++ linux-2.4.24/fs/ext3/extents.c     2004-11-03 00:36:44.894076664 +0300
-@@ -0,0 +1,2308 @@
+@@ -0,0 +1,2314 @@
 +/*
 + * Copyright(c) 2003, 2004, 2005, Cluster File Systems, Inc, info@clusterfs.com
 + * Written by Alex Tomas <alex@clusterfs.com>
@@ -181,7 +181,7 @@ Index: linux-2.4.24/fs/ext3/extents.c
 +{
 +      struct ext3_extent_header *neh = EXT_ROOT_HDR(tree);
 +      neh->eh_generation = ((EXT_FLAGS(neh) & ~EXT_FLAGS_CLR_UNKNOWN) << 24) |
-+                           (EXT_GENERATION(neh) + 1);
++                           (EXT_HDR_GEN(neh) + 1);
 +}
 +
 +static inline int ext3_ext_space_block(struct ext3_extents_tree *tree)
@@ -556,6 +556,7 @@ Index: linux-2.4.24/fs/ext3/extents.c
 +
 +      ix->ei_block = logical;
 +      ix->ei_leaf = ptr;
++      ix->ei_leaf_hi = ix->ei_unused = 0;
 +      curp->p_hdr->eh_entries++;
 +
 +      EXT_ASSERT(curp->p_hdr->eh_entries <= curp->p_hdr->eh_max);
@@ -718,6 +719,7 @@ Index: linux-2.4.24/fs/ext3/extents.c
 +              fidx = EXT_FIRST_INDEX(neh);
 +              fidx->ei_block = border;
 +              fidx->ei_leaf = oldblock;
++              fidx->ei_leaf_hi = fidx->ei_unused = 0;
 +
 +              ext_debug(tree, "int.index at %d (block %lu): %lu -> %lu\n",
 +                        i, newblock, border, oldblock);
@@ -851,6 +853,7 @@ Index: linux-2.4.24/fs/ext3/extents.c
 +      /* FIXME: it works, but actually path[0] can be index */
 +      curp->p_idx->ei_block = EXT_FIRST_EXTENT(path[0].p_hdr)->ee_block;
 +      curp->p_idx->ei_leaf = newblock;
++      curp->p_idx->ei_leaf_hi = curp->p_idx->ei_unused = 0;
 +
 +      neh = EXT_ROOT_HDR(tree);
 +      fidx = EXT_FIRST_INDEX(neh);
@@ -1399,6 +1402,7 @@ Index: linux-2.4.24/fs/ext3/extents.c
 +      if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) {
 +              ex->ee_block = cex->ec_block;
 +              ex->ee_start = cex->ec_start;
++              ex->ee_start_hi = 0;
 +              ex->ee_len = cex->ec_len;
 +              ext_debug(tree, "%lu cached by %lu:%lu:%lu\n",
 +                        (unsigned long) block,
@@ -1620,7 +1624,7 @@ Index: linux-2.4.24/fs/ext3/extents.c
 +
 +              if (num == 0) {
 +                      /* this extent is removed entirely mark slot unused */
-+                      ex->ee_start = 0;
++                      ex->ee_start = ex->ee_start_hi = 0;
 +                      eh->eh_entries--;
 +                      fu = ex;
 +              }
@@ -1642,7 +1646,7 @@ Index: linux-2.4.24/fs/ext3/extents.c
 +              while (lu < le) {
 +                      if (lu->ee_start) {
 +                              *fu = *lu;
-+                              lu->ee_start = 0;
++                              lu->ee_start = lu->ee_start_hi = 0;
 +                              fu++;
 +                      }
 +                      lu++;
@@ -1968,6 +1972,7 @@ Index: linux-2.4.24/fs/ext3/extents.c
 +              goal = ext3_ext_find_goal(inode, path, ex->ee_block);
 +              lock_kernel();
 +              ex->ee_start = ext3_new_block(handle, inode, goal, 0, 0, err);
++              ex->ee_start_hi = 0;
 +              unlock_kernel();
 +              if (ex->ee_start == 0) {
 +                      /* error occured: restore old extent */
@@ -2085,6 +2090,7 @@ Index: linux-2.4.24/fs/ext3/extents.c
 +      /* try to insert new extent into found leaf and return */
 +      newex.ee_block = iblock;
 +      newex.ee_start = newblock;
++      newex.ee_start_hi = 0;
 +      newex.ee_len = 1;
 +      err = ext3_ext_insert_extent(handle, &tree, path, &newex);
 +      if (err)
@@ -2465,12 +2471,14 @@ Index: linux-2.4.24/fs/ext3/super.c
        ext3_xattr_put_super(sb);
        journal_destroy(sbi->s_journal);
        if (!(sb->s_flags & MS_RDONLY)) {
-@@ -704,6 +705,10 @@
+@@ -704,6 +705,12 @@
                                return 0;
                        }
                }
 +              else if (!strcmp (this_char, "extents"))
 +                      set_opt (*mount_options, EXTENTS);
++              else if (!strcmp (this_char, "noextents"))
++                      clear_opt (*mount_options, EXTENTS);
 +              else if (!strcmp (this_char, "extdebug"))
 +                      set_opt (*mount_options, EXTDEBUG);
                else if (!strcmp (this_char, "grpid") ||
@@ -2548,11 +2556,12 @@ Index: linux-2.4.24/include/linux/ext3_fs.h
  #define EXT3_FEATURE_RO_COMPAT_SUPP   (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
                                         EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \
                                         EXT3_FEATURE_RO_COMPAT_BTREE_DIR)
-@@ -688,6 +696,7 @@
+@@ -688,6 +696,8 @@
  extern unsigned long ext3_count_free (struct buffer_head *, unsigned);
  
  /* inode.c */
 +extern int ext3_block_truncate_page(handle_t *, struct address_space *, loff_t);
++extern int ext3_writepage_trans_blocks(struct inode *inode);
  extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int);
  extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
  extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
@@ -2776,14 +2785,14 @@ Index: linux-2.4.24/include/linux/ext3_extents.h
 +      (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_max - 1)
 +#define EXT_MAX_INDEX(__hdr__) \
 +      (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_max - 1)
-+#define EXT_GENERATION(__hdr__) ((__hdr__)->eh_generation & 0x00ffffff)
++#define EXT_HDR_GEN(__hdr__)  ((__hdr__)->eh_generation & 0x00ffffff)
 +#define EXT_FLAGS(__hdr__)    ((__hdr__)->eh_generation >> 24)
 +#define EXT_FLAGS_CLR_UNKNOWN 0x7     /* Flags cleared on modification */
 +
 +#define EXT_BLOCK_HDR(__bh__)         ((struct ext3_extent_header *)(__bh__)->b_data)
 +#define EXT_ROOT_HDR(__tree__)        ((struct ext3_extent_header *)(__tree__)->root)
 +#define EXT_DEPTH(__tree__)   (EXT_ROOT_HDR(__tree__)->eh_depth)
-+
++#define EXT_GENERATION(__tree__) EXT_HDR_GEN(EXT_ROOT_HDR(__tree__))
 +
 +#define EXT_ASSERT(__x__) if (!(__x__)) BUG();
 +
index 125f747..f3b1fb5 100644 (file)
@@ -181,7 +181,7 @@ Index: linux-2.4.29/fs/ext3/extents.c
 +{
 +      struct ext3_extent_header *neh = EXT_ROOT_HDR(tree);
 +      neh->eh_generation = ((EXT_FLAGS(neh) & ~EXT_FLAGS_CLR_UNKNOWN) << 24) |
-+                           (EXT_GENERATION(neh) + 1);
++                           (EXT_HDR_GEN(neh) + 1);
 +}
 +
 +static inline int ext3_ext_space_block(struct ext3_extents_tree *tree)
@@ -2465,12 +2465,14 @@ Index: linux-2.4.29/fs/ext3/super.c
        ext3_xattr_put_super(sb);
        journal_destroy(sbi->s_journal);
        if (!(sb->s_flags & MS_RDONLY)) {
-@@ -702,6 +703,10 @@
+@@ -702,6 +703,12 @@
                                return 0;
                        }
                }
 +              else if (!strcmp (this_char, "extents"))
 +                      set_opt (*mount_options, EXTENTS);
++              else if (!strcmp (this_char, "noextents"))
++                      clear_opt (*mount_options, EXTENTS);
 +              else if (!strcmp (this_char, "extdebug"))
 +                      set_opt (*mount_options, EXTDEBUG);
                else if (!strcmp (this_char, "grpid") ||
@@ -2549,11 +2551,12 @@ Index: linux-2.4.29/include/linux/ext3_fs.h
  #define EXT3_FEATURE_RO_COMPAT_SUPP   (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
                                         EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \
                                         EXT3_FEATURE_RO_COMPAT_BTREE_DIR)
-@@ -702,6 +711,7 @@
+@@ -702,6 +711,8 @@
  extern unsigned long ext3_count_free (struct buffer_head *, unsigned);
  
  /* inode.c */
 +extern int ext3_block_truncate_page(handle_t *, struct address_space *, loff_t);
++extern int ext3_writepage_trans_blocks(struct inode *inode);
  extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int);
  extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
  extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
@@ -2777,14 +2780,14 @@ Index: linux-2.4.29/include/linux/ext3_extents.h
 +      (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_max - 1)
 +#define EXT_MAX_INDEX(__hdr__) \
 +      (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_max - 1)
-+#define EXT_GENERATION(__hdr__) ((__hdr__)->eh_generation & 0x00ffffff)
++#define EXT_HDR_GEN(__hdr__)  ((__hdr__)->eh_generation & 0x00ffffff)
 +#define EXT_FLAGS(__hdr__)    ((__hdr__)->eh_generation >> 24)
 +#define EXT_FLAGS_CLR_UNKNOWN 0x7     /* Flags cleared on modification */
 +
 +#define EXT_BLOCK_HDR(__bh__)         ((struct ext3_extent_header *)(__bh__)->b_data)
 +#define EXT_ROOT_HDR(__tree__)        ((struct ext3_extent_header *)(__tree__)->root)
 +#define EXT_DEPTH(__tree__)   (EXT_ROOT_HDR(__tree__)->eh_depth)
-+
++#define EXT_GENERATION(__tree__) EXT_HDR_GEN(EXT_ROOT_HDR(__tree__))
 +
 +#define EXT_ASSERT(__x__) if (!(__x__)) BUG();
 +
index b6439e6..f421f88 100644 (file)
@@ -2,7 +2,7 @@ Index: linux-2.6.12-rc6/fs/ext3/extents.c
 ===================================================================
 --- linux-2.6.12-rc6.orig/fs/ext3/extents.c    2005-06-14 16:31:25.756503133 +0200
 +++ linux-2.6.12-rc6/fs/ext3/extents.c 2005-06-14 16:31:25.836581257 +0200
-@@ -0,0 +1,2353 @@
+@@ -0,0 +1,2359 @@
 +/*
 + * Copyright(c) 2003, 2004, 2005, Cluster File Systems, Inc, info@clusterfs.com
 + * Written by Alex Tomas <alex@clusterfs.com>
@@ -178,7 +178,7 @@ Index: linux-2.6.12-rc6/fs/ext3/extents.c
 +{
 +      struct ext3_extent_header *neh = EXT_ROOT_HDR(tree);
 +      neh->eh_generation = ((EXT_FLAGS(neh) & ~EXT_FLAGS_CLR_UNKNOWN) << 24) |
-+                           (EXT_GENERATION(neh) + 1);
++                           (EXT_HDR_GEN(neh) + 1);
 +}
 +
 +static inline int ext3_ext_space_block(struct ext3_extents_tree *tree)
@@ -560,6 +560,7 @@ Index: linux-2.6.12-rc6/fs/ext3/extents.c
 +
 +      ix->ei_block = logical;
 +      ix->ei_leaf = ptr;
++      ix->ei_leaf_hi = ix->ei_unused = 0;
 +      curp->p_hdr->eh_entries++;
 +
 +      EXT_ASSERT(curp->p_hdr->eh_entries <= curp->p_hdr->eh_max);
@@ -722,6 +723,7 @@ Index: linux-2.6.12-rc6/fs/ext3/extents.c
 +              fidx = EXT_FIRST_INDEX(neh);
 +              fidx->ei_block = border;
 +              fidx->ei_leaf = oldblock;
++              fidx->ei_leaf_hi = fidx->ei_unused = 0;
 +
 +              ext_debug(tree, "int.index at %d (block %lu): %lu -> %lu\n",
 +                        i, newblock, border, oldblock);
@@ -855,6 +857,7 @@ Index: linux-2.6.12-rc6/fs/ext3/extents.c
 +      /* FIXME: it works, but actually path[0] can be index */
 +      curp->p_idx->ei_block = EXT_FIRST_EXTENT(path[0].p_hdr)->ee_block;
 +      curp->p_idx->ei_leaf = newblock;
++      curp->p_idx->ei_leaf_hi = curp->p_idx->ei_unused = 0;
 +
 +      neh = EXT_ROOT_HDR(tree);
 +      fidx = EXT_FIRST_INDEX(neh);
@@ -1403,6 +1406,7 @@ Index: linux-2.6.12-rc6/fs/ext3/extents.c
 +      if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) {
 +              ex->ee_block = cex->ec_block;
 +              ex->ee_start = cex->ec_start;
++              ex->ee_start_hi = 0;
 +              ex->ee_len = cex->ec_len;
 +              ext_debug(tree, "%lu cached by %lu:%lu:%lu\n",
 +                        (unsigned long) block,
@@ -1624,7 +1628,7 @@ Index: linux-2.6.12-rc6/fs/ext3/extents.c
 +
 +              if (num == 0) {
 +                      /* this extent is removed entirely mark slot unused */
-+                      ex->ee_start = 0;
++                      ex->ee_start = ex->ee_start_hi = 0;
 +                      eh->eh_entries--;
 +                      fu = ex;
 +              }
@@ -1646,7 +1650,7 @@ Index: linux-2.6.12-rc6/fs/ext3/extents.c
 +              while (lu < le) {
 +                      if (lu->ee_start) {
 +                              *fu = *lu;
-+                              lu->ee_start = 0;
++                              lu->ee_start = lu->ee_start_hi = 0;
 +                              fu++;
 +                      }
 +                      lu++;
@@ -2001,6 +2005,7 @@ Index: linux-2.6.12-rc6/fs/ext3/extents.c
 +              /* allocate new block for the extent */
 +              goal = ext3_ext_find_goal(inode, path, ex->ee_block);
 +              ex->ee_start = ext3_new_block(handle, inode, goal, err);
++              ex->ee_start_hi = 0;
 +              if (ex->ee_start == 0) {
 +                      /* error occured: restore old extent */
 +                      ex->ee_start = newblock;
@@ -2116,6 +2121,7 @@ Index: linux-2.6.12-rc6/fs/ext3/extents.c
 +      /* try to insert new extent into found leaf and return */
 +      newex.ee_block = iblock;
 +      newex.ee_start = newblock;
++      newex.ee_start_hi = 0;
 +      newex.ee_len = 1;
 +      err = ext3_ext_insert_extent(handle, &tree, path, &newex);
 +      if (err)
@@ -2523,26 +2529,30 @@ Index: linux-2.6.12-rc6/fs/ext3/super.c
        Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0,
        Opt_ignore, Opt_barrier, Opt_err, Opt_resize,
        Opt_iopen, Opt_noiopen, Opt_iopen_nopriv,
-+      Opt_extents, Opt_extdebug,
++      Opt_extents, Opt_noextents, Opt_extdebug,
  };
  
  static match_table_t tokens = {
-@@ -644,6 +647,8 @@
+@@ -644,6 +647,9 @@
        {Opt_iopen, "iopen"},
        {Opt_noiopen, "noiopen"},
        {Opt_iopen_nopriv, "iopen_nopriv"},
 +      {Opt_extents, "extents"},
++      {Opt_noextents, "noextents"},
 +      {Opt_extdebug, "extdebug"},
        {Opt_barrier, "barrier=%u"},
        {Opt_err, NULL},
        {Opt_resize, "resize"},
-@@ -953,6 +958,12 @@
+@@ -953,6 +958,15 @@
                case Opt_nobh:
                        set_opt(sbi->s_mount_opt, NOBH);
                        break;
 +              case Opt_extents:
 +                      set_opt (sbi->s_mount_opt, EXTENTS);
 +                      break;
++              case Opt_noextents:
++                      clear_opt (sbi->s_mount_opt, EXTENTS);
++                      break;
 +              case Opt_extdebug:
 +                      set_opt (sbi->s_mount_opt, EXTDEBUG);
 +                      break;
@@ -2621,11 +2631,13 @@ Index: linux-2.6.12-rc6/include/linux/ext3_fs.h
  #define EXT3_FEATURE_RO_COMPAT_SUPP   (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
                                         EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \
                                         EXT3_FEATURE_RO_COMPAT_BTREE_DIR)
-@@ -759,6 +767,7 @@
+@@ -759,6 +767,9 @@
  
  
  /* inode.c */
-+extern int ext3_block_truncate_page(handle_t *, struct page *, struct address_space *, loff_t);
++extern int ext3_block_truncate_page(handle_t *, struct page *,
++                                  struct address_space *, loff_t);
++extern int ext3_writepage_trans_blocks(struct inode *inode);
  extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int);
  extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
  extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
@@ -2849,14 +2861,14 @@ Index: linux-2.6.12-rc6/include/linux/ext3_extents.h
 +      (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_max - 1)
 +#define EXT_MAX_INDEX(__hdr__) \
 +      (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_max - 1)
-+#define EXT_GENERATION(__hdr__) ((__hdr__)->eh_generation & 0x00ffffff)
++#define EXT_HDR_GEN(__hdr__)  ((__hdr__)->eh_generation & 0x00ffffff)
 +#define EXT_FLAGS(__hdr__)    ((__hdr__)->eh_generation >> 24)
 +#define EXT_FLAGS_CLR_UNKNOWN 0x7     /* Flags cleared on modification */
 +
 +#define EXT_BLOCK_HDR(__bh__)         ((struct ext3_extent_header *)(__bh__)->b_data)
 +#define EXT_ROOT_HDR(__tree__)        ((struct ext3_extent_header *)(__tree__)->root)
 +#define EXT_DEPTH(__tree__)   (EXT_ROOT_HDR(__tree__)->eh_depth)
-+
++#define EXT_GENERATION(__tree__) EXT_HDR_GEN(EXT_ROOT_HDR(__tree__))
 +
 +#define EXT_ASSERT(__x__) if (!(__x__)) BUG();
 +
diff --git a/lustre/kernel_patches/patches/ext3-extents-2.6.15.patch b/lustre/kernel_patches/patches/ext3-extents-2.6.15.patch
new file mode 100644 (file)
index 0000000..3e18d55
--- /dev/null
@@ -0,0 +1,2933 @@
+Index: linux-2.6.16.21-0.8/fs/ext3/extents.c
+===================================================================
+--- /dev/null
++++ linux-2.6.16.21-0.8/fs/ext3/extents.c
+@@ -0,0 +1,2347 @@
++/*
++ * Copyright(c) 2003, 2004, 2005, Cluster File Systems, Inc, info@clusterfs.com
++ * Written by Alex Tomas <alex@clusterfs.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public Licens
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-
++ */
++
++/*
++ * Extents support for EXT3
++ *
++ * TODO:
++ *   - ext3_ext_walk_space() sould not use ext3_ext_find_extent()
++ *   - ext3_ext_calc_credits() could take 'mergable' into account
++ *   - ext3*_error() should be used in some situations
++ *   - find_goal() [to be tested and improved]
++ *   - smart tree reduction
++ *   - arch-independence
++ *     common on-disk format for big/little-endian arch
++ */
++
++#include <linux/module.h>
++#include <linux/fs.h>
++#include <linux/time.h>
++#include <linux/ext3_jbd.h>
++#include <linux/jbd.h>
++#include <linux/smp_lock.h>
++#include <linux/highuid.h>
++#include <linux/pagemap.h>
++#include <linux/quotaops.h>
++#include <linux/string.h>
++#include <linux/slab.h>
++#include <linux/ext3_extents.h>
++#include <asm/uaccess.h>
++
++
++static inline int ext3_ext_check_header(struct ext3_extent_header *eh)
++{
++      if (eh->eh_magic != EXT3_EXT_MAGIC) {
++              printk(KERN_ERR "EXT3-fs: invalid magic = 0x%x\n",
++                     (unsigned)eh->eh_magic);
++              return -EIO;
++      }
++      if (eh->eh_max == 0) {
++              printk(KERN_ERR "EXT3-fs: invalid eh_max = %u\n",
++                     (unsigned)eh->eh_max);
++              return -EIO;
++      }
++      if (eh->eh_entries > eh->eh_max) {
++              printk(KERN_ERR "EXT3-fs: invalid eh_entries = %u\n",
++                     (unsigned)eh->eh_entries);
++              return -EIO;
++      }
++      return 0;
++}
++
++static handle_t *ext3_ext_journal_restart(handle_t *handle, int needed)
++{
++      int err;
++
++      if (handle->h_buffer_credits > needed)
++              return handle;
++      if (!ext3_journal_extend(handle, needed))
++              return handle;
++      err = ext3_journal_restart(handle, needed);
++      
++      return handle;
++}
++
++static int inline
++ext3_ext_get_access_for_root(handle_t *h, struct ext3_extents_tree *tree)
++{
++      if (tree->ops->get_write_access)
++              return tree->ops->get_write_access(h,tree->buffer);
++      else
++              return 0;
++}
++
++static int inline
++ext3_ext_mark_root_dirty(handle_t *h, struct ext3_extents_tree *tree)
++{
++      if (tree->ops->mark_buffer_dirty)
++              return tree->ops->mark_buffer_dirty(h,tree->buffer);
++      else
++              return 0;
++}
++
++/*
++ * could return:
++ *  - EROFS
++ *  - ENOMEM
++ */
++static int ext3_ext_get_access(handle_t *handle,
++                             struct ext3_extents_tree *tree,
++                             struct ext3_ext_path *path)
++{
++      int err;
++
++      if (path->p_bh) {
++              /* path points to block */
++              err = ext3_journal_get_write_access(handle, path->p_bh);
++      } else {
++              /* path points to leaf/index in inode body */
++              err = ext3_ext_get_access_for_root(handle, tree);
++      }
++      return err;
++}
++
++/*
++ * could return:
++ *  - EROFS
++ *  - ENOMEM
++ *  - EIO
++ */
++static int ext3_ext_dirty(handle_t *handle, struct ext3_extents_tree *tree,
++                        struct ext3_ext_path *path)
++{
++      int err;
++      if (path->p_bh) {
++              /* path points to block */
++              err =ext3_journal_dirty_metadata(handle, path->p_bh);
++      } else {
++              /* path points to leaf/index in inode body */
++              err = ext3_ext_mark_root_dirty(handle, tree);
++      }
++      return err;
++}
++
++static int inline
++ext3_ext_new_block(handle_t *handle, struct ext3_extents_tree *tree,
++                 struct ext3_ext_path *path, struct ext3_extent *ex,
++                 int *err)
++{
++      int goal, depth, newblock;
++      struct inode *inode;
++
++      EXT_ASSERT(tree);
++      if (tree->ops->new_block)
++              return tree->ops->new_block(handle, tree, path, ex, err);
++
++      inode = tree->inode;
++      depth = EXT_DEPTH(tree);
++      if (path && depth > 0) {
++              goal = path[depth-1].p_block;
++      } else {
++              struct ext3_inode_info *ei = EXT3_I(inode);
++              unsigned long bg_start;
++              unsigned long colour;
++
++              bg_start = (ei->i_block_group *
++                          EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
++                      le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block);
++              colour = (current->pid % 16) *
++                      (EXT3_BLOCKS_PER_GROUP(inode->i_sb) / 16);
++              goal = bg_start + colour;
++      }
++
++      newblock = ext3_new_block(handle, inode, goal, err);
++      return newblock;
++}
++
++static inline void ext3_ext_tree_changed(struct ext3_extents_tree *tree)
++{
++      struct ext3_extent_header *neh;
++      neh = EXT_ROOT_HDR(tree);
++      neh->eh_generation++;
++}
++
++static inline int ext3_ext_space_block(struct ext3_extents_tree *tree)
++{
++      int size;
++
++      size = (tree->inode->i_sb->s_blocksize -
++              sizeof(struct ext3_extent_header)) /
++                              sizeof(struct ext3_extent);
++#ifdef AGRESSIVE_TEST
++      size = 6;
++#endif
++      return size;
++}
++
++static inline int ext3_ext_space_block_idx(struct ext3_extents_tree *tree)
++{
++      int size;
++
++      size = (tree->inode->i_sb->s_blocksize -
++              sizeof(struct ext3_extent_header)) /
++                              sizeof(struct ext3_extent_idx);
++#ifdef AGRESSIVE_TEST
++      size = 5;
++#endif
++      return size;
++}
++
++static inline int ext3_ext_space_root(struct ext3_extents_tree *tree)
++{
++      int size;
++
++      size = (tree->buffer_len - sizeof(struct ext3_extent_header)) /
++                      sizeof(struct ext3_extent);
++#ifdef AGRESSIVE_TEST
++      size = 3;
++#endif
++      return size;
++}
++
++static inline int ext3_ext_space_root_idx(struct ext3_extents_tree *tree)
++{
++      int size;
++
++      size = (tree->buffer_len - sizeof(struct ext3_extent_header)) /
++                      sizeof(struct ext3_extent_idx);
++#ifdef AGRESSIVE_TEST
++      size = 4;
++#endif
++      return size;
++}
++
++static void ext3_ext_show_path(struct ext3_extents_tree *tree,
++                             struct ext3_ext_path *path)
++{
++#ifdef EXT_DEBUG
++      int k, l = path->p_depth;
++
++      ext_debug(tree, "path:");
++      for (k = 0; k <= l; k++, path++) {
++              if (path->p_idx) {
++                      ext_debug(tree, "  %d->%d", path->p_idx->ei_block,
++                                path->p_idx->ei_leaf);
++              } else if (path->p_ext) {
++                      ext_debug(tree, "  %d:%d:%d",
++                                path->p_ext->ee_block,
++                                path->p_ext->ee_len,
++                                path->p_ext->ee_start);
++              } else
++                      ext_debug(tree, "  []");
++      }
++      ext_debug(tree, "\n");
++#endif
++}
++
++static void ext3_ext_show_leaf(struct ext3_extents_tree *tree,
++                             struct ext3_ext_path *path)
++{
++#ifdef EXT_DEBUG
++      int depth = EXT_DEPTH(tree);
++      struct ext3_extent_header *eh;
++      struct ext3_extent *ex;
++      int i;
++
++      if (!path)
++              return;
++
++      eh = path[depth].p_hdr;
++      ex = EXT_FIRST_EXTENT(eh);
++
++      for (i = 0; i < eh->eh_entries; i++, ex++) {
++              ext_debug(tree, "%d:%d:%d ",
++                        ex->ee_block, ex->ee_len, ex->ee_start);
++      }
++      ext_debug(tree, "\n");
++#endif
++}
++
++static void ext3_ext_drop_refs(struct ext3_ext_path *path)
++{
++      int depth = path->p_depth;
++      int i;
++
++      for (i = 0; i <= depth; i++, path++) {
++              if (path->p_bh) {
++                      brelse(path->p_bh);
++                      path->p_bh = NULL;
++              }
++      }
++}
++
++/*
++ * binary search for closest index by given block
++ */
++static inline void
++ext3_ext_binsearch_idx(struct ext3_extents_tree *tree,
++                     struct ext3_ext_path *path, int block)
++{
++      struct ext3_extent_header *eh = path->p_hdr;
++      struct ext3_extent_idx *ix;
++      int l = 0, k, r;
++
++      EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
++      EXT_ASSERT(eh->eh_entries <= eh->eh_max);
++      EXT_ASSERT(eh->eh_entries > 0);
++
++      ext_debug(tree, "binsearch for %d(idx):  ", block);
++
++      path->p_idx = ix = EXT_FIRST_INDEX(eh);
++
++      r = k = eh->eh_entries;
++      while (k > 1) {
++              k = (r - l) / 2;
++              if (block < ix[l + k].ei_block)
++                      r -= k;
++              else
++                      l += k;
++              ext_debug(tree, "%d:%d:%d ", k, l, r);
++      }
++
++      ix += l;
++      path->p_idx = ix;
++      ext_debug(tree," -> %d->%d ",path->p_idx->ei_block,path->p_idx->ei_leaf);
++
++      while (l++ < r) {
++              if (block < ix->ei_block) 
++                      break;
++              path->p_idx = ix++;
++      }
++      ext_debug(tree, "  -> %d->%d\n", path->p_idx->ei_block,
++                path->p_idx->ei_leaf);
++
++#ifdef CHECK_BINSEARCH 
++      {
++              struct ext3_extent_idx *chix;
++
++              chix = ix = EXT_FIRST_INDEX(eh);
++              for (k = 0; k < eh->eh_entries; k++, ix++) {
++                      if (k != 0 && ix->ei_block <= ix[-1].ei_block) {
++                              printk("k=%d, ix=0x%p, first=0x%p\n", k,
++                                     ix, EXT_FIRST_INDEX(eh));
++                              printk("%u <= %u\n",
++                                     ix->ei_block,ix[-1].ei_block);
++                      }
++                      EXT_ASSERT(k == 0 || ix->ei_block > ix[-1].ei_block);
++                      if (block < ix->ei_block) 
++                              break;
++                      chix = ix;
++              }
++              EXT_ASSERT(chix == path->p_idx);
++      }
++#endif
++}
++
++/*
++ * binary search for closest extent by given block
++ */
++static inline void
++ext3_ext_binsearch(struct ext3_extents_tree *tree,
++                 struct ext3_ext_path *path, int block)
++{
++      struct ext3_extent_header *eh = path->p_hdr;
++      struct ext3_extent *ex;
++      int l = 0, k, r;
++
++      EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
++      EXT_ASSERT(eh->eh_entries <= eh->eh_max);
++
++      if (eh->eh_entries == 0) {
++              /*
++               * this leaf is empty yet:
++               *  we get such a leaf in split/add case
++               */
++              return;
++      }
++      
++      ext_debug(tree, "binsearch for %d:  ", block);
++
++      path->p_ext = ex = EXT_FIRST_EXTENT(eh);
++
++      r = k = eh->eh_entries;
++      while (k > 1) {
++              k = (r - l) / 2;
++              if (block < ex[l + k].ee_block)
++                      r -= k;
++              else
++                      l += k;
++              ext_debug(tree, "%d:%d:%d ", k, l, r);
++      }
++
++      ex += l;
++      path->p_ext = ex;
++      ext_debug(tree, "  -> %d:%d:%d ", path->p_ext->ee_block,
++                path->p_ext->ee_start, path->p_ext->ee_len);
++
++      while (l++ < r) {
++              if (block < ex->ee_block) 
++                      break;
++              path->p_ext = ex++;
++      }
++      ext_debug(tree, "  -> %d:%d:%d\n", path->p_ext->ee_block,
++                path->p_ext->ee_start, path->p_ext->ee_len);
++
++#ifdef CHECK_BINSEARCH 
++      {
++              struct ext3_extent *chex;
++
++              chex = ex = EXT_FIRST_EXTENT(eh);
++              for (k = 0; k < eh->eh_entries; k++, ex++) {
++                      EXT_ASSERT(k == 0 || ex->ee_block > ex[-1].ee_block);
++                      if (block < ex->ee_block) 
++                              break;
++                      chex = ex;
++              }
++              EXT_ASSERT(chex == path->p_ext);
++      }
++#endif
++}
++
++int ext3_extent_tree_init(handle_t *handle, struct ext3_extents_tree *tree)
++{
++      struct ext3_extent_header *eh;
++
++      BUG_ON(tree->buffer_len == 0);
++      ext3_ext_get_access_for_root(handle, tree);
++      eh = EXT_ROOT_HDR(tree);
++      eh->eh_depth = 0;
++      eh->eh_entries = 0;
++      eh->eh_magic = EXT3_EXT_MAGIC;
++      eh->eh_max = ext3_ext_space_root(tree);
++      ext3_ext_mark_root_dirty(handle, tree);
++      ext3_ext_invalidate_cache(tree);
++      return 0;
++}
++
++struct ext3_ext_path *
++ext3_ext_find_extent(struct ext3_extents_tree *tree, int block,
++                   struct ext3_ext_path *path)
++{
++      struct ext3_extent_header *eh;
++      struct buffer_head *bh;
++      int depth, i, ppos = 0;
++
++      EXT_ASSERT(tree);
++      EXT_ASSERT(tree->inode);
++      EXT_ASSERT(tree->root);
++
++      eh = EXT_ROOT_HDR(tree);
++      EXT_ASSERT(eh);
++      if (ext3_ext_check_header(eh))
++              goto err;
++
++      i = depth = EXT_DEPTH(tree);
++      EXT_ASSERT(eh->eh_max);
++      EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
++      
++      /* account possible depth increase */
++      if (!path) {
++              path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 2),
++                             GFP_NOFS);
++              if (!path)
++                      return ERR_PTR(-ENOMEM);
++      }
++      memset(path, 0, sizeof(struct ext3_ext_path) * (depth + 1));
++      path[0].p_hdr = eh;
++
++      /* walk through the tree */
++      while (i) {
++              ext_debug(tree, "depth %d: num %d, max %d\n",
++                        ppos, eh->eh_entries, eh->eh_max);
++              ext3_ext_binsearch_idx(tree, path + ppos, block);
++              path[ppos].p_block = path[ppos].p_idx->ei_leaf;
++              path[ppos].p_depth = i;
++              path[ppos].p_ext = NULL;
++
++              bh = sb_bread(tree->inode->i_sb, path[ppos].p_block);
++              if (!bh)
++                      goto err;
++
++              eh = EXT_BLOCK_HDR(bh);
++              ppos++;
++              EXT_ASSERT(ppos <= depth);
++              path[ppos].p_bh = bh;
++              path[ppos].p_hdr = eh;
++              i--;
++
++              if (ext3_ext_check_header(eh))
++                      goto err;
++      }
++
++      path[ppos].p_depth = i;
++      path[ppos].p_hdr = eh;
++      path[ppos].p_ext = NULL;
++      path[ppos].p_idx = NULL;
++
++      if (ext3_ext_check_header(eh))
++              goto err;
++
++      /* find extent */
++      ext3_ext_binsearch(tree, path + ppos, block);
++
++      ext3_ext_show_path(tree, path);
++
++      return path;
++
++err:
++      printk(KERN_ERR "EXT3-fs: header is corrupted!\n");
++      ext3_ext_drop_refs(path);
++      kfree(path);
++      return ERR_PTR(-EIO);
++}
++
++/*
++ * insert new index [logical;ptr] into the block at cupr
++ * it check where to insert: before curp or after curp
++ */
++static int ext3_ext_insert_index(handle_t *handle,
++                               struct ext3_extents_tree *tree,
++                               struct ext3_ext_path *curp,
++                               int logical, int ptr)
++{
++      struct ext3_extent_idx *ix;
++      int len, err;
++
++      if ((err = ext3_ext_get_access(handle, tree, curp)))
++              return err;
++
++      EXT_ASSERT(logical != curp->p_idx->ei_block);
++      len = EXT_MAX_INDEX(curp->p_hdr) - curp->p_idx;
++      if (logical > curp->p_idx->ei_block) {
++              /* insert after */
++              if (curp->p_idx != EXT_LAST_INDEX(curp->p_hdr)) {
++                      len = (len - 1) * sizeof(struct ext3_extent_idx);
++                      len = len < 0 ? 0 : len;
++                      ext_debug(tree, "insert new index %d after: %d. "
++                                "move %d from 0x%p to 0x%p\n",
++                                logical, ptr, len,
++                                (curp->p_idx + 1), (curp->p_idx + 2));
++                      memmove(curp->p_idx + 2, curp->p_idx + 1, len);
++              }
++              ix = curp->p_idx + 1;
++      } else {
++              /* insert before */
++              len = len * sizeof(struct ext3_extent_idx);
++              len = len < 0 ? 0 : len;
++              ext_debug(tree, "insert new index %d before: %d. "
++                        "move %d from 0x%p to 0x%p\n",
++                        logical, ptr, len,
++                        curp->p_idx, (curp->p_idx + 1));
++              memmove(curp->p_idx + 1, curp->p_idx, len);
++              ix = curp->p_idx;
++      }
++
++      ix->ei_block = logical;
++      ix->ei_leaf = ptr;
++      curp->p_hdr->eh_entries++;
++
++      EXT_ASSERT(curp->p_hdr->eh_entries <= curp->p_hdr->eh_max);
++      EXT_ASSERT(ix <= EXT_LAST_INDEX(curp->p_hdr));
++
++      err = ext3_ext_dirty(handle, tree, curp);
++      ext3_std_error(tree->inode->i_sb, err);
++
++      return err;
++}
++
++/*
++ * routine inserts new subtree into the path, using free index entry
++ * at depth 'at:
++ *  - allocates all needed blocks (new leaf and all intermediate index blocks)
++ *  - makes decision where to split
++ *  - moves remaining extens and index entries (right to the split point)
++ *    into the newly allocated blocks
++ *  - initialize subtree
++ */
++static int ext3_ext_split(handle_t *handle, struct ext3_extents_tree *tree,
++                        struct ext3_ext_path *path,
++                        struct ext3_extent *newext, int at)
++{
++      struct buffer_head *bh = NULL;
++      int depth = EXT_DEPTH(tree);
++      struct ext3_extent_header *neh;
++      struct ext3_extent_idx *fidx;
++      struct ext3_extent *ex;
++      int i = at, k, m, a;
++      unsigned long newblock, oldblock, border;
++      int *ablocks = NULL; /* array of allocated blocks */
++      int err = 0;
++
++      /* make decision: where to split? */
++      /* FIXME: now desicion is simplest: at current extent */
++
++      /* if current leaf will be splitted, then we should use 
++       * border from split point */
++      EXT_ASSERT(path[depth].p_ext <= EXT_MAX_EXTENT(path[depth].p_hdr));
++      if (path[depth].p_ext != EXT_MAX_EXTENT(path[depth].p_hdr)) {
++              border = path[depth].p_ext[1].ee_block;
++              ext_debug(tree, "leaf will be splitted."
++                        " next leaf starts at %d\n",
++                        (int)border);
++      } else {
++              border = newext->ee_block;
++              ext_debug(tree, "leaf will be added."
++                        " next leaf starts at %d\n",
++                        (int)border);
++      }
++
++      /* 
++       * if error occurs, then we break processing
++       * and turn filesystem read-only. so, index won't
++       * be inserted and tree will be in consistent
++       * state. next mount will repair buffers too
++       */
++
++      /*
++       * get array to track all allocated blocks
++       * we need this to handle errors and free blocks
++       * upon them
++       */
++      ablocks = kmalloc(sizeof(unsigned long) * depth, GFP_NOFS);
++      if (!ablocks)
++              return -ENOMEM;
++      memset(ablocks, 0, sizeof(unsigned long) * depth);
++
++      /* allocate all needed blocks */
++      ext_debug(tree, "allocate %d blocks for indexes/leaf\n", depth - at);
++      for (a = 0; a < depth - at; a++) {
++              newblock = ext3_ext_new_block(handle, tree, path, newext, &err);
++              if (newblock == 0)
++                      goto cleanup;
++              ablocks[a] = newblock;
++      }
++
++      /* initialize new leaf */
++      newblock = ablocks[--a];
++      EXT_ASSERT(newblock);
++      bh = sb_getblk(tree->inode->i_sb, newblock);
++      if (!bh) {
++              err = -EIO;
++              goto cleanup;
++      }
++      lock_buffer(bh);
++
++      if ((err = ext3_journal_get_create_access(handle, bh)))
++              goto cleanup;
++
++      neh = EXT_BLOCK_HDR(bh);
++      neh->eh_entries = 0;
++      neh->eh_max = ext3_ext_space_block(tree);
++      neh->eh_magic = EXT3_EXT_MAGIC;
++      neh->eh_depth = 0;
++      ex = EXT_FIRST_EXTENT(neh);
++
++      /* move remain of path[depth] to the new leaf */
++      EXT_ASSERT(path[depth].p_hdr->eh_entries == path[depth].p_hdr->eh_max);
++      /* start copy from next extent */
++      /* TODO: we could do it by single memmove */
++      m = 0;
++      path[depth].p_ext++;
++      while (path[depth].p_ext <=
++                      EXT_MAX_EXTENT(path[depth].p_hdr)) {
++              ext_debug(tree, "move %d:%d:%d in new leaf %lu\n",
++                        path[depth].p_ext->ee_block,
++                        path[depth].p_ext->ee_start,
++                        path[depth].p_ext->ee_len,
++                        newblock);
++              memmove(ex++, path[depth].p_ext++, sizeof(struct ext3_extent));
++              neh->eh_entries++;
++              m++;
++      }
++      set_buffer_uptodate(bh);
++      unlock_buffer(bh);
++
++      if ((err = ext3_journal_dirty_metadata(handle, bh)))
++              goto cleanup;   
++      brelse(bh);
++      bh = NULL;
++
++      /* correct old leaf */
++      if (m) {
++              if ((err = ext3_ext_get_access(handle, tree, path + depth)))
++                      goto cleanup;
++              path[depth].p_hdr->eh_entries -= m;
++              if ((err = ext3_ext_dirty(handle, tree, path + depth)))
++                      goto cleanup;
++              
++      }
++
++      /* create intermediate indexes */
++      k = depth - at - 1;
++      EXT_ASSERT(k >= 0);
++      if (k)
++              ext_debug(tree, "create %d intermediate indices\n", k);
++      /* insert new index into current index block */
++      /* current depth stored in i var */
++      i = depth - 1;
++      while (k--) {
++              oldblock = newblock;
++              newblock = ablocks[--a];
++              bh = sb_getblk(tree->inode->i_sb, newblock);
++              if (!bh) {
++                      err = -EIO;
++                      goto cleanup;
++              }
++              lock_buffer(bh);
++
++              if ((err = ext3_journal_get_create_access(handle, bh)))
++                      goto cleanup;
++
++              neh = EXT_BLOCK_HDR(bh);
++              neh->eh_entries = 1;
++              neh->eh_magic = EXT3_EXT_MAGIC;
++              neh->eh_max = ext3_ext_space_block_idx(tree);
++              neh->eh_depth = depth - i; 
++              fidx = EXT_FIRST_INDEX(neh);
++              fidx->ei_block = border;
++              fidx->ei_leaf = oldblock;
++
++              ext_debug(tree, "int.index at %d (block %lu): %lu -> %lu\n",
++                        i, newblock, border, oldblock);
++              /* copy indexes */
++              m = 0;
++              path[i].p_idx++;
++
++              ext_debug(tree, "cur 0x%p, last 0x%p\n", path[i].p_idx,
++                        EXT_MAX_INDEX(path[i].p_hdr));
++              EXT_ASSERT(EXT_MAX_INDEX(path[i].p_hdr) ==
++                         EXT_LAST_INDEX(path[i].p_hdr));
++              while (path[i].p_idx <= EXT_MAX_INDEX(path[i].p_hdr)) {
++                      ext_debug(tree, "%d: move %d:%d in new index %lu\n",
++                                i, path[i].p_idx->ei_block,
++                                path[i].p_idx->ei_leaf, newblock);
++                      memmove(++fidx, path[i].p_idx++,
++                              sizeof(struct ext3_extent_idx));
++                      neh->eh_entries++;
++                      EXT_ASSERT(neh->eh_entries <= neh->eh_max);
++                      m++;
++              }
++              set_buffer_uptodate(bh);
++              unlock_buffer(bh);
++
++              if ((err = ext3_journal_dirty_metadata(handle, bh)))
++                      goto cleanup;
++              brelse(bh);
++              bh = NULL;
++
++              /* correct old index */
++              if (m) {
++                      err = ext3_ext_get_access(handle, tree, path + i);
++                      if (err)
++                              goto cleanup;
++                      path[i].p_hdr->eh_entries -= m;
++                      err = ext3_ext_dirty(handle, tree, path + i);
++                      if (err)
++                              goto cleanup;
++              }
++
++              i--;
++      }
++
++      /* insert new index */
++      if (!err)
++              err = ext3_ext_insert_index(handle, tree, path + at,
++                                          border, newblock);
++
++cleanup:
++      if (bh) {
++              if (buffer_locked(bh))
++                      unlock_buffer(bh);
++              brelse(bh);
++      }
++
++      if (err) {
++              /* free all allocated blocks in error case */
++              for (i = 0; i < depth; i++) {
++                      if (!ablocks[i])
++                              continue;
++                      ext3_free_blocks(handle, tree->inode, ablocks[i], 1);
++              }
++      }
++      kfree(ablocks);
++
++      return err;
++}
++
++/*
++ * routine implements tree growing procedure:
++ *  - allocates new block
++ *  - moves top-level data (index block or leaf) into the new block
++ *  - initialize new top-level, creating index that points to the
++ *    just created block
++ */
++static int ext3_ext_grow_indepth(handle_t *handle,
++                               struct ext3_extents_tree *tree,
++                               struct ext3_ext_path *path,
++                               struct ext3_extent *newext)
++{
++      struct ext3_ext_path *curp = path;
++      struct ext3_extent_header *neh;
++      struct ext3_extent_idx *fidx;
++      struct buffer_head *bh;
++      unsigned long newblock;
++      int err = 0;
++
++      newblock = ext3_ext_new_block(handle, tree, path, newext, &err);
++      if (newblock == 0)
++              return err;
++
++      bh = sb_getblk(tree->inode->i_sb, newblock);
++      if (!bh) {
++              err = -EIO;
++              ext3_std_error(tree->inode->i_sb, err);
++              return err;
++      }
++      lock_buffer(bh);
++
++      if ((err = ext3_journal_get_create_access(handle, bh))) {
++              unlock_buffer(bh);
++              goto out;       
++      }
++
++      /* move top-level index/leaf into new block */
++      memmove(bh->b_data, curp->p_hdr, tree->buffer_len);
++
++      /* set size of new block */
++      neh = EXT_BLOCK_HDR(bh);
++      /* old root could have indexes or leaves
++       * so calculate eh_max right way */
++      if (EXT_DEPTH(tree))
++              neh->eh_max = ext3_ext_space_block_idx(tree);
++      else
++              neh->eh_max = ext3_ext_space_block(tree);
++      neh->eh_magic = EXT3_EXT_MAGIC;
++      set_buffer_uptodate(bh);
++      unlock_buffer(bh);
++
++      if ((err = ext3_journal_dirty_metadata(handle, bh)))
++              goto out;
++
++      /* create index in new top-level index: num,max,pointer */
++      if ((err = ext3_ext_get_access(handle, tree, curp)))
++              goto out;
++
++      curp->p_hdr->eh_magic = EXT3_EXT_MAGIC;
++      curp->p_hdr->eh_max = ext3_ext_space_root_idx(tree);
++      curp->p_hdr->eh_entries = 1;
++      curp->p_idx = EXT_FIRST_INDEX(curp->p_hdr);
++      /* FIXME: it works, but actually path[0] can be index */
++      curp->p_idx->ei_block = EXT_FIRST_EXTENT(path[0].p_hdr)->ee_block;
++      curp->p_idx->ei_leaf = newblock;
++
++      neh = EXT_ROOT_HDR(tree);
++      fidx = EXT_FIRST_INDEX(neh);
++      ext_debug(tree, "new root: num %d(%d), lblock %d, ptr %d\n",
++                neh->eh_entries, neh->eh_max, fidx->ei_block, fidx->ei_leaf); 
++
++      neh->eh_depth = path->p_depth + 1;
++      err = ext3_ext_dirty(handle, tree, curp);
++out:
++      brelse(bh);
++
++      return err;
++}
++
++/*
++ * routine finds empty index and adds new leaf. if no free index found
++ * then it requests in-depth growing
++ */
++static int ext3_ext_create_new_leaf(handle_t *handle,
++                                  struct ext3_extents_tree *tree,
++                                  struct ext3_ext_path *path,
++                                  struct ext3_extent *newext)
++{
++      struct ext3_ext_path *curp;
++      int depth, i, err = 0;
++
++repeat:
++      i = depth = EXT_DEPTH(tree);
++      
++      /* walk up to the tree and look for free index entry */
++      curp = path + depth;
++      while (i > 0 && !EXT_HAS_FREE_INDEX(curp)) {
++              i--;
++              curp--;
++      }
++
++      /* we use already allocated block for index block
++       * so, subsequent data blocks should be contigoues */
++      if (EXT_HAS_FREE_INDEX(curp)) {
++              /* if we found index with free entry, then use that
++               * entry: create all needed subtree and add new leaf */
++              err = ext3_ext_split(handle, tree, path, newext, i);
++
++              /* refill path */
++              ext3_ext_drop_refs(path);
++              path = ext3_ext_find_extent(tree, newext->ee_block, path);
++              if (IS_ERR(path))
++                      err = PTR_ERR(path);
++      } else {
++              /* tree is full, time to grow in depth */
++              err = ext3_ext_grow_indepth(handle, tree, path, newext);
++
++              /* refill path */
++              ext3_ext_drop_refs(path);
++              path = ext3_ext_find_extent(tree, newext->ee_block, path);
++              if (IS_ERR(path))
++                      err = PTR_ERR(path);
++
++              /*
++               * only first (depth 0 -> 1) produces free space
++               * in all other cases we have to split growed tree
++               */
++              depth = EXT_DEPTH(tree);
++              if (path[depth].p_hdr->eh_entries == path[depth].p_hdr->eh_max) {
++                      /* now we need split */
++                      goto repeat;
++              }
++      }
++
++      if (err)
++              return err;
++
++      return 0;
++}
++
++/*
++ * returns allocated block in subsequent extent or EXT_MAX_BLOCK
++ * NOTE: it consider block number from index entry as
++ * allocated block. thus, index entries have to be consistent
++ * with leafs
++ */
++static unsigned long
++ext3_ext_next_allocated_block(struct ext3_ext_path *path)
++{
++      int depth;
++
++      EXT_ASSERT(path != NULL);
++      depth = path->p_depth;
++
++      if (depth == 0 && path->p_ext == NULL)
++              return EXT_MAX_BLOCK;
++
++      /* FIXME: what if index isn't full ?! */
++      while (depth >= 0) {
++              if (depth == path->p_depth) {
++                      /* leaf */
++                      if (path[depth].p_ext !=
++                          EXT_LAST_EXTENT(path[depth].p_hdr))
++                              return path[depth].p_ext[1].ee_block;
++              } else {
++                      /* index */
++                      if (path[depth].p_idx !=
++                          EXT_LAST_INDEX(path[depth].p_hdr))
++                              return path[depth].p_idx[1].ei_block;
++              }
++              depth--;        
++      }
++
++      return EXT_MAX_BLOCK;
++}
++
++/*
++ * returns first allocated block from next leaf or EXT_MAX_BLOCK
++ */
++static unsigned ext3_ext_next_leaf_block(struct ext3_extents_tree *tree,
++                                       struct ext3_ext_path *path)
++{
++      int depth;
++
++      EXT_ASSERT(path != NULL);
++      depth = path->p_depth;
++
++      /* zero-tree has no leaf blocks at all */
++      if (depth == 0)
++              return EXT_MAX_BLOCK;
++
++      /* go to index block */
++      depth--;
++      
++      while (depth >= 0) {
++              if (path[depth].p_idx !=
++                  EXT_LAST_INDEX(path[depth].p_hdr))
++                      return path[depth].p_idx[1].ei_block;
++              depth--;        
++      }
++
++      return EXT_MAX_BLOCK;
++}
++
++/*
++ * if leaf gets modified and modified extent is first in the leaf
++ * then we have to correct all indexes above
++ * TODO: do we need to correct tree in all cases?
++ */
++int ext3_ext_correct_indexes(handle_t *handle, struct ext3_extents_tree *tree,
++                           struct ext3_ext_path *path)
++{
++      struct ext3_extent_header *eh;
++      int depth = EXT_DEPTH(tree);    
++      struct ext3_extent *ex;
++      unsigned long border;
++      int k, err = 0;
++      
++      eh = path[depth].p_hdr;
++      ex = path[depth].p_ext;
++      EXT_ASSERT(ex);
++      EXT_ASSERT(eh);
++      
++      if (depth == 0) {
++              /* there is no tree at all */
++              return 0;
++      }
++      
++      if (ex != EXT_FIRST_EXTENT(eh)) {
++              /* we correct tree if first leaf got modified only */
++              return 0;
++      }
++      
++      /*
++       * TODO: we need correction if border is smaller then current one
++       */
++      k = depth - 1;
++      border = path[depth].p_ext->ee_block;
++      if ((err = ext3_ext_get_access(handle, tree, path + k)))
++              return err;
++      path[k].p_idx->ei_block = border;
++      if ((err = ext3_ext_dirty(handle, tree, path + k)))
++              return err;
++
++      while (k--) {
++              /* change all left-side indexes */
++              if (path[k+1].p_idx != EXT_FIRST_INDEX(path[k+1].p_hdr))
++                      break;
++              if ((err = ext3_ext_get_access(handle, tree, path + k)))
++                      break;
++              path[k].p_idx->ei_block = border;
++              if ((err = ext3_ext_dirty(handle, tree, path + k)))
++                      break;
++      }
++
++      return err;
++}
++
++static int inline
++ext3_can_extents_be_merged(struct ext3_extents_tree *tree,
++                         struct ext3_extent *ex1,
++                         struct ext3_extent *ex2)
++{
++      if (ex1->ee_block + ex1->ee_len != ex2->ee_block)
++              return 0;
++
++#ifdef AGRESSIVE_TEST
++      if (ex1->ee_len >= 4)
++              return 0;
++#endif
++
++      if (!tree->ops->mergable)
++              return 1;
++
++      return tree->ops->mergable(ex1, ex2);
++}
++
++/*
++ * this routine tries to merge requsted extent into the existing
++ * extent or inserts requested extent as new one into the tree,
++ * creating new leaf in no-space case
++ */
++int ext3_ext_insert_extent(handle_t *handle, struct ext3_extents_tree *tree,
++                         struct ext3_ext_path *path,
++                         struct ext3_extent *newext)
++{
++      struct ext3_extent_header * eh;
++      struct ext3_extent *ex, *fex;
++      struct ext3_extent *nearex; /* nearest extent */
++      struct ext3_ext_path *npath = NULL;
++      int depth, len, err, next;
++
++      EXT_ASSERT(newext->ee_len > 0);
++      depth = EXT_DEPTH(tree);
++      ex = path[depth].p_ext;
++      EXT_ASSERT(path[depth].p_hdr);
++
++      /* try to insert block into found extent and return */
++      if (ex && ext3_can_extents_be_merged(tree, ex, newext)) {
++              ext_debug(tree, "append %d block to %d:%d (from %d)\n",
++                        newext->ee_len, ex->ee_block, ex->ee_len,
++                        ex->ee_start);
++              if ((err = ext3_ext_get_access(handle, tree, path + depth)))
++                      return err;
++              ex->ee_len += newext->ee_len;
++              eh = path[depth].p_hdr;
++              nearex = ex;
++              goto merge;
++      }
++
++repeat:
++      depth = EXT_DEPTH(tree);
++      eh = path[depth].p_hdr;
++      if (eh->eh_entries < eh->eh_max)
++              goto has_space;
++
++      /* probably next leaf has space for us? */
++      fex = EXT_LAST_EXTENT(eh);
++      next = ext3_ext_next_leaf_block(tree, path);
++      if (newext->ee_block > fex->ee_block && next != EXT_MAX_BLOCK) {
++              ext_debug(tree, "next leaf block - %d\n", next);
++              EXT_ASSERT(!npath);
++              npath = ext3_ext_find_extent(tree, next, NULL);
++              if (IS_ERR(npath))
++                      return PTR_ERR(npath);
++              EXT_ASSERT(npath->p_depth == path->p_depth);
++              eh = npath[depth].p_hdr;
++              if (eh->eh_entries < eh->eh_max) {
++                      ext_debug(tree, "next leaf isnt full(%d)\n",
++                                eh->eh_entries);
++                      path = npath;
++                      goto repeat;
++              }
++              ext_debug(tree, "next leaf hasno free space(%d,%d)\n",
++                        eh->eh_entries, eh->eh_max);
++      }
++
++      /*
++       * there is no free space in found leaf
++       * we're gonna add new leaf in the tree
++       */
++      err = ext3_ext_create_new_leaf(handle, tree, path, newext);
++      if (err)
++              goto cleanup;
++      depth = EXT_DEPTH(tree);
++      eh = path[depth].p_hdr;
++
++has_space:
++      nearex = path[depth].p_ext;
++
++      if ((err = ext3_ext_get_access(handle, tree, path + depth)))
++              goto cleanup;
++
++      if (!nearex) {
++              /* there is no extent in this leaf, create first one */
++              ext_debug(tree, "first extent in the leaf: %d:%d:%d\n",
++                        newext->ee_block, newext->ee_start,
++                        newext->ee_len);
++              path[depth].p_ext = EXT_FIRST_EXTENT(eh);
++      } else if (newext->ee_block > nearex->ee_block) {
++              EXT_ASSERT(newext->ee_block != nearex->ee_block);
++              if (nearex != EXT_LAST_EXTENT(eh)) {
++                      len = EXT_MAX_EXTENT(eh) - nearex;
++                      len = (len - 1) * sizeof(struct ext3_extent);
++                      len = len < 0 ? 0 : len;
++                      ext_debug(tree, "insert %d:%d:%d after: nearest 0x%p, "
++                                "move %d from 0x%p to 0x%p\n",
++                                newext->ee_block, newext->ee_start,
++                                newext->ee_len,
++                                nearex, len, nearex + 1, nearex + 2);
++                      memmove(nearex + 2, nearex + 1, len);
++              }
++              path[depth].p_ext = nearex + 1;
++      } else {
++              EXT_ASSERT(newext->ee_block != nearex->ee_block);
++              len = (EXT_MAX_EXTENT(eh) - nearex) * sizeof(struct ext3_extent);
++              len = len < 0 ? 0 : len;
++              ext_debug(tree, "insert %d:%d:%d before: nearest 0x%p, "
++                        "move %d from 0x%p to 0x%p\n",
++                        newext->ee_block, newext->ee_start, newext->ee_len,
++                        nearex, len, nearex + 1, nearex + 2);
++              memmove(nearex + 1, nearex, len);
++              path[depth].p_ext = nearex;
++      }
++
++      eh->eh_entries++;
++      nearex = path[depth].p_ext;
++      nearex->ee_block = newext->ee_block;
++      nearex->ee_start = newext->ee_start;
++      nearex->ee_len = newext->ee_len;
++      /* FIXME: support for large fs */
++      nearex->ee_start_hi = 0;
++
++merge:
++      /* try to merge extents to the right */
++      while (nearex < EXT_LAST_EXTENT(eh)) {
++              if (!ext3_can_extents_be_merged(tree, nearex, nearex + 1))
++                      break;
++              /* merge with next extent! */
++              nearex->ee_len += nearex[1].ee_len;
++              if (nearex + 1 < EXT_LAST_EXTENT(eh)) {
++                      len = (EXT_LAST_EXTENT(eh) - nearex - 1) *
++                              sizeof(struct ext3_extent);
++                      memmove(nearex + 1, nearex + 2, len);
++              }
++              eh->eh_entries--;
++              EXT_ASSERT(eh->eh_entries > 0);
++      }
++
++      /* try to merge extents to the left */
++
++      /* time to correct all indexes above */
++      err = ext3_ext_correct_indexes(handle, tree, path);
++      if (err)
++              goto cleanup;
++
++      err = ext3_ext_dirty(handle, tree, path + depth);
++
++cleanup:
++      if (npath) {
++              ext3_ext_drop_refs(npath);
++              kfree(npath);
++      }
++      ext3_ext_tree_changed(tree);
++      ext3_ext_invalidate_cache(tree);
++      return err;
++}
++
++int ext3_ext_walk_space(struct ext3_extents_tree *tree, unsigned long block,
++                      unsigned long num, ext_prepare_callback func)
++{
++      struct ext3_ext_path *path = NULL;
++      struct ext3_ext_cache cbex;
++      struct ext3_extent *ex;
++      unsigned long next, start = 0, end = 0;
++      unsigned long last = block + num;
++      int depth, exists, err = 0;
++
++      EXT_ASSERT(tree);
++      EXT_ASSERT(func);
++      EXT_ASSERT(tree->inode);
++      EXT_ASSERT(tree->root);
++
++      while (block < last && block != EXT_MAX_BLOCK) {
++              num = last - block;
++              /* find extent for this block */
++              path = ext3_ext_find_extent(tree, block, path);
++              if (IS_ERR(path)) {
++                      err = PTR_ERR(path);
++                      path = NULL;
++                      break;
++              }
++
++              depth = EXT_DEPTH(tree);
++              EXT_ASSERT(path[depth].p_hdr);
++              ex = path[depth].p_ext;
++              next = ext3_ext_next_allocated_block(path);
++
++              exists = 0;
++              if (!ex) {
++                      /* there is no extent yet, so try to allocate
++                       * all requested space */
++                      start = block;
++                      end = block + num;
++              } else if (ex->ee_block > block) {
++                      /* need to allocate space before found extent */
++                      start = block;
++                      end = ex->ee_block;
++                      if (block + num < end)
++                              end = block + num;
++              } else if (block >= ex->ee_block + ex->ee_len) {
++                      /* need to allocate space after found extent */
++                      start = block;
++                      end = block + num;
++                      if (end >= next)
++                              end = next;
++              } else if (block >= ex->ee_block) {
++                      /* 
++                       * some part of requested space is covered
++                       * by found extent
++                       */
++                      start = block;
++                      end = ex->ee_block + ex->ee_len;
++                      if (block + num < end)
++                              end = block + num;
++                      exists = 1;
++              } else {
++                      BUG();
++              }
++              EXT_ASSERT(end > start);
++
++              if (!exists) {
++                      cbex.ec_block = start;
++                      cbex.ec_len = end - start;
++                      cbex.ec_start = 0;
++                      cbex.ec_type = EXT3_EXT_CACHE_GAP;
++              } else {
++                      cbex.ec_block = ex->ee_block;
++                      cbex.ec_len = ex->ee_len;
++                      cbex.ec_start = ex->ee_start;
++                      cbex.ec_type = EXT3_EXT_CACHE_EXTENT;
++              }
++
++              EXT_ASSERT(cbex.ec_len > 0);
++              EXT_ASSERT(path[depth].p_hdr);
++              err = func(tree, path, &cbex);
++              ext3_ext_drop_refs(path);
++
++              if (err < 0)
++                      break;
++              if (err == EXT_REPEAT)
++                      continue;
++              else if (err == EXT_BREAK) {
++                      err = 0;
++                      break;
++              }
++
++              if (EXT_DEPTH(tree) != depth) {
++                      /* depth was changed. we have to realloc path */
++                      kfree(path);
++                      path = NULL;
++              }
++
++              block = cbex.ec_block + cbex.ec_len;
++      }
++
++      if (path) {
++              ext3_ext_drop_refs(path);
++              kfree(path);
++      }
++
++      return err;
++}
++
++static inline void
++ext3_ext_put_in_cache(struct ext3_extents_tree *tree, __u32 block,
++                    __u32 len, __u32 start, int type)
++{
++      EXT_ASSERT(len > 0);
++      if (tree->cex) {
++              tree->cex->ec_type = type;
++              tree->cex->ec_block = block;
++              tree->cex->ec_len = len;
++              tree->cex->ec_start = start;
++      }
++}
++
++/*
++ * this routine calculate boundaries of the gap requested block fits into
++ * and cache this gap
++ */
++static inline void
++ext3_ext_put_gap_in_cache(struct ext3_extents_tree *tree,
++                        struct ext3_ext_path *path,
++                        unsigned long block)
++{
++      int depth = EXT_DEPTH(tree);
++      unsigned long lblock, len;
++      struct ext3_extent *ex;
++
++      if (!tree->cex)
++              return;
++
++      ex = path[depth].p_ext;
++      if (ex == NULL) {
++              /* there is no extent yet, so gap is [0;-] */
++              lblock = 0;
++              len = EXT_MAX_BLOCK;
++              ext_debug(tree, "cache gap(whole file):");
++      } else if (block < ex->ee_block) {
++              lblock = block;
++              len = ex->ee_block - block;
++              ext_debug(tree, "cache gap(before): %lu [%lu:%lu]",
++                        (unsigned long) block,
++                        (unsigned long) ex->ee_block,
++                        (unsigned long) ex->ee_len);
++      } else if (block >= ex->ee_block + ex->ee_len) {
++              lblock = ex->ee_block + ex->ee_len;
++              len = ext3_ext_next_allocated_block(path);
++              ext_debug(tree, "cache gap(after): [%lu:%lu] %lu",
++                        (unsigned long) ex->ee_block,
++                        (unsigned long) ex->ee_len,
++                        (unsigned long) block);
++              EXT_ASSERT(len > lblock);
++              len = len - lblock;
++      } else {
++              lblock = len = 0;
++              BUG();
++      }
++
++      ext_debug(tree, " -> %lu:%lu\n", (unsigned long) lblock, len);
++      ext3_ext_put_in_cache(tree, lblock, len, 0, EXT3_EXT_CACHE_GAP);
++}
++
++static inline int
++ext3_ext_in_cache(struct ext3_extents_tree *tree, unsigned long block,
++                struct ext3_extent *ex)
++{
++      struct ext3_ext_cache *cex = tree->cex;
++
++      /* is there cache storage at all? */
++      if (!cex)
++              return EXT3_EXT_CACHE_NO;
++
++      /* has cache valid data? */
++      if (cex->ec_type == EXT3_EXT_CACHE_NO)
++              return EXT3_EXT_CACHE_NO;
++
++      EXT_ASSERT(cex->ec_type == EXT3_EXT_CACHE_GAP ||
++                 cex->ec_type == EXT3_EXT_CACHE_EXTENT);
++      if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) {
++              ex->ee_block = cex->ec_block;
++              ex->ee_start = cex->ec_start;
++              ex->ee_len = cex->ec_len;
++              ext_debug(tree, "%lu cached by %lu:%lu:%lu\n",
++                        (unsigned long) block,
++                        (unsigned long) ex->ee_block,
++                        (unsigned long) ex->ee_len,
++                        (unsigned long) ex->ee_start);
++              return cex->ec_type;
++      }
++
++      /* not in cache */
++      return EXT3_EXT_CACHE_NO;
++}
++
++/*
++ * routine removes index from the index block
++ * it's used in truncate case only. thus all requests are for
++ * last index in the block only
++ */
++int ext3_ext_rm_idx(handle_t *handle, struct ext3_extents_tree *tree,
++                  struct ext3_ext_path *path)
++{
++      struct buffer_head *bh;
++      int err;
++      
++      /* free index block */
++      path--;
++      EXT_ASSERT(path->p_hdr->eh_entries);
++      if ((err = ext3_ext_get_access(handle, tree, path)))
++              return err;
++      path->p_hdr->eh_entries--;
++      if ((err = ext3_ext_dirty(handle, tree, path)))
++              return err;
++      ext_debug(tree, "index is empty, remove it, free block %d\n",
++                path->p_idx->ei_leaf);
++      bh = sb_find_get_block(tree->inode->i_sb, path->p_idx->ei_leaf);
++      ext3_forget(handle, 1, tree->inode, bh, path->p_idx->ei_leaf);
++      ext3_free_blocks(handle, tree->inode, path->p_idx->ei_leaf, 1);
++      return err;
++}
++
++int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *tree,
++                                   struct ext3_ext_path *path)
++{
++      int depth = EXT_DEPTH(tree);
++      int needed;
++
++      if (path) {
++              /* probably there is space in leaf? */
++              if (path[depth].p_hdr->eh_entries < path[depth].p_hdr->eh_max)
++                      return 1;
++      }
++      
++      /*
++       * the worste case we're expecting is creation of the
++       * new root (growing in depth) with index splitting
++       * for splitting we have to consider depth + 1 because
++       * previous growing could increase it
++       */
++      depth = depth + 1;
++
++      /* 
++       * growing in depth:
++       * block allocation + new root + old root
++       */
++      needed = EXT3_ALLOC_NEEDED + 2;
++
++      /* index split. we may need:
++       *   allocate intermediate indexes and new leaf
++       *   change two blocks at each level, but root
++       *   modify root block (inode)
++       */
++      needed += (depth * EXT3_ALLOC_NEEDED) + (2 * depth) + 1;
++
++      return needed;
++}
++
++static int
++ext3_ext_split_for_rm(handle_t *handle, struct ext3_extents_tree *tree,
++                    struct ext3_ext_path *path, unsigned long start,
++                    unsigned long end)
++{
++      struct ext3_extent *ex, tex;
++      struct ext3_ext_path *npath;
++      int depth, creds, err;
++
++      depth = EXT_DEPTH(tree);
++      ex = path[depth].p_ext;
++      EXT_ASSERT(ex);
++      EXT_ASSERT(end < ex->ee_block + ex->ee_len - 1);
++      EXT_ASSERT(ex->ee_block < start);
++
++      /* calculate tail extent */
++      tex.ee_block = end + 1;
++      EXT_ASSERT(tex.ee_block < ex->ee_block + ex->ee_len);
++      tex.ee_len = ex->ee_block + ex->ee_len - tex.ee_block;
++
++      creds = ext3_ext_calc_credits_for_insert(tree, path);
++      handle = ext3_ext_journal_restart(handle, creds);
++      if (IS_ERR(handle))
++              return PTR_ERR(handle);
++      
++      /* calculate head extent. use primary extent */
++      err = ext3_ext_get_access(handle, tree, path + depth);
++      if (err)
++              return err;
++      ex->ee_len = start - ex->ee_block;
++      err = ext3_ext_dirty(handle, tree, path + depth);
++      if (err)
++              return err;
++
++      /* FIXME: some callback to free underlying resource
++       * and correct ee_start? */
++      ext_debug(tree, "split extent: head %u:%u, tail %u:%u\n",
++                ex->ee_block, ex->ee_len, tex.ee_block, tex.ee_len);
++
++      npath = ext3_ext_find_extent(tree, ex->ee_block, NULL);
++      if (IS_ERR(npath))
++              return PTR_ERR(npath);
++      depth = EXT_DEPTH(tree);
++      EXT_ASSERT(npath[depth].p_ext->ee_block == ex->ee_block);
++      EXT_ASSERT(npath[depth].p_ext->ee_len == ex->ee_len);
++
++      err = ext3_ext_insert_extent(handle, tree, npath, &tex);
++      ext3_ext_drop_refs(npath);
++      kfree(npath);
++
++      return err;
++}
++
++static int
++ext3_ext_rm_leaf(handle_t *handle, struct ext3_extents_tree *tree,
++               struct ext3_ext_path *path, unsigned long start,
++               unsigned long end)
++{
++      struct ext3_extent *ex, *fu = NULL, *lu, *le;
++      int err = 0, correct_index = 0;
++      int depth = EXT_DEPTH(tree), credits;
++      struct ext3_extent_header *eh;
++      unsigned a, b, block, num;
++
++      ext_debug(tree, "remove [%lu:%lu] in leaf\n", start, end);
++      if (!path[depth].p_hdr)
++              path[depth].p_hdr = EXT_BLOCK_HDR(path[depth].p_bh);
++      eh = path[depth].p_hdr;
++      EXT_ASSERT(eh);
++      EXT_ASSERT(eh->eh_entries <= eh->eh_max);
++      EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
++      
++      /* find where to start removing */
++      le = ex = EXT_LAST_EXTENT(eh);
++      while (ex != EXT_FIRST_EXTENT(eh)) {
++              if (ex->ee_block <= end)
++                      break;
++              ex--;
++      }
++
++      if (start > ex->ee_block && end < ex->ee_block + ex->ee_len - 1) {
++              /* removal of internal part of the extent requested
++               * tail and head must be placed in different extent
++               * so, we have to insert one more extent */
++              path[depth].p_ext = ex;
++              return ext3_ext_split_for_rm(handle, tree, path, start, end);
++      }
++      
++      lu = ex;
++      while (ex >= EXT_FIRST_EXTENT(eh) && ex->ee_block + ex->ee_len > start) {
++              ext_debug(tree, "remove ext %u:%u\n", ex->ee_block, ex->ee_len);
++              path[depth].p_ext = ex;
++      
++              a = ex->ee_block > start ? ex->ee_block : start;
++              b = ex->ee_block + ex->ee_len - 1 < end ?
++                      ex->ee_block + ex->ee_len - 1 : end;
++              
++              ext_debug(tree, "  border %u:%u\n", a, b);
++
++              if (a != ex->ee_block && b != ex->ee_block + ex->ee_len - 1) {
++                      block = 0;
++                      num = 0;
++                      BUG();
++              } else if (a != ex->ee_block) {
++                      /* remove tail of the extent */
++                      block = ex->ee_block;
++                      num = a - block;
++              } else if (b != ex->ee_block + ex->ee_len - 1) {
++                      /* remove head of the extent */
++                      block = a;
++                      num = b - a;
++              } else {
++                      /* remove whole extent: excelent! */
++                      block = ex->ee_block; 
++                      num = 0;
++                      EXT_ASSERT(a == ex->ee_block &&
++                                 b == ex->ee_block + ex->ee_len - 1);
++              }
++
++              if (ex == EXT_FIRST_EXTENT(eh))
++                      correct_index = 1;
++
++              credits = 1;
++              if (correct_index)
++                      credits += (EXT_DEPTH(tree) * EXT3_ALLOC_NEEDED) + 1;
++              if (tree->ops->remove_extent_credits)
++                      credits+=tree->ops->remove_extent_credits(tree,ex,a,b);
++              
++              handle = ext3_ext_journal_restart(handle, credits);
++              if (IS_ERR(handle)) {
++                      err = PTR_ERR(handle);
++                      goto out;
++              }
++
++              err = ext3_ext_get_access(handle, tree, path + depth);
++              if (err)
++                      goto out;
++
++              if (tree->ops->remove_extent)
++                      err = tree->ops->remove_extent(tree, ex, a, b);
++              if (err)
++                      goto out;
++
++              if (num == 0) {
++                      /* this extent is removed entirely mark slot unused */
++                      ex->ee_start = 0;
++                      eh->eh_entries--;
++                      fu = ex;
++              }
++
++              ex->ee_block = block;
++              ex->ee_len = num;
++
++              err = ext3_ext_dirty(handle, tree, path + depth);
++              if (err)
++                      goto out;
++
++              ext_debug(tree, "new extent: %u:%u:%u\n",
++                        ex->ee_block, ex->ee_len, ex->ee_start);
++              ex--;
++      }
++
++      if (fu) {
++              /* reuse unused slots */
++              while (lu < le) {
++                      if (lu->ee_start) {
++                              *fu = *lu;
++                              lu->ee_start = 0;
++                              fu++;
++                      }
++                      lu++;
++              }
++      }
++
++      if (correct_index && eh->eh_entries)
++              err = ext3_ext_correct_indexes(handle, tree, path);
++
++      /* if this leaf is free, then we should
++       * remove it from index block above */
++      if (err == 0 && eh->eh_entries == 0 && path[depth].p_bh != NULL)
++              err = ext3_ext_rm_idx(handle, tree, path + depth);
++
++out:
++      return err;
++}
++
++
++static struct ext3_extent_idx *
++ext3_ext_last_covered(struct ext3_extent_header *hdr, unsigned long block)
++{
++      struct ext3_extent_idx *ix;
++      
++      ix = EXT_LAST_INDEX(hdr);
++      while (ix != EXT_FIRST_INDEX(hdr)) {
++              if (ix->ei_block <= block)
++                      break;
++              ix--;
++      }
++      return ix;
++}
++
++/*
++ * returns 1 if current index have to be freed (even partial)
++ */
++static int inline
++ext3_ext_more_to_rm(struct ext3_ext_path *path)
++{
++      EXT_ASSERT(path->p_idx);
++
++      if (path->p_idx < EXT_FIRST_INDEX(path->p_hdr))
++              return 0;
++
++      /*
++       * if truncate on deeper level happened it it wasn't partial
++       * so we have to consider current index for truncation
++       */
++      if (path->p_hdr->eh_entries == path->p_block)
++              return 0;
++      return 1;
++}
++
++int ext3_ext_remove_space(struct ext3_extents_tree *tree,
++                        unsigned long start, unsigned long end)
++{
++      struct inode *inode = tree->inode;
++      struct super_block *sb = inode->i_sb;
++      int depth = EXT_DEPTH(tree);
++      struct ext3_ext_path *path;
++      handle_t *handle;
++      int i = 0, err = 0;
++
++      ext_debug(tree, "space to be removed: %lu:%lu\n", start, end);
++
++      /* probably first extent we're gonna free will be last in block */
++      handle = ext3_journal_start(inode, depth + 1);
++      if (IS_ERR(handle))
++              return PTR_ERR(handle);
++
++      ext3_ext_invalidate_cache(tree);
++
++      /*
++       * we start scanning from right side freeing all the blocks
++       * after i_size and walking into the deep
++       */
++      path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 1), GFP_KERNEL);
++      if (IS_ERR(path)) {
++              ext3_error(sb, __FUNCTION__, "Can't allocate path array");
++              ext3_journal_stop(handle);
++              return -ENOMEM;
++      }
++      memset(path, 0, sizeof(struct ext3_ext_path) * (depth + 1));
++      path[i].p_hdr = EXT_ROOT_HDR(tree);
++      
++      while (i >= 0 && err == 0) {
++              if (i == depth) {
++                      /* this is leaf block */
++                      err = ext3_ext_rm_leaf(handle, tree, path, start, end);
++                      /* root level have p_bh == NULL, brelse() eats this */
++                      brelse(path[i].p_bh);
++                      i--;
++                      continue;
++              }
++              
++              /* this is index block */
++              if (!path[i].p_hdr) {
++                      ext_debug(tree, "initialize header\n");
++                      path[i].p_hdr = EXT_BLOCK_HDR(path[i].p_bh);
++              }
++
++              EXT_ASSERT(path[i].p_hdr->eh_entries <= path[i].p_hdr->eh_max);
++              EXT_ASSERT(path[i].p_hdr->eh_magic == EXT3_EXT_MAGIC);
++              
++              if (!path[i].p_idx) {
++                      /* this level hasn't touched yet */
++                      path[i].p_idx =
++                              ext3_ext_last_covered(path[i].p_hdr, end);
++                      path[i].p_block = path[i].p_hdr->eh_entries + 1;
++                      ext_debug(tree, "init index ptr: hdr 0x%p, num %d\n",
++                                path[i].p_hdr, path[i].p_hdr->eh_entries);
++              } else {
++                      /* we've already was here, see at next index */
++                      path[i].p_idx--;
++              }
++
++              ext_debug(tree, "level %d - index, first 0x%p, cur 0x%p\n",
++                        i, EXT_FIRST_INDEX(path[i].p_hdr),
++                        path[i].p_idx);
++              if (ext3_ext_more_to_rm(path + i)) {
++                      /* go to the next level */
++                      ext_debug(tree, "move to level %d (block %d)\n",
++                                i + 1, path[i].p_idx->ei_leaf);
++                      memset(path + i + 1, 0, sizeof(*path));
++                      path[i+1].p_bh = sb_bread(sb, path[i].p_idx->ei_leaf);
++                      if (!path[i+1].p_bh) {
++                              /* should we reset i_size? */
++                              err = -EIO;
++                              break;
++                      }
++                      /* put actual number of indexes to know is this
++                       * number got changed at the next iteration */
++                      path[i].p_block = path[i].p_hdr->eh_entries;
++                      i++;
++              } else {
++                      /* we finish processing this index, go up */
++                      if (path[i].p_hdr->eh_entries == 0 && i > 0) {
++                              /* index is empty, remove it
++                               * handle must be already prepared by the
++                               * truncatei_leaf() */
++                              err = ext3_ext_rm_idx(handle, tree, path + i);
++                      }
++                      /* root level have p_bh == NULL, brelse() eats this */
++                      brelse(path[i].p_bh);
++                      i--;
++                      ext_debug(tree, "return to level %d\n", i);
++              }
++      }
++
++      /* TODO: flexible tree reduction should be here */
++      if (path->p_hdr->eh_entries == 0) {
++              /*
++               * truncate to zero freed all the tree
++               * so, we need to correct eh_depth
++               */
++              err = ext3_ext_get_access(handle, tree, path);
++              if (err == 0) {
++                      EXT_ROOT_HDR(tree)->eh_depth = 0;
++                      EXT_ROOT_HDR(tree)->eh_max = ext3_ext_space_root(tree);
++                      err = ext3_ext_dirty(handle, tree, path);
++              }
++      }
++      ext3_ext_tree_changed(tree);
++
++      kfree(path);
++      ext3_journal_stop(handle);
++
++      return err;
++}
++
++int ext3_ext_calc_metadata_amount(struct ext3_extents_tree *tree, int blocks)
++{
++      int lcap, icap, rcap, leafs, idxs, num;
++
++      rcap = ext3_ext_space_root(tree);
++      if (blocks <= rcap) {
++              /* all extents fit to the root */
++              return 0;
++      }
++
++      rcap = ext3_ext_space_root_idx(tree);
++      lcap = ext3_ext_space_block(tree);
++      icap = ext3_ext_space_block_idx(tree);
++
++      num = leafs = (blocks + lcap - 1) / lcap;
++      if (leafs <= rcap) {
++              /* all pointers to leafs fit to the root */
++              return leafs;
++      }
++
++      /* ok. we need separate index block(s) to link all leaf blocks */
++      idxs = (leafs + icap - 1) / icap;
++      do {
++              num += idxs;
++              idxs = (idxs + icap - 1) / icap;
++      } while (idxs > rcap);
++
++      return num;
++}
++
++/*
++ * called at mount time
++ */
++void ext3_ext_init(struct super_block *sb)
++{
++      /*
++       * possible initialization would be here
++       */
++
++      if (test_opt(sb, EXTENTS)) {
++              printk("EXT3-fs: file extents enabled");
++#ifdef AGRESSIVE_TEST
++              printk(", agressive tests");
++#endif
++#ifdef CHECK_BINSEARCH
++              printk(", check binsearch");
++#endif
++              printk("\n");
++      }
++}
++
++/*
++ * called at umount time
++ */
++void ext3_ext_release(struct super_block *sb)
++{
++}
++
++/************************************************************************
++ * VFS related routines
++ ************************************************************************/
++
++static int ext3_get_inode_write_access(handle_t *handle, void *buffer)
++{
++      /* we use in-core data, not bh */
++      return 0;
++}
++
++static int ext3_mark_buffer_dirty(handle_t *handle, void *buffer)
++{
++      struct inode *inode = buffer;
++      return ext3_mark_inode_dirty(handle, inode);
++}
++
++static int ext3_ext_mergable(struct ext3_extent *ex1,
++                           struct ext3_extent *ex2)
++{
++      /* FIXME: support for large fs */
++      if (ex1->ee_start + ex1->ee_len == ex2->ee_start)
++              return 1;
++      return 0;
++}
++
++static int
++ext3_remove_blocks_credits(struct ext3_extents_tree *tree,
++                         struct ext3_extent *ex,
++                         unsigned long from, unsigned long to)
++{
++      int needed;
++      
++      /* at present, extent can't cross block group */;
++      needed = 4; /* bitmap + group desc + sb + inode */
++
++#ifdef CONFIG_QUOTA
++      needed += 2 * EXT3_SINGLEDATA_TRANS_BLOCKS;
++#endif
++      return needed;
++}
++
++static int
++ext3_remove_blocks(struct ext3_extents_tree *tree,
++                 struct ext3_extent *ex,
++                 unsigned long from, unsigned long to)
++{
++      int needed = ext3_remove_blocks_credits(tree, ex, from, to);
++      handle_t *handle = ext3_journal_start(tree->inode, needed);
++      struct buffer_head *bh;
++      int i;
++
++      if (IS_ERR(handle))
++              return PTR_ERR(handle);
++      if (from >= ex->ee_block && to == ex->ee_block + ex->ee_len - 1) {
++              /* tail removal */
++              unsigned long num, start;
++              num = ex->ee_block + ex->ee_len - from;
++              start = ex->ee_start + ex->ee_len - num;
++              ext_debug(tree, "free last %lu blocks starting %lu\n",
++                        num, start);
++              for (i = 0; i < num; i++) {
++                      bh = sb_find_get_block(tree->inode->i_sb, start + i);
++                      ext3_forget(handle, 0, tree->inode, bh, start + i);
++              }
++              ext3_free_blocks(handle, tree->inode, start, num);
++      } else if (from == ex->ee_block && to <= ex->ee_block + ex->ee_len - 1) {
++              printk("strange request: removal %lu-%lu from %u:%u\n",
++                     from, to, ex->ee_block, ex->ee_len);
++      } else {
++              printk("strange request: removal(2) %lu-%lu from %u:%u\n",
++                     from, to, ex->ee_block, ex->ee_len);
++      }
++      ext3_journal_stop(handle);
++      return 0;
++}
++
++static int ext3_ext_find_goal(struct inode *inode,
++                            struct ext3_ext_path *path, unsigned long block)
++{
++      struct ext3_inode_info *ei = EXT3_I(inode);
++      unsigned long bg_start;
++      unsigned long colour;
++      int depth;
++      
++      if (path) {
++              struct ext3_extent *ex;
++              depth = path->p_depth;
++              
++              /* try to predict block placement */
++              if ((ex = path[depth].p_ext))
++                      return ex->ee_start + (block - ex->ee_block);
++
++              /* it looks index is empty
++               * try to find starting from index itself */
++              if (path[depth].p_bh)
++                      return path[depth].p_bh->b_blocknr;
++      }
++
++      /* OK. use inode's group */
++      bg_start = (ei->i_block_group * EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
++              le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block);
++      colour = (current->pid % 16) *
++                      (EXT3_BLOCKS_PER_GROUP(inode->i_sb) / 16);
++      return bg_start + colour + block;
++}
++
++static int ext3_new_block_cb(handle_t *handle, struct ext3_extents_tree *tree,
++                           struct ext3_ext_path *path,
++                           struct ext3_extent *ex, int *err)
++{
++      struct inode *inode = tree->inode;
++      int newblock, goal;
++      
++      EXT_ASSERT(path);
++      EXT_ASSERT(ex);
++      EXT_ASSERT(ex->ee_start);
++      EXT_ASSERT(ex->ee_len);
++      
++      /* reuse block from the extent to order data/metadata */
++      newblock = ex->ee_start++;
++      ex->ee_len--;
++      if (ex->ee_len == 0) {
++              ex->ee_len = 1;
++              /* allocate new block for the extent */
++              goal = ext3_ext_find_goal(inode, path, ex->ee_block);
++              ex->ee_start = ext3_new_block(handle, inode, goal, err);
++              if (ex->ee_start == 0) {
++                      /* error occured: restore old extent */
++                      ex->ee_start = newblock;
++                      return 0;
++              }
++      }
++      return newblock;
++}
++
++static struct ext3_extents_helpers ext3_blockmap_helpers = {
++      .get_write_access       = ext3_get_inode_write_access,
++      .mark_buffer_dirty      = ext3_mark_buffer_dirty,
++      .mergable               = ext3_ext_mergable,
++      .new_block              = ext3_new_block_cb,
++      .remove_extent          = ext3_remove_blocks,
++      .remove_extent_credits  = ext3_remove_blocks_credits,
++};
++
++void ext3_init_tree_desc(struct ext3_extents_tree *tree,
++                       struct inode *inode)
++{
++      tree->inode = inode;
++      tree->root = (void *) EXT3_I(inode)->i_data;
++      tree->buffer = (void *) inode;
++      tree->buffer_len = sizeof(EXT3_I(inode)->i_data);
++      tree->cex = (struct ext3_ext_cache *) &EXT3_I(inode)->i_cached_extent;
++      tree->ops = &ext3_blockmap_helpers;
++}
++
++int ext3_ext_get_block(handle_t *handle, struct inode *inode,
++                     long iblock, struct buffer_head *bh_result,
++                     int create, int extend_disksize)
++{
++      struct ext3_ext_path *path = NULL;
++      struct ext3_extent newex;
++      struct ext3_extent *ex;
++      int goal, newblock, err = 0, depth;
++      struct ext3_extents_tree tree;
++
++      clear_buffer_new(bh_result);
++      ext3_init_tree_desc(&tree, inode);
++      ext_debug(&tree, "block %d requested for inode %u\n",
++                (int) iblock, (unsigned) inode->i_ino);
++      down(&EXT3_I(inode)->truncate_sem);
++
++      /* check in cache */
++      if ((goal = ext3_ext_in_cache(&tree, iblock, &newex))) {
++              if (goal == EXT3_EXT_CACHE_GAP) {
++                      if (!create) {
++                              /* block isn't allocated yet and
++                               * user don't want to allocate it */
++                              goto out2;
++                      }
++                      /* we should allocate requested block */
++              } else if (goal == EXT3_EXT_CACHE_EXTENT) {
++                      /* block is already allocated */
++                      newblock = iblock - newex.ee_block + newex.ee_start;
++                      goto out;
++              } else {
++                      EXT_ASSERT(0);
++              }
++      }
++
++      /* find extent for this block */
++      path = ext3_ext_find_extent(&tree, iblock, NULL);
++      if (IS_ERR(path)) {
++              err = PTR_ERR(path);
++              path = NULL;
++              goto out2;
++      }
++
++      depth = EXT_DEPTH(&tree);
++
++      /*
++       * consistent leaf must not be empty
++       * this situations is possible, though, _during_ tree modification
++       * this is why assert can't be put in ext3_ext_find_extent()
++       */
++      EXT_ASSERT(path[depth].p_ext != NULL || depth == 0);
++
++      if ((ex = path[depth].p_ext)) {
++              /* if found exent covers block, simple return it */
++              if (iblock >= ex->ee_block && iblock < ex->ee_block + ex->ee_len) {
++                      newblock = iblock - ex->ee_block + ex->ee_start;
++                      ext_debug(&tree, "%d fit into %d:%d -> %d\n",
++                                (int) iblock, ex->ee_block, ex->ee_len,
++                                newblock);
++                      ext3_ext_put_in_cache(&tree, ex->ee_block,
++                                            ex->ee_len, ex->ee_start,
++                                            EXT3_EXT_CACHE_EXTENT);
++                      goto out;
++              }
++      }
++
++      /*
++       * requested block isn't allocated yet
++       * we couldn't try to create block if create flag is zero 
++       */
++      if (!create) {
++              /* put just found gap into cache to speedup subsequest reqs */
++              ext3_ext_put_gap_in_cache(&tree, path, iblock);
++              goto out2;
++      }
++
++      /* allocate new block */
++      goal = ext3_ext_find_goal(inode, path, iblock);
++      newblock = ext3_new_block(handle, inode, goal, &err);
++      if (!newblock)
++              goto out2;
++      ext_debug(&tree, "allocate new block: goal %d, found %d\n",
++                goal, newblock);
++
++      /* try to insert new extent into found leaf and return */
++      newex.ee_block = iblock;
++      newex.ee_start = newblock;
++      newex.ee_len = 1;
++      err = ext3_ext_insert_extent(handle, &tree, path, &newex);
++      if (err)
++              goto out2;
++      
++      if (extend_disksize && inode->i_size > EXT3_I(inode)->i_disksize)
++              EXT3_I(inode)->i_disksize = inode->i_size;
++
++      /* previous routine could use block we allocated */
++      newblock = newex.ee_start;
++      set_buffer_new(bh_result);
++
++      ext3_ext_put_in_cache(&tree, newex.ee_block, newex.ee_len,
++                            newex.ee_start, EXT3_EXT_CACHE_EXTENT);
++out:
++      ext3_ext_show_leaf(&tree, path);
++      map_bh(bh_result, inode->i_sb, newblock);
++out2:
++      if (path) {
++              ext3_ext_drop_refs(path);
++              kfree(path);
++      }
++      up(&EXT3_I(inode)->truncate_sem);
++
++      return err;     
++}
++
++void ext3_ext_truncate(struct inode * inode, struct page *page)
++{
++      struct address_space *mapping = inode->i_mapping;
++      struct super_block *sb = inode->i_sb;
++      struct ext3_extents_tree tree;
++      unsigned long last_block;
++      handle_t *handle;
++      int err = 0;
++
++      ext3_init_tree_desc(&tree, inode);
++
++      /*
++       * probably first extent we're gonna free will be last in block
++       */
++      err = ext3_writepage_trans_blocks(inode) + 3;
++      handle = ext3_journal_start(inode, err);
++      if (IS_ERR(handle)) {
++              if (page) {
++                      clear_highpage(page);
++                      flush_dcache_page(page);
++                      unlock_page(page);
++                      page_cache_release(page);
++              }
++              return;
++      }
++
++      if (page)
++              ext3_block_truncate_page(handle, page, mapping, inode->i_size);
++
++      down(&EXT3_I(inode)->truncate_sem);
++      ext3_ext_invalidate_cache(&tree);
++
++      /* 
++       * TODO: optimization is possible here
++       * probably we need not scaning at all,
++       * because page truncation is enough
++       */
++      if (ext3_orphan_add(handle, inode))
++              goto out_stop;
++
++      /* we have to know where to truncate from in crash case */
++      EXT3_I(inode)->i_disksize = inode->i_size;
++      ext3_mark_inode_dirty(handle, inode);
++
++      last_block = (inode->i_size + sb->s_blocksize - 1) >>
++                      EXT3_BLOCK_SIZE_BITS(sb);
++      err = ext3_ext_remove_space(&tree, last_block, EXT_MAX_BLOCK);
++      
++      /* In a multi-transaction truncate, we only make the final
++       * transaction synchronous */
++      if (IS_SYNC(inode))
++              handle->h_sync = 1;
++
++out_stop:
++      /*
++       * If this was a simple ftruncate(), and the file will remain alive
++       * then we need to clear up the orphan record which we created above.
++       * However, if this was a real unlink then we were called by
++       * ext3_delete_inode(), and we allow that function to clean up the
++       * orphan info for us.
++       */
++      if (inode->i_nlink)
++              ext3_orphan_del(handle, inode);
++
++      up(&EXT3_I(inode)->truncate_sem);
++      ext3_journal_stop(handle);
++}
++
++/*
++ * this routine calculate max number of blocks we could modify
++ * in order to allocate new block for an inode
++ */
++int ext3_ext_writepage_trans_blocks(struct inode *inode, int num)
++{
++      struct ext3_extents_tree tree;
++      int needed;
++      
++      ext3_init_tree_desc(&tree, inode);
++      
++      needed = ext3_ext_calc_credits_for_insert(&tree, NULL);
++
++      /* caller want to allocate num blocks */
++      needed *= num;
++      
++#ifdef CONFIG_QUOTA
++      /* 
++       * FIXME: real calculation should be here
++       * it depends on blockmap format of qouta file
++       */
++      needed += 2 * EXT3_SINGLEDATA_TRANS_BLOCKS;
++#endif
++
++      return needed;
++}
++
++void ext3_extents_initialize_blockmap(handle_t *handle, struct inode *inode)
++{
++      struct ext3_extents_tree tree;
++
++      ext3_init_tree_desc(&tree, inode);
++      ext3_extent_tree_init(handle, &tree);
++}
++
++int ext3_ext_calc_blockmap_metadata(struct inode *inode, int blocks)
++{
++      struct ext3_extents_tree tree;
++
++      ext3_init_tree_desc(&tree, inode);
++      return ext3_ext_calc_metadata_amount(&tree, blocks);
++}
++      
++static int
++ext3_ext_store_extent_cb(struct ext3_extents_tree *tree,
++                       struct ext3_ext_path *path,
++                       struct ext3_ext_cache *newex)
++{
++      struct ext3_extent_buf *buf = (struct ext3_extent_buf *) tree->private;
++
++      if (newex->ec_type != EXT3_EXT_CACHE_EXTENT)
++              return EXT_CONTINUE;
++
++      if (buf->err < 0)
++              return EXT_BREAK;
++      if (buf->cur - buf->buffer + sizeof(*newex) > buf->buflen)
++              return EXT_BREAK;
++
++      if (!copy_to_user(buf->cur, newex, sizeof(*newex))) {
++              buf->err++;
++              buf->cur += sizeof(*newex);
++      } else {
++              buf->err = -EFAULT;
++              return EXT_BREAK;
++      }
++      return EXT_CONTINUE;
++}
++
++static int
++ext3_ext_collect_stats_cb(struct ext3_extents_tree *tree,
++                        struct ext3_ext_path *path,
++                        struct ext3_ext_cache *ex)
++{
++      struct ext3_extent_tree_stats *buf =
++              (struct ext3_extent_tree_stats *) tree->private;
++      int depth;
++
++      if (ex->ec_type != EXT3_EXT_CACHE_EXTENT)
++              return EXT_CONTINUE;
++
++      depth = EXT_DEPTH(tree);
++      buf->extents_num++;
++      if (path[depth].p_ext == EXT_FIRST_EXTENT(path[depth].p_hdr))
++              buf->leaf_num++;
++      return EXT_CONTINUE;
++}
++
++int ext3_ext_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
++                 unsigned long arg)
++{
++      int err = 0;
++
++      if (!(EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL))
++              return -EINVAL;
++
++      if (cmd == EXT3_IOC_GET_EXTENTS) {
++              struct ext3_extent_buf buf;
++              struct ext3_extents_tree tree;
++
++              if (copy_from_user(&buf, (void *) arg, sizeof(buf)))
++                      return -EFAULT;
++
++              ext3_init_tree_desc(&tree, inode);
++              buf.cur = buf.buffer;
++              buf.err = 0;
++              tree.private = &buf;
++              down(&EXT3_I(inode)->truncate_sem);
++              err = ext3_ext_walk_space(&tree, buf.start, EXT_MAX_BLOCK,
++                                        ext3_ext_store_extent_cb);
++              up(&EXT3_I(inode)->truncate_sem);
++              if (err == 0)
++                      err = buf.err;
++      } else if (cmd == EXT3_IOC_GET_TREE_STATS) {
++              struct ext3_extent_tree_stats buf;
++              struct ext3_extents_tree tree;
++
++              ext3_init_tree_desc(&tree, inode);
++              down(&EXT3_I(inode)->truncate_sem);
++              buf.depth = EXT_DEPTH(&tree);
++              buf.extents_num = 0;
++              buf.leaf_num = 0;
++              tree.private = &buf;
++              err = ext3_ext_walk_space(&tree, 0, EXT_MAX_BLOCK,
++                                        ext3_ext_collect_stats_cb);
++              up(&EXT3_I(inode)->truncate_sem);
++              if (!err)
++                      err = copy_to_user((void *) arg, &buf, sizeof(buf));
++      } else if (cmd == EXT3_IOC_GET_TREE_DEPTH) {
++              struct ext3_extents_tree tree;
++              ext3_init_tree_desc(&tree, inode);
++              down(&EXT3_I(inode)->truncate_sem);
++              err = EXT_DEPTH(&tree);
++              up(&EXT3_I(inode)->truncate_sem);
++      }
++
++      return err;
++}
++
++EXPORT_SYMBOL(ext3_init_tree_desc);
++EXPORT_SYMBOL(ext3_mark_inode_dirty);
++EXPORT_SYMBOL(ext3_ext_invalidate_cache);
++EXPORT_SYMBOL(ext3_ext_insert_extent);
++EXPORT_SYMBOL(ext3_ext_walk_space);
++EXPORT_SYMBOL(ext3_ext_find_goal);
++EXPORT_SYMBOL(ext3_ext_calc_credits_for_insert);
+Index: linux-2.6.16.21-0.8/fs/ext3/ialloc.c
+===================================================================
+--- linux-2.6.16.21-0.8.orig/fs/ext3/ialloc.c
++++ linux-2.6.16.21-0.8/fs/ext3/ialloc.c
+@@ -598,7 +598,7 @@ got:
+       ei->i_dir_start_lookup = 0;
+       ei->i_disksize = 0;
+-      ei->i_flags = EXT3_I(dir)->i_flags & ~EXT3_INDEX_FL;
++      ei->i_flags = EXT3_I(dir)->i_flags & ~(EXT3_INDEX_FL|EXT3_EXTENTS_FL);
+       if (S_ISLNK(mode))
+               ei->i_flags &= ~(EXT3_IMMUTABLE_FL|EXT3_APPEND_FL);
+       /* dirsync only applies to directories */
+@@ -642,6 +642,18 @@ got:
+       if (err)
+               goto fail_free_drop;
++      if (test_opt(sb, EXTENTS) && S_ISREG(inode->i_mode)) {
++              EXT3_I(inode)->i_flags |= EXT3_EXTENTS_FL;
++              ext3_extents_initialize_blockmap(handle, inode);
++              if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_EXTENTS)) {
++                      err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
++                      if (err) goto fail;
++                      EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_EXTENTS);
++                      BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "call ext3_journal_dirty_metadata");
++                      err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
++              }
++      }
++
+       err = ext3_mark_inode_dirty(handle, inode);
+       if (err) {
+               ext3_std_error(sb, err);
+Index: linux-2.6.16.21-0.8/fs/ext3/inode.c
+===================================================================
+--- linux-2.6.16.21-0.8.orig/fs/ext3/inode.c
++++ linux-2.6.16.21-0.8/fs/ext3/inode.c
+@@ -40,7 +40,7 @@
+ #include "iopen.h"
+ #include "acl.h"
+-static int ext3_writepage_trans_blocks(struct inode *inode);
++int ext3_writepage_trans_blocks(struct inode *inode);
+ /*
+  * Test whether an inode is a fast symlink.
+@@ -788,6 +788,17 @@ out:
+       return err;
+ }
++static inline int
++ext3_get_block_wrap(handle_t *handle, struct inode *inode, long block,
++                  struct buffer_head *bh, int create, int extend_disksize)
++{
++      if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
++              return ext3_ext_get_block(handle, inode, block, bh, create,
++                                        extend_disksize);
++      return ext3_get_block_handle(handle, inode, block, bh, create,
++                                   extend_disksize);
++}
++
+ static int ext3_get_block(struct inode *inode, sector_t iblock,
+                       struct buffer_head *bh_result, int create)
+ {
+@@ -798,8 +809,8 @@ static int ext3_get_block(struct inode *
+               handle = ext3_journal_current_handle();
+               J_ASSERT(handle != 0);
+       }
+-      ret = ext3_get_block_handle(handle, inode, iblock,
+-                              bh_result, create, 1);
++      ret = ext3_get_block_wrap(handle, inode, iblock,
++                                bh_result, create, 1);
+       return ret;
+ }
+@@ -843,7 +854,7 @@ ext3_direct_io_get_blocks(struct inode *
+ get_block:
+       if (ret == 0)
+-              ret = ext3_get_block_handle(handle, inode, iblock,
++              ret = ext3_get_block_wrap(handle, inode, iblock,
+                                       bh_result, create, 0);
+       bh_result->b_size = (1 << inode->i_blkbits);
+       return ret;
+@@ -863,7 +874,7 @@ struct buffer_head *ext3_getblk(handle_t
+       dummy.b_state = 0;
+       dummy.b_blocknr = -1000;
+       buffer_trace_init(&dummy.b_history);
+-      *errp = ext3_get_block_handle(handle, inode, block, &dummy, create, 1);
++      *errp = ext3_get_block_wrap(handle, inode, block, &dummy, create, 1);
+       if (!*errp && buffer_mapped(&dummy)) {
+               struct buffer_head *bh;
+               bh = sb_getblk(inode->i_sb, dummy.b_blocknr);
+@@ -1606,7 +1617,7 @@ void ext3_set_aops(struct inode *inode)
+  * This required during truncate. We need to physically zero the tail end
+  * of that block so it doesn't yield old data if the file is later grown.
+  */
+-static int ext3_block_truncate_page(handle_t *handle, struct page *page,
++int ext3_block_truncate_page(handle_t *handle, struct page *page,
+               struct address_space *mapping, loff_t from)
+ {
+       unsigned long index = from >> PAGE_CACHE_SHIFT;
+@@ -2116,6 +2127,9 @@ void ext3_truncate(struct inode * inode)
+                       return;
+       }
++      if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
++              return ext3_ext_truncate(inode, page);
++
+       handle = start_transaction(inode);
+       if (IS_ERR(handle)) {
+               if (page) {
+@@ -2863,12 +2877,15 @@ err_out:
+  * block and work out the exact number of indirects which are touched.  Pah.
+  */
+-static int ext3_writepage_trans_blocks(struct inode *inode)
++int ext3_writepage_trans_blocks(struct inode *inode)
+ {
+       int bpp = ext3_journal_blocks_per_page(inode);
+       int indirects = (EXT3_NDIR_BLOCKS % bpp) ? 5 : 3;
+       int ret;
++      if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
++              return ext3_ext_writepage_trans_blocks(inode, bpp);
++
+       if (ext3_should_journal_data(inode))
+               ret = 3 * (bpp + indirects) + 2;
+       else
+Index: linux-2.6.16.21-0.8/fs/ext3/Makefile
+===================================================================
+--- linux-2.6.16.21-0.8.orig/fs/ext3/Makefile
++++ linux-2.6.16.21-0.8/fs/ext3/Makefile
+@@ -5,7 +5,8 @@
+ obj-$(CONFIG_EXT3_FS) += ext3.o
+ ext3-y        := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
+-         ioctl.o namei.o super.o symlink.o hash.o resize.o
++         ioctl.o namei.o super.o symlink.o hash.o resize.o \
++         extents.o
+ ext3-$(CONFIG_EXT3_FS_XATTR)   += xattr.o xattr_user.o xattr_trusted.o
+ ext3-$(CONFIG_EXT3_FS_POSIX_ACL) += acl.o
+Index: linux-2.6.16.21-0.8/fs/ext3/super.c
+===================================================================
+--- linux-2.6.16.21-0.8.orig/fs/ext3/super.c
++++ linux-2.6.16.21-0.8/fs/ext3/super.c
+@@ -392,6 +392,7 @@ static void ext3_put_super (struct super
+       struct ext3_super_block *es = sbi->s_es;
+       int i;
++      ext3_ext_release(sb);
+       ext3_xattr_put_super(sb);
+       journal_destroy(sbi->s_journal);
+       if (!(sb->s_flags & MS_RDONLY)) {
+@@ -456,6 +457,8 @@ static struct inode *ext3_alloc_inode(st
+ #endif
+       ei->i_block_alloc_info = NULL;
+       ei->vfs_inode.i_version = 1;
++      
++      memset(&ei->i_cached_extent, 0, sizeof(ei->i_cached_extent));
+       return &ei->vfs_inode;
+ }
+@@ -638,6 +641,7 @@ enum {
+       Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
+       Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
+       Opt_iopen, Opt_noiopen, Opt_iopen_nopriv,
++      Opt_extents, Opt_extdebug,
+       Opt_grpquota
+ };
+@@ -689,6 +693,8 @@ static match_table_t tokens = {
+       {Opt_iopen, "iopen"},
+       {Opt_noiopen, "noiopen"},
+       {Opt_iopen_nopriv, "iopen_nopriv"},
++      {Opt_extents, "extents"},
++      {Opt_extdebug, "extdebug"},
+       {Opt_barrier, "barrier=%u"},
+       {Opt_err, NULL},
+       {Opt_resize, "resize"},
+@@ -1030,6 +1036,12 @@ clear_qf_name:
+               case Opt_nobh:
+                       set_opt(sbi->s_mount_opt, NOBH);
+                       break;
++              case Opt_extents:
++                      set_opt (sbi->s_mount_opt, EXTENTS);
++                      break;
++              case Opt_extdebug:
++                      set_opt (sbi->s_mount_opt, EXTDEBUG);
++                      break;
+               default:
+                       printk (KERN_ERR
+                               "EXT3-fs: Unrecognized mount option \"%s\" "
+@@ -1756,6 +1768,7 @@ static int ext3_fill_super (struct super
+       percpu_counter_mod(&sbi->s_dirs_counter,
+               ext3_count_dirs(sb));
++      ext3_ext_init(sb);
+       lock_kernel();
+       return 0;
+Index: linux-2.6.16.21-0.8/fs/ext3/ioctl.c
+===================================================================
+--- linux-2.6.16.21-0.8.orig/fs/ext3/ioctl.c
++++ linux-2.6.16.21-0.8/fs/ext3/ioctl.c
+@@ -125,6 +125,10 @@ flags_err:
+                       err = ext3_change_inode_journal_flag(inode, jflag);
+               return err;
+       }
++      case EXT3_IOC_GET_EXTENTS:
++      case EXT3_IOC_GET_TREE_STATS:
++      case EXT3_IOC_GET_TREE_DEPTH:
++              return ext3_ext_ioctl(inode, filp, cmd, arg);
+       case EXT3_IOC_GETVERSION:
+       case EXT3_IOC_GETVERSION_OLD:
+               return put_user(inode->i_generation, (int __user *) arg);
+Index: linux-2.6.16.21-0.8/include/linux/ext3_fs.h
+===================================================================
+--- linux-2.6.16.21-0.8.orig/include/linux/ext3_fs.h
++++ linux-2.6.16.21-0.8/include/linux/ext3_fs.h
+@@ -185,9 +185,10 @@ struct ext3_group_desc
+ #define EXT3_NOTAIL_FL                        0x00008000 /* file tail should not be merged */
+ #define EXT3_DIRSYNC_FL                       0x00010000 /* dirsync behaviour (directories only) */
+ #define EXT3_TOPDIR_FL                        0x00020000 /* Top of directory hierarchies*/
++#define EXT3_EXTENTS_FL                       0x00080000 /* Inode uses extents */
+ #define EXT3_RESERVED_FL              0x80000000 /* reserved for ext3 lib */
+-#define EXT3_FL_USER_VISIBLE          0x0003DFFF /* User visible flags */
++#define EXT3_FL_USER_VISIBLE          0x000BDFFF /* User visible flags */
+ #define EXT3_FL_USER_MODIFIABLE               0x000380FF /* User modifiable flags */
+ /*
+@@ -237,6 +238,9 @@ struct ext3_new_group_data {
+ #endif
+ #define EXT3_IOC_GETRSVSZ             _IOR('f', 5, long)
+ #define EXT3_IOC_SETRSVSZ             _IOW('f', 6, long)
++#define EXT3_IOC_GET_EXTENTS          _IOR('f', 7, long)
++#define EXT3_IOC_GET_TREE_DEPTH               _IOR('f', 8, long)
++#define EXT3_IOC_GET_TREE_STATS               _IOR('f', 9, long)
+ /*
+  *  Mount options
+@@ -377,6 +381,8 @@ struct ext3_inode {
+ #define EXT3_MOUNT_GRPQUOTA           0x200000 /* "old" group quota */
+ #define EXT3_MOUNT_IOPEN              0x400000        /* Allow access via iopen */
+ #define EXT3_MOUNT_IOPEN_NOPRIV               0x800000/* Make iopen world-readable */
++#define EXT3_MOUNT_EXTENTS            0x1000000/* Extents support */
++#define EXT3_MOUNT_EXTDEBUG           0x2000000/* Extents debug */
+ /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
+ #ifndef clear_opt
+@@ -565,11 +571,13 @@ static inline struct ext3_inode_info *EX
+ #define EXT3_FEATURE_INCOMPAT_RECOVER         0x0004 /* Needs recovery */
+ #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV     0x0008 /* Journal device */
+ #define EXT3_FEATURE_INCOMPAT_META_BG         0x0010
++#define EXT3_FEATURE_INCOMPAT_EXTENTS         0x0040 /* extents support */
+ #define EXT3_FEATURE_COMPAT_SUPP      EXT2_FEATURE_COMPAT_EXT_ATTR
+ #define EXT3_FEATURE_INCOMPAT_SUPP    (EXT3_FEATURE_INCOMPAT_FILETYPE| \
+                                        EXT3_FEATURE_INCOMPAT_RECOVER| \
+-                                       EXT3_FEATURE_INCOMPAT_META_BG)
++                                       EXT3_FEATURE_INCOMPAT_META_BG| \
++                                       EXT3_FEATURE_INCOMPAT_EXTENTS)
+ #define EXT3_FEATURE_RO_COMPAT_SUPP   (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
+                                        EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \
+                                        EXT3_FEATURE_RO_COMPAT_BTREE_DIR)
+@@ -776,6 +784,7 @@ extern unsigned long ext3_count_free (st
+ /* inode.c */
++extern int ext3_block_truncate_page(handle_t *, struct page *, struct address_space *, loff_t);
+ extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int);
+ extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
+ extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
+@@ -792,6 +801,7 @@ extern int ext3_get_inode_loc(struct ino
+ extern void ext3_truncate (struct inode *);
+ extern void ext3_set_inode_flags(struct inode *);
+ extern void ext3_set_aops(struct inode *inode);
++extern int ext3_writepage_trans_blocks(struct inode *inode);
+ /* ioctl.c */
+ extern int ext3_ioctl (struct inode *, struct file *, unsigned int,
+@@ -845,6 +855,16 @@ extern struct inode_operations ext3_spec
+ extern struct inode_operations ext3_symlink_inode_operations;
+ extern struct inode_operations ext3_fast_symlink_inode_operations;
++/* extents.c */
++extern int ext3_ext_writepage_trans_blocks(struct inode *, int);
++extern int ext3_ext_get_block(handle_t *, struct inode *, long,
++                            struct buffer_head *, int, int);
++extern void ext3_ext_truncate(struct inode *, struct page *);
++extern void ext3_ext_init(struct super_block *);
++extern void ext3_ext_release(struct super_block *);
++extern void ext3_extents_initialize_blockmap(handle_t *, struct inode *);
++extern int ext3_ext_ioctl(struct inode *inode, struct file *filp,
++                        unsigned int cmd, unsigned long arg);
+ #endif        /* __KERNEL__ */
+Index: linux-2.6.16.21-0.8/include/linux/ext3_extents.h
+===================================================================
+--- /dev/null
++++ linux-2.6.16.21-0.8/include/linux/ext3_extents.h
+@@ -0,0 +1,264 @@
++/*
++ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com
++ * Written by Alex Tomas <alex@clusterfs.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public Licens
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-
++ */
++
++#ifndef _LINUX_EXT3_EXTENTS
++#define _LINUX_EXT3_EXTENTS
++
++/*
++ * with AGRESSIVE_TEST defined capacity of index/leaf blocks
++ * become very little, so index split, in-depth growing and
++ * other hard changes happens much more often
++ * this is for debug purposes only
++ */
++#define AGRESSIVE_TEST_
++
++/*
++ * if CHECK_BINSEARCH defined, then results of binary search
++ * will be checked by linear search
++ */
++#define CHECK_BINSEARCH_
++
++/*
++ * if EXT_DEBUG is defined you can use 'extdebug' mount option
++ * to get lots of info what's going on
++ */
++#define EXT_DEBUG_
++#ifdef EXT_DEBUG
++#define ext_debug(tree,fmt,a...)                      \
++do {                                                  \
++      if (test_opt((tree)->inode->i_sb, EXTDEBUG))    \
++              printk(fmt, ##a);                       \
++} while (0);
++#else
++#define ext_debug(tree,fmt,a...)
++#endif
++
++/*
++ * if EXT_STATS is defined then stats numbers are collected
++ * these number will be displayed at umount time
++ */
++#define EXT_STATS_
++
++
++#define EXT3_ALLOC_NEEDED     3       /* block bitmap + group desc. + sb */
++
++/*
++ * ext3_inode has i_block array (total 60 bytes)
++ * first 4 bytes are used to store:
++ *  - tree depth (0 mean there is no tree yet. all extents in the inode)
++ *  - number of alive extents in the inode
++ */
++
++/*
++ * this is extent on-disk structure
++ * it's used at the bottom of the tree
++ */
++struct ext3_extent {
++      __u32   ee_block;       /* first logical block extent covers */
++      __u16   ee_len;         /* number of blocks covered by extent */
++      __u16   ee_start_hi;    /* high 16 bits of physical block */
++      __u32   ee_start;       /* low 32 bigs of physical block */
++};
++
++/*
++ * this is index on-disk structure
++ * it's used at all the levels, but the bottom
++ */
++struct ext3_extent_idx {
++      __u32   ei_block;       /* index covers logical blocks from 'block' */
++      __u32   ei_leaf;        /* pointer to the physical block of the next *
++                               * level. leaf or next index could bet here */
++      __u16   ei_leaf_hi;     /* high 16 bits of physical block */
++      __u16   ei_unused;
++};
++
++/*
++ * each block (leaves and indexes), even inode-stored has header
++ */
++struct ext3_extent_header {   
++      __u16   eh_magic;       /* probably will support different formats */   
++      __u16   eh_entries;     /* number of valid entries */
++      __u16   eh_max;         /* capacity of store in entries */
++      __u16   eh_depth;       /* has tree real underlaying blocks? */
++      __u32   eh_generation;  /* generation of the tree */
++};
++
++#define EXT3_EXT_MAGIC                0xf30a
++
++/*
++ * array of ext3_ext_path contains path to some extent
++ * creation/lookup routines use it for traversal/splitting/etc
++ * truncate uses it to simulate recursive walking
++ */
++struct ext3_ext_path {
++      __u32                           p_block;
++      __u16                           p_depth;
++      struct ext3_extent              *p_ext;
++      struct ext3_extent_idx          *p_idx;
++      struct ext3_extent_header       *p_hdr;
++      struct buffer_head              *p_bh;
++};
++
++/*
++ * structure for external API
++ */
++
++/*
++ * storage for cached extent
++ */
++struct ext3_ext_cache {
++      __u32   ec_start;
++      __u32   ec_block;
++      __u32   ec_len;
++      __u32   ec_type;
++};
++
++#define EXT3_EXT_CACHE_NO     0
++#define EXT3_EXT_CACHE_GAP    1
++#define EXT3_EXT_CACHE_EXTENT 2
++
++/*
++ * ext3_extents_tree is used to pass initial information
++ * to top-level extents API
++ */
++struct ext3_extents_helpers;
++struct ext3_extents_tree {
++      struct inode *inode;    /* inode which tree belongs to */
++      void *root;             /* ptr to data top of tree resides at */
++      void *buffer;           /* will be passed as arg to ^^ routines */
++      int buffer_len;
++      void *private;
++      struct ext3_ext_cache *cex;/* last found extent */
++      struct ext3_extents_helpers *ops;
++};
++
++struct ext3_extents_helpers {
++      int (*get_write_access)(handle_t *h, void *buffer);
++      int (*mark_buffer_dirty)(handle_t *h, void *buffer);
++      int (*mergable)(struct ext3_extent *ex1, struct ext3_extent *ex2);
++      int (*remove_extent_credits)(struct ext3_extents_tree *,
++                                   struct ext3_extent *, unsigned long,
++                                   unsigned long);
++      int (*remove_extent)(struct ext3_extents_tree *,
++                           struct ext3_extent *, unsigned long,
++                           unsigned long);
++      int (*new_block)(handle_t *, struct ext3_extents_tree *,
++                       struct ext3_ext_path *, struct ext3_extent *,
++                       int *);
++};
++
++/*
++ * to be called by ext3_ext_walk_space()
++ * negative retcode - error
++ * positive retcode - signal for ext3_ext_walk_space(), see below
++ * callback must return valid extent (passed or newly created)
++ */
++typedef int (*ext_prepare_callback)(struct ext3_extents_tree *,
++                                  struct ext3_ext_path *,
++                                  struct ext3_ext_cache *);
++
++#define EXT_CONTINUE  0
++#define EXT_BREAK     1
++#define EXT_REPEAT    2
++
++
++#define EXT_MAX_BLOCK 0xffffffff
++
++
++#define EXT_FIRST_EXTENT(__hdr__) \
++      ((struct ext3_extent *) (((char *) (__hdr__)) +         \
++                               sizeof(struct ext3_extent_header)))
++#define EXT_FIRST_INDEX(__hdr__) \
++      ((struct ext3_extent_idx *) (((char *) (__hdr__)) +     \
++                                   sizeof(struct ext3_extent_header)))
++#define EXT_HAS_FREE_INDEX(__path__) \
++      ((__path__)->p_hdr->eh_entries < (__path__)->p_hdr->eh_max)
++#define EXT_LAST_EXTENT(__hdr__) \
++      (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_entries - 1)
++#define EXT_LAST_INDEX(__hdr__) \
++      (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_entries - 1)
++#define EXT_MAX_EXTENT(__hdr__) \
++      (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_max - 1)
++#define EXT_MAX_INDEX(__hdr__) \
++      (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_max - 1)
++
++#define EXT_ROOT_HDR(tree) \
++      ((struct ext3_extent_header *) (tree)->root)
++#define EXT_BLOCK_HDR(bh) \
++      ((struct ext3_extent_header *) (bh)->b_data)
++#define EXT_DEPTH(_t_)        \
++      (((struct ext3_extent_header *)((_t_)->root))->eh_depth)
++#define EXT_GENERATION(_t_)   \
++      (((struct ext3_extent_header *)((_t_)->root))->eh_generation)
++
++
++#define EXT_ASSERT(__x__) if (!(__x__)) BUG();
++
++#define EXT_CHECK_PATH(tree,path)                                     \
++{                                                                     \
++      int depth = EXT_DEPTH(tree);                                    \
++      BUG_ON((unsigned long) (path) < __PAGE_OFFSET);                 \
++      BUG_ON((unsigned long) (path)[depth].p_idx <                    \
++                      __PAGE_OFFSET && (path)[depth].p_idx != NULL);  \
++      BUG_ON((unsigned long) (path)[depth].p_ext <                    \
++                      __PAGE_OFFSET && (path)[depth].p_ext != NULL);  \
++      BUG_ON((unsigned long) (path)[depth].p_hdr < __PAGE_OFFSET);    \
++      BUG_ON((unsigned long) (path)[depth].p_bh < __PAGE_OFFSET       \
++                      && depth != 0);                                 \
++      BUG_ON((path)[0].p_depth != depth);                             \
++}
++
++
++/*
++ * this structure is used to gather extents from the tree via ioctl
++ */
++struct ext3_extent_buf {
++      unsigned long start;
++      int buflen;
++      void *buffer;
++      void *cur;
++      int err;
++};
++
++/*
++ * this structure is used to collect stats info about the tree
++ */
++struct ext3_extent_tree_stats {
++      int depth;
++      int extents_num;
++      int leaf_num;
++};
++
++extern void ext3_init_tree_desc(struct ext3_extents_tree *, struct inode *);
++extern int ext3_extent_tree_init(handle_t *, struct ext3_extents_tree *);
++extern int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *, struct ext3_ext_path *);
++extern int ext3_ext_insert_extent(handle_t *, struct ext3_extents_tree *, struct ext3_ext_path *, struct ext3_extent *);
++extern int ext3_ext_walk_space(struct ext3_extents_tree *, unsigned long, unsigned long, ext_prepare_callback);
++extern int ext3_ext_remove_space(struct ext3_extents_tree *, unsigned long, unsigned long);
++extern struct ext3_ext_path * ext3_ext_find_extent(struct ext3_extents_tree *, int, struct ext3_ext_path *);
++extern int ext3_ext_calc_blockmap_metadata(struct inode *, int);
++
++static inline void
++ext3_ext_invalidate_cache(struct ext3_extents_tree *tree)
++{
++      if (tree->cex)
++              tree->cex->ec_type = EXT3_EXT_CACHE_NO;
++}
++
++
++#endif /* _LINUX_EXT3_EXTENTS */
+Index: linux-2.6.16.21-0.8/include/linux/ext3_fs_i.h
+===================================================================
+--- linux-2.6.16.21-0.8.orig/include/linux/ext3_fs_i.h
++++ linux-2.6.16.21-0.8/include/linux/ext3_fs_i.h
+@@ -133,6 +133,8 @@ struct ext3_inode_info {
+        */
+       struct semaphore truncate_sem;
+       struct inode vfs_inode;
++
++      __u32 i_cached_extent[4];
+ };
+ #endif        /* _LINUX_EXT3_FS_I */
diff --git a/lustre/kernel_patches/patches/ext3-extents-2.6.18-vanilla.patch b/lustre/kernel_patches/patches/ext3-extents-2.6.18-vanilla.patch
new file mode 100644 (file)
index 0000000..e89e8e7
--- /dev/null
@@ -0,0 +1,2935 @@
+Index: linux-stage/fs/ext3/extents.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-stage/fs/ext3/extents.c      2006-07-16 14:10:21.000000000 +0800
+@@ -0,0 +1,2347 @@
++/*
++ * Copyright(c) 2003, 2004, 2005, Cluster File Systems, Inc, info@clusterfs.com
++ * Written by Alex Tomas <alex@clusterfs.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public Licens
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-
++ */
++
++/*
++ * Extents support for EXT3
++ *
++ * TODO:
++ *   - ext3_ext_walk_space() sould not use ext3_ext_find_extent()
++ *   - ext3_ext_calc_credits() could take 'mergable' into account
++ *   - ext3*_error() should be used in some situations
++ *   - find_goal() [to be tested and improved]
++ *   - smart tree reduction
++ *   - arch-independence
++ *     common on-disk format for big/little-endian arch
++ */
++
++#include <linux/module.h>
++#include <linux/fs.h>
++#include <linux/time.h>
++#include <linux/ext3_jbd.h>
++#include <linux/jbd.h>
++#include <linux/smp_lock.h>
++#include <linux/highuid.h>
++#include <linux/pagemap.h>
++#include <linux/quotaops.h>
++#include <linux/string.h>
++#include <linux/slab.h>
++#include <linux/ext3_extents.h>
++#include <asm/uaccess.h>
++
++
++static inline int ext3_ext_check_header(struct ext3_extent_header *eh)
++{
++      if (eh->eh_magic != EXT3_EXT_MAGIC) {
++              printk(KERN_ERR "EXT3-fs: invalid magic = 0x%x\n",
++                     (unsigned)eh->eh_magic);
++              return -EIO;
++      }
++      if (eh->eh_max == 0) {
++              printk(KERN_ERR "EXT3-fs: invalid eh_max = %u\n",
++                     (unsigned)eh->eh_max);
++              return -EIO;
++      }
++      if (eh->eh_entries > eh->eh_max) {
++              printk(KERN_ERR "EXT3-fs: invalid eh_entries = %u\n",
++                     (unsigned)eh->eh_entries);
++              return -EIO;
++      }
++      return 0;
++}
++
++static handle_t *ext3_ext_journal_restart(handle_t *handle, int needed)
++{
++      int err;
++
++      if (handle->h_buffer_credits > needed)
++              return handle;
++      if (!ext3_journal_extend(handle, needed))
++              return handle;
++      err = ext3_journal_restart(handle, needed);
++      
++      return handle;
++}
++
++static int inline
++ext3_ext_get_access_for_root(handle_t *h, struct ext3_extents_tree *tree)
++{
++      if (tree->ops->get_write_access)
++              return tree->ops->get_write_access(h,tree->buffer);
++      else
++              return 0;
++}
++
++static int inline
++ext3_ext_mark_root_dirty(handle_t *h, struct ext3_extents_tree *tree)
++{
++      if (tree->ops->mark_buffer_dirty)
++              return tree->ops->mark_buffer_dirty(h,tree->buffer);
++      else
++              return 0;
++}
++
++/*
++ * could return:
++ *  - EROFS
++ *  - ENOMEM
++ */
++static int ext3_ext_get_access(handle_t *handle,
++                             struct ext3_extents_tree *tree,
++                             struct ext3_ext_path *path)
++{
++      int err;
++
++      if (path->p_bh) {
++              /* path points to block */
++              err = ext3_journal_get_write_access(handle, path->p_bh);
++      } else {
++              /* path points to leaf/index in inode body */
++              err = ext3_ext_get_access_for_root(handle, tree);
++      }
++      return err;
++}
++
++/*
++ * could return:
++ *  - EROFS
++ *  - ENOMEM
++ *  - EIO
++ */
++static int ext3_ext_dirty(handle_t *handle, struct ext3_extents_tree *tree,
++                        struct ext3_ext_path *path)
++{
++      int err;
++      if (path->p_bh) {
++              /* path points to block */
++              err =ext3_journal_dirty_metadata(handle, path->p_bh);
++      } else {
++              /* path points to leaf/index in inode body */
++              err = ext3_ext_mark_root_dirty(handle, tree);
++      }
++      return err;
++}
++
++static int inline
++ext3_ext_new_block(handle_t *handle, struct ext3_extents_tree *tree,
++                 struct ext3_ext_path *path, struct ext3_extent *ex,
++                 int *err)
++{
++      int goal, depth, newblock;
++      struct inode *inode;
++
++      EXT_ASSERT(tree);
++      if (tree->ops->new_block)
++              return tree->ops->new_block(handle, tree, path, ex, err);
++
++      inode = tree->inode;
++      depth = EXT_DEPTH(tree);
++      if (path && depth > 0) {
++              goal = path[depth-1].p_block;
++      } else {
++              struct ext3_inode_info *ei = EXT3_I(inode);
++              unsigned long bg_start;
++              unsigned long colour;
++
++              bg_start = (ei->i_block_group *
++                          EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
++                      le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block);
++              colour = (current->pid % 16) *
++                      (EXT3_BLOCKS_PER_GROUP(inode->i_sb) / 16);
++              goal = bg_start + colour;
++      }
++
++      newblock = ext3_new_block(handle, inode, goal, err);
++      return newblock;
++}
++
++static inline void ext3_ext_tree_changed(struct ext3_extents_tree *tree)
++{
++      struct ext3_extent_header *neh;
++      neh = EXT_ROOT_HDR(tree);
++      neh->eh_generation++;
++}
++
++static inline int ext3_ext_space_block(struct ext3_extents_tree *tree)
++{
++      int size;
++
++      size = (tree->inode->i_sb->s_blocksize -
++              sizeof(struct ext3_extent_header)) /
++                              sizeof(struct ext3_extent);
++#ifdef AGRESSIVE_TEST
++      size = 6;
++#endif
++      return size;
++}
++
++static inline int ext3_ext_space_block_idx(struct ext3_extents_tree *tree)
++{
++      int size;
++
++      size = (tree->inode->i_sb->s_blocksize -
++              sizeof(struct ext3_extent_header)) /
++                              sizeof(struct ext3_extent_idx);
++#ifdef AGRESSIVE_TEST
++      size = 5;
++#endif
++      return size;
++}
++
++static inline int ext3_ext_space_root(struct ext3_extents_tree *tree)
++{
++      int size;
++
++      size = (tree->buffer_len - sizeof(struct ext3_extent_header)) /
++                      sizeof(struct ext3_extent);
++#ifdef AGRESSIVE_TEST
++      size = 3;
++#endif
++      return size;
++}
++
++static inline int ext3_ext_space_root_idx(struct ext3_extents_tree *tree)
++{
++      int size;
++
++      size = (tree->buffer_len - sizeof(struct ext3_extent_header)) /
++                      sizeof(struct ext3_extent_idx);
++#ifdef AGRESSIVE_TEST
++      size = 4;
++#endif
++      return size;
++}
++
++static void ext3_ext_show_path(struct ext3_extents_tree *tree,
++                             struct ext3_ext_path *path)
++{
++#ifdef EXT_DEBUG
++      int k, l = path->p_depth;
++
++      ext_debug(tree, "path:");
++      for (k = 0; k <= l; k++, path++) {
++              if (path->p_idx) {
++                      ext_debug(tree, "  %d->%d", path->p_idx->ei_block,
++                                path->p_idx->ei_leaf);
++              } else if (path->p_ext) {
++                      ext_debug(tree, "  %d:%d:%d",
++                                path->p_ext->ee_block,
++                                path->p_ext->ee_len,
++                                path->p_ext->ee_start);
++              } else
++                      ext_debug(tree, "  []");
++      }
++      ext_debug(tree, "\n");
++#endif
++}
++
++static void ext3_ext_show_leaf(struct ext3_extents_tree *tree,
++                             struct ext3_ext_path *path)
++{
++#ifdef EXT_DEBUG
++      int depth = EXT_DEPTH(tree);
++      struct ext3_extent_header *eh;
++      struct ext3_extent *ex;
++      int i;
++
++      if (!path)
++              return;
++
++      eh = path[depth].p_hdr;
++      ex = EXT_FIRST_EXTENT(eh);
++
++      for (i = 0; i < eh->eh_entries; i++, ex++) {
++              ext_debug(tree, "%d:%d:%d ",
++                        ex->ee_block, ex->ee_len, ex->ee_start);
++      }
++      ext_debug(tree, "\n");
++#endif
++}
++
++static void ext3_ext_drop_refs(struct ext3_ext_path *path)
++{
++      int depth = path->p_depth;
++      int i;
++
++      for (i = 0; i <= depth; i++, path++) {
++              if (path->p_bh) {
++                      brelse(path->p_bh);
++                      path->p_bh = NULL;
++              }
++      }
++}
++
++/*
++ * binary search for closest index by given block
++ */
++static inline void
++ext3_ext_binsearch_idx(struct ext3_extents_tree *tree,
++                     struct ext3_ext_path *path, int block)
++{
++      struct ext3_extent_header *eh = path->p_hdr;
++      struct ext3_extent_idx *ix;
++      int l = 0, k, r;
++
++      EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
++      EXT_ASSERT(eh->eh_entries <= eh->eh_max);
++      EXT_ASSERT(eh->eh_entries > 0);
++
++      ext_debug(tree, "binsearch for %d(idx):  ", block);
++
++      path->p_idx = ix = EXT_FIRST_INDEX(eh);
++
++      r = k = eh->eh_entries;
++      while (k > 1) {
++              k = (r - l) / 2;
++              if (block < ix[l + k].ei_block)
++                      r -= k;
++              else
++                      l += k;
++              ext_debug(tree, "%d:%d:%d ", k, l, r);
++      }
++
++      ix += l;
++      path->p_idx = ix;
++      ext_debug(tree," -> %d->%d ",path->p_idx->ei_block,path->p_idx->ei_leaf);
++
++      while (l++ < r) {
++              if (block < ix->ei_block) 
++                      break;
++              path->p_idx = ix++;
++      }
++      ext_debug(tree, "  -> %d->%d\n", path->p_idx->ei_block,
++                path->p_idx->ei_leaf);
++
++#ifdef CHECK_BINSEARCH 
++      {
++              struct ext3_extent_idx *chix;
++
++              chix = ix = EXT_FIRST_INDEX(eh);
++              for (k = 0; k < eh->eh_entries; k++, ix++) {
++                      if (k != 0 && ix->ei_block <= ix[-1].ei_block) {
++                              printk("k=%d, ix=0x%p, first=0x%p\n", k,
++                                     ix, EXT_FIRST_INDEX(eh));
++                              printk("%u <= %u\n",
++                                     ix->ei_block,ix[-1].ei_block);
++                      }
++                      EXT_ASSERT(k == 0 || ix->ei_block > ix[-1].ei_block);
++                      if (block < ix->ei_block) 
++                              break;
++                      chix = ix;
++              }
++              EXT_ASSERT(chix == path->p_idx);
++      }
++#endif
++}
++
++/*
++ * binary search for closest extent by given block
++ */
++static inline void
++ext3_ext_binsearch(struct ext3_extents_tree *tree,
++                 struct ext3_ext_path *path, int block)
++{
++      struct ext3_extent_header *eh = path->p_hdr;
++      struct ext3_extent *ex;
++      int l = 0, k, r;
++
++      EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
++      EXT_ASSERT(eh->eh_entries <= eh->eh_max);
++
++      if (eh->eh_entries == 0) {
++              /*
++               * this leaf is empty yet:
++               *  we get such a leaf in split/add case
++               */
++              return;
++      }
++      
++      ext_debug(tree, "binsearch for %d:  ", block);
++
++      path->p_ext = ex = EXT_FIRST_EXTENT(eh);
++
++      r = k = eh->eh_entries;
++      while (k > 1) {
++              k = (r - l) / 2;
++              if (block < ex[l + k].ee_block)
++                      r -= k;
++              else
++                      l += k;
++              ext_debug(tree, "%d:%d:%d ", k, l, r);
++      }
++
++      ex += l;
++      path->p_ext = ex;
++      ext_debug(tree, "  -> %d:%d:%d ", path->p_ext->ee_block,
++                path->p_ext->ee_start, path->p_ext->ee_len);
++
++      while (l++ < r) {
++              if (block < ex->ee_block) 
++                      break;
++              path->p_ext = ex++;
++      }
++      ext_debug(tree, "  -> %d:%d:%d\n", path->p_ext->ee_block,
++                path->p_ext->ee_start, path->p_ext->ee_len);
++
++#ifdef CHECK_BINSEARCH 
++      {
++              struct ext3_extent *chex;
++
++              chex = ex = EXT_FIRST_EXTENT(eh);
++              for (k = 0; k < eh->eh_entries; k++, ex++) {
++                      EXT_ASSERT(k == 0 || ex->ee_block > ex[-1].ee_block);
++                      if (block < ex->ee_block) 
++                              break;
++                      chex = ex;
++              }
++              EXT_ASSERT(chex == path->p_ext);
++      }
++#endif
++}
++
++int ext3_extent_tree_init(handle_t *handle, struct ext3_extents_tree *tree)
++{
++      struct ext3_extent_header *eh;
++
++      BUG_ON(tree->buffer_len == 0);
++      ext3_ext_get_access_for_root(handle, tree);
++      eh = EXT_ROOT_HDR(tree);
++      eh->eh_depth = 0;
++      eh->eh_entries = 0;
++      eh->eh_magic = EXT3_EXT_MAGIC;
++      eh->eh_max = ext3_ext_space_root(tree);
++      ext3_ext_mark_root_dirty(handle, tree);
++      ext3_ext_invalidate_cache(tree);
++      return 0;
++}
++
++struct ext3_ext_path *
++ext3_ext_find_extent(struct ext3_extents_tree *tree, int block,
++                   struct ext3_ext_path *path)
++{
++      struct ext3_extent_header *eh;
++      struct buffer_head *bh;
++      int depth, i, ppos = 0;
++
++      EXT_ASSERT(tree);
++      EXT_ASSERT(tree->inode);
++      EXT_ASSERT(tree->root);
++
++      eh = EXT_ROOT_HDR(tree);
++      EXT_ASSERT(eh);
++      if (ext3_ext_check_header(eh))
++              goto err;
++
++      i = depth = EXT_DEPTH(tree);
++      EXT_ASSERT(eh->eh_max);
++      EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
++      
++      /* account possible depth increase */
++      if (!path) {
++              path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 2),
++                             GFP_NOFS);
++              if (!path)
++                      return ERR_PTR(-ENOMEM);
++      }
++      memset(path, 0, sizeof(struct ext3_ext_path) * (depth + 1));
++      path[0].p_hdr = eh;
++
++      /* walk through the tree */
++      while (i) {
++              ext_debug(tree, "depth %d: num %d, max %d\n",
++                        ppos, eh->eh_entries, eh->eh_max);
++              ext3_ext_binsearch_idx(tree, path + ppos, block);
++              path[ppos].p_block = path[ppos].p_idx->ei_leaf;
++              path[ppos].p_depth = i;
++              path[ppos].p_ext = NULL;
++
++              bh = sb_bread(tree->inode->i_sb, path[ppos].p_block);
++              if (!bh)
++                      goto err;
++
++              eh = EXT_BLOCK_HDR(bh);
++              ppos++;
++              EXT_ASSERT(ppos <= depth);
++              path[ppos].p_bh = bh;
++              path[ppos].p_hdr = eh;
++              i--;
++
++              if (ext3_ext_check_header(eh))
++                      goto err;
++      }
++
++      path[ppos].p_depth = i;
++      path[ppos].p_hdr = eh;
++      path[ppos].p_ext = NULL;
++      path[ppos].p_idx = NULL;
++
++      if (ext3_ext_check_header(eh))
++              goto err;
++
++      /* find extent */
++      ext3_ext_binsearch(tree, path + ppos, block);
++
++      ext3_ext_show_path(tree, path);
++
++      return path;
++
++err:
++      printk(KERN_ERR "EXT3-fs: header is corrupted!\n");
++      ext3_ext_drop_refs(path);
++      kfree(path);
++      return ERR_PTR(-EIO);
++}
++
++/*
++ * insert new index [logical;ptr] into the block at cupr
++ * it check where to insert: before curp or after curp
++ */
++static int ext3_ext_insert_index(handle_t *handle,
++                               struct ext3_extents_tree *tree,
++                               struct ext3_ext_path *curp,
++                               int logical, int ptr)
++{
++      struct ext3_extent_idx *ix;
++      int len, err;
++
++      if ((err = ext3_ext_get_access(handle, tree, curp)))
++              return err;
++
++      EXT_ASSERT(logical != curp->p_idx->ei_block);
++      len = EXT_MAX_INDEX(curp->p_hdr) - curp->p_idx;
++      if (logical > curp->p_idx->ei_block) {
++              /* insert after */
++              if (curp->p_idx != EXT_LAST_INDEX(curp->p_hdr)) {
++                      len = (len - 1) * sizeof(struct ext3_extent_idx);
++                      len = len < 0 ? 0 : len;
++                      ext_debug(tree, "insert new index %d after: %d. "
++                                "move %d from 0x%p to 0x%p\n",
++                                logical, ptr, len,
++                                (curp->p_idx + 1), (curp->p_idx + 2));
++                      memmove(curp->p_idx + 2, curp->p_idx + 1, len);
++              }
++              ix = curp->p_idx + 1;
++      } else {
++              /* insert before */
++              len = len * sizeof(struct ext3_extent_idx);
++              len = len < 0 ? 0 : len;
++              ext_debug(tree, "insert new index %d before: %d. "
++                        "move %d from 0x%p to 0x%p\n",
++                        logical, ptr, len,
++                        curp->p_idx, (curp->p_idx + 1));
++              memmove(curp->p_idx + 1, curp->p_idx, len);
++              ix = curp->p_idx;
++      }
++
++      ix->ei_block = logical;
++      ix->ei_leaf = ptr;
++      curp->p_hdr->eh_entries++;
++
++      EXT_ASSERT(curp->p_hdr->eh_entries <= curp->p_hdr->eh_max);
++      EXT_ASSERT(ix <= EXT_LAST_INDEX(curp->p_hdr));
++
++      err = ext3_ext_dirty(handle, tree, curp);
++      ext3_std_error(tree->inode->i_sb, err);
++
++      return err;
++}
++
++/*
++ * routine inserts new subtree into the path, using free index entry
++ * at depth 'at:
++ *  - allocates all needed blocks (new leaf and all intermediate index blocks)
++ *  - makes decision where to split
++ *  - moves remaining extens and index entries (right to the split point)
++ *    into the newly allocated blocks
++ *  - initialize subtree
++ */
++static int ext3_ext_split(handle_t *handle, struct ext3_extents_tree *tree,
++                        struct ext3_ext_path *path,
++                        struct ext3_extent *newext, int at)
++{
++      struct buffer_head *bh = NULL;
++      int depth = EXT_DEPTH(tree);
++      struct ext3_extent_header *neh;
++      struct ext3_extent_idx *fidx;
++      struct ext3_extent *ex;
++      int i = at, k, m, a;
++      unsigned long newblock, oldblock, border;
++      int *ablocks = NULL; /* array of allocated blocks */
++      int err = 0;
++
++      /* make decision: where to split? */
++      /* FIXME: now desicion is simplest: at current extent */
++
++      /* if current leaf will be splitted, then we should use 
++       * border from split point */
++      EXT_ASSERT(path[depth].p_ext <= EXT_MAX_EXTENT(path[depth].p_hdr));
++      if (path[depth].p_ext != EXT_MAX_EXTENT(path[depth].p_hdr)) {
++              border = path[depth].p_ext[1].ee_block;
++              ext_debug(tree, "leaf will be splitted."
++                        " next leaf starts at %d\n",
++                        (int)border);
++      } else {
++              border = newext->ee_block;
++              ext_debug(tree, "leaf will be added."
++                        " next leaf starts at %d\n",
++                        (int)border);
++      }
++
++      /* 
++       * if error occurs, then we break processing
++       * and turn filesystem read-only. so, index won't
++       * be inserted and tree will be in consistent
++       * state. next mount will repair buffers too
++       */
++
++      /*
++       * get array to track all allocated blocks
++       * we need this to handle errors and free blocks
++       * upon them
++       */
++      ablocks = kmalloc(sizeof(unsigned long) * depth, GFP_NOFS);
++      if (!ablocks)
++              return -ENOMEM;
++      memset(ablocks, 0, sizeof(unsigned long) * depth);
++
++      /* allocate all needed blocks */
++      ext_debug(tree, "allocate %d blocks for indexes/leaf\n", depth - at);
++      for (a = 0; a < depth - at; a++) {
++              newblock = ext3_ext_new_block(handle, tree, path, newext, &err);
++              if (newblock == 0)
++                      goto cleanup;
++              ablocks[a] = newblock;
++      }
++
++      /* initialize new leaf */
++      newblock = ablocks[--a];
++      EXT_ASSERT(newblock);
++      bh = sb_getblk(tree->inode->i_sb, newblock);
++      if (!bh) {
++              err = -EIO;
++              goto cleanup;
++      }
++      lock_buffer(bh);
++
++      if ((err = ext3_journal_get_create_access(handle, bh)))
++              goto cleanup;
++
++      neh = EXT_BLOCK_HDR(bh);
++      neh->eh_entries = 0;
++      neh->eh_max = ext3_ext_space_block(tree);
++      neh->eh_magic = EXT3_EXT_MAGIC;
++      neh->eh_depth = 0;
++      ex = EXT_FIRST_EXTENT(neh);
++
++      /* move remain of path[depth] to the new leaf */
++      EXT_ASSERT(path[depth].p_hdr->eh_entries == path[depth].p_hdr->eh_max);
++      /* start copy from next extent */
++      /* TODO: we could do it by single memmove */
++      m = 0;
++      path[depth].p_ext++;
++      while (path[depth].p_ext <=
++                      EXT_MAX_EXTENT(path[depth].p_hdr)) {
++              ext_debug(tree, "move %d:%d:%d in new leaf %lu\n",
++                        path[depth].p_ext->ee_block,
++                        path[depth].p_ext->ee_start,
++                        path[depth].p_ext->ee_len,
++                        newblock);
++              memmove(ex++, path[depth].p_ext++, sizeof(struct ext3_extent));
++              neh->eh_entries++;
++              m++;
++      }
++      set_buffer_uptodate(bh);
++      unlock_buffer(bh);
++
++      if ((err = ext3_journal_dirty_metadata(handle, bh)))
++              goto cleanup;   
++      brelse(bh);
++      bh = NULL;
++
++      /* correct old leaf */
++      if (m) {
++              if ((err = ext3_ext_get_access(handle, tree, path + depth)))
++                      goto cleanup;
++              path[depth].p_hdr->eh_entries -= m;
++              if ((err = ext3_ext_dirty(handle, tree, path + depth)))
++                      goto cleanup;
++              
++      }
++
++      /* create intermediate indexes */
++      k = depth - at - 1;
++      EXT_ASSERT(k >= 0);
++      if (k)
++              ext_debug(tree, "create %d intermediate indices\n", k);
++      /* insert new index into current index block */
++      /* current depth stored in i var */
++      i = depth - 1;
++      while (k--) {
++              oldblock = newblock;
++              newblock = ablocks[--a];
++              bh = sb_getblk(tree->inode->i_sb, newblock);
++              if (!bh) {
++                      err = -EIO;
++                      goto cleanup;
++              }
++              lock_buffer(bh);
++
++              if ((err = ext3_journal_get_create_access(handle, bh)))
++                      goto cleanup;
++
++              neh = EXT_BLOCK_HDR(bh);
++              neh->eh_entries = 1;
++              neh->eh_magic = EXT3_EXT_MAGIC;
++              neh->eh_max = ext3_ext_space_block_idx(tree);
++              neh->eh_depth = depth - i; 
++              fidx = EXT_FIRST_INDEX(neh);
++              fidx->ei_block = border;
++              fidx->ei_leaf = oldblock;
++
++              ext_debug(tree, "int.index at %d (block %lu): %lu -> %lu\n",
++                        i, newblock, border, oldblock);
++              /* copy indexes */
++              m = 0;
++              path[i].p_idx++;
++
++              ext_debug(tree, "cur 0x%p, last 0x%p\n", path[i].p_idx,
++                        EXT_MAX_INDEX(path[i].p_hdr));
++              EXT_ASSERT(EXT_MAX_INDEX(path[i].p_hdr) ==
++                         EXT_LAST_INDEX(path[i].p_hdr));
++              while (path[i].p_idx <= EXT_MAX_INDEX(path[i].p_hdr)) {
++                      ext_debug(tree, "%d: move %d:%d in new index %lu\n",
++                                i, path[i].p_idx->ei_block,
++                                path[i].p_idx->ei_leaf, newblock);
++                      memmove(++fidx, path[i].p_idx++,
++                              sizeof(struct ext3_extent_idx));
++                      neh->eh_entries++;
++                      EXT_ASSERT(neh->eh_entries <= neh->eh_max);
++                      m++;
++              }
++              set_buffer_uptodate(bh);
++              unlock_buffer(bh);
++
++              if ((err = ext3_journal_dirty_metadata(handle, bh)))
++                      goto cleanup;
++              brelse(bh);
++              bh = NULL;
++
++              /* correct old index */
++              if (m) {
++                      err = ext3_ext_get_access(handle, tree, path + i);
++                      if (err)
++                              goto cleanup;
++                      path[i].p_hdr->eh_entries -= m;
++                      err = ext3_ext_dirty(handle, tree, path + i);
++                      if (err)
++                              goto cleanup;
++              }
++
++              i--;
++      }
++
++      /* insert new index */
++      if (!err)
++              err = ext3_ext_insert_index(handle, tree, path + at,
++                                          border, newblock);
++
++cleanup:
++      if (bh) {
++              if (buffer_locked(bh))
++                      unlock_buffer(bh);
++              brelse(bh);
++      }
++
++      if (err) {
++              /* free all allocated blocks in error case */
++              for (i = 0; i < depth; i++) {
++                      if (!ablocks[i])
++                              continue;
++                      ext3_free_blocks(handle, tree->inode, ablocks[i], 1);
++              }
++      }
++      kfree(ablocks);
++
++      return err;
++}
++
++/*
++ * routine implements tree growing procedure:
++ *  - allocates new block
++ *  - moves top-level data (index block or leaf) into the new block
++ *  - initialize new top-level, creating index that points to the
++ *    just created block
++ */
++static int ext3_ext_grow_indepth(handle_t *handle,
++                               struct ext3_extents_tree *tree,
++                               struct ext3_ext_path *path,
++                               struct ext3_extent *newext)
++{
++      struct ext3_ext_path *curp = path;
++      struct ext3_extent_header *neh;
++      struct ext3_extent_idx *fidx;
++      struct buffer_head *bh;
++      unsigned long newblock;
++      int err = 0;
++
++      newblock = ext3_ext_new_block(handle, tree, path, newext, &err);
++      if (newblock == 0)
++              return err;
++
++      bh = sb_getblk(tree->inode->i_sb, newblock);
++      if (!bh) {
++              err = -EIO;
++              ext3_std_error(tree->inode->i_sb, err);
++              return err;
++      }
++      lock_buffer(bh);
++
++      if ((err = ext3_journal_get_create_access(handle, bh))) {
++              unlock_buffer(bh);
++              goto out;       
++      }
++
++      /* move top-level index/leaf into new block */
++      memmove(bh->b_data, curp->p_hdr, tree->buffer_len);
++
++      /* set size of new block */
++      neh = EXT_BLOCK_HDR(bh);
++      /* old root could have indexes or leaves
++       * so calculate eh_max right way */
++      if (EXT_DEPTH(tree))
++              neh->eh_max = ext3_ext_space_block_idx(tree);
++      else
++              neh->eh_max = ext3_ext_space_block(tree);
++      neh->eh_magic = EXT3_EXT_MAGIC;
++      set_buffer_uptodate(bh);
++      unlock_buffer(bh);
++
++      if ((err = ext3_journal_dirty_metadata(handle, bh)))
++              goto out;
++
++      /* create index in new top-level index: num,max,pointer */
++      if ((err = ext3_ext_get_access(handle, tree, curp)))
++              goto out;
++
++      curp->p_hdr->eh_magic = EXT3_EXT_MAGIC;
++      curp->p_hdr->eh_max = ext3_ext_space_root_idx(tree);
++      curp->p_hdr->eh_entries = 1;
++      curp->p_idx = EXT_FIRST_INDEX(curp->p_hdr);
++      /* FIXME: it works, but actually path[0] can be index */
++      curp->p_idx->ei_block = EXT_FIRST_EXTENT(path[0].p_hdr)->ee_block;
++      curp->p_idx->ei_leaf = newblock;
++
++      neh = EXT_ROOT_HDR(tree);
++      fidx = EXT_FIRST_INDEX(neh);
++      ext_debug(tree, "new root: num %d(%d), lblock %d, ptr %d\n",
++                neh->eh_entries, neh->eh_max, fidx->ei_block, fidx->ei_leaf); 
++
++      neh->eh_depth = path->p_depth + 1;
++      err = ext3_ext_dirty(handle, tree, curp);
++out:
++      brelse(bh);
++
++      return err;
++}
++
++/*
++ * routine finds empty index and adds new leaf. if no free index found
++ * then it requests in-depth growing
++ */
++static int ext3_ext_create_new_leaf(handle_t *handle,
++                                  struct ext3_extents_tree *tree,
++                                  struct ext3_ext_path *path,
++                                  struct ext3_extent *newext)
++{
++      struct ext3_ext_path *curp;
++      int depth, i, err = 0;
++
++repeat:
++      i = depth = EXT_DEPTH(tree);
++      
++      /* walk up to the tree and look for free index entry */
++      curp = path + depth;
++      while (i > 0 && !EXT_HAS_FREE_INDEX(curp)) {
++              i--;
++              curp--;
++      }
++
++      /* we use already allocated block for index block
++       * so, subsequent data blocks should be contigoues */
++      if (EXT_HAS_FREE_INDEX(curp)) {
++              /* if we found index with free entry, then use that
++               * entry: create all needed subtree and add new leaf */
++              err = ext3_ext_split(handle, tree, path, newext, i);
++
++              /* refill path */
++              ext3_ext_drop_refs(path);
++              path = ext3_ext_find_extent(tree, newext->ee_block, path);
++              if (IS_ERR(path))
++                      err = PTR_ERR(path);
++      } else {
++              /* tree is full, time to grow in depth */
++              err = ext3_ext_grow_indepth(handle, tree, path, newext);
++
++              /* refill path */
++              ext3_ext_drop_refs(path);
++              path = ext3_ext_find_extent(tree, newext->ee_block, path);
++              if (IS_ERR(path))
++                      err = PTR_ERR(path);
++
++              /*
++               * only first (depth 0 -> 1) produces free space
++               * in all other cases we have to split growed tree
++               */
++              depth = EXT_DEPTH(tree);
++              if (path[depth].p_hdr->eh_entries == path[depth].p_hdr->eh_max) {
++                      /* now we need split */
++                      goto repeat;
++              }
++      }
++
++      if (err)
++              return err;
++
++      return 0;
++}
++
++/*
++ * returns allocated block in subsequent extent or EXT_MAX_BLOCK
++ * NOTE: it consider block number from index entry as
++ * allocated block. thus, index entries have to be consistent
++ * with leafs
++ */
++static unsigned long
++ext3_ext_next_allocated_block(struct ext3_ext_path *path)
++{
++      int depth;
++
++      EXT_ASSERT(path != NULL);
++      depth = path->p_depth;
++
++      if (depth == 0 && path->p_ext == NULL)
++              return EXT_MAX_BLOCK;
++
++      /* FIXME: what if index isn't full ?! */
++      while (depth >= 0) {
++              if (depth == path->p_depth) {
++                      /* leaf */
++                      if (path[depth].p_ext !=
++                          EXT_LAST_EXTENT(path[depth].p_hdr))
++                              return path[depth].p_ext[1].ee_block;
++              } else {
++                      /* index */
++                      if (path[depth].p_idx !=
++                          EXT_LAST_INDEX(path[depth].p_hdr))
++                              return path[depth].p_idx[1].ei_block;
++              }
++              depth--;        
++      }
++
++      return EXT_MAX_BLOCK;
++}
++
++/*
++ * returns first allocated block from next leaf or EXT_MAX_BLOCK
++ */
++static unsigned ext3_ext_next_leaf_block(struct ext3_extents_tree *tree,
++                                       struct ext3_ext_path *path)
++{
++      int depth;
++
++      EXT_ASSERT(path != NULL);
++      depth = path->p_depth;
++
++      /* zero-tree has no leaf blocks at all */
++      if (depth == 0)
++              return EXT_MAX_BLOCK;
++
++      /* go to index block */
++      depth--;
++      
++      while (depth >= 0) {
++              if (path[depth].p_idx !=
++                  EXT_LAST_INDEX(path[depth].p_hdr))
++                      return path[depth].p_idx[1].ei_block;
++              depth--;        
++      }
++
++      return EXT_MAX_BLOCK;
++}
++
++/*
++ * if leaf gets modified and modified extent is first in the leaf
++ * then we have to correct all indexes above
++ * TODO: do we need to correct tree in all cases?
++ */
++int ext3_ext_correct_indexes(handle_t *handle, struct ext3_extents_tree *tree,
++                           struct ext3_ext_path *path)
++{
++      struct ext3_extent_header *eh;
++      int depth = EXT_DEPTH(tree);    
++      struct ext3_extent *ex;
++      unsigned long border;
++      int k, err = 0;
++      
++      eh = path[depth].p_hdr;
++      ex = path[depth].p_ext;
++      EXT_ASSERT(ex);
++      EXT_ASSERT(eh);
++      
++      if (depth == 0) {
++              /* there is no tree at all */
++              return 0;
++      }
++      
++      if (ex != EXT_FIRST_EXTENT(eh)) {
++              /* we correct tree if first leaf got modified only */
++              return 0;
++      }
++      
++      /*
++       * TODO: we need correction if border is smaller then current one
++       */
++      k = depth - 1;
++      border = path[depth].p_ext->ee_block;
++      if ((err = ext3_ext_get_access(handle, tree, path + k)))
++              return err;
++      path[k].p_idx->ei_block = border;
++      if ((err = ext3_ext_dirty(handle, tree, path + k)))
++              return err;
++
++      while (k--) {
++              /* change all left-side indexes */
++              if (path[k+1].p_idx != EXT_FIRST_INDEX(path[k+1].p_hdr))
++                      break;
++              if ((err = ext3_ext_get_access(handle, tree, path + k)))
++                      break;
++              path[k].p_idx->ei_block = border;
++              if ((err = ext3_ext_dirty(handle, tree, path + k)))
++                      break;
++      }
++
++      return err;
++}
++
++static int inline
++ext3_can_extents_be_merged(struct ext3_extents_tree *tree,
++                         struct ext3_extent *ex1,
++                         struct ext3_extent *ex2)
++{
++      if (ex1->ee_block + ex1->ee_len != ex2->ee_block)
++              return 0;
++
++#ifdef AGRESSIVE_TEST
++      if (ex1->ee_len >= 4)
++              return 0;
++#endif
++
++      if (!tree->ops->mergable)
++              return 1;
++
++      return tree->ops->mergable(ex1, ex2);
++}
++
++/*
++ * this routine tries to merge requsted extent into the existing
++ * extent or inserts requested extent as new one into the tree,
++ * creating new leaf in no-space case
++ */
++int ext3_ext_insert_extent(handle_t *handle, struct ext3_extents_tree *tree,
++                         struct ext3_ext_path *path,
++                         struct ext3_extent *newext)
++{
++      struct ext3_extent_header * eh;
++      struct ext3_extent *ex, *fex;
++      struct ext3_extent *nearex; /* nearest extent */
++      struct ext3_ext_path *npath = NULL;
++      int depth, len, err, next;
++
++      EXT_ASSERT(newext->ee_len > 0);
++      depth = EXT_DEPTH(tree);
++      ex = path[depth].p_ext;
++      EXT_ASSERT(path[depth].p_hdr);
++
++      /* try to insert block into found extent and return */
++      if (ex && ext3_can_extents_be_merged(tree, ex, newext)) {
++              ext_debug(tree, "append %d block to %d:%d (from %d)\n",
++                        newext->ee_len, ex->ee_block, ex->ee_len,
++                        ex->ee_start);
++              if ((err = ext3_ext_get_access(handle, tree, path + depth)))
++                      return err;
++              ex->ee_len += newext->ee_len;
++              eh = path[depth].p_hdr;
++              nearex = ex;
++              goto merge;
++      }
++
++repeat:
++      depth = EXT_DEPTH(tree);
++      eh = path[depth].p_hdr;
++      if (eh->eh_entries < eh->eh_max)
++              goto has_space;
++
++      /* probably next leaf has space for us? */
++      fex = EXT_LAST_EXTENT(eh);
++      next = ext3_ext_next_leaf_block(tree, path);
++      if (newext->ee_block > fex->ee_block && next != EXT_MAX_BLOCK) {
++              ext_debug(tree, "next leaf block - %d\n", next);
++              EXT_ASSERT(!npath);
++              npath = ext3_ext_find_extent(tree, next, NULL);
++              if (IS_ERR(npath))
++                      return PTR_ERR(npath);
++              EXT_ASSERT(npath->p_depth == path->p_depth);
++              eh = npath[depth].p_hdr;
++              if (eh->eh_entries < eh->eh_max) {
++                      ext_debug(tree, "next leaf isnt full(%d)\n",
++                                eh->eh_entries);
++                      path = npath;
++                      goto repeat;
++              }
++              ext_debug(tree, "next leaf hasno free space(%d,%d)\n",
++                        eh->eh_entries, eh->eh_max);
++      }
++
++      /*
++       * there is no free space in found leaf
++       * we're gonna add new leaf in the tree
++       */
++      err = ext3_ext_create_new_leaf(handle, tree, path, newext);
++      if (err)
++              goto cleanup;
++      depth = EXT_DEPTH(tree);
++      eh = path[depth].p_hdr;
++
++has_space:
++      nearex = path[depth].p_ext;
++
++      if ((err = ext3_ext_get_access(handle, tree, path + depth)))
++              goto cleanup;
++
++      if (!nearex) {
++              /* there is no extent in this leaf, create first one */
++              ext_debug(tree, "first extent in the leaf: %d:%d:%d\n",
++                        newext->ee_block, newext->ee_start,
++                        newext->ee_len);
++              path[depth].p_ext = EXT_FIRST_EXTENT(eh);
++      } else if (newext->ee_block > nearex->ee_block) {
++              EXT_ASSERT(newext->ee_block != nearex->ee_block);
++              if (nearex != EXT_LAST_EXTENT(eh)) {
++                      len = EXT_MAX_EXTENT(eh) - nearex;
++                      len = (len - 1) * sizeof(struct ext3_extent);
++                      len = len < 0 ? 0 : len;
++                      ext_debug(tree, "insert %d:%d:%d after: nearest 0x%p, "
++                                "move %d from 0x%p to 0x%p\n",
++                                newext->ee_block, newext->ee_start,
++                                newext->ee_len,
++                                nearex, len, nearex + 1, nearex + 2);
++                      memmove(nearex + 2, nearex + 1, len);
++              }
++              path[depth].p_ext = nearex + 1;
++      } else {
++              EXT_ASSERT(newext->ee_block != nearex->ee_block);
++              len = (EXT_MAX_EXTENT(eh) - nearex) * sizeof(struct ext3_extent);
++              len = len < 0 ? 0 : len;
++              ext_debug(tree, "insert %d:%d:%d before: nearest 0x%p, "
++                        "move %d from 0x%p to 0x%p\n",
++                        newext->ee_block, newext->ee_start, newext->ee_len,
++                        nearex, len, nearex + 1, nearex + 2);
++              memmove(nearex + 1, nearex, len);
++              path[depth].p_ext = nearex;
++      }
++
++      eh->eh_entries++;
++      nearex = path[depth].p_ext;
++      nearex->ee_block = newext->ee_block;
++      nearex->ee_start = newext->ee_start;
++      nearex->ee_len = newext->ee_len;
++      /* FIXME: support for large fs */
++      nearex->ee_start_hi = 0;
++
++merge:
++      /* try to merge extents to the right */
++      while (nearex < EXT_LAST_EXTENT(eh)) {
++              if (!ext3_can_extents_be_merged(tree, nearex, nearex + 1))
++                      break;
++              /* merge with next extent! */
++              nearex->ee_len += nearex[1].ee_len;
++              if (nearex + 1 < EXT_LAST_EXTENT(eh)) {
++                      len = (EXT_LAST_EXTENT(eh) - nearex - 1) *
++                              sizeof(struct ext3_extent);
++                      memmove(nearex + 1, nearex + 2, len);
++              }
++              eh->eh_entries--;
++              EXT_ASSERT(eh->eh_entries > 0);
++      }
++
++      /* try to merge extents to the left */
++
++      /* time to correct all indexes above */
++      err = ext3_ext_correct_indexes(handle, tree, path);
++      if (err)
++              goto cleanup;
++
++      err = ext3_ext_dirty(handle, tree, path + depth);
++
++cleanup:
++      if (npath) {
++              ext3_ext_drop_refs(npath);
++              kfree(npath);
++      }
++      ext3_ext_tree_changed(tree);
++      ext3_ext_invalidate_cache(tree);
++      return err;
++}
++
++int ext3_ext_walk_space(struct ext3_extents_tree *tree, unsigned long block,
++                      unsigned long num, ext_prepare_callback func)
++{
++      struct ext3_ext_path *path = NULL;
++      struct ext3_ext_cache cbex;
++      struct ext3_extent *ex;
++      unsigned long next, start = 0, end = 0;
++      unsigned long last = block + num;
++      int depth, exists, err = 0;
++
++      EXT_ASSERT(tree);
++      EXT_ASSERT(func);
++      EXT_ASSERT(tree->inode);
++      EXT_ASSERT(tree->root);
++
++      while (block < last && block != EXT_MAX_BLOCK) {
++              num = last - block;
++              /* find extent for this block */
++              path = ext3_ext_find_extent(tree, block, path);
++              if (IS_ERR(path)) {
++                      err = PTR_ERR(path);
++                      path = NULL;
++                      break;
++              }
++
++              depth = EXT_DEPTH(tree);
++              EXT_ASSERT(path[depth].p_hdr);
++              ex = path[depth].p_ext;
++              next = ext3_ext_next_allocated_block(path);
++
++              exists = 0;
++              if (!ex) {
++                      /* there is no extent yet, so try to allocate
++                       * all requested space */
++                      start = block;
++                      end = block + num;
++              } else if (ex->ee_block > block) {
++                      /* need to allocate space before found extent */
++                      start = block;
++                      end = ex->ee_block;
++                      if (block + num < end)
++                              end = block + num;
++              } else if (block >= ex->ee_block + ex->ee_len) {
++                      /* need to allocate space after found extent */
++                      start = block;
++                      end = block + num;
++                      if (end >= next)
++                              end = next;
++              } else if (block >= ex->ee_block) {
++                      /* 
++                       * some part of requested space is covered
++                       * by found extent
++                       */
++                      start = block;
++                      end = ex->ee_block + ex->ee_len;
++                      if (block + num < end)
++                              end = block + num;
++                      exists = 1;
++              } else {
++                      BUG();
++              }
++              EXT_ASSERT(end > start);
++
++              if (!exists) {
++                      cbex.ec_block = start;
++                      cbex.ec_len = end - start;
++                      cbex.ec_start = 0;
++                      cbex.ec_type = EXT3_EXT_CACHE_GAP;
++              } else {
++                      cbex.ec_block = ex->ee_block;
++                      cbex.ec_len = ex->ee_len;
++                      cbex.ec_start = ex->ee_start;
++                      cbex.ec_type = EXT3_EXT_CACHE_EXTENT;
++              }
++
++              EXT_ASSERT(cbex.ec_len > 0);
++              EXT_ASSERT(path[depth].p_hdr);
++              err = func(tree, path, &cbex);
++              ext3_ext_drop_refs(path);
++
++              if (err < 0)
++                      break;
++              if (err == EXT_REPEAT)
++                      continue;
++              else if (err == EXT_BREAK) {
++                      err = 0;
++                      break;
++              }
++
++              if (EXT_DEPTH(tree) != depth) {
++                      /* depth was changed. we have to realloc path */
++                      kfree(path);
++                      path = NULL;
++              }
++
++              block = cbex.ec_block + cbex.ec_len;
++      }
++
++      if (path) {
++              ext3_ext_drop_refs(path);
++              kfree(path);
++      }
++
++      return err;
++}
++
++static inline void
++ext3_ext_put_in_cache(struct ext3_extents_tree *tree, __u32 block,
++                    __u32 len, __u32 start, int type)
++{
++      EXT_ASSERT(len > 0);
++      if (tree->cex) {
++              tree->cex->ec_type = type;
++              tree->cex->ec_block = block;
++              tree->cex->ec_len = len;
++              tree->cex->ec_start = start;
++      }
++}
++
++/*
++ * this routine calculate boundaries of the gap requested block fits into
++ * and cache this gap
++ */
++static inline void
++ext3_ext_put_gap_in_cache(struct ext3_extents_tree *tree,
++                        struct ext3_ext_path *path,
++                        unsigned long block)
++{
++      int depth = EXT_DEPTH(tree);
++      unsigned long lblock, len;
++      struct ext3_extent *ex;
++
++      if (!tree->cex)
++              return;
++
++      ex = path[depth].p_ext;
++      if (ex == NULL) {
++              /* there is no extent yet, so gap is [0;-] */
++              lblock = 0;
++              len = EXT_MAX_BLOCK;
++              ext_debug(tree, "cache gap(whole file):");
++      } else if (block < ex->ee_block) {
++              lblock = block;
++              len = ex->ee_block - block;
++              ext_debug(tree, "cache gap(before): %lu [%lu:%lu]",
++                        (unsigned long) block,
++                        (unsigned long) ex->ee_block,
++                        (unsigned long) ex->ee_len);
++      } else if (block >= ex->ee_block + ex->ee_len) {
++              lblock = ex->ee_block + ex->ee_len;
++              len = ext3_ext_next_allocated_block(path);
++              ext_debug(tree, "cache gap(after): [%lu:%lu] %lu",
++                        (unsigned long) ex->ee_block,
++                        (unsigned long) ex->ee_len,
++                        (unsigned long) block);
++              EXT_ASSERT(len > lblock);
++              len = len - lblock;
++      } else {
++              lblock = len = 0;
++              BUG();
++      }
++
++      ext_debug(tree, " -> %lu:%lu\n", (unsigned long) lblock, len);
++      ext3_ext_put_in_cache(tree, lblock, len, 0, EXT3_EXT_CACHE_GAP);
++}
++
++static inline int
++ext3_ext_in_cache(struct ext3_extents_tree *tree, unsigned long block,
++                struct ext3_extent *ex)
++{
++      struct ext3_ext_cache *cex = tree->cex;
++
++      /* is there cache storage at all? */
++      if (!cex)
++              return EXT3_EXT_CACHE_NO;
++
++      /* has cache valid data? */
++      if (cex->ec_type == EXT3_EXT_CACHE_NO)
++              return EXT3_EXT_CACHE_NO;
++
++      EXT_ASSERT(cex->ec_type == EXT3_EXT_CACHE_GAP ||
++                 cex->ec_type == EXT3_EXT_CACHE_EXTENT);
++      if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) {
++              ex->ee_block = cex->ec_block;
++              ex->ee_start = cex->ec_start;
++              ex->ee_len = cex->ec_len;
++              ext_debug(tree, "%lu cached by %lu:%lu:%lu\n",
++                        (unsigned long) block,
++                        (unsigned long) ex->ee_block,
++                        (unsigned long) ex->ee_len,
++                        (unsigned long) ex->ee_start);
++              return cex->ec_type;
++      }
++
++      /* not in cache */
++      return EXT3_EXT_CACHE_NO;
++}
++
++/*
++ * routine removes index from the index block
++ * it's used in truncate case only. thus all requests are for
++ * last index in the block only
++ */
++int ext3_ext_rm_idx(handle_t *handle, struct ext3_extents_tree *tree,
++                  struct ext3_ext_path *path)
++{
++      struct buffer_head *bh;
++      int err;
++      
++      /* free index block */
++      path--;
++      EXT_ASSERT(path->p_hdr->eh_entries);
++      if ((err = ext3_ext_get_access(handle, tree, path)))
++              return err;
++      path->p_hdr->eh_entries--;
++      if ((err = ext3_ext_dirty(handle, tree, path)))
++              return err;
++      ext_debug(tree, "index is empty, remove it, free block %d\n",
++                path->p_idx->ei_leaf);
++      bh = sb_find_get_block(tree->inode->i_sb, path->p_idx->ei_leaf);
++      ext3_forget(handle, 1, tree->inode, bh, path->p_idx->ei_leaf);
++      ext3_free_blocks(handle, tree->inode, path->p_idx->ei_leaf, 1);
++      return err;
++}
++
++int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *tree,
++                                   struct ext3_ext_path *path)
++{
++      int depth = EXT_DEPTH(tree);
++      int needed;
++
++      if (path) {
++              /* probably there is space in leaf? */
++              if (path[depth].p_hdr->eh_entries < path[depth].p_hdr->eh_max)
++                      return 1;
++      }
++      
++      /*
++       * the worste case we're expecting is creation of the
++       * new root (growing in depth) with index splitting
++       * for splitting we have to consider depth + 1 because
++       * previous growing could increase it
++       */
++      depth = depth + 1;
++
++      /* 
++       * growing in depth:
++       * block allocation + new root + old root
++       */
++      needed = EXT3_ALLOC_NEEDED + 2;
++
++      /* index split. we may need:
++       *   allocate intermediate indexes and new leaf
++       *   change two blocks at each level, but root
++       *   modify root block (inode)
++       */
++      needed += (depth * EXT3_ALLOC_NEEDED) + (2 * depth) + 1;
++
++      return needed;
++}
++
++static int
++ext3_ext_split_for_rm(handle_t *handle, struct ext3_extents_tree *tree,
++                    struct ext3_ext_path *path, unsigned long start,
++                    unsigned long end)
++{
++      struct ext3_extent *ex, tex;
++      struct ext3_ext_path *npath;
++      int depth, creds, err;
++
++      depth = EXT_DEPTH(tree);
++      ex = path[depth].p_ext;
++      EXT_ASSERT(ex);
++      EXT_ASSERT(end < ex->ee_block + ex->ee_len - 1);
++      EXT_ASSERT(ex->ee_block < start);
++
++      /* calculate tail extent */
++      tex.ee_block = end + 1;
++      EXT_ASSERT(tex.ee_block < ex->ee_block + ex->ee_len);
++      tex.ee_len = ex->ee_block + ex->ee_len - tex.ee_block;
++
++      creds = ext3_ext_calc_credits_for_insert(tree, path);
++      handle = ext3_ext_journal_restart(handle, creds);
++      if (IS_ERR(handle))
++              return PTR_ERR(handle);
++      
++      /* calculate head extent. use primary extent */
++      err = ext3_ext_get_access(handle, tree, path + depth);
++      if (err)
++              return err;
++      ex->ee_len = start - ex->ee_block;
++      err = ext3_ext_dirty(handle, tree, path + depth);
++      if (err)
++              return err;
++
++      /* FIXME: some callback to free underlying resource
++       * and correct ee_start? */
++      ext_debug(tree, "split extent: head %u:%u, tail %u:%u\n",
++                ex->ee_block, ex->ee_len, tex.ee_block, tex.ee_len);
++
++      npath = ext3_ext_find_extent(tree, ex->ee_block, NULL);
++      if (IS_ERR(npath))
++              return PTR_ERR(npath);
++      depth = EXT_DEPTH(tree);
++      EXT_ASSERT(npath[depth].p_ext->ee_block == ex->ee_block);
++      EXT_ASSERT(npath[depth].p_ext->ee_len == ex->ee_len);
++
++      err = ext3_ext_insert_extent(handle, tree, npath, &tex);
++      ext3_ext_drop_refs(npath);
++      kfree(npath);
++
++      return err;
++}
++
++static int
++ext3_ext_rm_leaf(handle_t *handle, struct ext3_extents_tree *tree,
++               struct ext3_ext_path *path, unsigned long start,
++               unsigned long end)
++{
++      struct ext3_extent *ex, *fu = NULL, *lu, *le;
++      int err = 0, correct_index = 0;
++      int depth = EXT_DEPTH(tree), credits;
++      struct ext3_extent_header *eh;
++      unsigned a, b, block, num;
++
++      ext_debug(tree, "remove [%lu:%lu] in leaf\n", start, end);
++      if (!path[depth].p_hdr)
++              path[depth].p_hdr = EXT_BLOCK_HDR(path[depth].p_bh);
++      eh = path[depth].p_hdr;
++      EXT_ASSERT(eh);
++      EXT_ASSERT(eh->eh_entries <= eh->eh_max);
++      EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
++      
++      /* find where to start removing */
++      le = ex = EXT_LAST_EXTENT(eh);
++      while (ex != EXT_FIRST_EXTENT(eh)) {
++              if (ex->ee_block <= end)
++                      break;
++              ex--;
++      }
++
++      if (start > ex->ee_block && end < ex->ee_block + ex->ee_len - 1) {
++              /* removal of internal part of the extent requested
++               * tail and head must be placed in different extent
++               * so, we have to insert one more extent */
++              path[depth].p_ext = ex;
++              return ext3_ext_split_for_rm(handle, tree, path, start, end);
++      }
++      
++      lu = ex;
++      while (ex >= EXT_FIRST_EXTENT(eh) && ex->ee_block + ex->ee_len > start) {
++              ext_debug(tree, "remove ext %u:%u\n", ex->ee_block, ex->ee_len);
++              path[depth].p_ext = ex;
++      
++              a = ex->ee_block > start ? ex->ee_block : start;
++              b = ex->ee_block + ex->ee_len - 1 < end ?
++                      ex->ee_block + ex->ee_len - 1 : end;
++              
++              ext_debug(tree, "  border %u:%u\n", a, b);
++
++              if (a != ex->ee_block && b != ex->ee_block + ex->ee_len - 1) {
++                      block = 0;
++                      num = 0;
++                      BUG();
++              } else if (a != ex->ee_block) {
++                      /* remove tail of the extent */
++                      block = ex->ee_block;
++                      num = a - block;
++              } else if (b != ex->ee_block + ex->ee_len - 1) {
++                      /* remove head of the extent */
++                      block = a;
++                      num = b - a;
++              } else {
++                      /* remove whole extent: excelent! */
++                      block = ex->ee_block; 
++                      num = 0;
++                      EXT_ASSERT(a == ex->ee_block &&
++                                 b == ex->ee_block + ex->ee_len - 1);
++              }
++
++              if (ex == EXT_FIRST_EXTENT(eh))
++                      correct_index = 1;
++
++              credits = 1;
++              if (correct_index)
++                      credits += (EXT_DEPTH(tree) * EXT3_ALLOC_NEEDED) + 1;
++              if (tree->ops->remove_extent_credits)
++                      credits+=tree->ops->remove_extent_credits(tree,ex,a,b);
++              
++              handle = ext3_ext_journal_restart(handle, credits);
++              if (IS_ERR(handle)) {
++                      err = PTR_ERR(handle);
++                      goto out;
++              }
++
++              err = ext3_ext_get_access(handle, tree, path + depth);
++              if (err)
++                      goto out;
++
++              if (tree->ops->remove_extent)
++                      err = tree->ops->remove_extent(tree, ex, a, b);
++              if (err)
++                      goto out;
++
++              if (num == 0) {
++                      /* this extent is removed entirely mark slot unused */
++                      ex->ee_start = 0;
++                      eh->eh_entries--;
++                      fu = ex;
++              }
++
++              ex->ee_block = block;
++              ex->ee_len = num;
++
++              err = ext3_ext_dirty(handle, tree, path + depth);
++              if (err)
++                      goto out;
++
++              ext_debug(tree, "new extent: %u:%u:%u\n",
++                        ex->ee_block, ex->ee_len, ex->ee_start);
++              ex--;
++      }
++
++      if (fu) {
++              /* reuse unused slots */
++              while (lu < le) {
++                      if (lu->ee_start) {
++                              *fu = *lu;
++                              lu->ee_start = 0;
++                              fu++;
++                      }
++                      lu++;
++              }
++      }
++
++      if (correct_index && eh->eh_entries)
++              err = ext3_ext_correct_indexes(handle, tree, path);
++
++      /* if this leaf is free, then we should
++       * remove it from index block above */
++      if (err == 0 && eh->eh_entries == 0 && path[depth].p_bh != NULL)
++              err = ext3_ext_rm_idx(handle, tree, path + depth);
++
++out:
++      return err;
++}
++
++
++static struct ext3_extent_idx *
++ext3_ext_last_covered(struct ext3_extent_header *hdr, unsigned long block)
++{
++      struct ext3_extent_idx *ix;
++      
++      ix = EXT_LAST_INDEX(hdr);
++      while (ix != EXT_FIRST_INDEX(hdr)) {
++              if (ix->ei_block <= block)
++                      break;
++              ix--;
++      }
++      return ix;
++}
++
++/*
++ * returns 1 if current index have to be freed (even partial)
++ */
++static int inline
++ext3_ext_more_to_rm(struct ext3_ext_path *path)
++{
++      EXT_ASSERT(path->p_idx);
++
++      if (path->p_idx < EXT_FIRST_INDEX(path->p_hdr))
++              return 0;
++
++      /*
++       * if truncate on deeper level happened it it wasn't partial
++       * so we have to consider current index for truncation
++       */
++      if (path->p_hdr->eh_entries == path->p_block)
++              return 0;
++      return 1;
++}
++
++int ext3_ext_remove_space(struct ext3_extents_tree *tree,
++                        unsigned long start, unsigned long end)
++{
++      struct inode *inode = tree->inode;
++      struct super_block *sb = inode->i_sb;
++      int depth = EXT_DEPTH(tree);
++      struct ext3_ext_path *path;
++      handle_t *handle;
++      int i = 0, err = 0;
++
++      ext_debug(tree, "space to be removed: %lu:%lu\n", start, end);
++
++      /* probably first extent we're gonna free will be last in block */
++      handle = ext3_journal_start(inode, depth + 1);
++      if (IS_ERR(handle))
++              return PTR_ERR(handle);
++
++      ext3_ext_invalidate_cache(tree);
++
++      /*
++       * we start scanning from right side freeing all the blocks
++       * after i_size and walking into the deep
++       */
++      path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 1), GFP_KERNEL);
++      if (IS_ERR(path)) {
++              ext3_error(sb, __FUNCTION__, "Can't allocate path array");
++              ext3_journal_stop(handle);
++              return -ENOMEM;
++      }
++      memset(path, 0, sizeof(struct ext3_ext_path) * (depth + 1));
++      path[i].p_hdr = EXT_ROOT_HDR(tree);
++      
++      while (i >= 0 && err == 0) {
++              if (i == depth) {
++                      /* this is leaf block */
++                      err = ext3_ext_rm_leaf(handle, tree, path, start, end);
++                      /* root level have p_bh == NULL, brelse() eats this */
++                      brelse(path[i].p_bh);
++                      i--;
++                      continue;
++              }
++              
++              /* this is index block */
++              if (!path[i].p_hdr) {
++                      ext_debug(tree, "initialize header\n");
++                      path[i].p_hdr = EXT_BLOCK_HDR(path[i].p_bh);
++              }
++
++              EXT_ASSERT(path[i].p_hdr->eh_entries <= path[i].p_hdr->eh_max);
++              EXT_ASSERT(path[i].p_hdr->eh_magic == EXT3_EXT_MAGIC);
++              
++              if (!path[i].p_idx) {
++                      /* this level hasn't touched yet */
++                      path[i].p_idx =
++                              ext3_ext_last_covered(path[i].p_hdr, end);
++                      path[i].p_block = path[i].p_hdr->eh_entries + 1;
++                      ext_debug(tree, "init index ptr: hdr 0x%p, num %d\n",
++                                path[i].p_hdr, path[i].p_hdr->eh_entries);
++              } else {
++                      /* we've already was here, see at next index */
++                      path[i].p_idx--;
++              }
++
++              ext_debug(tree, "level %d - index, first 0x%p, cur 0x%p\n",
++                        i, EXT_FIRST_INDEX(path[i].p_hdr),
++                        path[i].p_idx);
++              if (ext3_ext_more_to_rm(path + i)) {
++                      /* go to the next level */
++                      ext_debug(tree, "move to level %d (block %d)\n",
++                                i + 1, path[i].p_idx->ei_leaf);
++                      memset(path + i + 1, 0, sizeof(*path));
++                      path[i+1].p_bh = sb_bread(sb, path[i].p_idx->ei_leaf);
++                      if (!path[i+1].p_bh) {
++                              /* should we reset i_size? */
++                              err = -EIO;
++                              break;
++                      }
++                      /* put actual number of indexes to know is this
++                       * number got changed at the next iteration */
++                      path[i].p_block = path[i].p_hdr->eh_entries;
++                      i++;
++              } else {
++                      /* we finish processing this index, go up */
++                      if (path[i].p_hdr->eh_entries == 0 && i > 0) {
++                              /* index is empty, remove it
++                               * handle must be already prepared by the
++                               * truncatei_leaf() */
++                              err = ext3_ext_rm_idx(handle, tree, path + i);
++                      }
++                      /* root level have p_bh == NULL, brelse() eats this */
++                      brelse(path[i].p_bh);
++                      i--;
++                      ext_debug(tree, "return to level %d\n", i);
++              }
++      }
++
++      /* TODO: flexible tree reduction should be here */
++      if (path->p_hdr->eh_entries == 0) {
++              /*
++               * truncate to zero freed all the tree
++               * so, we need to correct eh_depth
++               */
++              err = ext3_ext_get_access(handle, tree, path);
++              if (err == 0) {
++                      EXT_ROOT_HDR(tree)->eh_depth = 0;
++                      EXT_ROOT_HDR(tree)->eh_max = ext3_ext_space_root(tree);
++                      err = ext3_ext_dirty(handle, tree, path);
++              }
++      }
++      ext3_ext_tree_changed(tree);
++
++      kfree(path);
++      ext3_journal_stop(handle);
++
++      return err;
++}
++
++int ext3_ext_calc_metadata_amount(struct ext3_extents_tree *tree, int blocks)
++{
++      int lcap, icap, rcap, leafs, idxs, num;
++
++      rcap = ext3_ext_space_root(tree);
++      if (blocks <= rcap) {
++              /* all extents fit to the root */
++              return 0;
++      }
++
++      rcap = ext3_ext_space_root_idx(tree);
++      lcap = ext3_ext_space_block(tree);
++      icap = ext3_ext_space_block_idx(tree);
++
++      num = leafs = (blocks + lcap - 1) / lcap;
++      if (leafs <= rcap) {
++              /* all pointers to leafs fit to the root */
++              return leafs;
++      }
++
++      /* ok. we need separate index block(s) to link all leaf blocks */
++      idxs = (leafs + icap - 1) / icap;
++      do {
++              num += idxs;
++              idxs = (idxs + icap - 1) / icap;
++      } while (idxs > rcap);
++
++      return num;
++}
++
++/*
++ * called at mount time
++ */
++void ext3_ext_init(struct super_block *sb)
++{
++      /*
++       * possible initialization would be here
++       */
++
++      if (test_opt(sb, EXTENTS)) {
++              printk("EXT3-fs: file extents enabled");
++#ifdef AGRESSIVE_TEST
++              printk(", agressive tests");
++#endif
++#ifdef CHECK_BINSEARCH
++              printk(", check binsearch");
++#endif
++              printk("\n");
++      }
++}
++
++/*
++ * called at umount time
++ */
++void ext3_ext_release(struct super_block *sb)
++{
++}
++
++/************************************************************************
++ * VFS related routines
++ ************************************************************************/
++
++static int ext3_get_inode_write_access(handle_t *handle, void *buffer)
++{
++      /* we use in-core data, not bh */
++      return 0;
++}
++
++static int ext3_mark_buffer_dirty(handle_t *handle, void *buffer)
++{
++      struct inode *inode = buffer;
++      return ext3_mark_inode_dirty(handle, inode);
++}
++
++static int ext3_ext_mergable(struct ext3_extent *ex1,
++                           struct ext3_extent *ex2)
++{
++      /* FIXME: support for large fs */
++      if (ex1->ee_start + ex1->ee_len == ex2->ee_start)
++              return 1;
++      return 0;
++}
++
++static int
++ext3_remove_blocks_credits(struct ext3_extents_tree *tree,
++                         struct ext3_extent *ex,
++                         unsigned long from, unsigned long to)
++{
++      int needed;
++      
++      /* at present, extent can't cross block group */;
++      needed = 4; /* bitmap + group desc + sb + inode */
++
++#ifdef CONFIG_QUOTA
++      needed += 2 * EXT3_SINGLEDATA_TRANS_BLOCKS;
++#endif
++      return needed;
++}
++
++static int
++ext3_remove_blocks(struct ext3_extents_tree *tree,
++                 struct ext3_extent *ex,
++                 unsigned long from, unsigned long to)
++{
++      int needed = ext3_remove_blocks_credits(tree, ex, from, to);
++      handle_t *handle = ext3_journal_start(tree->inode, needed);
++      struct buffer_head *bh;
++      int i;
++
++      if (IS_ERR(handle))
++              return PTR_ERR(handle);
++      if (from >= ex->ee_block && to == ex->ee_block + ex->ee_len - 1) {
++              /* tail removal */
++              unsigned long num, start;
++              num = ex->ee_block + ex->ee_len - from;
++              start = ex->ee_start + ex->ee_len - num;
++              ext_debug(tree, "free last %lu blocks starting %lu\n",
++                        num, start);
++              for (i = 0; i < num; i++) {
++                      bh = sb_find_get_block(tree->inode->i_sb, start + i);
++                      ext3_forget(handle, 0, tree->inode, bh, start + i);
++              }
++              ext3_free_blocks(handle, tree->inode, start, num);
++      } else if (from == ex->ee_block && to <= ex->ee_block + ex->ee_len - 1) {
++              printk("strange request: removal %lu-%lu from %u:%u\n",
++                     from, to, ex->ee_block, ex->ee_len);
++      } else {
++              printk("strange request: removal(2) %lu-%lu from %u:%u\n",
++                     from, to, ex->ee_block, ex->ee_len);
++      }
++      ext3_journal_stop(handle);
++      return 0;
++}
++
++static int ext3_ext_find_goal(struct inode *inode,
++                            struct ext3_ext_path *path, unsigned long block)
++{
++      struct ext3_inode_info *ei = EXT3_I(inode);
++      unsigned long bg_start;
++      unsigned long colour;
++      int depth;
++      
++      if (path) {
++              struct ext3_extent *ex;
++              depth = path->p_depth;
++              
++              /* try to predict block placement */
++              if ((ex = path[depth].p_ext))
++                      return ex->ee_start + (block - ex->ee_block);
++
++              /* it looks index is empty
++               * try to find starting from index itself */
++              if (path[depth].p_bh)
++                      return path[depth].p_bh->b_blocknr;
++      }
++
++      /* OK. use inode's group */
++      bg_start = (ei->i_block_group * EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
++              le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block);
++      colour = (current->pid % 16) *
++                      (EXT3_BLOCKS_PER_GROUP(inode->i_sb) / 16);
++      return bg_start + colour + block;
++}
++
++static int ext3_new_block_cb(handle_t *handle, struct ext3_extents_tree *tree,
++                           struct ext3_ext_path *path,
++                           struct ext3_extent *ex, int *err)
++{
++      struct inode *inode = tree->inode;
++      int newblock, goal;
++      
++      EXT_ASSERT(path);
++      EXT_ASSERT(ex);
++      EXT_ASSERT(ex->ee_start);
++      EXT_ASSERT(ex->ee_len);
++      
++      /* reuse block from the extent to order data/metadata */
++      newblock = ex->ee_start++;
++      ex->ee_len--;
++      if (ex->ee_len == 0) {
++              ex->ee_len = 1;
++              /* allocate new block for the extent */
++              goal = ext3_ext_find_goal(inode, path, ex->ee_block);
++              ex->ee_start = ext3_new_block(handle, inode, goal, err);
++              if (ex->ee_start == 0) {
++                      /* error occured: restore old extent */
++                      ex->ee_start = newblock;
++                      return 0;
++              }
++      }
++      return newblock;
++}
++
++static struct ext3_extents_helpers ext3_blockmap_helpers = {
++      .get_write_access       = ext3_get_inode_write_access,
++      .mark_buffer_dirty      = ext3_mark_buffer_dirty,
++      .mergable               = ext3_ext_mergable,
++      .new_block              = ext3_new_block_cb,
++      .remove_extent          = ext3_remove_blocks,
++      .remove_extent_credits  = ext3_remove_blocks_credits,
++};
++
++void ext3_init_tree_desc(struct ext3_extents_tree *tree,
++                       struct inode *inode)
++{
++      tree->inode = inode;
++      tree->root = (void *) EXT3_I(inode)->i_data;
++      tree->buffer = (void *) inode;
++      tree->buffer_len = sizeof(EXT3_I(inode)->i_data);
++      tree->cex = (struct ext3_ext_cache *) &EXT3_I(inode)->i_cached_extent;
++      tree->ops = &ext3_blockmap_helpers;
++}
++
++int ext3_ext_get_block(handle_t *handle, struct inode *inode,
++                     long iblock, struct buffer_head *bh_result,
++                     int create, int extend_disksize)
++{
++      struct ext3_ext_path *path = NULL;
++      struct ext3_extent newex;
++      struct ext3_extent *ex;
++      int goal, newblock, err = 0, depth;
++      struct ext3_extents_tree tree;
++
++      clear_buffer_new(bh_result);
++      ext3_init_tree_desc(&tree, inode);
++      ext_debug(&tree, "block %d requested for inode %u\n",
++                (int) iblock, (unsigned) inode->i_ino);
++      mutex_lock(&EXT3_I(inode)->truncate_mutex);
++
++      /* check in cache */
++      if ((goal = ext3_ext_in_cache(&tree, iblock, &newex))) {
++              if (goal == EXT3_EXT_CACHE_GAP) {
++                      if (!create) {
++                              /* block isn't allocated yet and
++                               * user don't want to allocate it */
++                              goto out2;
++                      }
++                      /* we should allocate requested block */
++              } else if (goal == EXT3_EXT_CACHE_EXTENT) {
++                      /* block is already allocated */
++                      newblock = iblock - newex.ee_block + newex.ee_start;
++                      goto out;
++              } else {
++                      EXT_ASSERT(0);
++              }
++      }
++
++      /* find extent for this block */
++      path = ext3_ext_find_extent(&tree, iblock, NULL);
++      if (IS_ERR(path)) {
++              err = PTR_ERR(path);
++              path = NULL;
++              goto out2;
++      }
++
++      depth = EXT_DEPTH(&tree);
++
++      /*
++       * consistent leaf must not be empty
++       * this situations is possible, though, _during_ tree modification
++       * this is why assert can't be put in ext3_ext_find_extent()
++       */
++      EXT_ASSERT(path[depth].p_ext != NULL || depth == 0);
++
++      if ((ex = path[depth].p_ext)) {
++              /* if found exent covers block, simple return it */
++              if (iblock >= ex->ee_block && iblock < ex->ee_block + ex->ee_len) {
++                      newblock = iblock - ex->ee_block + ex->ee_start;
++                      ext_debug(&tree, "%d fit into %d:%d -> %d\n",
++                                (int) iblock, ex->ee_block, ex->ee_len,
++                                newblock);
++                      ext3_ext_put_in_cache(&tree, ex->ee_block,
++                                            ex->ee_len, ex->ee_start,
++                                            EXT3_EXT_CACHE_EXTENT);
++                      goto out;
++              }
++      }
++
++      /*
++       * requested block isn't allocated yet
++       * we couldn't try to create block if create flag is zero 
++       */
++      if (!create) {
++              /* put just found gap into cache to speedup subsequest reqs */
++              ext3_ext_put_gap_in_cache(&tree, path, iblock);
++              goto out2;
++      }
++
++      /* allocate new block */
++      goal = ext3_ext_find_goal(inode, path, iblock);
++      newblock = ext3_new_block(handle, inode, goal, &err);
++      if (!newblock)
++              goto out2;
++      ext_debug(&tree, "allocate new block: goal %d, found %d\n",
++                goal, newblock);
++
++      /* try to insert new extent into found leaf and return */
++      newex.ee_block = iblock;
++      newex.ee_start = newblock;
++      newex.ee_len = 1;
++      err = ext3_ext_insert_extent(handle, &tree, path, &newex);
++      if (err)
++              goto out2;
++      
++      if (extend_disksize && inode->i_size > EXT3_I(inode)->i_disksize)
++              EXT3_I(inode)->i_disksize = inode->i_size;
++
++      /* previous routine could use block we allocated */
++      newblock = newex.ee_start;
++      set_buffer_new(bh_result);
++
++      ext3_ext_put_in_cache(&tree, newex.ee_block, newex.ee_len,
++                            newex.ee_start, EXT3_EXT_CACHE_EXTENT);
++out:
++      ext3_ext_show_leaf(&tree, path);
++      map_bh(bh_result, inode->i_sb, newblock);
++out2:
++      if (path) {
++              ext3_ext_drop_refs(path);
++              kfree(path);
++      }
++      mutex_unlock(&EXT3_I(inode)->truncate_mutex);
++
++      return err;     
++}
++
++void ext3_ext_truncate(struct inode * inode, struct page *page)
++{
++      struct address_space *mapping = inode->i_mapping;
++      struct super_block *sb = inode->i_sb;
++      struct ext3_extents_tree tree;
++      unsigned long last_block;
++      handle_t *handle;
++      int err = 0;
++
++      ext3_init_tree_desc(&tree, inode);
++
++      /*
++       * probably first extent we're gonna free will be last in block
++       */
++      err = ext3_writepage_trans_blocks(inode) + 3;
++      handle = ext3_journal_start(inode, err);
++      if (IS_ERR(handle)) {
++              if (page) {
++                      clear_highpage(page);
++                      flush_dcache_page(page);
++                      unlock_page(page);
++                      page_cache_release(page);
++              }
++              return;
++      }
++
++      if (page)
++              ext3_block_truncate_page(handle, page, mapping, inode->i_size);
++
++      mutex_lock(&EXT3_I(inode)->truncate_mutex);
++      ext3_ext_invalidate_cache(&tree);
++
++      /* 
++       * TODO: optimization is possible here
++       * probably we need not scaning at all,
++       * because page truncation is enough
++       */
++      if (ext3_orphan_add(handle, inode))
++              goto out_stop;
++
++      /* we have to know where to truncate from in crash case */
++      EXT3_I(inode)->i_disksize = inode->i_size;
++      ext3_mark_inode_dirty(handle, inode);
++
++      last_block = (inode->i_size + sb->s_blocksize - 1) >>
++                      EXT3_BLOCK_SIZE_BITS(sb);
++      err = ext3_ext_remove_space(&tree, last_block, EXT_MAX_BLOCK);
++      
++      /* In a multi-transaction truncate, we only make the final
++       * transaction synchronous */
++      if (IS_SYNC(inode))
++              handle->h_sync = 1;
++
++out_stop:
++      /*
++       * If this was a simple ftruncate(), and the file will remain alive
++       * then we need to clear up the orphan record which we created above.
++       * However, if this was a real unlink then we were called by
++       * ext3_delete_inode(), and we allow that function to clean up the
++       * orphan info for us.
++       */
++      if (inode->i_nlink)
++              ext3_orphan_del(handle, inode);
++
++      mutex_unlock(&EXT3_I(inode)->truncate_mutex);
++      ext3_journal_stop(handle);
++}
++
++/*
++ * this routine calculate max number of blocks we could modify
++ * in order to allocate new block for an inode
++ */
++int ext3_ext_writepage_trans_blocks(struct inode *inode, int num)
++{
++      struct ext3_extents_tree tree;
++      int needed;
++      
++      ext3_init_tree_desc(&tree, inode);
++      
++      needed = ext3_ext_calc_credits_for_insert(&tree, NULL);
++
++      /* caller want to allocate num blocks */
++      needed *= num;
++      
++#ifdef CONFIG_QUOTA
++      /* 
++       * FIXME: real calculation should be here
++       * it depends on blockmap format of qouta file
++       */
++      needed += 2 * EXT3_SINGLEDATA_TRANS_BLOCKS;
++#endif
++
++      return needed;
++}
++
++void ext3_extents_initialize_blockmap(handle_t *handle, struct inode *inode)
++{
++      struct ext3_extents_tree tree;
++
++      ext3_init_tree_desc(&tree, inode);
++      ext3_extent_tree_init(handle, &tree);
++}
++
++int ext3_ext_calc_blockmap_metadata(struct inode *inode, int blocks)
++{
++      struct ext3_extents_tree tree;
++
++      ext3_init_tree_desc(&tree, inode);
++      return ext3_ext_calc_metadata_amount(&tree, blocks);
++}
++      
++static int
++ext3_ext_store_extent_cb(struct ext3_extents_tree *tree,
++                       struct ext3_ext_path *path,
++                       struct ext3_ext_cache *newex)
++{
++      struct ext3_extent_buf *buf = (struct ext3_extent_buf *) tree->private;
++
++      if (newex->ec_type != EXT3_EXT_CACHE_EXTENT)
++              return EXT_CONTINUE;
++
++      if (buf->err < 0)
++              return EXT_BREAK;
++      if (buf->cur - buf->buffer + sizeof(*newex) > buf->buflen)
++              return EXT_BREAK;
++
++      if (!copy_to_user(buf->cur, newex, sizeof(*newex))) {
++              buf->err++;
++              buf->cur += sizeof(*newex);
++      } else {
++              buf->err = -EFAULT;
++              return EXT_BREAK;
++      }
++      return EXT_CONTINUE;
++}
++
++static int
++ext3_ext_collect_stats_cb(struct ext3_extents_tree *tree,
++                        struct ext3_ext_path *path,
++                        struct ext3_ext_cache *ex)
++{
++      struct ext3_extent_tree_stats *buf =
++              (struct ext3_extent_tree_stats *) tree->private;
++      int depth;
++
++      if (ex->ec_type != EXT3_EXT_CACHE_EXTENT)
++              return EXT_CONTINUE;
++
++      depth = EXT_DEPTH(tree);
++      buf->extents_num++;
++      if (path[depth].p_ext == EXT_FIRST_EXTENT(path[depth].p_hdr))
++              buf->leaf_num++;
++      return EXT_CONTINUE;
++}
++
++int ext3_ext_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
++                 unsigned long arg)
++{
++      int err = 0;
++
++      if (!(EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL))
++              return -EINVAL;
++
++      if (cmd == EXT3_IOC_GET_EXTENTS) {
++              struct ext3_extent_buf buf;
++              struct ext3_extents_tree tree;
++
++              if (copy_from_user(&buf, (void *) arg, sizeof(buf)))
++                      return -EFAULT;
++
++              ext3_init_tree_desc(&tree, inode);
++              buf.cur = buf.buffer;
++              buf.err = 0;
++              tree.private = &buf;
++              mutex_lock(&EXT3_I(inode)->truncate_mutex);
++              err = ext3_ext_walk_space(&tree, buf.start, EXT_MAX_BLOCK,
++                                        ext3_ext_store_extent_cb);
++              mutex_unlock(&EXT3_I(inode)->truncate_mutex);
++              if (err == 0)
++                      err = buf.err;
++      } else if (cmd == EXT3_IOC_GET_TREE_STATS) {
++              struct ext3_extent_tree_stats buf;
++              struct ext3_extents_tree tree;
++
++              ext3_init_tree_desc(&tree, inode);
++              mutex_lock(&EXT3_I(inode)->truncate_mutex);
++              buf.depth = EXT_DEPTH(&tree);
++              buf.extents_num = 0;
++              buf.leaf_num = 0;
++              tree.private = &buf;
++              err = ext3_ext_walk_space(&tree, 0, EXT_MAX_BLOCK,
++                                        ext3_ext_collect_stats_cb);
++              mutex_unlock(&EXT3_I(inode)->truncate_mutex);
++              if (!err)
++                      err = copy_to_user((void *) arg, &buf, sizeof(buf));
++      } else if (cmd == EXT3_IOC_GET_TREE_DEPTH) {
++              struct ext3_extents_tree tree;
++              ext3_init_tree_desc(&tree, inode);
++              mutex_lock(&EXT3_I(inode)->truncate_mutex);
++              err = EXT_DEPTH(&tree);
++              mutex_unlock(&EXT3_I(inode)->truncate_mutex);
++      }
++
++      return err;
++}
++
++EXPORT_SYMBOL(ext3_init_tree_desc);
++EXPORT_SYMBOL(ext3_mark_inode_dirty);
++EXPORT_SYMBOL(ext3_ext_invalidate_cache);
++EXPORT_SYMBOL(ext3_ext_insert_extent);
++EXPORT_SYMBOL(ext3_ext_walk_space);
++EXPORT_SYMBOL(ext3_ext_find_goal);
++EXPORT_SYMBOL(ext3_ext_calc_credits_for_insert);
+Index: linux-stage/fs/ext3/ialloc.c
+===================================================================
+--- linux-stage.orig/fs/ext3/ialloc.c  2006-07-16 13:55:31.000000000 +0800
++++ linux-stage/fs/ext3/ialloc.c       2006-07-16 14:10:20.000000000 +0800
+@@ -600,7 +600,7 @@ got:
+       ei->i_dir_start_lookup = 0;
+       ei->i_disksize = 0;
+-      ei->i_flags = EXT3_I(dir)->i_flags & ~EXT3_INDEX_FL;
++      ei->i_flags = EXT3_I(dir)->i_flags & ~(EXT3_INDEX_FL|EXT3_EXTENTS_FL);
+       if (S_ISLNK(mode))
+               ei->i_flags &= ~(EXT3_IMMUTABLE_FL|EXT3_APPEND_FL);
+       /* dirsync only applies to directories */
+@@ -644,6 +644,18 @@ got:
+       if (err)
+               goto fail_free_drop;
++      if (test_opt(sb, EXTENTS) && S_ISREG(inode->i_mode)) {
++              EXT3_I(inode)->i_flags |= EXT3_EXTENTS_FL;
++              ext3_extents_initialize_blockmap(handle, inode);
++              if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_EXTENTS)) {
++                      err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
++                      if (err) goto fail;
++                      EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_EXTENTS);
++                      BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "call ext3_journal_dirty_metadata");
++                      err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
++              }
++      }
++
+       err = ext3_mark_inode_dirty(handle, inode);
+       if (err) {
+               ext3_std_error(sb, err);
+Index: linux-stage/fs/ext3/inode.c
+===================================================================
+--- linux-stage.orig/fs/ext3/inode.c   2006-07-16 13:55:31.000000000 +0800
++++ linux-stage/fs/ext3/inode.c        2006-07-16 14:11:28.000000000 +0800
+@@ -40,7 +40,7 @@
+ #include "iopen.h"
+ #include "acl.h"
+-static int ext3_writepage_trans_blocks(struct inode *inode);
++int ext3_writepage_trans_blocks(struct inode *inode);
+ /*
+  * Test whether an inode is a fast symlink.
+@@ -944,6 +944,17 @@ out:
+ #define DIO_CREDITS (EXT3_RESERVE_TRANS_BLOCKS + 32)
++static inline int
++ext3_get_block_wrap(handle_t *handle, struct inode *inode, long block,
++                  struct buffer_head *bh, int create, int extend_disksize)
++{
++      if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
++              return ext3_ext_get_block(handle, inode, block, bh, create,
++                                        extend_disksize);
++      return ext3_get_blocks_handle(handle, inode, block, 1, bh, create,
++                                   extend_disksize);
++}
++
+ static int ext3_get_block(struct inode *inode, sector_t iblock,
+                       struct buffer_head *bh_result, int create)
+ {
+@@ -984,8 +995,8 @@ static int ext3_get_block(struct inode *
+ get_block:
+       if (ret == 0) {
+-              ret = ext3_get_blocks_handle(handle, inode, iblock,
+-                                      max_blocks, bh_result, create, 0);
++              ret = ext3_get_block_wrap(handle, inode, iblock,
++                                              bh_result, create, 0);
+               if (ret > 0) {
+                       bh_result->b_size = (ret << inode->i_blkbits);
+                       ret = 0;
+@@ -1008,7 +1019,7 @@ struct buffer_head *ext3_getblk(handle_t
+       dummy.b_state = 0;
+       dummy.b_blocknr = -1000;
+       buffer_trace_init(&dummy.b_history);
+-      err = ext3_get_blocks_handle(handle, inode, block, 1,
++      err = ext3_get_block_wrap(handle, inode, block,
+                                       &dummy, create, 1);
+       if (err == 1) {
+               err = 0;
+@@ -1756,7 +1767,7 @@ void ext3_set_aops(struct inode *inode)
+  * This required during truncate. We need to physically zero the tail end
+  * of that block so it doesn't yield old data if the file is later grown.
+  */
+-static int ext3_block_truncate_page(handle_t *handle, struct page *page,
++int ext3_block_truncate_page(handle_t *handle, struct page *page,
+               struct address_space *mapping, loff_t from)
+ {
+       ext3_fsblk_t index = from >> PAGE_CACHE_SHIFT;
+@@ -2260,6 +2271,9 @@ void ext3_truncate(struct inode *inode)
+                       return;
+       }
++      if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
++              return ext3_ext_truncate(inode, page);
++
+       handle = start_transaction(inode);
+       if (IS_ERR(handle)) {
+               if (page) {
+@@ -3004,12 +3018,15 @@ err_out:
+  * block and work out the exact number of indirects which are touched.  Pah.
+  */
+-static int ext3_writepage_trans_blocks(struct inode *inode)
++int ext3_writepage_trans_blocks(struct inode *inode)
+ {
+       int bpp = ext3_journal_blocks_per_page(inode);
+       int indirects = (EXT3_NDIR_BLOCKS % bpp) ? 5 : 3;
+       int ret;
++      if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
++              return ext3_ext_writepage_trans_blocks(inode, bpp);
++
+       if (ext3_should_journal_data(inode))
+               ret = 3 * (bpp + indirects) + 2;
+       else
+@@ -3277,7 +3294,7 @@ int ext3_prep_san_write(struct inode *in
+       /* alloc blocks one by one */
+       for (i = 0; i < nblocks; i++) {
+-              ret = ext3_get_block_handle(handle, inode, blocks[i],
++              ret = ext3_get_blocks_handle(handle, inode, blocks[i], 1,
+                                               &bh_tmp, 1, 1);
+               if (ret)
+                       break;
+@@ -3337,7 +3354,7 @@ int ext3_map_inode_page(struct inode *in
+                 if (blocks[i] != 0)
+                         continue;
+-                rc = ext3_get_block_handle(handle, inode, iblock, &dummy, 1, 1);
++                rc = ext3_get_blocks_handle(handle, inode, iblock, 1, &dummy, 1, 1);
+                 if (rc) {
+                         printk(KERN_INFO "ext3_map_inode_page: error reading "
+                                "block %ld\n", iblock);
+Index: linux-stage/fs/ext3/Makefile
+===================================================================
+--- linux-stage.orig/fs/ext3/Makefile  2006-07-16 13:55:31.000000000 +0800
++++ linux-stage/fs/ext3/Makefile       2006-07-16 14:10:21.000000000 +0800
+@@ -5,7 +5,8 @@
+ obj-$(CONFIG_EXT3_FS) += ext3.o
+ ext3-y        := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
+-         ioctl.o namei.o super.o symlink.o hash.o resize.o
++         ioctl.o namei.o super.o symlink.o hash.o resize.o \
++         extents.o
+ ext3-$(CONFIG_EXT3_FS_XATTR)   += xattr.o xattr_user.o xattr_trusted.o
+ ext3-$(CONFIG_EXT3_FS_POSIX_ACL) += acl.o
+Index: linux-stage/fs/ext3/super.c
+===================================================================
+--- linux-stage.orig/fs/ext3/super.c   2006-07-16 13:55:31.000000000 +0800
++++ linux-stage/fs/ext3/super.c        2006-07-16 14:10:21.000000000 +0800
+@@ -391,6 +391,7 @@ static void ext3_put_super (struct super
+       struct ext3_super_block *es = sbi->s_es;
+       int i;
++      ext3_ext_release(sb);
+       ext3_xattr_put_super(sb);
+       journal_destroy(sbi->s_journal);
+       if (!(sb->s_flags & MS_RDONLY)) {
+@@ -455,6 +456,8 @@ static struct inode *ext3_alloc_inode(st
+ #endif
+       ei->i_block_alloc_info = NULL;
+       ei->vfs_inode.i_version = 1;
++      
++      memset(&ei->i_cached_extent, 0, sizeof(ei->i_cached_extent));
+       return &ei->vfs_inode;
+ }
+@@ -638,6 +641,7 @@ enum {
+       Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
+       Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
+       Opt_iopen, Opt_noiopen, Opt_iopen_nopriv,
++      Opt_extents, Opt_extdebug,
+       Opt_grpquota
+ };
+@@ -690,6 +694,8 @@ static match_table_t tokens = {
+       {Opt_iopen, "iopen"},
+       {Opt_noiopen, "noiopen"},
+       {Opt_iopen_nopriv, "iopen_nopriv"},
++      {Opt_extents, "extents"},
++      {Opt_extdebug, "extdebug"},
+       {Opt_barrier, "barrier=%u"},
+       {Opt_err, NULL},
+       {Opt_resize, "resize"},
+@@ -1035,6 +1041,12 @@ clear_qf_name:
+               case Opt_bh:
+                       clear_opt(sbi->s_mount_opt, NOBH);
+                       break;
++              case Opt_extents:
++                      set_opt (sbi->s_mount_opt, EXTENTS);
++                      break;
++              case Opt_extdebug:
++                      set_opt (sbi->s_mount_opt, EXTDEBUG);
++                      break;
+               default:
+                       printk (KERN_ERR
+                               "EXT3-fs: Unrecognized mount option \"%s\" "
+@@ -1760,6 +1772,7 @@ static int ext3_fill_super (struct super
+               test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered":
+               "writeback");
++      ext3_ext_init(sb);
+       lock_kernel();
+       return 0;
+Index: linux-stage/fs/ext3/ioctl.c
+===================================================================
+--- linux-stage.orig/fs/ext3/ioctl.c   2006-07-16 13:55:31.000000000 +0800
++++ linux-stage/fs/ext3/ioctl.c        2006-07-16 13:55:31.000000000 +0800
+@@ -135,6 +135,10 @@ flags_err:
+               mutex_unlock(&inode->i_mutex);
+               return err;
+       }
++      case EXT3_IOC_GET_EXTENTS:
++      case EXT3_IOC_GET_TREE_STATS:
++      case EXT3_IOC_GET_TREE_DEPTH:
++              return ext3_ext_ioctl(inode, filp, cmd, arg);
+       case EXT3_IOC_GETVERSION:
+       case EXT3_IOC_GETVERSION_OLD:
+               return put_user(inode->i_generation, (int __user *) arg);
+Index: linux-stage/include/linux/ext3_fs.h
+===================================================================
+--- linux-stage.orig/include/linux/ext3_fs.h   2006-07-16 13:55:31.000000000 +0800
++++ linux-stage/include/linux/ext3_fs.h        2006-07-16 14:10:21.000000000 +0800
+@@ -181,9 +181,10 @@ struct ext3_group_desc
+ #define EXT3_NOTAIL_FL                        0x00008000 /* file tail should not be merged */
+ #define EXT3_DIRSYNC_FL                       0x00010000 /* dirsync behaviour (directories only) */
+ #define EXT3_TOPDIR_FL                        0x00020000 /* Top of directory hierarchies*/
++#define EXT3_EXTENTS_FL                       0x00080000 /* Inode uses extents */
+ #define EXT3_RESERVED_FL              0x80000000 /* reserved for ext3 lib */
+-#define EXT3_FL_USER_VISIBLE          0x0003DFFF /* User visible flags */
++#define EXT3_FL_USER_VISIBLE          0x000BDFFF /* User visible flags */
+ #define EXT3_FL_USER_MODIFIABLE               0x000380FF /* User modifiable flags */
+ /*
+@@ -233,6 +234,9 @@ struct ext3_new_group_data {
+ #endif
+ #define EXT3_IOC_GETRSVSZ             _IOR('f', 5, long)
+ #define EXT3_IOC_SETRSVSZ             _IOW('f', 6, long)
++#define EXT3_IOC_GET_EXTENTS          _IOR('f', 7, long)
++#define EXT3_IOC_GET_TREE_DEPTH               _IOR('f', 8, long)
++#define EXT3_IOC_GET_TREE_STATS               _IOR('f', 9, long)
+ /*
+  *  Mount options
+@@ -373,6 +377,8 @@ struct ext3_inode {
+ #define EXT3_MOUNT_GRPQUOTA           0x200000 /* "old" group quota */
+ #define EXT3_MOUNT_IOPEN              0x400000        /* Allow access via iopen */
+ #define EXT3_MOUNT_IOPEN_NOPRIV               0x800000/* Make iopen world-readable */
++#define EXT3_MOUNT_EXTENTS            0x1000000/* Extents support */
++#define EXT3_MOUNT_EXTDEBUG           0x2000000/* Extents debug */
+ /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
+ #ifndef clear_opt
+@@ -563,11 +569,13 @@ static inline struct ext3_inode_info *EX
+ #define EXT3_FEATURE_INCOMPAT_RECOVER         0x0004 /* Needs recovery */
+ #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV     0x0008 /* Journal device */
+ #define EXT3_FEATURE_INCOMPAT_META_BG         0x0010
++#define EXT3_FEATURE_INCOMPAT_EXTENTS         0x0040 /* extents support */
+ #define EXT3_FEATURE_COMPAT_SUPP      EXT2_FEATURE_COMPAT_EXT_ATTR
+ #define EXT3_FEATURE_INCOMPAT_SUPP    (EXT3_FEATURE_INCOMPAT_FILETYPE| \
+                                        EXT3_FEATURE_INCOMPAT_RECOVER| \
+-                                       EXT3_FEATURE_INCOMPAT_META_BG)
++                                       EXT3_FEATURE_INCOMPAT_META_BG| \
++                                       EXT3_FEATURE_INCOMPAT_EXTENTS)
+ #define EXT3_FEATURE_RO_COMPAT_SUPP   (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
+                                        EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \
+                                        EXT3_FEATURE_RO_COMPAT_BTREE_DIR)
+@@ -787,6 +795,8 @@ extern unsigned long ext3_count_free (st
+ /* inode.c */
++extern int ext3_block_truncate_page(handle_t *, struct page *,
++                                      struct address_space *, loff_t);
+ int ext3_forget(handle_t *handle, int is_metadata, struct inode *inode,
+               struct buffer_head *bh, ext3_fsblk_t blocknr);
+ struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
+@@ -860,6 +870,16 @@ extern struct inode_operations ext3_spec
+ extern struct inode_operations ext3_symlink_inode_operations;
+ extern struct inode_operations ext3_fast_symlink_inode_operations;
++/* extents.c */
++extern int ext3_ext_writepage_trans_blocks(struct inode *, int);
++extern int ext3_ext_get_block(handle_t *, struct inode *, long,
++                            struct buffer_head *, int, int);
++extern void ext3_ext_truncate(struct inode *, struct page *);
++extern void ext3_ext_init(struct super_block *);
++extern void ext3_ext_release(struct super_block *);
++extern void ext3_extents_initialize_blockmap(handle_t *, struct inode *);
++extern int ext3_ext_ioctl(struct inode *inode, struct file *filp,
++                        unsigned int cmd, unsigned long arg);
+ #endif        /* __KERNEL__ */
+Index: linux-stage/include/linux/ext3_extents.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-stage/include/linux/ext3_extents.h   2006-07-16 13:55:31.000000000 +0800
+@@ -0,0 +1,264 @@
++/*
++ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com
++ * Written by Alex Tomas <alex@clusterfs.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public Licens
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-
++ */
++
++#ifndef _LINUX_EXT3_EXTENTS
++#define _LINUX_EXT3_EXTENTS
++
++/*
++ * with AGRESSIVE_TEST defined capacity of index/leaf blocks
++ * become very little, so index split, in-depth growing and
++ * other hard changes happens much more often
++ * this is for debug purposes only
++ */
++#define AGRESSIVE_TEST_
++
++/*
++ * if CHECK_BINSEARCH defined, then results of binary search
++ * will be checked by linear search
++ */
++#define CHECK_BINSEARCH_
++
++/*
++ * if EXT_DEBUG is defined you can use 'extdebug' mount option
++ * to get lots of info what's going on
++ */
++#define EXT_DEBUG_
++#ifdef EXT_DEBUG
++#define ext_debug(tree,fmt,a...)                      \
++do {                                                  \
++      if (test_opt((tree)->inode->i_sb, EXTDEBUG))    \
++              printk(fmt, ##a);                       \
++} while (0);
++#else
++#define ext_debug(tree,fmt,a...)
++#endif
++
++/*
++ * if EXT_STATS is defined then stats numbers are collected
++ * these number will be displayed at umount time
++ */
++#define EXT_STATS_
++
++
++#define EXT3_ALLOC_NEEDED     3       /* block bitmap + group desc. + sb */
++
++/*
++ * ext3_inode has i_block array (total 60 bytes)
++ * first 4 bytes are used to store:
++ *  - tree depth (0 mean there is no tree yet. all extents in the inode)
++ *  - number of alive extents in the inode
++ */
++
++/*
++ * this is extent on-disk structure
++ * it's used at the bottom of the tree
++ */
++struct ext3_extent {
++      __u32   ee_block;       /* first logical block extent covers */
++      __u16   ee_len;         /* number of blocks covered by extent */
++      __u16   ee_start_hi;    /* high 16 bits of physical block */
++      __u32   ee_start;       /* low 32 bigs of physical block */
++};
++
++/*
++ * this is index on-disk structure
++ * it's used at all the levels, but the bottom
++ */
++struct ext3_extent_idx {
++      __u32   ei_block;       /* index covers logical blocks from 'block' */
++      __u32   ei_leaf;        /* pointer to the physical block of the next *
++                               * level. leaf or next index could bet here */
++      __u16   ei_leaf_hi;     /* high 16 bits of physical block */
++      __u16   ei_unused;
++};
++
++/*
++ * each block (leaves and indexes), even inode-stored has header
++ */
++struct ext3_extent_header {   
++      __u16   eh_magic;       /* probably will support different formats */   
++      __u16   eh_entries;     /* number of valid entries */
++      __u16   eh_max;         /* capacity of store in entries */
++      __u16   eh_depth;       /* has tree real underlaying blocks? */
++      __u32   eh_generation;  /* generation of the tree */
++};
++
++#define EXT3_EXT_MAGIC                0xf30a
++
++/*
++ * array of ext3_ext_path contains path to some extent
++ * creation/lookup routines use it for traversal/splitting/etc
++ * truncate uses it to simulate recursive walking
++ */
++struct ext3_ext_path {
++      __u32                           p_block;
++      __u16                           p_depth;
++      struct ext3_extent              *p_ext;
++      struct ext3_extent_idx          *p_idx;
++      struct ext3_extent_header       *p_hdr;
++      struct buffer_head              *p_bh;
++};
++
++/*
++ * structure for external API
++ */
++
++/*
++ * storage for cached extent
++ */
++struct ext3_ext_cache {
++      __u32   ec_start;
++      __u32   ec_block;
++      __u32   ec_len;
++      __u32   ec_type;
++};
++
++#define EXT3_EXT_CACHE_NO     0
++#define EXT3_EXT_CACHE_GAP    1
++#define EXT3_EXT_CACHE_EXTENT 2
++
++/*
++ * ext3_extents_tree is used to pass initial information
++ * to top-level extents API
++ */
++struct ext3_extents_helpers;
++struct ext3_extents_tree {
++      struct inode *inode;    /* inode which tree belongs to */
++      void *root;             /* ptr to data top of tree resides at */
++      void *buffer;           /* will be passed as arg to ^^ routines */
++      int buffer_len;
++      void *private;
++      struct ext3_ext_cache *cex;/* last found extent */
++      struct ext3_extents_helpers *ops;
++};
++
++struct ext3_extents_helpers {
++      int (*get_write_access)(handle_t *h, void *buffer);
++      int (*mark_buffer_dirty)(handle_t *h, void *buffer);
++      int (*mergable)(struct ext3_extent *ex1, struct ext3_extent *ex2);
++      int (*remove_extent_credits)(struct ext3_extents_tree *,
++                                   struct ext3_extent *, unsigned long,
++                                   unsigned long);
++      int (*remove_extent)(struct ext3_extents_tree *,
++                           struct ext3_extent *, unsigned long,
++                           unsigned long);
++      int (*new_block)(handle_t *, struct ext3_extents_tree *,
++                       struct ext3_ext_path *, struct ext3_extent *,
++                       int *);
++};
++
++/*
++ * to be called by ext3_ext_walk_space()
++ * negative retcode - error
++ * positive retcode - signal for ext3_ext_walk_space(), see below
++ * callback must return valid extent (passed or newly created)
++ */
++typedef int (*ext_prepare_callback)(struct ext3_extents_tree *,
++                                  struct ext3_ext_path *,
++                                  struct ext3_ext_cache *);
++
++#define EXT_CONTINUE  0
++#define EXT_BREAK     1
++#define EXT_REPEAT    2
++
++
++#define EXT_MAX_BLOCK 0xffffffff
++
++
++#define EXT_FIRST_EXTENT(__hdr__) \
++      ((struct ext3_extent *) (((char *) (__hdr__)) +         \
++                               sizeof(struct ext3_extent_header)))
++#define EXT_FIRST_INDEX(__hdr__) \
++      ((struct ext3_extent_idx *) (((char *) (__hdr__)) +     \
++                                   sizeof(struct ext3_extent_header)))
++#define EXT_HAS_FREE_INDEX(__path__) \
++      ((__path__)->p_hdr->eh_entries < (__path__)->p_hdr->eh_max)
++#define EXT_LAST_EXTENT(__hdr__) \
++      (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_entries - 1)
++#define EXT_LAST_INDEX(__hdr__) \
++      (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_entries - 1)
++#define EXT_MAX_EXTENT(__hdr__) \
++      (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_max - 1)
++#define EXT_MAX_INDEX(__hdr__) \
++      (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_max - 1)
++
++#define EXT_ROOT_HDR(tree) \
++      ((struct ext3_extent_header *) (tree)->root)
++#define EXT_BLOCK_HDR(bh) \
++      ((struct ext3_extent_header *) (bh)->b_data)
++#define EXT_DEPTH(_t_)        \
++      (((struct ext3_extent_header *)((_t_)->root))->eh_depth)
++#define EXT_GENERATION(_t_)   \
++      (((struct ext3_extent_header *)((_t_)->root))->eh_generation)
++
++
++#define EXT_ASSERT(__x__) if (!(__x__)) BUG();
++
++#define EXT_CHECK_PATH(tree,path)                                     \
++{                                                                     \
++      int depth = EXT_DEPTH(tree);                                    \
++      BUG_ON((unsigned long) (path) < __PAGE_OFFSET);                 \
++      BUG_ON((unsigned long) (path)[depth].p_idx <                    \
++                      __PAGE_OFFSET && (path)[depth].p_idx != NULL);  \
++      BUG_ON((unsigned long) (path)[depth].p_ext <                    \
++                      __PAGE_OFFSET && (path)[depth].p_ext != NULL);  \
++      BUG_ON((unsigned long) (path)[depth].p_hdr < __PAGE_OFFSET);    \
++      BUG_ON((unsigned long) (path)[depth].p_bh < __PAGE_OFFSET       \
++                      && depth != 0);                                 \
++      BUG_ON((path)[0].p_depth != depth);                             \
++}
++
++
++/*
++ * this structure is used to gather extents from the tree via ioctl
++ */
++struct ext3_extent_buf {
++      unsigned long start;
++      int buflen;
++      void *buffer;
++      void *cur;
++      int err;
++};
++
++/*
++ * this structure is used to collect stats info about the tree
++ */
++struct ext3_extent_tree_stats {
++      int depth;
++      int extents_num;
++      int leaf_num;
++};
++
++extern void ext3_init_tree_desc(struct ext3_extents_tree *, struct inode *);
++extern int ext3_extent_tree_init(handle_t *, struct ext3_extents_tree *);
++extern int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *, struct ext3_ext_path *);
++extern int ext3_ext_insert_extent(handle_t *, struct ext3_extents_tree *, struct ext3_ext_path *, struct ext3_extent *);
++extern int ext3_ext_walk_space(struct ext3_extents_tree *, unsigned long, unsigned long, ext_prepare_callback);
++extern int ext3_ext_remove_space(struct ext3_extents_tree *, unsigned long, unsigned long);
++extern struct ext3_ext_path * ext3_ext_find_extent(struct ext3_extents_tree *, int, struct ext3_ext_path *);
++extern int ext3_ext_calc_blockmap_metadata(struct inode *, int);
++
++static inline void
++ext3_ext_invalidate_cache(struct ext3_extents_tree *tree)
++{
++      if (tree->cex)
++              tree->cex->ec_type = EXT3_EXT_CACHE_NO;
++}
++
++
++#endif /* _LINUX_EXT3_EXTENTS */
+Index: linux-stage/include/linux/ext3_fs_i.h
+===================================================================
+--- linux-stage.orig/include/linux/ext3_fs_i.h 2006-07-16 13:55:30.000000000 +0800
++++ linux-stage/include/linux/ext3_fs_i.h      2006-07-16 14:10:20.000000000 +0800
+@@ -142,6 +142,8 @@ struct ext3_inode_info {
+        */
+       struct mutex truncate_mutex;
+       struct inode vfs_inode;
++
++      __u32 i_cached_extent[4];
+ };
+ #endif        /* _LINUX_EXT3_FS_I */
index 9e78214..b6c37c1 100644 (file)
@@ -3,7 +3,7 @@ Index: linux-2.6.5-sles9/fs/ext3/extents.c
 ===================================================================
 --- linux-2.6.5-sles9.orig/fs/ext3/extents.c   2005-02-17 22:07:57.023609040 +0300
 +++ linux-2.6.5-sles9/fs/ext3/extents.c        2005-02-23 01:02:37.396435640 +0300
-@@ -0,0 +1,2355 @@
+@@ -0,0 +1,2361 @@
 +/*
 + * Copyright(c) 2003, 2004, 2005, Cluster File Systems, Inc, info@clusterfs.com
 + * Written by Alex Tomas <alex@clusterfs.com>
@@ -179,7 +179,7 @@ Index: linux-2.6.5-sles9/fs/ext3/extents.c
 +{
 +      struct ext3_extent_header *neh = EXT_ROOT_HDR(tree);
 +      neh->eh_generation = ((EXT_FLAGS(neh) & ~EXT_FLAGS_CLR_UNKNOWN) << 24) |
-+                           (EXT_GENERATION(neh) + 1);
++                           (EXT_HDR_GEN(neh) + 1);
 +}
 +
 +static inline int ext3_ext_space_block(struct ext3_extents_tree *tree)
@@ -561,6 +561,7 @@ Index: linux-2.6.5-sles9/fs/ext3/extents.c
 +
 +      ix->ei_block = logical;
 +      ix->ei_leaf = ptr;
++      ix->ei_leaf_hi = ix->ei_unused = 0;
 +      curp->p_hdr->eh_entries++;
 +
 +      EXT_ASSERT(curp->p_hdr->eh_entries <= curp->p_hdr->eh_max);
@@ -723,6 +724,7 @@ Index: linux-2.6.5-sles9/fs/ext3/extents.c
 +              fidx = EXT_FIRST_INDEX(neh);
 +              fidx->ei_block = border;
 +              fidx->ei_leaf = oldblock;
++              fidx->ei_leaf_hi = fidx->ei_unused = 0;
 +
 +              ext_debug(tree, "int.index at %d (block %lu): %lu -> %lu\n",
 +                        i, newblock, border, oldblock);
@@ -856,6 +858,7 @@ Index: linux-2.6.5-sles9/fs/ext3/extents.c
 +      /* FIXME: it works, but actually path[0] can be index */
 +      curp->p_idx->ei_block = EXT_FIRST_EXTENT(path[0].p_hdr)->ee_block;
 +      curp->p_idx->ei_leaf = newblock;
++      curp->p_idx->ei_leaf_hi = curp->p_idx->ei_unused = 0;
 +
 +      neh = EXT_ROOT_HDR(tree);
 +      fidx = EXT_FIRST_INDEX(neh);
@@ -1404,6 +1407,7 @@ Index: linux-2.6.5-sles9/fs/ext3/extents.c
 +      if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) {
 +              ex->ee_block = cex->ec_block;
 +              ex->ee_start = cex->ec_start;
++              ex->ee_start_hi = 0;
 +              ex->ee_len = cex->ec_len;
 +              ext_debug(tree, "%lu cached by %lu:%lu:%lu\n",
 +                        (unsigned long) block,
@@ -1625,7 +1629,7 @@ Index: linux-2.6.5-sles9/fs/ext3/extents.c
 +
 +              if (num == 0) {
 +                      /* this extent is removed entirely mark slot unused */
-+                      ex->ee_start = 0;
++                      ex->ee_start = ex->ee_start_hi = 0;
 +                      eh->eh_entries--;
 +                      fu = ex;
 +              }
@@ -1647,7 +1651,7 @@ Index: linux-2.6.5-sles9/fs/ext3/extents.c
 +              while (lu < le) {
 +                      if (lu->ee_start) {
 +                              *fu = *lu;
-+                              lu->ee_start = 0;
++                              lu->ee_start = lu->ee_start_hi = 0;
 +                              fu++;
 +                      }
 +                      lu++;
@@ -2002,6 +2006,7 @@ Index: linux-2.6.5-sles9/fs/ext3/extents.c
 +              /* allocate new block for the extent */
 +              goal = ext3_ext_find_goal(inode, path, ex->ee_block);
 +              ex->ee_start = ext3_new_block(handle, inode, goal, err);
++              ex->ee_start_hi = 0;
 +              if (ex->ee_start == 0) {
 +                      /* error occured: restore old extent */
 +                      ex->ee_start = newblock;
@@ -2117,6 +2122,7 @@ Index: linux-2.6.5-sles9/fs/ext3/extents.c
 +      /* try to insert new extent into found leaf and return */
 +      newex.ee_block = iblock;
 +      newex.ee_start = newblock;
++      newex.ee_start_hi = 0;
 +      newex.ee_len = 1;
 +      err = ext3_ext_insert_extent(handle, &tree, path, &newex);
 +      if (err)
@@ -2512,26 +2518,30 @@ Index: linux-2.6.5-sles9/fs/ext3/super.c
        Opt_ignore, Opt_barrier,
        Opt_err,
        Opt_iopen, Opt_noiopen, Opt_iopen_nopriv,
-+      Opt_extents, Opt_extdebug,
++      Opt_extents, Opt_noextents, Opt_extdebug,
  };
  
  static match_table_t tokens = {
-@@ -582,6 +585,8 @@
+@@ -582,6 +585,9 @@
        {Opt_iopen, "iopen"},
        {Opt_noiopen, "noiopen"},
        {Opt_iopen_nopriv, "iopen_nopriv"},
 +      {Opt_extents, "extents"},
++      {Opt_noextents, "noextents"},
 +      {Opt_extdebug, "extdebug"},
        {Opt_barrier, "barrier=%u"},
        {Opt_err, NULL}
  };
-@@ -797,6 +802,12 @@
+@@ -797,6 +802,15 @@
                        break;
                case Opt_ignore:
                        break;
 +              case Opt_extents:
 +                      set_opt (sbi->s_mount_opt, EXTENTS);
 +                      break;
++              case Opt_noextents:
++                      clear_opt (sbi->s_mount_opt, EXTENTS);
++                      break;
 +              case Opt_extdebug:
 +                      set_opt (sbi->s_mount_opt, EXTDEBUG);
 +                      break;
@@ -2611,11 +2621,13 @@ Index: linux-2.6.5-sles9/include/linux/ext3_fs.h
  #define EXT3_FEATURE_RO_COMPAT_SUPP   (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
                                         EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \
                                         EXT3_FEATURE_RO_COMPAT_BTREE_DIR)
-@@ -729,6 +735,7 @@
+@@ -729,6 +735,9 @@
  
  
  /* inode.c */
-+extern int ext3_block_truncate_page(handle_t *, struct page *, struct address_space *, loff_t);
++extern int ext3_block_truncate_page(handle_t *, struct page *,
++                                  struct address_space *, loff_t);
++extern int ext3_writepage_trans_blocks(struct inode *inode);
  extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int);
  extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
  extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
@@ -2839,14 +2851,14 @@ Index: linux-2.6.5-sles9/include/linux/ext3_extents.h
 +      (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_max - 1)
 +#define EXT_MAX_INDEX(__hdr__) \
 +      (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_max - 1)
-+#define EXT_GENERATION(__hdr__) ((__hdr__)->eh_generation & 0x00ffffff)
++#define EXT_HDR_GEN(__hdr__)  ((__hdr__)->eh_generation & 0x00ffffff)
 +#define EXT_FLAGS(__hdr__)    ((__hdr__)->eh_generation >> 24)
 +#define EXT_FLAGS_CLR_UNKNOWN 0x7     /* Flags cleared on modification */
 +
 +#define EXT_BLOCK_HDR(__bh__)         ((struct ext3_extent_header *)(__bh__)->b_data)
 +#define EXT_ROOT_HDR(__tree__)        ((struct ext3_extent_header *)(__tree__)->root)
 +#define EXT_DEPTH(__tree__)   (EXT_ROOT_HDR(__tree__)->eh_depth)
-+
++#define EXT_GENERATION(__tree__) EXT_HDR_GEN(EXT_ROOT_HDR(__tree__))
 +
 +#define EXT_ASSERT(__x__) if (!(__x__)) BUG();
 +
index bd95c54..5b5558c 100644 (file)
@@ -2,7 +2,7 @@ Index: linux-stage/fs/ext3/extents.c
 ===================================================================
 --- linux-stage.orig/fs/ext3/extents.c 2005-02-25 15:33:48.890198160 +0200
 +++ linux-stage/fs/ext3/extents.c      2005-02-25 15:33:48.917194056 +0200
-@@ -0,0 +1,2353 @@
+@@ -0,0 +1,2359 @@
 +/*
 + * Copyright(c) 2003, 2004, 2005, Cluster File Systems, Inc, info@clusterfs.com
 + * Written by Alex Tomas <alex@clusterfs.com>
@@ -178,7 +178,7 @@ Index: linux-stage/fs/ext3/extents.c
 +{
 +      struct ext3_extent_header *neh = EXT_ROOT_HDR(tree);
 +      neh->eh_generation = ((EXT_FLAGS(neh) & ~EXT_FLAGS_CLR_UNKNOWN) << 24) |
-+                           (EXT_GENERATION(neh) + 1);
++                           (EXT_HDR_GEN(neh) + 1);
 +}
 +
 +static inline int ext3_ext_space_block(struct ext3_extents_tree *tree)
@@ -560,6 +560,7 @@ Index: linux-stage/fs/ext3/extents.c
 +
 +      ix->ei_block = logical;
 +      ix->ei_leaf = ptr;
++      ix->ei_leaf_hi = ix->ei_unused = 0;
 +      curp->p_hdr->eh_entries++;
 +
 +      EXT_ASSERT(curp->p_hdr->eh_entries <= curp->p_hdr->eh_max);
@@ -722,6 +723,7 @@ Index: linux-stage/fs/ext3/extents.c
 +              fidx = EXT_FIRST_INDEX(neh);
 +              fidx->ei_block = border;
 +              fidx->ei_leaf = oldblock;
++              fidx->ei_leaf_hi = fidx->ei_unused = 0;
 +
 +              ext_debug(tree, "int.index at %d (block %lu): %lu -> %lu\n",
 +                        i, newblock, border, oldblock);
@@ -855,6 +857,7 @@ Index: linux-stage/fs/ext3/extents.c
 +      /* FIXME: it works, but actually path[0] can be index */
 +      curp->p_idx->ei_block = EXT_FIRST_EXTENT(path[0].p_hdr)->ee_block;
 +      curp->p_idx->ei_leaf = newblock;
++      curp->p_idx->ei_leaf_hi = curp->p_idx->ei_unused = 0;
 +
 +      neh = EXT_ROOT_HDR(tree);
 +      fidx = EXT_FIRST_INDEX(neh);
@@ -1403,6 +1406,7 @@ Index: linux-stage/fs/ext3/extents.c
 +      if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) {
 +              ex->ee_block = cex->ec_block;
 +              ex->ee_start = cex->ec_start;
++              ex->ee_start_hi = 0;
 +              ex->ee_len = cex->ec_len;
 +              ext_debug(tree, "%lu cached by %lu:%lu:%lu\n",
 +                        (unsigned long) block,
@@ -1624,7 +1628,7 @@ Index: linux-stage/fs/ext3/extents.c
 +
 +              if (num == 0) {
 +                      /* this extent is removed entirely mark slot unused */
-+                      ex->ee_start = 0;
++                      ex->ee_start = ex->ee_start_hi = 0;
 +                      eh->eh_entries--;
 +                      fu = ex;
 +              }
@@ -1646,7 +1650,7 @@ Index: linux-stage/fs/ext3/extents.c
 +              while (lu < le) {
 +                      if (lu->ee_start) {
 +                              *fu = *lu;
-+                              lu->ee_start = 0;
++                              lu->ee_start = lu->ee_start_hi = 0;
 +                              fu++;
 +                      }
 +                      lu++;
@@ -2001,6 +2005,7 @@ Index: linux-stage/fs/ext3/extents.c
 +              /* allocate new block for the extent */
 +              goal = ext3_ext_find_goal(inode, path, ex->ee_block);
 +              ex->ee_start = ext3_new_block(handle, inode, goal, err);
++              ex->ee_start_hi = 0;
 +              if (ex->ee_start == 0) {
 +                      /* error occured: restore old extent */
 +                      ex->ee_start = newblock;
@@ -2116,6 +2121,7 @@ Index: linux-stage/fs/ext3/extents.c
 +      /* try to insert new extent into found leaf and return */
 +      newex.ee_block = iblock;
 +      newex.ee_start = newblock;
++      newex.ee_start_hi = 0;
 +      newex.ee_len = 1;
 +      err = ext3_ext_insert_extent(handle, &tree, path, &newex);
 +      if (err)
@@ -2507,26 +2513,30 @@ Index: linux-stage/fs/ext3/super.c
        Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0,
        Opt_ignore, Opt_barrier, Opt_err, Opt_resize,
        Opt_iopen, Opt_noiopen, Opt_iopen_nopriv,
-+      Opt_extents, Opt_extdebug,
++      Opt_extents, Opt_noextents, Opt_extdebug,
  };
  
  static match_table_t tokens = {
-@@ -639,6 +644,8 @@
+@@ -639,6 +644,9 @@
        {Opt_iopen, "iopen"},
        {Opt_noiopen, "noiopen"},
        {Opt_iopen_nopriv, "iopen_nopriv"},
 +      {Opt_extents, "extents"},
++      {Opt_noextents, "noextents"},
 +      {Opt_extdebug, "extdebug"},
        {Opt_barrier, "barrier=%u"},
        {Opt_err, NULL},
        {Opt_resize, "resize"},
-@@ -943,6 +950,12 @@
+@@ -943,6 +950,15 @@
                        match_int(&args[0], &option);
                        *n_blocks_count = option;
                        break;
 +              case Opt_extents:
 +                      set_opt (sbi->s_mount_opt, EXTENTS);
 +                      break;
++              case Opt_noextents:
++                      clear_opt (sbi->s_mount_opt, EXTENTS);
++                      break;
 +              case Opt_extdebug:
 +                      set_opt (sbi->s_mount_opt, EXTDEBUG);
 +                      break;
@@ -2606,11 +2616,13 @@ Index: linux-stage/include/linux/ext3_fs.h
  #define EXT3_FEATURE_RO_COMPAT_SUPP   (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
                                         EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \
                                         EXT3_FEATURE_RO_COMPAT_BTREE_DIR)
-@@ -756,6 +763,7 @@
+@@ -756,6 +763,9 @@
  
  
  /* inode.c */
-+extern int ext3_block_truncate_page(handle_t *, struct page *, struct address_space *, loff_t);
++extern int ext3_block_truncate_page(handle_t *, struct page *,
++                                  struct address_space *, loff_t);
++extern int ext3_writepage_trans_blocks(struct inode *inode);
  extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int);
  extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
  extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
@@ -2834,14 +2846,14 @@ Index: linux-stage/include/linux/ext3_extents.h
 +      (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_max - 1)
 +#define EXT_MAX_INDEX(__hdr__) \
 +      (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_max - 1)
-+#define EXT_GENERATION(__hdr__) ((__hdr__)->eh_generation & 0x00ffffff)
++#define EXT_HDR_GEN(__hdr__)  ((__hdr__)->eh_generation & 0x00ffffff)
 +#define EXT_FLAGS(__hdr__)    ((__hdr__)->eh_generation >> 24)
 +#define EXT_FLAGS_CLR_UNKNOWN 0x7     /* Flags cleared on modification */
 +
 +#define EXT_BLOCK_HDR(__bh__)         ((struct ext3_extent_header *)(__bh__)->b_data)
 +#define EXT_ROOT_HDR(__tree__)        ((struct ext3_extent_header *)(__tree__)->root)
 +#define EXT_DEPTH(__tree__)   (EXT_ROOT_HDR(__tree__)->eh_depth)
-+
++#define EXT_GENERATION(__tree__) EXT_HDR_GEN(EXT_ROOT_HDR(__tree__))
 +
 +#define EXT_ASSERT(__x__) if (!(__x__)) BUG();
 +
diff --git a/lustre/kernel_patches/patches/ext3-external-journal-2.6.9.patch b/lustre/kernel_patches/patches/ext3-external-journal-2.6.9.patch
new file mode 100644 (file)
index 0000000..7cc86f2
--- /dev/null
@@ -0,0 +1,150 @@
+Signed-off-by: Johann Lombardi <johann.lombardi@bull.net>
+
+Index: linux-2.6.9-full/fs/ext3/super.c
+===================================================================
+--- linux-2.6.9-full.orig/fs/ext3/super.c      2006-05-20 01:14:14.000000000 +0400
++++ linux-2.6.9-full/fs/ext3/super.c   2006-05-20 01:17:10.000000000 +0400
+@@ -39,7 +39,8 @@
+ #include "xattr.h"
+ #include "acl.h"
+-static int ext3_load_journal(struct super_block *, struct ext3_super_block *);
++static int ext3_load_journal(struct super_block *, struct ext3_super_block *,
++                           unsigned long journal_devnum);
+ static int ext3_create_journal(struct super_block *, struct ext3_super_block *,
+                              int);
+ static void ext3_commit_super (struct super_block * sb,
+@@ -591,7 +592,7 @@ enum {
+       Opt_nouid32, Opt_check, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov,
+       Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl,
+       Opt_reservation, Opt_noreservation, Opt_noload,
+-      Opt_commit, Opt_journal_update, Opt_journal_inum,
++      Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev,
+       Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
+       Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
+       Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0,
+@@ -630,6 +631,7 @@ static match_table_t tokens = {
+       {Opt_commit, "commit=%u"},
+       {Opt_journal_update, "journal=update"},
+       {Opt_journal_inum, "journal=%u"},
++      {Opt_journal_dev, "journal_dev=%u"},
+       {Opt_abort, "abort"},
+       {Opt_data_journal, "data=journal"},
+       {Opt_data_ordered, "data=ordered"},
+@@ -675,8 +677,9 @@ static unsigned long get_sb_block(void *
+       return sb_block;
+ }
+-static int parse_options (char * options, struct super_block *sb,
+-                        unsigned long * inum, unsigned long *n_blocks_count, int is_remount)
++static int parse_options (char *options, struct super_block *sb,
++                        unsigned long *inum, unsigned long *journal_devnum, 
++                        unsigned long *n_blocks_count, int is_remount)
+ {
+       struct ext3_sb_info *sbi = EXT3_SB(sb);
+       char * p;
+@@ -816,6 +819,16 @@ static int parse_options (char * options
+                               return 0;
+                       *inum = option;
+                       break;
++              case Opt_journal_dev:
++                      if (is_remount) {
++                              printk(KERN_ERR "EXT3-fs: cannot specify "
++                                     "journal on remount\n");
++                              return 0;
++                      }
++                      if (match_int(&args[0], &option))
++                              return 0;
++                      *journal_devnum = option;
++                      break;
+               case Opt_noload:
+                       set_opt (sbi->s_mount_opt, NOLOAD);
+                       break;
+@@ -1278,6 +1291,7 @@ static int ext3_fill_super (struct super
+       unsigned long logic_sb_block;
+       unsigned long offset = 0;
+       unsigned long journal_inum = 0;
++      unsigned long journal_devnum = 0;
+       unsigned long def_mount_opts;
+       struct inode *root;
+       int blocksize;
+@@ -1361,7 +1375,8 @@ static int ext3_fill_super (struct super
+       set_opt(sbi->s_mount_opt, RESERVATION);
+-      if (!parse_options ((char *) data, sb, &journal_inum, NULL, 0))
++      if (!parse_options ((char *) data, sb, &journal_inum, &journal_devnum, 
++                          NULL, 0))
+               goto failed_mount;
+       set_sb_time_gran(sb, 1000000000U);
+@@ -1567,7 +1582,7 @@ static int ext3_fill_super (struct super
+        */
+       if (!test_opt(sb, NOLOAD) &&
+           EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
+-              if (ext3_load_journal(sb, es))
++              if (ext3_load_journal(sb, es, journal_devnum))
+                       goto failed_mount2;
+       } else if (journal_inum) {
+               if (ext3_create_journal(sb, es, journal_inum))
+@@ -1831,15 +1846,24 @@ out_bdev:
+       return NULL;
+ }
+-static int ext3_load_journal(struct super_block * sb,
+-                           struct ext3_super_block * es)
++static int ext3_load_journal(struct super_block *sb,
++                           struct ext3_super_block *es,
++                           unsigned long journal_devnum)
+ {
+       journal_t *journal;
+       int journal_inum = le32_to_cpu(es->s_journal_inum);
+-      dev_t journal_dev = new_decode_dev(le32_to_cpu(es->s_journal_dev));
++      dev_t journal_dev;
+       int err = 0;
+       int really_read_only;
++      if (journal_devnum &&
++          journal_devnum != le32_to_cpu(es->s_journal_dev)) {
++              printk(KERN_INFO "EXT3-fs: external journal device major/minor "
++                      "numbers have changed\n");
++              journal_dev = new_decode_dev(journal_devnum);
++      } else
++              journal_dev = new_decode_dev(le32_to_cpu(es->s_journal_dev));
++
+       really_read_only = bdev_read_only(sb->s_bdev);
+       /*
+@@ -1898,6 +1922,16 @@ static int ext3_load_journal(struct supe
+       EXT3_SB(sb)->s_journal = journal;
+       ext3_clear_journal_err(sb, es);
++
++      if (journal_devnum &&
++          journal_devnum != le32_to_cpu(es->s_journal_dev)) {
++              es->s_journal_dev = cpu_to_le32(journal_devnum);
++              sb->s_dirt = 1;
++
++              /* Make sure we flush the recovery flag to disk. */
++              ext3_commit_super(sb, es, 1);
++      }
++
+       return 0;
+ }
+@@ -2105,13 +2139,13 @@ int ext3_remount (struct super_block * s
+ {
+       struct ext3_super_block * es;
+       struct ext3_sb_info *sbi = EXT3_SB(sb);
+-      unsigned long tmp;
++      unsigned long tmp1, tmp2;
+       unsigned long n_blocks_count = 0;
+       /*
+        * Allow the "check" option to be passed as a remount option.
+        */
+-      if (!parse_options(data, sb, &tmp, &n_blocks_count, 1))
++      if (!parse_options(data, sb, &tmp1, &tmp2, &n_blocks_count, 1))
+               return -EINVAL;
+       if (sbi->s_mount_opt & EXT3_MOUNT_ABORT)
diff --git a/lustre/kernel_patches/patches/ext3-filterdata-2.6.15.patch b/lustre/kernel_patches/patches/ext3-filterdata-2.6.15.patch
new file mode 100644 (file)
index 0000000..e6d431f
--- /dev/null
@@ -0,0 +1,25 @@
+Index: linux-2.6.15/include/linux/ext3_fs_i.h
+===================================================================
+--- linux-2.6.15.orig/include/linux/ext3_fs_i.h        2006-02-24 15:41:30.000000000 +0300
++++ linux-2.6.15/include/linux/ext3_fs_i.h     2006-02-24 15:41:31.000000000 +0300
+@@ -135,6 +135,8 @@ struct ext3_inode_info {
+       struct inode vfs_inode;
+       __u32 i_cached_extent[4];
++
++      void *i_filterdata;
+ };
+ #endif        /* _LINUX_EXT3_FS_I */
+Index: linux-2.6.15/fs/ext3/super.c
+===================================================================
+--- linux-2.6.15.orig/fs/ext3/super.c  2006-02-24 15:41:30.000000000 +0300
++++ linux-2.6.15/fs/ext3/super.c       2006-02-24 15:42:02.000000000 +0300
+@@ -459,6 +459,7 @@ static struct inode *ext3_alloc_inode(st
+       ei->vfs_inode.i_version = 1;
+       
+       memset(&ei->i_cached_extent, 0, sizeof(ei->i_cached_extent));
++      ei->i_filterdata = NULL;
+       return &ei->vfs_inode;
+ }
index 12343cc..e5fdc42 100644 (file)
@@ -26,25 +26,25 @@ Index: linux-2.6.9/fs/ext3/hash.c
                return -1;
 Index: linux-2.6.9/fs/ext3/super.c
 ===================================================================
---- linux-2.6.9.orig/fs/ext3/super.c   2006-04-23 22:38:55.000000000 +0800
-+++ linux-2.6.9/fs/ext3/super.c        2006-04-23 22:39:56.000000000 +0800
-@@ -598,6 +598,7 @@
-       Opt_ignore, Opt_barrier, Opt_err, Opt_resize,
+--- super.c.orig       2006-08-17 09:26:01.000000000 +0300
++++ super.c    2006-08-17 09:31:22.000000000 +0300
+@@ -599,6 +599,7 @@ enum {
        Opt_iopen, Opt_noiopen, Opt_iopen_nopriv,
-       Opt_extents, Opt_extdebug, Opt_mballoc,
-+      Opt_hashfunc,
+       Opt_extents, Opt_noextents, Opt_extdebug,
+       Opt_mballoc, Opt_nomballoc, Opt_stripe,
++        Opt_hashfunc,
  };
  
  static match_table_t tokens = {
-@@ -651,6 +652,7 @@
-       {Opt_extdebug, "extdebug"},
-       {Opt_mballoc, "mballoc"},
+@@ -655,6 +656,7 @@ static match_table_t tokens = {
+       {Opt_nomballoc, "nomballoc"},
+       {Opt_stripe, "stripe=%u"},
        {Opt_barrier, "barrier=%u"},
 +      {Opt_hashfunc,"hash=%s"},
        {Opt_err, NULL},
        {Opt_resize, "resize"},
  };
-@@ -675,6 +677,7 @@
+@@ -679,6 +681,7 @@ static unsigned long get_sb_block(void *
        return sb_block;
  }
  
@@ -52,27 +52,26 @@ Index: linux-2.6.9/fs/ext3/super.c
  static int parse_options (char * options, struct super_block *sb,
                          unsigned long * inum, unsigned long *n_blocks_count, int is_remount)
  {
-@@ -963,6 +966,23 @@
-               case Opt_mballoc:
-                       set_opt (sbi->s_mount_opt, MBALLOC);
+@@ -980,6 +983,22 @@ clear_qf_name:
+                               return 0;
+                       sbi->s_stripe = option;
                        break;
 +              case Opt_hashfunc:
 +                      if (strncmp (args[0].from,"legacy",6) == 0){
-+               user_selected_hash_function = 0;
-+            } else if (strncmp (args[0].from,"half_md4",8) == 0){
-+               user_selected_hash_function = 1;
-+            } else if (strncmp (args[0].from,"tea",3) == 0){
-+               user_selected_hash_function = 2;
-+            } else if (strncmp (args[0].from,"r5",2) == 0){
-+               user_selected_hash_function = 3;
-+            } else if (strncmp (args[0].from,"same",4) == 0){
-+               user_selected_hash_function = 4;
-+            } else {
-+               printk ("Hashfunc name wrong\n");
-+               return 0;
-+            }
-+                       break;
-+      
++                                user_selected_hash_function = 0;
++                        } else if (strncmp (args[0].from,"half_md4",8) == 0){
++                                user_selected_hash_function = 1;
++                        } else if (strncmp (args[0].from,"tea",3) == 0){
++                                user_selected_hash_function = 2;
++                        } else if (strncmp (args[0].from,"r5",2) == 0){
++                                user_selected_hash_function = 3;
++                        } else if (strncmp (args[0].from,"same",4) == 0){
++                                user_selected_hash_function = 4;
++                        } else {
++                                printk ("Hashfunc name wrong\n");
++                                return 0;
++                        }
++                      break;
                default:
                        printk (KERN_ERR
                                "EXT3-fs: Unrecognized mount option \"%s\" "
diff --git a/lustre/kernel_patches/patches/ext3-lookup-dotdot-2.4.20.patch b/lustre/kernel_patches/patches/ext3-lookup-dotdot-2.4.20.patch
new file mode 100644 (file)
index 0000000..8fc1bd7
--- /dev/null
@@ -0,0 +1,63 @@
+Index: linux-2.4.21/fs/ext3/namei.c
+===================================================================
+--- linux-2.4.21.orig/fs/ext3/namei.c  2006-04-29 20:48:26.000000000 +0400
++++ linux-2.4.21/fs/ext3/namei.c       2006-05-06 01:31:51.000000000 +0400
+@@ -955,6 +955,38 @@ static struct dentry *ext3_lookup(struct
+               }
+       }
++      /* ".." shouldn't go into dcache to preserve dcache hierarchy
++       * otherwise we'll get parent being a child of actual child.
++       * see bug 10458 for details -bzzz */
++      if (inode && (dentry->d_name.name[0] == '.' && (dentry->d_name.len == 1 ||
++              (dentry->d_name.len == 2 && dentry->d_name.name[1] == '.')))) {
++              struct dentry *tmp, *goal = NULL;
++              struct list_head *lp;
++
++              /* first, look for an existing dentry - any one is good */
++              spin_lock(&dcache_lock);
++              list_for_each(lp, &inode->i_dentry) {
++                      tmp = list_entry(lp, struct dentry, d_alias);
++                      goal = tmp;
++                      dget_locked(goal);
++                      break;
++              }
++              if (goal == NULL) {
++                      /* there is no alias, we need to make current dentry:
++                       *  a) inaccessible for __d_lookup()
++                       *  b) inaccessible for iopen */
++                      J_ASSERT(list_empty(&dentry->d_alias));
++                      dentry->d_flags |= DCACHE_NFSFS_RENAMED;
++                      /* this is d_instantiate() ... */
++                      list_add(&dentry->d_alias, &inode->i_dentry);
++                      dentry->d_inode = inode;
++              }
++              spin_unlock(&dcache_lock);
++              if (goal)
++                      iput(inode);
++              return goal;
++      }
++
+       return iopen_connect_dentry(dentry, inode, 1);
+ }
+Index: linux-2.4.21/fs/ext3/iopen.c
+===================================================================
+--- linux-2.4.21.orig/fs/ext3/iopen.c  2006-04-29 20:48:23.000000000 +0400
++++ linux-2.4.21/fs/ext3/iopen.c       2006-04-29 20:59:50.000000000 +0400
+@@ -92,9 +92,12 @@ static struct dentry *iopen_lookup(struc
+               assert(!(alternate->d_flags & DCACHE_NFSD_DISCONNECTED));
+       }
+-      if (!list_empty(&inode->i_dentry)) {
+-              alternate = list_entry(inode->i_dentry.next,
+-                                     struct dentry, d_alias);
++      list_for_each(lp, &inode->i_dentry) {
++              alternate = list_entry(lp, struct dentry, d_alias);
++              /* ignore dentries created for ".." to preserve
++               * proper dcache hierarchy -- bug 10458 */
++              if (alternate->d_flags & DCACHE_NFSFS_RENAMED)
++                      continue;
+               dget_locked(alternate);
+               alternate->d_vfs_flags |= DCACHE_REFERENCED;
+               iput(inode);
diff --git a/lustre/kernel_patches/patches/ext3-lookup-dotdot-2.6.9.patch b/lustre/kernel_patches/patches/ext3-lookup-dotdot-2.6.9.patch
new file mode 100644 (file)
index 0000000..a05256b
--- /dev/null
@@ -0,0 +1,63 @@
+Index: linux-2.6.9-full/fs/ext3/iopen.c
+===================================================================
+--- linux-2.6.9-full.orig/fs/ext3/iopen.c      2006-04-25 08:51:11.000000000 +0400
++++ linux-2.6.9-full/fs/ext3/iopen.c   2006-05-06 01:21:11.000000000 +0400
+@@ -94,9 +94,12 @@ static struct dentry *iopen_lookup(struc
+               assert(!(alternate->d_flags & DCACHE_DISCONNECTED));
+       }
+-      if (!list_empty(&inode->i_dentry)) {
+-              alternate = list_entry(inode->i_dentry.next,
+-                                     struct dentry, d_alias);
++      list_for_each(lp, &inode->i_dentry) {
++              alternate = list_entry(lp, struct dentry, d_alias);
++              /* ignore dentries created for ".." to preserve
++               * proper dcache hierarchy -- bug 10458 */
++              if (alternate->d_flags & DCACHE_NFSFS_RENAMED)
++                      continue;
+               dget_locked(alternate);
+               spin_lock(&alternate->d_lock);
+               alternate->d_flags |= DCACHE_REFERENCED;
+Index: linux-2.6.9-full/fs/ext3/namei.c
+===================================================================
+--- linux-2.6.9-full.orig/fs/ext3/namei.c      2006-05-06 01:21:10.000000000 +0400
++++ linux-2.6.9-full/fs/ext3/namei.c   2006-05-06 01:29:30.000000000 +0400
+@@ -1003,6 +1003,38 @@ static struct dentry *ext3_lookup(struct
+                       return ERR_PTR(-EACCES);
+       }
++      /* ".." shouldn't go into dcache to preserve dcache hierarchy
++       * otherwise we'll get parent being a child of actual child.
++       * see bug 10458 for details -bzzz */
++      if (inode && (dentry->d_name.name[0] == '.' && (dentry->d_name.len == 1 ||
++              (dentry->d_name.len == 2 && dentry->d_name.name[1] == '.')))) {
++              struct dentry *tmp, *goal = NULL;
++              struct list_head *lp;
++
++              /* first, look for an existing dentry - any one is good */
++              spin_lock(&dcache_lock);
++              list_for_each(lp, &inode->i_dentry) {
++                      tmp = list_entry(lp, struct dentry, d_alias);
++                      goal = tmp;
++                      dget_locked(goal);
++                      break;
++              }
++              if (goal == NULL) {
++                      /* there is no alias, we need to make current dentry:
++                       *  a) inaccessible for __d_lookup()
++                       *  b) inaccessible for iopen */
++                      J_ASSERT(list_empty(&dentry->d_alias));
++                      dentry->d_flags |= DCACHE_NFSFS_RENAMED;
++                      /* this is d_instantiate() ... */
++                      list_add(&dentry->d_alias, &inode->i_dentry);
++                      dentry->d_inode = inode;
++              }
++              spin_unlock(&dcache_lock);
++              if (goal)
++                      iput(inode);
++              return goal;
++      }
++
+       return iopen_connect_dentry(dentry, inode, 1);
+ }
diff --git a/lustre/kernel_patches/patches/ext3-mballoc2-2.6-fc5.patch b/lustre/kernel_patches/patches/ext3-mballoc2-2.6-fc5.patch
new file mode 100644 (file)
index 0000000..325d080
--- /dev/null
@@ -0,0 +1,2779 @@
+Index: linux-2.6.16.i686/fs/ext3/inode.c
+===================================================================
+--- linux-2.6.16.i686.orig/fs/ext3/inode.c     2006-05-30 22:55:32.000000000 +0800
++++ linux-2.6.16.i686/fs/ext3/inode.c  2006-05-30 23:02:59.000000000 +0800
+@@ -568,7 +568,7 @@
+               ext3_journal_forget(handle, branch[i].bh);
+       }
+       for (i = 0; i < keys; i++)
+-              ext3_free_blocks(handle, inode, le32_to_cpu(branch[i].key), 1);
++              ext3_free_blocks(handle, inode, le32_to_cpu(branch[i].key), 1, 1);
+       return err;
+ }
+@@ -1862,7 +1862,7 @@
+               }
+       }
+-      ext3_free_blocks(handle, inode, block_to_free, count);
++      ext3_free_blocks(handle, inode, block_to_free, count, 1);
+ }
+ /**
+@@ -2035,7 +2035,7 @@
+                               ext3_journal_test_restart(handle, inode);
+                       }
+-                      ext3_free_blocks(handle, inode, nr, 1);
++                      ext3_free_blocks(handle, inode, nr, 1, 1);
+                       if (parent_bh) {
+                               /*
+Index: linux-2.6.16.i686/fs/ext3/mballoc.c
+===================================================================
+--- linux-2.6.16.i686.orig/fs/ext3/mballoc.c   2006-05-31 04:14:15.752410384 +0800
++++ linux-2.6.16.i686/fs/ext3/mballoc.c        2006-05-30 23:03:38.000000000 +0800
+@@ -0,0 +1,2434 @@
++/*
++ * Copyright (c) 2003-2005, Cluster File Systems, Inc, info@clusterfs.com
++ * Written by Alex Tomas <alex@clusterfs.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public Licens
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-
++ */
++
++
++/*
++ * mballoc.c contains the multiblocks allocation routines
++ */
++
++#include <linux/config.h>
++#include <linux/time.h>
++#include <linux/fs.h>
++#include <linux/namei.h>
++#include <linux/jbd.h>
++#include <linux/ext3_fs.h>
++#include <linux/ext3_jbd.h>
++#include <linux/quotaops.h>
++#include <linux/buffer_head.h>
++#include <linux/module.h>
++#include <linux/swap.h>
++#include <linux/proc_fs.h>
++#include <linux/pagemap.h>
++#include <linux/seq_file.h>
++
++/*
++ * TODO:
++ *   - bitmap read-ahead (proposed by Oleg Drokin aka green)
++ *   - track min/max extents in each group for better group selection
++ *   - mb_mark_used() may allocate chunk right after splitting buddy
++ *   - special flag to advice allocator to look for requested + N blocks
++ *     this may improve interaction between extents and mballoc
++ *   - tree of groups sorted by number of free blocks
++ *   - percpu reservation code (hotpath)
++ *   - error handling
++ */
++
++/*
++ * with AGRESSIVE_CHECK allocator runs consistency checks over
++ * structures. these checks slow things down a lot
++ */
++#define AGGRESSIVE_CHECK__
++
++/*
++ */
++#define MB_DEBUG__
++#ifdef MB_DEBUG
++#define mb_debug(fmt,a...)    printk(fmt, ##a)
++#else
++#define mb_debug(fmt,a...)
++#endif
++
++/*
++ * with EXT3_MB_HISTORY mballoc stores last N allocations in memory
++ * and you can monitor it in /proc/fs/ext3/<dev>/mb_history
++ */
++#define EXT3_MB_HISTORY
++
++/*
++ * How long mballoc can look for a best extent (in found extents)
++ */
++long ext3_mb_max_to_scan = 500;
++
++/*
++ * How long mballoc must look for a best extent
++ */
++long ext3_mb_min_to_scan = 30;
++
++/*
++ * with 'ext3_mb_stats' allocator will collect stats that will be
++ * shown at umount. The collecting costs though!
++ */
++
++long ext3_mb_stats = 1;
++
++#ifdef EXT3_BB_MAX_BLOCKS
++#undef EXT3_BB_MAX_BLOCKS
++#endif
++#define EXT3_BB_MAX_BLOCKS    30
++
++struct ext3_free_metadata {
++      unsigned short group;
++      unsigned short num;
++      unsigned short blocks[EXT3_BB_MAX_BLOCKS];
++      struct list_head list;
++};
++
++struct ext3_group_info {
++      unsigned long   bb_state;
++      unsigned long   bb_tid;
++      struct ext3_free_metadata *bb_md_cur;
++      unsigned short  bb_first_free;
++      unsigned short  bb_free;
++      unsigned short  bb_fragments;
++      unsigned short  bb_counters[];
++};
++
++
++#define EXT3_GROUP_INFO_NEED_INIT_BIT 0
++#define EXT3_GROUP_INFO_LOCKED_BIT    1
++
++#define EXT3_MB_GRP_NEED_INIT(grp)    \
++      (test_bit(EXT3_GROUP_INFO_NEED_INIT_BIT, &(grp)->bb_state))
++
++struct ext3_free_extent {
++      __u16 fe_start;
++      __u16 fe_len;
++      __u16 fe_group;
++};
++
++struct ext3_allocation_context {
++      struct super_block *ac_sb;
++
++      /* search goals */
++      struct ext3_free_extent ac_g_ex;
++      
++      /* the best found extent */
++      struct ext3_free_extent ac_b_ex;
++      
++      /* number of iterations done. we have to track to limit searching */
++      unsigned long ac_ex_scanned;
++      __u16 ac_groups_scanned;
++      __u16 ac_found;
++      __u16 ac_tail;
++      __u16 ac_buddy;
++      __u8 ac_status; 
++      __u8 ac_flags;          /* allocation hints */
++      __u8 ac_criteria;
++      __u8 ac_repeats;
++      __u8 ac_2order;         /* if request is to allocate 2^N blocks and
++                               * N > 0, the field stores N, otherwise 0 */
++};
++
++#define AC_STATUS_CONTINUE    1
++#define AC_STATUS_FOUND               2
++#define AC_STATUS_BREAK               3
++
++struct ext3_mb_history {
++      struct ext3_free_extent goal;   /* goal allocation */
++      struct ext3_free_extent result; /* result allocation */
++      __u16 found;    /* how many extents have been found */
++      __u16 groups;   /* how many groups have been scanned */
++      __u16 tail;     /* what tail broke some buddy */
++      __u16 buddy;    /* buddy the tail ^^^ broke */
++      __u8 cr;        /* which phase the result extent was found at */
++      __u8 merged;
++};
++
++struct ext3_buddy {
++      struct page *bd_buddy_page;
++      void *bd_buddy;
++      struct page *bd_bitmap_page;
++      void *bd_bitmap;
++      struct ext3_group_info *bd_info;
++      struct super_block *bd_sb;
++      __u16 bd_blkbits;
++      __u16 bd_group;
++};
++#define EXT3_MB_BITMAP(e3b)   ((e3b)->bd_bitmap)
++#define EXT3_MB_BUDDY(e3b)    ((e3b)->bd_buddy)
++
++#ifndef EXT3_MB_HISTORY
++#define ext3_mb_store_history(sb,ac)
++#else
++static void ext3_mb_store_history(struct super_block *,
++                              struct ext3_allocation_context *ac);
++#endif
++
++#define in_range(b, first, len)       ((b) >= (first) && (b) <= (first) + (len) - 1)
++
++static struct proc_dir_entry *proc_root_ext3;
++
++int ext3_create (struct inode *, struct dentry *, int, struct nameidata *);
++struct buffer_head * read_block_bitmap(struct super_block *, unsigned int);
++int ext3_new_block_old(handle_t *, struct inode *, unsigned long, int *);
++int ext3_mb_reserve_blocks(struct super_block *, int);
++void ext3_mb_release_blocks(struct super_block *, int);
++void ext3_mb_poll_new_transaction(struct super_block *, handle_t *);
++void ext3_mb_free_committed_blocks(struct super_block *);
++
++#if BITS_PER_LONG == 64
++#define mb_correct_addr_and_bit(bit,addr)             \
++{                                                     \
++      bit += ((unsigned long) addr & 7UL) << 3;       \
++      addr = (void *) ((unsigned long) addr & ~7UL);  \
++}
++#elif BITS_PER_LONG == 32
++#define mb_correct_addr_and_bit(bit,addr)             \
++{                                                     \
++      bit += ((unsigned long) addr & 3UL) << 3;       \
++      addr = (void *) ((unsigned long) addr & ~3UL);  \
++}
++#else
++#error "how many bits you are?!"
++#endif
++
++static inline int mb_test_bit(int bit, void *addr)
++{
++      mb_correct_addr_and_bit(bit,addr);
++      return ext2_test_bit(bit, addr);
++}
++
++static inline void mb_set_bit(int bit, void *addr)
++{
++      mb_correct_addr_and_bit(bit,addr);
++      ext2_set_bit(bit, addr);
++}
++
++static inline void mb_set_bit_atomic(int bit, void *addr)
++{
++      mb_correct_addr_and_bit(bit,addr);
++      ext2_set_bit_atomic(NULL, bit, addr);
++}
++
++static inline void mb_clear_bit(int bit, void *addr)
++{
++      mb_correct_addr_and_bit(bit,addr);
++      ext2_clear_bit(bit, addr);
++}
++
++static inline void mb_clear_bit_atomic(int bit, void *addr)
++{
++      mb_correct_addr_and_bit(bit,addr);
++      ext2_clear_bit_atomic(NULL, bit, addr);
++}
++
++static inline int mb_find_next_zero_bit(void *addr, int max, int start)
++{
++      int fix;
++#if BITS_PER_LONG == 64
++      fix = ((unsigned long) addr & 7UL) << 3;
++      addr = (void *) ((unsigned long) addr & ~7UL);
++#elif BITS_PER_LONG == 32
++      fix = ((unsigned long) addr & 3UL) << 3;
++      addr = (void *) ((unsigned long) addr & ~3UL);
++#else
++#error "how many bits you are?!"
++#endif
++      max += fix;
++      start += fix;
++      return ext2_find_next_zero_bit(addr, max, start) - fix;
++}
++
++static inline void *mb_find_buddy(struct ext3_buddy *e3b, int order, int *max)
++{
++      char *bb;
++
++      J_ASSERT(EXT3_MB_BITMAP(e3b) != EXT3_MB_BUDDY(e3b));
++      J_ASSERT(max != NULL);
++
++      if (order > e3b->bd_blkbits + 1) {
++              *max = 0;
++              return NULL;
++      }
++
++      /* at order 0 we see each particular block */
++      *max = 1 << (e3b->bd_blkbits + 3);
++      if (order == 0)
++              return EXT3_MB_BITMAP(e3b);
++
++      bb = EXT3_MB_BUDDY(e3b) + EXT3_SB(e3b->bd_sb)->s_mb_offsets[order];
++      *max = EXT3_SB(e3b->bd_sb)->s_mb_maxs[order];
++
++      return bb;
++}
++
++#ifdef AGGRESSIVE_CHECK
++
++static void mb_check_buddy(struct ext3_buddy *e3b)
++{
++      int order = e3b->bd_blkbits + 1;
++      int max, max2, i, j, k, count;
++      int fragments = 0, fstart;
++      void *buddy, *buddy2;
++
++      if (!test_opt(e3b->bd_sb, MBALLOC))
++              return;
++
++      {
++              static int mb_check_counter = 0;
++              if (mb_check_counter++ % 300 != 0)
++                      return;
++      }
++      
++      while (order > 1) {
++              buddy = mb_find_buddy(e3b, order, &max);
++              J_ASSERT(buddy);
++              buddy2 = mb_find_buddy(e3b, order - 1, &max2);
++              J_ASSERT(buddy2);
++              J_ASSERT(buddy != buddy2);
++              J_ASSERT(max * 2 == max2);
++
++              count = 0;
++              for (i = 0; i < max; i++) {
++
++                      if (mb_test_bit(i, buddy)) {
++                              /* only single bit in buddy2 may be 1 */
++                              if (!mb_test_bit(i << 1, buddy2))
++                                      J_ASSERT(mb_test_bit((i<<1)+1, buddy2));
++                              else if (!mb_test_bit((i << 1) + 1, buddy2))
++                                      J_ASSERT(mb_test_bit(i << 1, buddy2));
++                              continue;
++                      }
++
++                      /* both bits in buddy2 must be 0 */
++                      J_ASSERT(mb_test_bit(i << 1, buddy2));
++                      J_ASSERT(mb_test_bit((i << 1) + 1, buddy2));
++
++                      for (j = 0; j < (1 << order); j++) {
++                              k = (i * (1 << order)) + j;
++                              J_ASSERT(!mb_test_bit(k, EXT3_MB_BITMAP(e3b)));
++                      }
++                      count++;
++              }
++              J_ASSERT(e3b->bd_info->bb_counters[order] == count);
++              order--;
++      }
++
++      fstart = -1;
++      buddy = mb_find_buddy(e3b, 0, &max);
++      for (i = 0; i < max; i++) {
++              if (!mb_test_bit(i, buddy)) {
++                      J_ASSERT(i >= e3b->bd_info->bb_first_free);
++                      if (fstart == -1) {
++                              fragments++;
++                              fstart = i;
++                      }
++                      continue;
++              }
++              fstart = -1;
++              /* check used bits only */
++              for (j = 0; j < e3b->bd_blkbits + 1; j++) {
++                      buddy2 = mb_find_buddy(e3b, j, &max2);
++                      k = i >> j;
++                      J_ASSERT(k < max2);
++                      J_ASSERT(mb_test_bit(k, buddy2));
++              }
++      }
++      J_ASSERT(!EXT3_MB_GRP_NEED_INIT(e3b->bd_info));
++      J_ASSERT(e3b->bd_info->bb_fragments == fragments);
++}
++
++#else
++#define mb_check_buddy(e3b)
++#endif
++
++/* find most significant bit */
++static int inline fmsb(unsigned short word)
++{
++      int order;
++
++      if (word > 255) {
++              order = 7;
++              word >>= 8;
++      } else {
++              order = -1;
++      }
++
++      do {
++              order++;
++              word >>= 1;
++      } while (word != 0);
++
++      return order;
++}
++
++static void inline
++ext3_mb_mark_free_simple(struct super_block *sb, void *buddy, unsigned first,
++                              int len, struct ext3_group_info *grp)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      unsigned short min, max, chunk, border;
++
++      mb_debug("mark %u/%u free\n", first, len);
++      J_ASSERT(len < EXT3_BLOCKS_PER_GROUP(sb));
++
++      border = 2 << sb->s_blocksize_bits;
++
++      while (len > 0) {
++              /* find how many blocks can be covered since this position */
++              max = ffs(first | border) - 1;
++
++              /* find how many blocks of power 2 we need to mark */
++              min = fmsb(len);
++
++              mb_debug("  %u/%u -> max %u, min %u\n",
++                      first & ((2 << sb->s_blocksize_bits) - 1),
++                      len, max, min);
++
++              if (max < min)
++                      min = max;
++              chunk = 1 << min;
++
++              /* mark multiblock chunks only */
++              grp->bb_counters[min]++;
++              if (min > 0) {
++                      mb_debug("    set %u at %u \n", first >> min,
++                              sbi->s_mb_offsets[min]);
++                      mb_clear_bit(first >> min, buddy + sbi->s_mb_offsets[min]);
++              }
++
++              len -= chunk;
++              first += chunk;
++      }
++}
++
++static void
++ext3_mb_generate_buddy(struct super_block *sb, void *buddy, void *bitmap,
++                      struct ext3_group_info *grp)
++{
++      unsigned short max = EXT3_BLOCKS_PER_GROUP(sb);
++      unsigned short i = 0, first, len;
++      unsigned free = 0, fragments = 0;
++      unsigned long long period = get_cycles();
++
++      i = mb_find_next_zero_bit(bitmap, max, 0);
++      grp->bb_first_free = i;
++      while (i < max) {
++              fragments++;
++              first = i;
++              i = find_next_bit(bitmap, max, i);
++              len = i - first;
++              free += len;
++              if (len > 1) 
++                      ext3_mb_mark_free_simple(sb, buddy, first, len, grp);
++              else
++                      grp->bb_counters[0]++;
++              if (i < max)
++                      i = mb_find_next_zero_bit(bitmap, max, i);
++      }
++      grp->bb_fragments = fragments;
++
++      /* bb_state shouldn't being modified because all
++       * others waits for init completion on page lock */
++      clear_bit(EXT3_GROUP_INFO_NEED_INIT_BIT, &grp->bb_state);
++      if (free != grp->bb_free) {
++              printk("EXT3-fs: %u blocks in bitmap, %u in group descriptor\n",
++                      free, grp->bb_free);
++              grp->bb_free = free;
++      }
++
++      period = get_cycles() - period;
++      spin_lock(&EXT3_SB(sb)->s_bal_lock);
++      EXT3_SB(sb)->s_mb_buddies_generated++;
++      EXT3_SB(sb)->s_mb_generation_time += period;
++      spin_unlock(&EXT3_SB(sb)->s_bal_lock);
++}
++
++static int ext3_mb_init_cache(struct page *page)
++{
++      int blocksize, blocks_per_page, groups_per_page;
++      int err = 0, i, first_group, first_block;
++      struct super_block *sb;
++      struct buffer_head *bhs;
++      struct buffer_head **bh;
++      struct inode *inode;
++      char *data, *bitmap;
++
++      mb_debug("init page %lu\n", page->index);
++
++      inode = page->mapping->host;
++      sb = inode->i_sb;
++      blocksize = 1 << inode->i_blkbits;
++      blocks_per_page = PAGE_CACHE_SIZE / blocksize;
++      
++      groups_per_page = blocks_per_page >> 1;
++      if (groups_per_page == 0)
++              groups_per_page = 1;
++
++      /* allocate buffer_heads to read bitmaps */
++      if (groups_per_page > 1) {
++              err = -ENOMEM;
++              i = sizeof(struct buffer_head *) * groups_per_page;
++              bh = kmalloc(i, GFP_NOFS);
++              if (bh == NULL)
++                      goto out;
++              memset(bh, 0, i);
++      } else
++              bh = &bhs;
++      
++      first_group = page->index * blocks_per_page / 2;
++      
++      /* read all groups the page covers into the cache */
++      for (i = 0; i < groups_per_page; i++) {
++              struct ext3_group_desc * desc;
++
++              if (first_group + i >= EXT3_SB(sb)->s_groups_count)
++                      break;
++
++              err = -EIO;
++              desc = ext3_get_group_desc(sb, first_group + i, NULL);
++              if (desc == NULL)
++                      goto out;
++
++              err = -ENOMEM;
++              bh[i] = sb_getblk(sb, le32_to_cpu(desc->bg_block_bitmap));
++              if (bh[i] == NULL)
++                      goto out;
++
++              if (buffer_uptodate(bh[i]))
++                      continue;
++
++              lock_buffer(bh[i]);
++              if (buffer_uptodate(bh[i])) {
++                      unlock_buffer(bh[i]);
++                      continue;
++              }
++
++              get_bh(bh[i]);
++              bh[i]->b_end_io = end_buffer_read_sync;
++              submit_bh(READ, bh[i]);
++              mb_debug("read bitmap for group %u\n", first_group + i);
++      }
++
++      /* wait for I/O completion */
++      for (i = 0; i < groups_per_page && bh[i]; i++)
++              wait_on_buffer(bh[i]);
++
++      /* XXX: I/O error handling here */
++
++      first_block = page->index * blocks_per_page;
++      for (i = 0; i < blocks_per_page; i++) {
++              int group;
++
++              group = (first_block + i) >> 1;
++              if (group >= EXT3_SB(sb)->s_groups_count)
++                      break;
++
++              data = page_address(page) + (i * blocksize);
++              bitmap = bh[group - first_group]->b_data;
++
++              if ((first_block + i) & 1) {
++                      /* this is block of buddy */
++                      mb_debug("put buddy for group %u in page %lu/%x\n",
++                              group, page->index, i * blocksize);
++                      memset(data, 0xff, blocksize);
++                      EXT3_SB(sb)->s_group_info[group]->bb_fragments = 0;
++                      memset(EXT3_SB(sb)->s_group_info[group]->bb_counters, 0,
++                              sizeof(unsigned short)*(sb->s_blocksize_bits+2));
++                      ext3_mb_generate_buddy(sb, data, bitmap,
++                                              EXT3_SB(sb)->s_group_info[group]);
++              } else {
++                      /* this is block of bitmap */
++                      mb_debug("put bitmap for group %u in page %lu/%x\n",
++                              group, page->index, i * blocksize);
++                      memcpy(data, bitmap, blocksize);
++              }
++      }
++      SetPageUptodate(page);
++
++out:
++      for (i = 0; i < groups_per_page && bh[i]; i++)
++              brelse(bh[i]);
++      if (bh && bh != &bhs)
++              kfree(bh);
++      return err;
++}
++
++static int ext3_mb_load_buddy(struct super_block *sb, int group,
++              struct ext3_buddy *e3b)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      struct inode *inode = sbi->s_buddy_cache;
++      int blocks_per_page, block, pnum, poff;
++      struct page *page;
++
++      mb_debug("load group %u\n", group);
++
++      blocks_per_page = PAGE_CACHE_SIZE / sb->s_blocksize;
++
++      e3b->bd_blkbits = sb->s_blocksize_bits;
++      e3b->bd_info = sbi->s_group_info[group];
++      e3b->bd_sb = sb;
++      e3b->bd_group = group;
++      e3b->bd_buddy_page = NULL;
++      e3b->bd_bitmap_page = NULL;
++
++      block = group * 2;
++      pnum = block / blocks_per_page;
++      poff = block % blocks_per_page;
++
++      page = find_get_page(inode->i_mapping, pnum);
++      if (page == NULL || !PageUptodate(page)) {
++              if (page)
++                      page_cache_release(page);
++              page = find_or_create_page(inode->i_mapping, pnum, GFP_NOFS);
++              if (page) {
++                      if (!PageUptodate(page))
++                              ext3_mb_init_cache(page);
++                      unlock_page(page);
++              }
++      }
++      if (page == NULL || !PageUptodate(page))
++              goto err;
++      e3b->bd_bitmap_page = page;
++      e3b->bd_bitmap = page_address(page) + (poff * sb->s_blocksize);
++      mark_page_accessed(page);
++
++      block++;
++      pnum = block / blocks_per_page;
++      poff = block % blocks_per_page;
++
++      page = find_get_page(inode->i_mapping, pnum);
++      if (page == NULL || !PageUptodate(page)) {
++              if (page)
++                      page_cache_release(page);
++              page = find_or_create_page(inode->i_mapping, pnum, GFP_NOFS);
++              if (page) {
++                      if (!PageUptodate(page))
++                              ext3_mb_init_cache(page);
++                      unlock_page(page);
++              }
++      }
++      if (page == NULL || !PageUptodate(page))
++              goto err;
++      e3b->bd_buddy_page = page;
++      e3b->bd_buddy = page_address(page) + (poff * sb->s_blocksize);
++      mark_page_accessed(page);
++
++      J_ASSERT(e3b->bd_bitmap_page != NULL);
++      J_ASSERT(e3b->bd_buddy_page != NULL);
++
++      return 0;
++
++err:
++      if (e3b->bd_bitmap_page)
++              page_cache_release(e3b->bd_bitmap_page);
++      if (e3b->bd_buddy_page)
++              page_cache_release(e3b->bd_buddy_page);
++      e3b->bd_buddy = NULL;
++      e3b->bd_bitmap = NULL;
++      return -EIO;
++}
++
++static void ext3_mb_release_desc(struct ext3_buddy *e3b)
++{
++      if (e3b->bd_bitmap_page)
++              page_cache_release(e3b->bd_bitmap_page);
++      if (e3b->bd_buddy_page)
++              page_cache_release(e3b->bd_buddy_page);
++}
++
++
++static inline void
++ext3_lock_group(struct super_block *sb, int group)
++{
++      bit_spin_lock(EXT3_GROUP_INFO_LOCKED_BIT,
++                      &EXT3_SB(sb)->s_group_info[group]->bb_state);
++}
++
++static inline void
++ext3_unlock_group(struct super_block *sb, int group)
++{
++      bit_spin_unlock(EXT3_GROUP_INFO_LOCKED_BIT,
++                      &EXT3_SB(sb)->s_group_info[group]->bb_state);
++}
++
++static int mb_find_order_for_block(struct ext3_buddy *e3b, int block)
++{
++      int order = 1;
++      void *bb;
++
++      J_ASSERT(EXT3_MB_BITMAP(e3b) != EXT3_MB_BUDDY(e3b));
++      J_ASSERT(block < (1 << (e3b->bd_blkbits + 3)));
++
++      bb = EXT3_MB_BUDDY(e3b);
++      while (order <= e3b->bd_blkbits + 1) {
++              block = block >> 1;
++              if (!mb_test_bit(block, bb)) {
++                      /* this block is part of buddy of order 'order' */
++                      return order;
++              }
++              bb += 1 << (e3b->bd_blkbits - order);
++              order++;
++      }
++      return 0;
++}
++
++static inline void mb_clear_bits(void *bm, int cur, int len)
++{
++      __u32 *addr;
++
++      len = cur + len;
++      while (cur < len) {
++              if ((cur & 31) == 0 && (len - cur) >= 32) {
++                      /* fast path: clear whole word at once */
++                      addr = bm + (cur >> 3);
++                      *addr = 0;
++                      cur += 32;
++                      continue;
++              }
++              mb_clear_bit_atomic(cur, bm);
++              cur++;
++      }
++}
++
++static inline void mb_set_bits(void *bm, int cur, int len)
++{
++      __u32 *addr;
++
++      len = cur + len;
++      while (cur < len) {
++              if ((cur & 31) == 0 && (len - cur) >= 32) {
++                      /* fast path: clear whole word at once */
++                      addr = bm + (cur >> 3);
++                      *addr = 0xffffffff;
++                      cur += 32;
++                      continue;
++              }
++              mb_set_bit_atomic(cur, bm);
++              cur++;
++      }
++}
++
++static int mb_free_blocks(struct ext3_buddy *e3b, int first, int count)
++{
++      int block = 0, max = 0, order;
++      void *buddy, *buddy2;
++
++      mb_check_buddy(e3b);
++
++      e3b->bd_info->bb_free += count;
++      if (first < e3b->bd_info->bb_first_free)
++              e3b->bd_info->bb_first_free = first;
++
++      /* let's maintain fragments counter */
++      if (first != 0)
++              block = !mb_test_bit(first - 1, EXT3_MB_BITMAP(e3b));
++      if (first + count < EXT3_SB(e3b->bd_sb)->s_mb_maxs[0])
++              max = !mb_test_bit(first + count, EXT3_MB_BITMAP(e3b));
++      if (block && max)
++              e3b->bd_info->bb_fragments--;
++      else if (!block && !max)
++              e3b->bd_info->bb_fragments++;
++
++      /* let's maintain buddy itself */
++      while (count-- > 0) {
++              block = first++;
++              order = 0;
++
++              J_ASSERT(mb_test_bit(block, EXT3_MB_BITMAP(e3b)));
++              mb_clear_bit(block, EXT3_MB_BITMAP(e3b));
++              e3b->bd_info->bb_counters[order]++;
++
++              /* start of the buddy */
++              buddy = mb_find_buddy(e3b, order, &max);
++
++              do {
++                      block &= ~1UL;
++                      if (mb_test_bit(block, buddy) ||
++                                      mb_test_bit(block + 1, buddy))
++                              break;
++
++                      /* both the buddies are free, try to coalesce them */
++                      buddy2 = mb_find_buddy(e3b, order + 1, &max);
++
++                      if (!buddy2)
++                              break;
++
++                      if (order > 0) {
++                              /* for special purposes, we don't set
++                               * free bits in bitmap */
++                              mb_set_bit(block, buddy);
++                              mb_set_bit(block + 1, buddy);
++                      }
++                      e3b->bd_info->bb_counters[order]--;
++                      e3b->bd_info->bb_counters[order]--;
++
++                      block = block >> 1;
++                      order++;
++                      e3b->bd_info->bb_counters[order]++;
++
++                      mb_clear_bit(block, buddy2);
++                      buddy = buddy2;
++              } while (1);
++      }
++      mb_check_buddy(e3b);
++
++      return 0;
++}
++
++static int mb_find_extent(struct ext3_buddy *e3b, int order, int block,
++                              int needed, struct ext3_free_extent *ex)
++{
++      int next, max, ord;
++      void *buddy;
++
++      J_ASSERT(ex != NULL);
++
++      buddy = mb_find_buddy(e3b, order, &max);
++      J_ASSERT(buddy);
++      J_ASSERT(block < max);
++      if (mb_test_bit(block, buddy)) {
++              ex->fe_len = 0;
++              ex->fe_start = 0;
++              ex->fe_group = 0;
++              return 0;
++      }
++
++      if (likely(order == 0)) {
++              /* find actual order */
++              order = mb_find_order_for_block(e3b, block);
++              block = block >> order;
++      }
++
++      ex->fe_len = 1 << order;
++      ex->fe_start = block << order;
++      ex->fe_group = e3b->bd_group;
++
++      while (needed > ex->fe_len && (buddy = mb_find_buddy(e3b, order, &max))) {
++
++              if (block + 1 >= max)
++                      break;
++
++              next = (block + 1) * (1 << order);
++              if (mb_test_bit(next, EXT3_MB_BITMAP(e3b)))
++                      break;
++
++              ord = mb_find_order_for_block(e3b, next);
++
++              order = ord;
++              block = next >> order;
++              ex->fe_len += 1 << order;
++      }
++
++      J_ASSERT(ex->fe_start + ex->fe_len <= (1 << (e3b->bd_blkbits + 3)));
++      return ex->fe_len;
++}
++
++static int mb_mark_used(struct ext3_buddy *e3b, struct ext3_free_extent *ex)
++{
++      int ord, mlen = 0, max = 0, cur;
++      int start = ex->fe_start;
++      int len = ex->fe_len;
++      unsigned ret = 0;
++      int len0 = len;
++      void *buddy;
++
++      mb_check_buddy(e3b);
++
++      e3b->bd_info->bb_free -= len;
++      if (e3b->bd_info->bb_first_free == start)
++              e3b->bd_info->bb_first_free += len;
++
++      /* let's maintain fragments counter */
++      if (start != 0)
++              mlen = !mb_test_bit(start - 1, EXT3_MB_BITMAP(e3b));
++      if (start + len < EXT3_SB(e3b->bd_sb)->s_mb_maxs[0])
++              max = !mb_test_bit(start + len, EXT3_MB_BITMAP(e3b));
++      if (mlen && max)
++              e3b->bd_info->bb_fragments++;
++      else if (!mlen && !max)
++              e3b->bd_info->bb_fragments--;
++
++      /* let's maintain buddy itself */
++      while (len) {
++              ord = mb_find_order_for_block(e3b, start);
++
++              if (((start >> ord) << ord) == start && len >= (1 << ord)) {
++                      /* the whole chunk may be allocated at once! */
++                      mlen = 1 << ord;
++                      buddy = mb_find_buddy(e3b, ord, &max);
++                      J_ASSERT((start >> ord) < max);
++                      mb_set_bit(start >> ord, buddy);
++                      e3b->bd_info->bb_counters[ord]--;
++                      start += mlen;
++                      len -= mlen;
++                      J_ASSERT(len >= 0);
++                      continue;
++              }
++
++              /* store for history */
++              if (ret == 0)
++                      ret = len | (ord << 16);
++
++              /* we have to split large buddy */
++              J_ASSERT(ord > 0);
++              buddy = mb_find_buddy(e3b, ord, &max);
++              mb_set_bit(start >> ord, buddy);
++              e3b->bd_info->bb_counters[ord]--;
++
++              ord--;
++              cur = (start >> ord) & ~1U;
++              buddy = mb_find_buddy(e3b, ord, &max);
++              mb_clear_bit(cur, buddy);
++              mb_clear_bit(cur + 1, buddy);
++              e3b->bd_info->bb_counters[ord]++;
++              e3b->bd_info->bb_counters[ord]++;
++      }
++
++      /* now drop all the bits in bitmap */
++      mb_set_bits(EXT3_MB_BITMAP(e3b), ex->fe_start, len0);
++
++      mb_check_buddy(e3b);
++
++      return ret;
++}
++
++/*
++ * Must be called under group lock!
++ */
++static void ext3_mb_use_best_found(struct ext3_allocation_context *ac,
++                                      struct ext3_buddy *e3b)
++{
++      unsigned long ret;
++
++      ac->ac_b_ex.fe_len = min(ac->ac_b_ex.fe_len, ac->ac_g_ex.fe_len);
++      ret = mb_mark_used(e3b, &ac->ac_b_ex);
++
++      ac->ac_status = AC_STATUS_FOUND;
++      ac->ac_tail = ret & 0xffff;
++      ac->ac_buddy = ret >> 16;
++}
++
++/*
++ * The routine checks whether found extent is good enough. If it is,
++ * then the extent gets marked used and flag is set to the context
++ * to stop scanning. Otherwise, the extent is compared with the
++ * previous found extent and if new one is better, then it's stored
++ * in the context. Later, the best found extent will be used, if
++ * mballoc can't find good enough extent.
++ *
++ * FIXME: real allocation policy is to be designed yet!
++ */
++static void ext3_mb_measure_extent(struct ext3_allocation_context *ac,
++                                      struct ext3_free_extent *ex,
++                                      struct ext3_buddy *e3b)
++{
++      struct ext3_free_extent *bex = &ac->ac_b_ex;
++      struct ext3_free_extent *gex = &ac->ac_g_ex;
++
++      J_ASSERT(ex->fe_len > 0);
++      J_ASSERT(ex->fe_len < (1 << ac->ac_sb->s_blocksize_bits) * 8);
++      J_ASSERT(ex->fe_start < (1 << ac->ac_sb->s_blocksize_bits) * 8);
++
++      ac->ac_found++;
++
++      /*
++       * The special case - take what you catch first
++       */
++      if (unlikely(ac->ac_flags & EXT3_MB_HINT_FIRST)) {
++              *bex = *ex;
++              ext3_mb_use_best_found(ac, e3b);
++              return;
++      }
++
++      /*
++       * Let's check whether the chuck is good enough
++       */
++      if (ex->fe_len == gex->fe_len) {
++              *bex = *ex;
++              ext3_mb_use_best_found(ac, e3b);
++              return;
++      }
++
++      /*
++       * If this is first found extent, just store it in the context
++       */
++      if (bex->fe_len == 0) {
++              *bex = *ex;
++              return;
++      }
++
++      /*
++       * If new found extent is better, store it in the context
++       */
++      if (bex->fe_len < gex->fe_len) {
++              /* if the request isn't satisfied, any found extent
++               * larger than previous best one is better */
++              if (ex->fe_len > bex->fe_len)
++                      *bex = *ex;
++      } else if (ex->fe_len > gex->fe_len) {
++              /* if the request is satisfied, then we try to find
++               * an extent that still satisfy the request, but is
++               * smaller than previous one */
++              *bex = *ex;
++      }
++
++      /*
++       * Let's scan at least few extents and don't pick up a first one
++       */
++      if (bex->fe_len > gex->fe_len && ac->ac_found > ext3_mb_min_to_scan)
++              ac->ac_status = AC_STATUS_BREAK;
++
++      /*
++       * We don't want to scan for a whole year
++       */
++      if (ac->ac_found > ext3_mb_max_to_scan)
++              ac->ac_status = AC_STATUS_BREAK;
++}
++
++static int ext3_mb_try_best_found(struct ext3_allocation_context *ac,
++                                      struct ext3_buddy *e3b)
++{
++      struct ext3_free_extent ex = ac->ac_b_ex;
++      int group = ex.fe_group, max, err;
++
++      J_ASSERT(ex.fe_len > 0);
++      err = ext3_mb_load_buddy(ac->ac_sb, group, e3b);
++      if (err)
++              return err;
++
++      ext3_lock_group(ac->ac_sb, group);
++      max = mb_find_extent(e3b, 0, ex.fe_start, ex.fe_len, &ex);
++      
++      if (max > 0) {
++              ac->ac_b_ex = ex;
++              ext3_mb_use_best_found(ac, e3b);
++      }
++
++      ext3_unlock_group(ac->ac_sb, group);
++
++      ext3_mb_release_desc(e3b);
++
++      return 0;
++}
++
++static int ext3_mb_find_by_goal(struct ext3_allocation_context *ac,
++                              struct ext3_buddy *e3b)
++{
++      int group = ac->ac_g_ex.fe_group, max, err;
++      struct ext3_free_extent ex;
++
++      err = ext3_mb_load_buddy(ac->ac_sb, group, e3b);
++      if (err)
++              return err;
++
++      ext3_lock_group(ac->ac_sb, group);
++      max = mb_find_extent(e3b, 0, ac->ac_g_ex.fe_start,
++                              ac->ac_g_ex.fe_len, &ex);
++      
++      if (max > 0) {
++              J_ASSERT(ex.fe_len > 0);
++              J_ASSERT(ex.fe_group == ac->ac_g_ex.fe_group);
++              J_ASSERT(ex.fe_start == ac->ac_g_ex.fe_start);
++              ac->ac_found++;
++              ac->ac_b_ex = ex;
++              ext3_mb_use_best_found(ac, e3b);
++      }
++      ext3_unlock_group(ac->ac_sb, group);
++
++      ext3_mb_release_desc(e3b);
++
++      return 0;
++}
++
++/*
++ * The routine scans buddy structures (not bitmap!) from given order
++ * to max order and tries to find big enough chunk to satisfy the req
++ */
++static void ext3_mb_simple_scan_group(struct ext3_allocation_context *ac,
++                                      struct ext3_buddy *e3b)
++{
++      struct super_block *sb = ac->ac_sb;
++      struct ext3_group_info *grp = e3b->bd_info;
++      void *buddy;
++      int i, k, max;
++
++      J_ASSERT(ac->ac_2order > 0);
++      for (i = ac->ac_2order; i < sb->s_blocksize_bits + 1; i++) {
++              if (grp->bb_counters[i] == 0)
++                      continue;
++
++              buddy = mb_find_buddy(e3b, i, &max);
++              if (buddy == NULL) {
++                      printk(KERN_ALERT "looking for wrong order?\n");
++                      break;
++              }
++
++              k = mb_find_next_zero_bit(buddy, max, 0);
++              J_ASSERT(k < max);
++
++              ac->ac_found++;
++
++              ac->ac_b_ex.fe_len = 1 << i;
++              ac->ac_b_ex.fe_start = k << i;
++              ac->ac_b_ex.fe_group = e3b->bd_group;
++              
++              ext3_mb_use_best_found(ac, e3b);
++              J_ASSERT(ac->ac_b_ex.fe_len == ac->ac_g_ex.fe_len);
++
++              if (unlikely(ext3_mb_stats))
++                      atomic_inc(&EXT3_SB(sb)->s_bal_2orders);
++
++              break;
++      }
++}
++
++/*
++ * The routine scans the group and measures all found extents.
++ * In order to optimize scanning, caller must pass number of
++ * free blocks in the group, so the routine can know upper limit.
++ */
++static void ext3_mb_complex_scan_group(struct ext3_allocation_context *ac,
++                                      struct ext3_buddy *e3b)
++{
++      struct super_block *sb = ac->ac_sb;
++      void *bitmap = EXT3_MB_BITMAP(e3b);
++      struct ext3_free_extent ex;
++      int i, free;
++
++      free = e3b->bd_info->bb_free;
++      J_ASSERT(free > 0);
++
++      i = e3b->bd_info->bb_first_free;
++
++      while (free && ac->ac_status == AC_STATUS_CONTINUE) {
++              i = mb_find_next_zero_bit(bitmap, sb->s_blocksize * 8, i);
++              if (i >= sb->s_blocksize * 8) {
++                      J_ASSERT(free == 0);
++                      break;
++              }
++
++              mb_find_extent(e3b, 0, i, ac->ac_g_ex.fe_len, &ex);
++              J_ASSERT(ex.fe_len > 0);
++              J_ASSERT(free >= ex.fe_len);
++
++              ext3_mb_measure_extent(ac, &ex, e3b);
++
++              i += ex.fe_len;
++              free -= ex.fe_len;
++      }
++}
++
++static int ext3_mb_good_group(struct ext3_allocation_context *ac,
++                              int group, int cr)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(ac->ac_sb);
++      struct ext3_group_info *grp = sbi->s_group_info[group];
++      unsigned free, fragments, i, bits;
++
++      J_ASSERT(cr >= 0 && cr < 4);
++      J_ASSERT(!EXT3_MB_GRP_NEED_INIT(grp));
++
++      free = grp->bb_free;
++      fragments = grp->bb_fragments;
++      if (free == 0)
++              return 0;
++      if (fragments == 0)
++              return 0;
++
++      switch (cr) {
++              case 0:
++                      J_ASSERT(ac->ac_2order != 0);
++                      bits = ac->ac_sb->s_blocksize_bits + 1;
++                      for (i = ac->ac_2order; i < bits; i++)
++                              if (grp->bb_counters[i] > 0)
++                                      return 1;
++              case 1:
++                      if ((free / fragments) >= ac->ac_g_ex.fe_len)
++                              return 1;
++              case 2:
++                      if (free >= ac->ac_g_ex.fe_len)
++                              return 1;
++              case 3:
++                      return 1;
++              default:
++                      BUG();
++      }
++
++      return 0;
++}
++
++int ext3_mb_new_blocks(handle_t *handle, struct inode *inode,
++                     unsigned long goal, int *len, int flags, int *errp)
++{
++      struct buffer_head *bitmap_bh = NULL;
++      struct ext3_allocation_context ac;
++      int i, group, block, cr, err = 0;
++      struct ext3_group_desc *gdp;
++      struct ext3_super_block *es;
++      struct buffer_head *gdp_bh;
++      struct ext3_sb_info *sbi;
++      struct super_block *sb;
++      struct ext3_buddy e3b;
++
++      J_ASSERT(len != NULL);
++      J_ASSERT(*len > 0);
++
++      sb = inode->i_sb;
++      if (!sb) {
++              printk("ext3_mb_new_nblocks: nonexistent device");
++              return 0;
++      }
++
++      if (!test_opt(sb, MBALLOC)) {
++              static int ext3_mballoc_warning = 0;
++              if (ext3_mballoc_warning == 0) {
++                      printk(KERN_ERR "EXT3-fs: multiblock request with "
++                              "mballoc disabled!\n");
++                      ext3_mballoc_warning++;
++              }
++              *len = 1;
++              err = ext3_new_block_old(handle, inode, goal, errp);
++              return err;
++      }
++
++      ext3_mb_poll_new_transaction(sb, handle);
++
++      sbi = EXT3_SB(sb);
++      es = EXT3_SB(sb)->s_es;
++
++      /*
++       * We can't allocate > group size
++       */
++      if (*len >= EXT3_BLOCKS_PER_GROUP(sb) - 10)
++              *len = EXT3_BLOCKS_PER_GROUP(sb) - 10;
++
++      if (!(flags & EXT3_MB_HINT_RESERVED)) {
++              /* someone asks for non-reserved blocks */
++              BUG_ON(*len > 1);
++              err = ext3_mb_reserve_blocks(sb, 1);
++              if (err) {
++                      *errp = err;
++                      return 0;
++              }
++      }
++
++      /*
++       * Check quota for allocation of this blocks.
++       */
++      while (*len && DQUOT_ALLOC_BLOCK(inode, *len))
++              *len -= 1;
++      if (*len == 0) {
++              *errp = -EDQUOT;
++              block = 0;
++              goto out;
++      }
++
++      /* start searching from the goal */
++      if (goal < le32_to_cpu(es->s_first_data_block) ||
++          goal >= le32_to_cpu(es->s_blocks_count))
++              goal = le32_to_cpu(es->s_first_data_block);
++      group = (goal - le32_to_cpu(es->s_first_data_block)) /
++                      EXT3_BLOCKS_PER_GROUP(sb);
++      block = ((goal - le32_to_cpu(es->s_first_data_block)) %
++                      EXT3_BLOCKS_PER_GROUP(sb));
++
++      /* set up allocation goals */
++      ac.ac_b_ex.fe_group = 0;
++      ac.ac_b_ex.fe_start = 0;
++      ac.ac_b_ex.fe_len = 0;
++      ac.ac_status = AC_STATUS_CONTINUE;
++      ac.ac_groups_scanned = 0;
++      ac.ac_ex_scanned = 0;
++      ac.ac_found = 0;
++      ac.ac_sb = inode->i_sb;
++      ac.ac_g_ex.fe_group = group;
++      ac.ac_g_ex.fe_start = block;
++      ac.ac_g_ex.fe_len = *len;
++      ac.ac_flags = flags;
++      ac.ac_2order = 0;
++      ac.ac_criteria = 0;
++
++      /* probably, the request is for 2^8+ blocks (1/2/3/... MB) */
++      i = ffs(*len);
++      if (i >= 8) {
++              i--;
++              if ((*len & (~(1 << i))) == 0)
++                      ac.ac_2order = i;
++      }
++
++      /* Sometimes, caller may want to merge even small
++       * number of blocks to an existing extent */
++      if (ac.ac_flags & EXT3_MB_HINT_MERGE) {
++              err = ext3_mb_find_by_goal(&ac, &e3b);
++              if (err)
++                      goto out_err;
++              if (ac.ac_status == AC_STATUS_FOUND)
++                      goto found;
++      }
++
++      /* Let's just scan groups to find more-less suitable blocks */
++      cr = ac.ac_2order ? 0 : 1;
++repeat:
++      for (; cr < 4 && ac.ac_status == AC_STATUS_CONTINUE; cr++) {
++              ac.ac_criteria = cr;
++              for (i = 0; i < EXT3_SB(sb)->s_groups_count; group++, i++) {
++                      if (group == EXT3_SB(sb)->s_groups_count)
++                              group = 0;
++
++                      if (EXT3_MB_GRP_NEED_INIT(sbi->s_group_info[group])) {
++                              /* we need full data about the group
++                               * to make a good selection */
++                              err = ext3_mb_load_buddy(ac.ac_sb, group, &e3b);
++                              if (err)
++                                      goto out_err;
++                              ext3_mb_release_desc(&e3b);
++                      }
++                              
++                      /* check is group good for our criteries */
++                      if (!ext3_mb_good_group(&ac, group, cr))
++                              continue;
++
++                      err = ext3_mb_load_buddy(ac.ac_sb, group, &e3b);
++                      if (err)
++                              goto out_err;
++
++                      ext3_lock_group(sb, group);
++                      if (!ext3_mb_good_group(&ac, group, cr)) {
++                              /* someone did allocation from this group */
++                              ext3_unlock_group(sb, group);
++                              ext3_mb_release_desc(&e3b);
++                              continue;
++                      }
++
++                      ac.ac_groups_scanned++;
++                      if (cr == 0)
++                              ext3_mb_simple_scan_group(&ac, &e3b);
++                      else
++                              ext3_mb_complex_scan_group(&ac, &e3b);
++
++                      ext3_unlock_group(sb, group);
++
++                      ext3_mb_release_desc(&e3b);
++
++                      if (err)
++                              goto out_err;
++                      if (ac.ac_status != AC_STATUS_CONTINUE)
++                              break;
++              }
++      }
++
++      if (ac.ac_b_ex.fe_len > 0 && ac.ac_status != AC_STATUS_FOUND &&
++                      !(ac.ac_flags & EXT3_MB_HINT_FIRST)) {
++              /*
++               * We've been searching too long. Let's try to allocate
++               * the best chunk we've found so far
++               */
++
++              /*if (ac.ac_found > ext3_mb_max_to_scan)
++                      printk(KERN_ERR "EXT3-fs: too long searching at "
++                              "%u (%d/%d)\n", cr, ac.ac_b_ex.fe_len,
++                              ac.ac_g_ex.fe_len);*/
++              ext3_mb_try_best_found(&ac, &e3b);
++              if (ac.ac_status != AC_STATUS_FOUND) {
++                      /*
++                       * Someone more lucky has already allocated it.
++                       * The only thing we can do is just take first
++                       * found block(s)
++                       */
++                      printk(KERN_ERR "EXT3-fs: and someone won our chunk\n");
++                      ac.ac_b_ex.fe_group = 0;
++                      ac.ac_b_ex.fe_start = 0;
++                      ac.ac_b_ex.fe_len = 0;
++                      ac.ac_status = AC_STATUS_CONTINUE;
++                      ac.ac_flags |= EXT3_MB_HINT_FIRST;
++                      cr = 3;
++                      goto repeat;
++              }
++      }
++
++      if (ac.ac_status != AC_STATUS_FOUND) {
++              /*
++               * We aren't lucky definitely
++               */
++              DQUOT_FREE_BLOCK(inode, *len);
++              *errp = -ENOSPC;
++              block = 0;
++#if 1
++              printk(KERN_ERR "EXT3-fs: cant allocate: status %d, flags %d\n",
++                      ac.ac_status, ac.ac_flags);
++              printk(KERN_ERR "EXT3-fs: goal %d, best found %d/%d/%d, cr %d\n",
++                      ac.ac_g_ex.fe_len, ac.ac_b_ex.fe_group,
++                      ac.ac_b_ex.fe_start, ac.ac_b_ex.fe_len, cr);
++              printk(KERN_ERR "EXT3-fs: %lu block reserved, %d found\n",
++                      sbi->s_blocks_reserved, ac.ac_found);
++              printk("EXT3-fs: groups: ");
++              for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++)
++                      printk("%d: %d ", i,
++                              sbi->s_group_info[i]->bb_free);
++              printk("\n");
++#endif
++              goto out;
++      }
++
++found:
++      J_ASSERT(ac.ac_b_ex.fe_len > 0);
++
++      /* good news - free block(s) have been found. now it's time
++       * to mark block(s) in good old journaled bitmap */
++      block = ac.ac_b_ex.fe_group * EXT3_BLOCKS_PER_GROUP(sb)
++                      + ac.ac_b_ex.fe_start
++                      + le32_to_cpu(es->s_first_data_block);
++
++      /* we made a desicion, now mark found blocks in good old
++       * bitmap to be journaled */
++
++      ext3_debug("using block group %d(%d)\n",
++                      ac.ac_b_group.group, gdp->bg_free_blocks_count);
++
++      bitmap_bh = read_block_bitmap(sb, ac.ac_b_ex.fe_group);
++      if (!bitmap_bh) {
++              *errp = -EIO;
++              goto out_err;
++      }
++
++      err = ext3_journal_get_write_access(handle, bitmap_bh);
++      if (err) {
++              *errp = err;
++              goto out_err;
++      }
++
++      gdp = ext3_get_group_desc(sb, ac.ac_b_ex.fe_group, &gdp_bh);
++      if (!gdp) {
++              *errp = -EIO;
++              goto out_err;
++      }
++      
++      err = ext3_journal_get_write_access(handle, gdp_bh);
++      if (err)
++              goto out_err;
++
++      block = ac.ac_b_ex.fe_group * EXT3_BLOCKS_PER_GROUP(sb)
++                      + ac.ac_b_ex.fe_start
++                      + le32_to_cpu(es->s_first_data_block);
++
++      if (block == le32_to_cpu(gdp->bg_block_bitmap) ||
++          block == le32_to_cpu(gdp->bg_inode_bitmap) ||
++          in_range(block, le32_to_cpu(gdp->bg_inode_table),
++                    EXT3_SB(sb)->s_itb_per_group))
++              ext3_error(sb, "ext3_new_block",
++                          "Allocating block in system zone - "
++                          "block = %u", block);
++#ifdef AGGRESSIVE_CHECK
++      for (i = 0; i < ac.ac_b_ex.fe_len; i++)
++              J_ASSERT(!mb_test_bit(ac.ac_b_ex.fe_start + i, bitmap_bh->b_data));
++#endif
++      mb_set_bits(bitmap_bh->b_data, ac.ac_b_ex.fe_start, ac.ac_b_ex.fe_len);
++
++      spin_lock(sb_bgl_lock(sbi, ac.ac_b_ex.fe_group));
++      gdp->bg_free_blocks_count =
++                      cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count)
++                                      - ac.ac_b_ex.fe_len);
++      spin_unlock(sb_bgl_lock(sbi, ac.ac_b_ex.fe_group));
++      percpu_counter_mod(&sbi->s_freeblocks_counter, - ac.ac_b_ex.fe_len);
++
++      err = ext3_journal_dirty_metadata(handle, bitmap_bh);
++      if (err)
++              goto out_err;
++      err = ext3_journal_dirty_metadata(handle, gdp_bh);
++      if (err)
++              goto out_err;
++
++      sb->s_dirt = 1;
++      *errp = 0;
++      brelse(bitmap_bh);
++
++      /* drop non-allocated, but dquote'd blocks */
++      J_ASSERT(*len >= ac.ac_b_ex.fe_len);
++      DQUOT_FREE_BLOCK(inode, *len - ac.ac_b_ex.fe_len);
++
++      *len = ac.ac_b_ex.fe_len;
++      J_ASSERT(*len > 0);
++      J_ASSERT(block != 0);
++      goto out;
++
++out_err:
++      /* if we've already allocated something, roll it back */
++      if (ac.ac_status == AC_STATUS_FOUND) {
++              /* FIXME: free blocks here */
++      }
++
++      DQUOT_FREE_BLOCK(inode, *len);
++      brelse(bitmap_bh);
++      *errp = err;
++      block = 0;
++out:
++      if (!(flags & EXT3_MB_HINT_RESERVED)) {
++              /* block wasn't reserved before and we reserved it
++               * at the beginning of allocation. it doesn't matter
++               * whether we allocated anything or we failed: time
++               * to release reservation. NOTE: because I expect
++               * any multiblock request from delayed allocation
++               * path only, here is single block always */
++              ext3_mb_release_blocks(sb, 1);
++      }
++      
++      if (unlikely(ext3_mb_stats) && ac.ac_g_ex.fe_len > 1) {
++              atomic_inc(&sbi->s_bal_reqs);
++              atomic_add(*len, &sbi->s_bal_allocated);
++              if (*len >= ac.ac_g_ex.fe_len)
++                      atomic_inc(&sbi->s_bal_success);
++              atomic_add(ac.ac_found, &sbi->s_bal_ex_scanned);
++              if (ac.ac_g_ex.fe_start == ac.ac_b_ex.fe_start &&
++                              ac.ac_g_ex.fe_group == ac.ac_b_ex.fe_group)
++                      atomic_inc(&sbi->s_bal_goals);
++              if (ac.ac_found > ext3_mb_max_to_scan)
++                      atomic_inc(&sbi->s_bal_breaks);
++      }
++
++      ext3_mb_store_history(sb, &ac);
++
++      return block;
++}
++EXPORT_SYMBOL(ext3_mb_new_blocks);
++
++#ifdef EXT3_MB_HISTORY
++struct ext3_mb_proc_session {
++      struct ext3_mb_history *history;
++      struct super_block *sb;
++      int start;
++      int max;
++};
++
++static void *ext3_mb_history_skip_empty(struct ext3_mb_proc_session *s,
++                                      struct ext3_mb_history *hs,
++                                      int first)
++{
++      if (hs == s->history + s->max)
++              hs = s->history;
++      if (!first && hs == s->history + s->start)
++              return NULL;
++      while (hs->goal.fe_len == 0) {
++              hs++;
++              if (hs == s->history + s->max)
++                      hs = s->history;
++              if (hs == s->history + s->start)
++                      return NULL;
++      }
++      return hs;
++}
++
++static void *ext3_mb_seq_history_start(struct seq_file *seq, loff_t *pos)
++{
++      struct ext3_mb_proc_session *s = seq->private;
++      struct ext3_mb_history *hs;
++      int l = *pos;
++
++      if (l == 0)
++              return SEQ_START_TOKEN;
++      hs = ext3_mb_history_skip_empty(s, s->history + s->start, 1);
++      if (!hs)
++              return NULL;
++      while (--l && (hs = ext3_mb_history_skip_empty(s, ++hs, 0)) != NULL);
++      return hs;
++}
++
++static void *ext3_mb_seq_history_next(struct seq_file *seq, void *v, loff_t *pos)
++{
++      struct ext3_mb_proc_session *s = seq->private;
++      struct ext3_mb_history *hs = v;
++
++      ++*pos;
++      if (v == SEQ_START_TOKEN)
++              return ext3_mb_history_skip_empty(s, s->history + s->start, 1);
++      else
++              return ext3_mb_history_skip_empty(s, ++hs, 0);
++}
++
++static int ext3_mb_seq_history_show(struct seq_file *seq, void *v)
++{
++      struct ext3_mb_history *hs = v;
++      char buf[20], buf2[20];
++
++      if (v == SEQ_START_TOKEN) {
++              seq_printf(seq, "%-17s %-17s %-5s %-5s %-2s %-5s %-5s %-6s\n",
++                       "goal", "result", "found", "grps", "cr", "merge",
++                       "tail", "broken");
++              return 0;
++      }
++
++      sprintf(buf, "%u/%u/%u", hs->goal.fe_group,
++              hs->goal.fe_start, hs->goal.fe_len);
++      sprintf(buf2, "%u/%u/%u", hs->result.fe_group,
++              hs->result.fe_start, hs->result.fe_len);
++      seq_printf(seq, "%-17s %-17s %-5u %-5u %-2u %-5s %-5u %-6u\n", buf,
++                      buf2, hs->found, hs->groups, hs->cr, 
++                      hs->merged ? "M" : "", hs->tail,
++                      hs->buddy ? 1 << hs->buddy : 0);
++      return 0;
++}
++
++static void ext3_mb_seq_history_stop(struct seq_file *seq, void *v)
++{
++}
++
++static struct seq_operations ext3_mb_seq_history_ops = {
++      .start  = ext3_mb_seq_history_start,
++      .next   = ext3_mb_seq_history_next,
++      .stop   = ext3_mb_seq_history_stop,
++      .show   = ext3_mb_seq_history_show,
++};
++
++static int ext3_mb_seq_history_open(struct inode *inode, struct file *file)
++{
++      struct super_block *sb = PDE(inode)->data;
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      struct ext3_mb_proc_session *s;
++      int rc, size;
++
++      s = kmalloc(sizeof(*s), GFP_KERNEL);
++      if (s == NULL)
++              return -EIO;
++      size = sizeof(struct ext3_mb_history) * sbi->s_mb_history_max;
++      s->history = kmalloc(size, GFP_KERNEL);
++      if (s == NULL) {
++              kfree(s);
++              return -EIO;
++      }
++
++      spin_lock(&sbi->s_mb_history_lock);
++      memcpy(s->history, sbi->s_mb_history, size);
++      s->max = sbi->s_mb_history_max;
++      s->start = sbi->s_mb_history_cur % s->max;
++      spin_unlock(&sbi->s_mb_history_lock);
++      
++      rc = seq_open(file, &ext3_mb_seq_history_ops);
++      if (rc == 0) {
++              struct seq_file *m = (struct seq_file *)file->private_data;
++              m->private = s;
++      } else {
++              kfree(s->history);
++              kfree(s);
++      }
++      return rc;
++
++}
++
++static int ext3_mb_seq_history_release(struct inode *inode, struct file *file)
++{
++      struct seq_file *seq = (struct seq_file *)file->private_data;
++      struct ext3_mb_proc_session *s = seq->private;
++      kfree(s->history);
++      kfree(s);
++      return seq_release(inode, file);
++}
++
++static struct file_operations ext3_mb_seq_history_fops = {
++      .owner          = THIS_MODULE,
++      .open           = ext3_mb_seq_history_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = ext3_mb_seq_history_release,
++};
++
++static void ext3_mb_history_release(struct super_block *sb)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      char name[64];
++
++      snprintf(name, sizeof(name) - 1, "%s", bdevname(sb->s_bdev, name));
++      remove_proc_entry("mb_history", sbi->s_mb_proc);
++      remove_proc_entry(name, proc_root_ext3);
++
++      if (sbi->s_mb_history)
++              kfree(sbi->s_mb_history);
++}
++
++static void ext3_mb_history_init(struct super_block *sb)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      char name[64];
++      int i;
++
++      snprintf(name, sizeof(name) - 1, "%s", bdevname(sb->s_bdev, name));
++      sbi->s_mb_proc = proc_mkdir(name, proc_root_ext3);
++      if (sbi->s_mb_proc != NULL) {
++              struct proc_dir_entry *p;
++              p = create_proc_entry("mb_history", S_IRUGO, sbi->s_mb_proc);
++              if (p) {
++                      p->proc_fops = &ext3_mb_seq_history_fops;
++                      p->data = sb;
++              }
++      }
++
++      sbi->s_mb_history_max = 1000;
++      sbi->s_mb_history_cur = 0;
++      spin_lock_init(&sbi->s_mb_history_lock);
++      i = sbi->s_mb_history_max * sizeof(struct ext3_mb_history);
++      sbi->s_mb_history = kmalloc(i, GFP_KERNEL);
++      memset(sbi->s_mb_history, 0, i);
++      /* if we can't allocate history, then we simple won't use it */
++}
++
++static void
++ext3_mb_store_history(struct super_block *sb, struct ext3_allocation_context *ac)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      struct ext3_mb_history h;
++
++      if (likely(sbi->s_mb_history == NULL))
++              return;
++
++      h.goal = ac->ac_g_ex;
++      h.result = ac->ac_b_ex;
++      h.found = ac->ac_found;
++      h.cr = ac->ac_criteria;
++      h.groups = ac->ac_groups_scanned;
++      h.tail = ac->ac_tail;
++      h.buddy = ac->ac_buddy;
++      h.merged = 0;
++      if (ac->ac_g_ex.fe_start == ac->ac_b_ex.fe_start &&
++                      ac->ac_g_ex.fe_group == ac->ac_b_ex.fe_group)
++              h.merged = 1;
++
++      spin_lock(&sbi->s_mb_history_lock);
++      memcpy(sbi->s_mb_history + sbi->s_mb_history_cur, &h, sizeof(h));
++      if (++sbi->s_mb_history_cur >= sbi->s_mb_history_max)
++              sbi->s_mb_history_cur = 0;
++      spin_unlock(&sbi->s_mb_history_lock);
++}
++
++#else
++#define ext3_mb_history_release(sb)
++#define ext3_mb_history_init(sb)
++#endif
++
++int ext3_mb_init_backend(struct super_block *sb)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      int i, len;
++
++      len = sizeof(struct ext3_buddy_group_blocks *) * sbi->s_groups_count;
++      sbi->s_group_info = kmalloc(len, GFP_KERNEL);
++      if (sbi->s_group_info == NULL) {
++              printk(KERN_ERR "EXT3-fs: can't allocate mem for buddy\n");
++              return -ENOMEM;
++      }
++      memset(sbi->s_group_info, 0, len);
++
++      sbi->s_buddy_cache = new_inode(sb);
++      if (sbi->s_buddy_cache == NULL) {
++              printk(KERN_ERR "EXT3-fs: can't get new inode\n");
++              kfree(sbi->s_group_info);
++              return -ENOMEM;
++      }
++
++      /* 
++       * calculate needed size. if change bb_counters size,
++       * don't forget about ext3_mb_generate_buddy()
++       */
++      len = sizeof(struct ext3_group_info);
++      len += sizeof(unsigned short) * (sb->s_blocksize_bits + 2);
++      for (i = 0; i < sbi->s_groups_count; i++) {
++              struct ext3_group_desc * desc;
++
++              sbi->s_group_info[i] = kmalloc(len, GFP_KERNEL);
++              if (sbi->s_group_info[i] == NULL) {
++                      printk(KERN_ERR "EXT3-fs: cant allocate mem for buddy\n");
++                      goto err_out;
++              }
++              desc = ext3_get_group_desc(sb, i, NULL);
++              if (desc == NULL) {
++                      printk(KERN_ERR "EXT3-fs: cant read descriptor %u\n", i);
++                      goto err_out;
++              }
++              memset(sbi->s_group_info[i], 0, len);
++              set_bit(EXT3_GROUP_INFO_NEED_INIT_BIT,
++                      &sbi->s_group_info[i]->bb_state);
++              sbi->s_group_info[i]->bb_free =
++                      le16_to_cpu(desc->bg_free_blocks_count);
++      }
++
++      return 0;
++
++err_out:
++      while (--i >= 0)
++              kfree(sbi->s_group_info[i]);
++      iput(sbi->s_buddy_cache);
++
++      return -ENOMEM;
++}
++
++int ext3_mb_init(struct super_block *sb, int needs_recovery)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      struct inode *root = sb->s_root->d_inode;
++      unsigned i, offset, max;
++      struct dentry *dentry;
++
++      if (!test_opt(sb, MBALLOC))
++              return 0;
++
++      i = (sb->s_blocksize_bits + 2) * sizeof(unsigned short);
++
++      sbi->s_mb_offsets = kmalloc(i, GFP_KERNEL);
++      if (sbi->s_mb_offsets == NULL) {
++              clear_opt(sbi->s_mount_opt, MBALLOC);
++              return -ENOMEM;
++      }
++      sbi->s_mb_maxs = kmalloc(i, GFP_KERNEL);
++      if (sbi->s_mb_maxs == NULL) {
++              clear_opt(sbi->s_mount_opt, MBALLOC);
++              kfree(sbi->s_mb_maxs);
++              return -ENOMEM;
++      }
++
++       /* order 0 is regular bitmap */
++      sbi->s_mb_maxs[0] = sb->s_blocksize << 3;
++      sbi->s_mb_offsets[0] = 0;
++
++      i = 1;
++      offset = 0;
++      max = sb->s_blocksize << 2;
++      do {
++              sbi->s_mb_offsets[i] = offset;
++              sbi->s_mb_maxs[i] = max;
++              offset += 1 << (sb->s_blocksize_bits - i);
++              max = max >> 1;
++              i++;
++      } while (i <= sb->s_blocksize_bits + 1);
++      
++
++      /* init file for buddy data */
++      if ((i = ext3_mb_init_backend(sb))) {
++              clear_opt(sbi->s_mount_opt, MBALLOC);
++              kfree(sbi->s_mb_offsets);
++              kfree(sbi->s_mb_maxs);
++              return i;
++      }
++
++      spin_lock_init(&sbi->s_reserve_lock);
++      spin_lock_init(&sbi->s_md_lock);
++      INIT_LIST_HEAD(&sbi->s_active_transaction);
++      INIT_LIST_HEAD(&sbi->s_closed_transaction);
++      INIT_LIST_HEAD(&sbi->s_committed_transaction);
++      spin_lock_init(&sbi->s_bal_lock);
++
++      /* remove old on-disk buddy file */
++      mutex_lock(&root->i_mutex);
++      dentry = lookup_one_len(".buddy", sb->s_root, strlen(".buddy"));
++      if (dentry->d_inode != NULL) {
++              i = vfs_unlink(root, dentry);
++              if (i != 0)
++                      printk("EXT3-fs: can't remove .buddy file: %d\n", i);
++      }
++      dput(dentry);
++      mutex_unlock(&root->i_mutex);
++
++      ext3_mb_history_init(sb);
++
++      printk("EXT3-fs: mballoc enabled\n");
++      return 0;
++}
++
++int ext3_mb_release(struct super_block *sb)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      int i;
++      
++      if (!test_opt(sb, MBALLOC))
++              return 0;
++
++      /* release freed, non-committed blocks */
++      spin_lock(&sbi->s_md_lock);
++      list_splice_init(&sbi->s_closed_transaction,
++                      &sbi->s_committed_transaction);
++      list_splice_init(&sbi->s_active_transaction,
++                      &sbi->s_committed_transaction);
++      spin_unlock(&sbi->s_md_lock);
++      ext3_mb_free_committed_blocks(sb);
++
++      if (sbi->s_group_info) {
++              for (i = 0; i < sbi->s_groups_count; i++) {
++                      if (sbi->s_group_info[i] == NULL)
++                              continue;
++                      kfree(sbi->s_group_info[i]);
++              }
++              kfree(sbi->s_group_info);
++      }
++      if (sbi->s_mb_offsets)
++              kfree(sbi->s_mb_offsets);
++      if (sbi->s_mb_maxs)
++              kfree(sbi->s_mb_maxs);
++      if (sbi->s_buddy_cache)
++              iput(sbi->s_buddy_cache);
++      if (sbi->s_blocks_reserved)
++              printk("ext3-fs: %ld blocks being reserved at umount!\n",
++                              sbi->s_blocks_reserved);
++      if (ext3_mb_stats) {
++              printk("EXT3-fs: mballoc: %u blocks %u reqs (%u success)\n",
++                      atomic_read(&sbi->s_bal_allocated),
++                      atomic_read(&sbi->s_bal_reqs),
++                      atomic_read(&sbi->s_bal_success));
++              printk("EXT3-fs: mballoc: %u extents scanned, %u goal hits, "
++                      "%u 2^N hits, %u breaks\n",
++                      atomic_read(&sbi->s_bal_ex_scanned),
++                      atomic_read(&sbi->s_bal_goals),
++                      atomic_read(&sbi->s_bal_2orders),
++                      atomic_read(&sbi->s_bal_breaks));
++              printk("EXT3-fs: mballoc: %lu generated and it took %Lu\n",
++                      sbi->s_mb_buddies_generated++,
++                      sbi->s_mb_generation_time);
++      }
++
++      ext3_mb_history_release(sb);
++
++      return 0;
++}
++
++void ext3_mb_free_committed_blocks(struct super_block *sb)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      int err, i, count = 0, count2 = 0;
++      struct ext3_free_metadata *md;
++      struct ext3_buddy e3b;
++
++      if (list_empty(&sbi->s_committed_transaction))
++              return;
++
++      /* there is committed blocks to be freed yet */
++      do {
++              /* get next array of blocks */
++              md = NULL;
++              spin_lock(&sbi->s_md_lock);
++              if (!list_empty(&sbi->s_committed_transaction)) {
++                      md = list_entry(sbi->s_committed_transaction.next,
++                                      struct ext3_free_metadata, list);
++                      list_del(&md->list);
++              }
++              spin_unlock(&sbi->s_md_lock);
++
++              if (md == NULL)
++                      break;
++
++              mb_debug("gonna free %u blocks in group %u (0x%p):",
++                              md->num, md->group, md);
++
++              err = ext3_mb_load_buddy(sb, md->group, &e3b);
++              BUG_ON(err != 0);
++
++              /* there are blocks to put in buddy to make them really free */
++              count += md->num;
++              count2++;
++              ext3_lock_group(sb, md->group);
++              for (i = 0; i < md->num; i++) {
++                      mb_debug(" %u", md->blocks[i]);
++                      mb_free_blocks(&e3b, md->blocks[i], 1);
++              }
++              mb_debug("\n");
++              ext3_unlock_group(sb, md->group);
++
++              /* balance refcounts from ext3_mb_free_metadata() */
++              page_cache_release(e3b.bd_buddy_page);
++              page_cache_release(e3b.bd_bitmap_page);
++
++              kfree(md);
++              ext3_mb_release_desc(&e3b);
++
++      } while (md);
++      mb_debug("freed %u blocks in %u structures\n", count, count2);
++}
++
++void ext3_mb_poll_new_transaction(struct super_block *sb, handle_t *handle)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++
++      if (sbi->s_last_transaction == handle->h_transaction->t_tid)
++              return;
++
++      /* new transaction! time to close last one and free blocks for
++       * committed transaction. we know that only transaction can be
++       * active, so previos transaction can be being logged and we
++       * know that transaction before previous is known to be already
++       * logged. this means that now we may free blocks freed in all
++       * transactions before previous one. hope I'm clear enough ... */
++
++      spin_lock(&sbi->s_md_lock);
++      if (sbi->s_last_transaction != handle->h_transaction->t_tid) {
++              mb_debug("new transaction %lu, old %lu\n",
++                              (unsigned long) handle->h_transaction->t_tid,
++                              (unsigned long) sbi->s_last_transaction);
++              list_splice_init(&sbi->s_closed_transaction,
++                                      &sbi->s_committed_transaction);
++              list_splice_init(&sbi->s_active_transaction,
++                                      &sbi->s_closed_transaction);
++              sbi->s_last_transaction = handle->h_transaction->t_tid;
++      }
++      spin_unlock(&sbi->s_md_lock);
++
++      ext3_mb_free_committed_blocks(sb);
++}
++
++int ext3_mb_free_metadata(handle_t *handle, struct ext3_buddy *e3b,
++                              int group, int block, int count)
++{
++      struct ext3_group_info *db = e3b->bd_info;
++      struct super_block *sb = e3b->bd_sb;
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      struct ext3_free_metadata *md;
++      int i;
++
++      J_ASSERT(e3b->bd_bitmap_page != NULL);
++      J_ASSERT(e3b->bd_buddy_page != NULL);
++
++      ext3_lock_group(sb, group);
++      for (i = 0; i < count; i++) {
++              md = db->bb_md_cur;
++              if (md && db->bb_tid != handle->h_transaction->t_tid) {
++                      db->bb_md_cur = NULL;
++                      md = NULL;
++              }
++
++              if (md == NULL) {
++                      ext3_unlock_group(sb, group);
++                      md = kmalloc(sizeof(*md), GFP_KERNEL);
++                      if (md == NULL)
++                              return -ENOMEM;
++                      md->num = 0;
++                      md->group = group;
++
++                      ext3_lock_group(sb, group);
++                      if (db->bb_md_cur == NULL) {
++                              spin_lock(&sbi->s_md_lock);
++                              list_add(&md->list, &sbi->s_active_transaction);
++                              spin_unlock(&sbi->s_md_lock);
++                              /* protect buddy cache from being freed,
++                               * otherwise we'll refresh it from
++                               * on-disk bitmap and lose not-yet-available
++                               * blocks */
++                              page_cache_get(e3b->bd_buddy_page);
++                              page_cache_get(e3b->bd_bitmap_page);
++                              db->bb_md_cur = md;
++                              db->bb_tid = handle->h_transaction->t_tid;
++                              mb_debug("new md 0x%p for group %u\n",
++                                                      md, md->group);
++                      } else {
++                              kfree(md);
++                              md = db->bb_md_cur;
++                      }
++              }
++
++              BUG_ON(md->num >= EXT3_BB_MAX_BLOCKS);
++              md->blocks[md->num] = block + i;
++              md->num++;
++              if (md->num == EXT3_BB_MAX_BLOCKS) {
++                      /* no more space, put full container on a sb's list */
++                      db->bb_md_cur = NULL;
++              }
++      }
++      ext3_unlock_group(sb, group);
++      return 0;
++}
++
++void ext3_mb_free_blocks(handle_t *handle, struct inode *inode,
++                      unsigned long block, unsigned long count,
++                      int metadata, int *freed)
++{
++      struct buffer_head *bitmap_bh = NULL;
++      struct ext3_group_desc *gdp;
++      struct ext3_super_block *es;
++      unsigned long bit, overflow;
++      struct buffer_head *gd_bh;
++      unsigned long block_group;
++      struct ext3_sb_info *sbi;
++      struct super_block *sb;
++      struct ext3_buddy e3b;
++      int err = 0, ret;
++
++      *freed = 0;
++      sb = inode->i_sb;
++      if (!sb) {
++              printk ("ext3_free_blocks: nonexistent device");
++              return;
++      }
++
++      ext3_mb_poll_new_transaction(sb, handle);
++
++      sbi = EXT3_SB(sb);
++      es = EXT3_SB(sb)->s_es;
++      if (block < le32_to_cpu(es->s_first_data_block) ||
++          block + count < block ||
++          block + count > le32_to_cpu(es->s_blocks_count)) {
++              ext3_error (sb, "ext3_free_blocks",
++                          "Freeing blocks not in datazone - "
++                          "block = %lu, count = %lu", block, count);
++              goto error_return;
++      }
++
++      ext3_debug("freeing block %lu\n", block);
++
++do_more:
++      overflow = 0;
++      block_group = (block - le32_to_cpu(es->s_first_data_block)) /
++                    EXT3_BLOCKS_PER_GROUP(sb);
++      bit = (block - le32_to_cpu(es->s_first_data_block)) %
++                    EXT3_BLOCKS_PER_GROUP(sb);
++      /*
++       * Check to see if we are freeing blocks across a group
++       * boundary.
++       */
++      if (bit + count > EXT3_BLOCKS_PER_GROUP(sb)) {
++              overflow = bit + count - EXT3_BLOCKS_PER_GROUP(sb);
++              count -= overflow;
++      }
++      brelse(bitmap_bh);
++      bitmap_bh = read_block_bitmap(sb, block_group);
++      if (!bitmap_bh)
++              goto error_return;
++      gdp = ext3_get_group_desc (sb, block_group, &gd_bh);
++      if (!gdp)
++              goto error_return;
++
++      if (in_range (le32_to_cpu(gdp->bg_block_bitmap), block, count) ||
++          in_range (le32_to_cpu(gdp->bg_inode_bitmap), block, count) ||
++          in_range (block, le32_to_cpu(gdp->bg_inode_table),
++                    EXT3_SB(sb)->s_itb_per_group) ||
++          in_range (block + count - 1, le32_to_cpu(gdp->bg_inode_table),
++                    EXT3_SB(sb)->s_itb_per_group))
++              ext3_error (sb, "ext3_free_blocks",
++                          "Freeing blocks in system zones - "
++                          "Block = %lu, count = %lu",
++                          block, count);
++
++      BUFFER_TRACE(bitmap_bh, "getting write access");
++      err = ext3_journal_get_write_access(handle, bitmap_bh);
++      if (err)
++              goto error_return;
++
++      /*
++       * We are about to modify some metadata.  Call the journal APIs
++       * to unshare ->b_data if a currently-committing transaction is
++       * using it
++       */
++      BUFFER_TRACE(gd_bh, "get_write_access");
++      err = ext3_journal_get_write_access(handle, gd_bh);
++      if (err)
++              goto error_return;
++
++      err = ext3_mb_load_buddy(sb, block_group, &e3b);
++      if (err)
++              goto error_return;
++
++#ifdef AGGRESSIVE_CHECK
++      {
++              int i;
++              for (i = 0; i < count; i++)
++                      J_ASSERT(mb_test_bit(bit + i, bitmap_bh->b_data));
++      }
++#endif
++      mb_clear_bits(bitmap_bh->b_data, bit, count);
++
++      /* We dirtied the bitmap block */
++      BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");
++      err = ext3_journal_dirty_metadata(handle, bitmap_bh);
++
++      if (metadata) {
++              /* blocks being freed are metadata. these blocks shouldn't
++               * be used until this transaction is committed */
++              ext3_mb_free_metadata(handle, &e3b, block_group, bit, count);
++      } else { 
++              ext3_lock_group(sb, block_group);
++              mb_free_blocks(&e3b, bit, count);
++              ext3_unlock_group(sb, block_group);
++      }
++
++      spin_lock(sb_bgl_lock(sbi, block_group));
++      gdp->bg_free_blocks_count =
++              cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) + count);
++      spin_unlock(sb_bgl_lock(sbi, block_group));
++      percpu_counter_mod(&sbi->s_freeblocks_counter, count);
++      
++      ext3_mb_release_desc(&e3b);
++
++      *freed = count;
++
++      /* And the group descriptor block */
++      BUFFER_TRACE(gd_bh, "dirtied group descriptor block");
++      ret = ext3_journal_dirty_metadata(handle, gd_bh);
++      if (!err) err = ret;
++
++      if (overflow && !err) {
++              block += count;
++              count = overflow;
++              goto do_more;
++      }
++      sb->s_dirt = 1;
++error_return:
++      brelse(bitmap_bh);
++      ext3_std_error(sb, err);
++      return;
++}
++
++int ext3_mb_reserve_blocks(struct super_block *sb, int blocks)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      int free, ret = -ENOSPC;
++
++      BUG_ON(blocks < 0);
++      spin_lock(&sbi->s_reserve_lock);
++      free = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
++      if (blocks <= free - sbi->s_blocks_reserved) {
++              sbi->s_blocks_reserved += blocks;
++              ret = 0;
++      }
++      spin_unlock(&sbi->s_reserve_lock);
++      return ret;
++}
++
++void ext3_mb_release_blocks(struct super_block *sb, int blocks)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++
++      BUG_ON(blocks < 0);
++      spin_lock(&sbi->s_reserve_lock);
++      sbi->s_blocks_reserved -= blocks;
++      WARN_ON(sbi->s_blocks_reserved < 0);
++      if (sbi->s_blocks_reserved < 0)
++              sbi->s_blocks_reserved = 0;
++      spin_unlock(&sbi->s_reserve_lock);
++}
++
++int ext3_new_block(handle_t *handle, struct inode *inode,
++              unsigned long goal, int *errp)
++{
++      int ret, len;
++
++      if (!test_opt(inode->i_sb, MBALLOC)) {
++              ret = ext3_new_block_old(handle, inode, goal, errp);
++              goto out;
++      }
++      len = 1;
++      ret = ext3_mb_new_blocks(handle, inode, goal, &len, 0, errp);
++out:
++      return ret;
++}
++
++
++void ext3_free_blocks(handle_t *handle, struct inode * inode,
++                      unsigned long block, unsigned long count, int metadata)
++{
++      struct super_block *sb;
++      int freed;
++
++      sb = inode->i_sb;
++      if (!test_opt(sb, MBALLOC))
++              ext3_free_blocks_sb(handle, sb, block, count, &freed);
++      else
++              ext3_mb_free_blocks(handle, inode, block, count, metadata, &freed);
++      if (freed)
++              DQUOT_FREE_BLOCK(inode, freed);
++      return;
++}
++
++#define EXT3_ROOT                 "ext3"
++#define EXT3_MB_STATS_NAME        "mb_stats"
++#define EXT3_MB_MAX_TO_SCAN_NAME  "mb_max_to_scan"
++#define EXT3_MB_MIN_TO_SCAN_NAME  "mb_min_to_scan"
++
++static int ext3_mb_stats_read(char *page, char **start, off_t off,
++              int count, int *eof, void *data)
++{
++      int len;
++
++      *eof = 1;
++      if (off != 0)
++              return 0;
++
++      len = sprintf(page, "%ld\n", ext3_mb_stats);
++      *start = page;
++      return len;
++}
++
++static int ext3_mb_stats_write(struct file *file, const char *buffer,
++              unsigned long count, void *data)
++{
++      char str[32];
++
++      if (count >= sizeof(str)) {
++              printk(KERN_ERR "EXT3: %s string to long, max %u bytes\n",
++                     EXT3_MB_STATS_NAME, (int)sizeof(str));
++              return -EOVERFLOW;
++      }
++
++      if (copy_from_user(str, buffer, count))
++              return -EFAULT;
++
++      /* Only set to 0 or 1 respectively; zero->0; non-zero->1 */
++      ext3_mb_stats = (simple_strtol(str, NULL, 0) != 0);
++      return count;
++}
++
++static int ext3_mb_max_to_scan_read(char *page, char **start, off_t off,
++              int count, int *eof, void *data)
++{
++      int len;
++
++      *eof = 1;
++      if (off != 0)
++              return 0;
++
++      len = sprintf(page, "%ld\n", ext3_mb_max_to_scan);
++      *start = page;
++      return len;
++}
++
++static int ext3_mb_max_to_scan_write(struct file *file, const char *buffer,
++              unsigned long count, void *data)
++{
++      char str[32];
++      long value;
++
++      if (count >= sizeof(str)) {
++              printk(KERN_ERR "EXT3: %s string to long, max %u bytes\n",
++                     EXT3_MB_MAX_TO_SCAN_NAME, (int)sizeof(str));
++              return -EOVERFLOW;
++      }
++
++      if (copy_from_user(str, buffer, count))
++              return -EFAULT;
++
++      /* Only set to 0 or 1 respectively; zero->0; non-zero->1 */
++      value = simple_strtol(str, NULL, 0);
++      if (value <= 0)
++              return -ERANGE;
++
++      ext3_mb_max_to_scan = value;    
++
++      return count;
++}
++
++static int ext3_mb_min_to_scan_read(char *page, char **start, off_t off,
++              int count, int *eof, void *data)
++{
++      int len;
++
++      *eof = 1;
++      if (off != 0)
++              return 0;
++
++      len = sprintf(page, "%ld\n", ext3_mb_min_to_scan);
++      *start = page;
++      return len;
++}
++
++static int ext3_mb_min_to_scan_write(struct file *file, const char *buffer,
++              unsigned long count, void *data)
++{
++      char str[32];
++      long value;
++
++      if (count >= sizeof(str)) {
++              printk(KERN_ERR "EXT3: %s string to long, max %u bytes\n",
++                     EXT3_MB_MIN_TO_SCAN_NAME, (int)sizeof(str));
++              return -EOVERFLOW;
++      }
++
++      if (copy_from_user(str, buffer, count))
++              return -EFAULT;
++
++      /* Only set to 0 or 1 respectively; zero->0; non-zero->1 */
++      value = simple_strtol(str, NULL, 0);
++      if (value <= 0)
++              return -ERANGE;
++
++      ext3_mb_min_to_scan = value;    
++
++      return count;
++}
++
++int __init init_ext3_proc(void)
++{
++      struct proc_dir_entry *proc_ext3_mb_stats;
++      struct proc_dir_entry *proc_ext3_mb_max_to_scan;
++      struct proc_dir_entry *proc_ext3_mb_min_to_scan;
++
++      proc_root_ext3 = proc_mkdir(EXT3_ROOT, proc_root_fs);
++      if (proc_root_ext3 == NULL) {
++              printk(KERN_ERR "EXT3: Unable to create %s\n", EXT3_ROOT);
++              return -EIO;
++      }
++
++      /* Initialize EXT3_MB_STATS_NAME */
++      proc_ext3_mb_stats = create_proc_entry(EXT3_MB_STATS_NAME,
++                      S_IFREG | S_IRUGO | S_IWUSR, proc_root_ext3);
++      if (proc_ext3_mb_stats == NULL) {
++              printk(KERN_ERR "EXT3: Unable to create %s\n",
++                              EXT3_MB_STATS_NAME);
++              remove_proc_entry(EXT3_ROOT, proc_root_fs);
++              return -EIO;
++      }
++
++      proc_ext3_mb_stats->data = NULL;
++      proc_ext3_mb_stats->read_proc  = ext3_mb_stats_read;
++      proc_ext3_mb_stats->write_proc = ext3_mb_stats_write;
++
++      /* Initialize EXT3_MAX_TO_SCAN_NAME */
++      proc_ext3_mb_max_to_scan = create_proc_entry(
++                      EXT3_MB_MAX_TO_SCAN_NAME,
++                      S_IFREG | S_IRUGO | S_IWUSR, proc_root_ext3);
++      if (proc_ext3_mb_max_to_scan == NULL) {
++              printk(KERN_ERR "EXT3: Unable to create %s\n",
++                              EXT3_MB_MAX_TO_SCAN_NAME);
++              remove_proc_entry(EXT3_MB_STATS_NAME, proc_root_ext3);
++              remove_proc_entry(EXT3_ROOT, proc_root_fs);
++              return -EIO;
++      }
++
++      proc_ext3_mb_max_to_scan->data = NULL;
++      proc_ext3_mb_max_to_scan->read_proc  = ext3_mb_max_to_scan_read;
++      proc_ext3_mb_max_to_scan->write_proc = ext3_mb_max_to_scan_write;
++
++      /* Initialize EXT3_MIN_TO_SCAN_NAME */
++      proc_ext3_mb_min_to_scan = create_proc_entry(
++                      EXT3_MB_MIN_TO_SCAN_NAME,
++                      S_IFREG | S_IRUGO | S_IWUSR, proc_root_ext3);
++      if (proc_ext3_mb_min_to_scan == NULL) {
++              printk(KERN_ERR "EXT3: Unable to create %s\n",
++                              EXT3_MB_MIN_TO_SCAN_NAME);
++              remove_proc_entry(EXT3_MB_MAX_TO_SCAN_NAME, proc_root_ext3);
++              remove_proc_entry(EXT3_MB_STATS_NAME, proc_root_ext3);
++              remove_proc_entry(EXT3_ROOT, proc_root_fs);
++              return -EIO;
++      }
++
++      proc_ext3_mb_min_to_scan->data = NULL;
++      proc_ext3_mb_min_to_scan->read_proc  = ext3_mb_min_to_scan_read;
++      proc_ext3_mb_min_to_scan->write_proc = ext3_mb_min_to_scan_write;
++
++      return 0;
++}
++
++void exit_ext3_proc(void)
++{
++      remove_proc_entry(EXT3_MB_STATS_NAME, proc_root_ext3);
++      remove_proc_entry(EXT3_MB_MAX_TO_SCAN_NAME, proc_root_ext3);
++      remove_proc_entry(EXT3_MB_MIN_TO_SCAN_NAME, proc_root_ext3);
++      remove_proc_entry(EXT3_ROOT, proc_root_fs);
++}
++
+Index: linux-2.6.16.i686/fs/ext3/extents.c
+===================================================================
+--- linux-2.6.16.i686.orig/fs/ext3/extents.c   2006-05-30 22:55:32.000000000 +0800
++++ linux-2.6.16.i686/fs/ext3/extents.c        2006-05-30 23:02:59.000000000 +0800
+@@ -771,7 +771,7 @@
+               for (i = 0; i < depth; i++) {
+                       if (!ablocks[i])
+                               continue;
+-                      ext3_free_blocks(handle, tree->inode, ablocks[i], 1);
++                      ext3_free_blocks(handle, tree->inode, ablocks[i], 1, 1);
+               }
+       }
+       kfree(ablocks);
+@@ -1428,7 +1428,7 @@
+                 path->p_idx->ei_leaf);
+       bh = sb_find_get_block(tree->inode->i_sb, path->p_idx->ei_leaf);
+       ext3_forget(handle, 1, tree->inode, bh, path->p_idx->ei_leaf);
+-      ext3_free_blocks(handle, tree->inode, path->p_idx->ei_leaf, 1);
++      ext3_free_blocks(handle, tree->inode, path->p_idx->ei_leaf, 1, 1);
+       return err;
+ }
+@@ -1913,10 +1913,12 @@
+       int needed = ext3_remove_blocks_credits(tree, ex, from, to);
+       handle_t *handle = ext3_journal_start(tree->inode, needed);
+       struct buffer_head *bh;
+-      int i;
++      int i, metadata = 0;
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
++      if (S_ISDIR(tree->inode->i_mode) || S_ISLNK(tree->inode->i_mode))
++              metadata = 1;
+       if (from >= ex->ee_block && to == ex->ee_block + ex->ee_len - 1) {
+               /* tail removal */
+               unsigned long num, start;
+@@ -1928,7 +1930,7 @@
+                       bh = sb_find_get_block(tree->inode->i_sb, start + i);
+                       ext3_forget(handle, 0, tree->inode, bh, start + i);
+               }
+-              ext3_free_blocks(handle, tree->inode, start, num);
++              ext3_free_blocks(handle, tree->inode, start, num, metadata);
+       } else if (from == ex->ee_block && to <= ex->ee_block + ex->ee_len - 1) {
+               printk("strange request: removal %lu-%lu from %u:%u\n",
+                      from, to, ex->ee_block, ex->ee_len);
+Index: linux-2.6.16.i686/fs/ext3/xattr.c
+===================================================================
+--- linux-2.6.16.i686.orig/fs/ext3/xattr.c     2006-03-20 13:53:29.000000000 +0800
++++ linux-2.6.16.i686/fs/ext3/xattr.c  2006-05-30 23:02:59.000000000 +0800
+@@ -484,7 +484,7 @@
+               ea_bdebug(bh, "refcount now=0; freeing");
+               if (ce)
+                       mb_cache_entry_free(ce);
+-              ext3_free_blocks(handle, inode, bh->b_blocknr, 1);
++              ext3_free_blocks(handle, inode, bh->b_blocknr, 1, 1);
+               get_bh(bh);
+               ext3_forget(handle, 1, inode, bh, bh->b_blocknr);
+       } else {
+@@ -804,7 +804,7 @@
+                       new_bh = sb_getblk(sb, block);
+                       if (!new_bh) {
+ getblk_failed:
+-                              ext3_free_blocks(handle, inode, block, 1);
++                              ext3_free_blocks(handle, inode, block, 1, 1);
+                               error = -EIO;
+                               goto cleanup;
+                       }
+Index: linux-2.6.16.i686/fs/ext3/balloc.c
+===================================================================
+--- linux-2.6.16.i686.orig/fs/ext3/balloc.c    2006-03-20 13:53:29.000000000 +0800
++++ linux-2.6.16.i686/fs/ext3/balloc.c 2006-05-30 23:02:59.000000000 +0800
+@@ -80,7 +80,7 @@
+  *
+  * Return buffer_head on success or NULL in case of failure.
+  */
+-static struct buffer_head *
++struct buffer_head *
+ read_block_bitmap(struct super_block *sb, unsigned int block_group)
+ {
+       struct ext3_group_desc * desc;
+@@ -491,24 +491,6 @@
+       return;
+ }
+-/* Free given blocks, update quota and i_blocks field */
+-void ext3_free_blocks(handle_t *handle, struct inode *inode,
+-                      unsigned long block, unsigned long count)
+-{
+-      struct super_block * sb;
+-      int dquot_freed_blocks;
+-
+-      sb = inode->i_sb;
+-      if (!sb) {
+-              printk ("ext3_free_blocks: nonexistent device");
+-              return;
+-      }
+-      ext3_free_blocks_sb(handle, sb, block, count, &dquot_freed_blocks);
+-      if (dquot_freed_blocks)
+-              DQUOT_FREE_BLOCK(inode, dquot_freed_blocks);
+-      return;
+-}
+-
+ /*
+  * For ext3 allocations, we must not reuse any blocks which are
+  * allocated in the bitmap buffer's "last committed data" copy.  This
+@@ -1154,7 +1136,7 @@
+  * bitmap, and then for any free bit if that fails.
+  * This function also updates quota and i_blocks field.
+  */
+-int ext3_new_block(handle_t *handle, struct inode *inode,
++int ext3_new_block_old(handle_t *handle, struct inode *inode,
+                       unsigned long goal, int *errp)
+ {
+       struct buffer_head *bitmap_bh = NULL;
+Index: linux-2.6.16.i686/fs/ext3/super.c
+===================================================================
+--- linux-2.6.16.i686.orig/fs/ext3/super.c     2006-05-30 22:55:32.000000000 +0800
++++ linux-2.6.16.i686/fs/ext3/super.c  2006-05-30 23:02:59.000000000 +0800
+@@ -392,6 +392,7 @@
+       struct ext3_super_block *es = sbi->s_es;
+       int i;
++      ext3_mb_release(sb);
+       ext3_ext_release(sb);
+       ext3_xattr_put_super(sb);
+       journal_destroy(sbi->s_journal);
+@@ -640,7 +641,7 @@
+       Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
+       Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
+       Opt_iopen, Opt_noiopen, Opt_iopen_nopriv,
+-      Opt_extents, Opt_extdebug,
++      Opt_extents, Opt_extdebug, Opt_mballoc,
+       Opt_grpquota
+ };
+@@ -694,6 +695,7 @@
+       {Opt_iopen_nopriv, "iopen_nopriv"},
+       {Opt_extents, "extents"},
+       {Opt_extdebug, "extdebug"},
++      {Opt_mballoc, "mballoc"},
+       {Opt_barrier, "barrier=%u"},
+       {Opt_err, NULL},
+       {Opt_resize, "resize"},
+@@ -1041,6 +1043,9 @@
+               case Opt_extdebug:
+                       set_opt (sbi->s_mount_opt, EXTDEBUG);
+                       break;
++              case Opt_mballoc:
++                      set_opt (sbi->s_mount_opt, MBALLOC);
++                      break;
+               default:
+                       printk (KERN_ERR
+                               "EXT3-fs: Unrecognized mount option \"%s\" "
+@@ -1766,6 +1771,7 @@
+               ext3_count_dirs(sb));
+       ext3_ext_init(sb);
++      ext3_mb_init(sb, needs_recovery);
+       lock_kernel();
+       return 0;
+@@ -2699,7 +2705,13 @@
+ static int __init init_ext3_fs(void)
+ {
+-      int err = init_ext3_xattr();
++      int err;
++
++      err = init_ext3_proc();
++      if (err)
++              return err;
++
++      err = init_ext3_xattr();
+       if (err)
+               return err;
+       err = init_inodecache();
+@@ -2721,6 +2733,7 @@
+       unregister_filesystem(&ext3_fs_type);
+       destroy_inodecache();
+       exit_ext3_xattr();
++      exit_ext3_proc();
+ }
+ int ext3_prep_san_write(struct inode *inode, long *blocks,
+Index: linux-2.6.16.i686/fs/ext3/Makefile
+===================================================================
+--- linux-2.6.16.i686.orig/fs/ext3/Makefile    2006-05-30 22:55:32.000000000 +0800
++++ linux-2.6.16.i686/fs/ext3/Makefile 2006-05-30 23:02:59.000000000 +0800
+@@ -6,7 +6,7 @@
+ ext3-y        := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
+          ioctl.o namei.o super.o symlink.o hash.o resize.o \
+-         extents.o
++         extents.o mballoc.o
+ ext3-$(CONFIG_EXT3_FS_XATTR)   += xattr.o xattr_user.o xattr_trusted.o
+ ext3-$(CONFIG_EXT3_FS_POSIX_ACL) += acl.o
+Index: linux-2.6.16.i686/include/linux/ext3_fs.h
+===================================================================
+--- linux-2.6.16.i686.orig/include/linux/ext3_fs.h     2006-05-30 22:55:32.000000000 +0800
++++ linux-2.6.16.i686/include/linux/ext3_fs.h  2006-05-30 23:02:59.000000000 +0800
+@@ -57,6 +57,14 @@
+ #define ext3_debug(f, a...)   do {} while (0)
+ #endif
++#define EXT3_MULTIBLOCK_ALLOCATOR     1
++
++#define EXT3_MB_HINT_MERGE            1
++#define EXT3_MB_HINT_RESERVED         2
++#define EXT3_MB_HINT_METADATA         4
++#define EXT3_MB_HINT_FIRST            8
++#define EXT3_MB_HINT_BEST             16
++
+ /*
+  * Special inodes numbers
+  */
+@@ -383,6 +391,7 @@
+ #define EXT3_MOUNT_IOPEN_NOPRIV               0x800000/* Make iopen world-readable */
+ #define EXT3_MOUNT_EXTENTS            0x1000000/* Extents support */
+ #define EXT3_MOUNT_EXTDEBUG           0x2000000/* Extents debug */
++#define EXT3_MOUNT_MBALLOC            0x800000/* Buddy allocation support */
+ /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
+ #ifndef clear_opt
+@@ -744,7 +753,7 @@
+ extern unsigned long ext3_bg_num_gdb(struct super_block *sb, int group);
+ extern int ext3_new_block (handle_t *, struct inode *, unsigned long, int *);
+ extern void ext3_free_blocks (handle_t *, struct inode *, unsigned long,
+-                            unsigned long);
++                            unsigned long, int);
+ extern void ext3_free_blocks_sb (handle_t *, struct super_block *,
+                                unsigned long, unsigned long, int *);
+ extern unsigned long ext3_count_free_blocks (struct super_block *);
+@@ -865,6 +874,17 @@
+ extern int ext3_ext_ioctl(struct inode *inode, struct file *filp,
+                         unsigned int cmd, unsigned long arg);
++/* mballoc.c */
++extern long ext3_mb_stats;
++extern long ext3_mb_max_to_scan;
++extern int ext3_mb_init(struct super_block *, int);
++extern int ext3_mb_release(struct super_block *);
++extern int ext3_mb_new_blocks(handle_t *, struct inode *, unsigned long, int *, int, int *);
++extern int ext3_mb_reserve_blocks(struct super_block *, int);
++extern void ext3_mb_release_blocks(struct super_block *, int);
++int __init init_ext3_proc(void);
++void exit_ext3_proc(void);
++
+ #endif        /* __KERNEL__ */
+ /* EXT3_IOC_CREATE_INUM at bottom of file (visible to kernel and user). */
+Index: linux-2.6.16.i686/include/linux/ext3_fs_sb.h
+===================================================================
+--- linux-2.6.16.i686.orig/include/linux/ext3_fs_sb.h  2006-03-20 13:53:29.000000000 +0800
++++ linux-2.6.16.i686/include/linux/ext3_fs_sb.h       2006-05-30 23:02:59.000000000 +0800
+@@ -21,8 +21,14 @@
+ #include <linux/wait.h>
+ #include <linux/blockgroup_lock.h>
+ #include <linux/percpu_counter.h>
++#include <linux/list.h>
+ #endif
+ #include <linux/rbtree.h>
++#include <linux/proc_fs.h>
++
++struct ext3_buddy_group_blocks;
++struct ext3_mb_history;
++#define EXT3_BB_MAX_BLOCKS
+ /*
+  * third extended-fs super-block data in memory
+@@ -78,6 +84,38 @@
+       char *s_qf_names[MAXQUOTAS];            /* Names of quota files with journalled quota */
+       int s_jquota_fmt;                       /* Format of quota to use */
+ #endif
++
++      /* for buddy allocator */
++      struct ext3_group_info **s_group_info;
++      struct inode *s_buddy_cache;
++      long s_blocks_reserved;
++      spinlock_t s_reserve_lock;
++      struct list_head s_active_transaction;
++      struct list_head s_closed_transaction;
++      struct list_head s_committed_transaction;
++      spinlock_t s_md_lock;
++      tid_t s_last_transaction;
++      int s_mb_factor;
++      unsigned short *s_mb_offsets, *s_mb_maxs;
++
++      /* history to debug policy */
++      struct ext3_mb_history *s_mb_history;
++      int s_mb_history_cur;
++      int s_mb_history_max;
++      struct proc_dir_entry *s_mb_proc;
++      spinlock_t s_mb_history_lock;
++
++      /* stats for buddy allocator */
++      atomic_t s_bal_reqs;    /* number of reqs with len > 1 */
++      atomic_t s_bal_success; /* we found long enough chunks */
++      atomic_t s_bal_allocated;       /* in blocks */
++      atomic_t s_bal_ex_scanned;      /* total extents scanned */
++      atomic_t s_bal_goals;   /* goal hits */
++      atomic_t s_bal_breaks;  /* too long searches */
++      atomic_t s_bal_2orders; /* 2^order hits */
++      spinlock_t s_bal_lock;
++      unsigned long s_mb_buddies_generated;
++      unsigned long long s_mb_generation_time;
+ };
+ #endif        /* _LINUX_EXT3_FS_SB */
index 2a64875..c77ebdd 100644 (file)
@@ -1,7 +1,7 @@
-Index: linux-2.6.5-7.201/include/linux/ext3_fs.h
+Index: linux-2.6.5-7.252-full/include/linux/ext3_fs.h
 ===================================================================
---- linux-2.6.5-7.201.orig/include/linux/ext3_fs.h     2005-12-17 02:53:30.000000000 +0300
-+++ linux-2.6.5-7.201/include/linux/ext3_fs.h  2005-12-17 03:13:38.000000000 +0300
+--- linux-2.6.5-7.252-full.orig/include/linux/ext3_fs.h        2006-04-25 17:42:19.000000000 +0400
++++ linux-2.6.5-7.252-full/include/linux/ext3_fs.h     2006-04-26 23:40:28.000000000 +0400
 @@ -57,6 +57,14 @@ struct statfs;
  #define ext3_debug(f, a...)   do {} while (0)
  #endif
@@ -31,8 +31,8 @@ Index: linux-2.6.5-7.201/include/linux/ext3_fs.h
  extern void ext3_free_blocks (handle_t *, struct inode *, unsigned long,
 -                            unsigned long);
 +                            unsigned long, int);
-+extern void ext3_free_blocks_old (handle_t *, struct inode *, unsigned long,
-+                                      unsigned long);
++extern void ext3_free_blocks_old(handle_t *, struct inode *, unsigned long,
++                               unsigned long);
  extern unsigned long ext3_count_free_blocks (struct super_block *);
  extern void ext3_check_blocks_bitmap (struct super_block *);
  extern struct ext3_group_desc * ext3_get_group_desc(struct super_block * sb,
@@ -54,10 +54,10 @@ Index: linux-2.6.5-7.201/include/linux/ext3_fs.h
  #endif        /* __KERNEL__ */
  
  #define EXT3_IOC_CREATE_INUM                  _IOW('f', 5, long)
-Index: linux-2.6.5-7.201/include/linux/ext3_fs_sb.h
+Index: linux-2.6.5-7.252-full/include/linux/ext3_fs_sb.h
 ===================================================================
---- linux-2.6.5-7.201.orig/include/linux/ext3_fs_sb.h  2005-12-17 02:53:25.000000000 +0300
-+++ linux-2.6.5-7.201/include/linux/ext3_fs_sb.h       2005-12-17 03:10:23.000000000 +0300
+--- linux-2.6.5-7.252-full.orig/include/linux/ext3_fs_sb.h     2006-04-25 17:42:19.000000000 +0400
++++ linux-2.6.5-7.252-full/include/linux/ext3_fs_sb.h  2006-04-26 23:40:28.000000000 +0400
 @@ -23,9 +23,15 @@
  #define EXT_INCLUDE
  #include <linux/blockgroup_lock.h>
@@ -74,13 +74,13 @@ Index: linux-2.6.5-7.201/include/linux/ext3_fs_sb.h
  
  /*
   * third extended-fs super-block data in memory
-@@ -78,6 +84,38 @@ struct ext3_sb_info {
+@@ -78,6 +84,43 @@ struct ext3_sb_info {
        struct timer_list turn_ro_timer;        /* For turning read-only (crash simulation) */
        wait_queue_head_t ro_wait_queue;        /* For people waiting for the fs to go read-only */
  #endif
 +
 +      /* for buddy allocator */
-+      struct ext3_group_info **s_group_info;
++      struct ext3_group_info ***s_group_info;
 +      struct inode *s_buddy_cache;
 +      long s_blocks_reserved;
 +      spinlock_t s_reserve_lock;
@@ -91,6 +91,7 @@ Index: linux-2.6.5-7.201/include/linux/ext3_fs_sb.h
 +      tid_t s_last_transaction;
 +      int s_mb_factor;
 +      unsigned short *s_mb_offsets, *s_mb_maxs;
++      unsigned long s_stripe;
 +
 +      /* history to debug policy */
 +      struct ext3_mb_history *s_mb_history;
@@ -111,12 +112,16 @@ Index: linux-2.6.5-7.201/include/linux/ext3_fs_sb.h
 +      unsigned long s_mb_buddies_generated;
 +      unsigned long long s_mb_generation_time;
  };
++
++#define EXT3_GROUP_INFO(sb, group)                                       \
++      EXT3_SB(sb)->s_group_info[(group) >> EXT3_DESC_PER_BLOCK_BITS(sb)] \
++                               [(group) & (EXT3_DESC_PER_BLOCK(sb) - 1)]
  
  #endif        /* _LINUX_EXT3_FS_SB */
-Index: linux-2.6.5-7.201/fs/ext3/super.c
+Index: linux-2.6.5-7.252-full/fs/ext3/super.c
 ===================================================================
---- linux-2.6.5-7.201.orig/fs/ext3/super.c     2005-12-17 02:53:30.000000000 +0300
-+++ linux-2.6.5-7.201/fs/ext3/super.c  2005-12-17 03:10:23.000000000 +0300
+--- linux-2.6.5-7.252-full.orig/fs/ext3/super.c        2006-04-25 17:42:19.000000000 +0400
++++ linux-2.6.5-7.252-full/fs/ext3/super.c     2006-04-26 23:40:28.000000000 +0400
 @@ -389,6 +389,7 @@ void ext3_put_super (struct super_block 
        struct ext3_super_block *es = sbi->s_es;
        int i;
@@ -125,34 +130,45 @@ Index: linux-2.6.5-7.201/fs/ext3/super.c
        ext3_ext_release(sb);
        ext3_xattr_put_super(sb);
        journal_destroy(sbi->s_journal);
-@@ -543,7 +544,7 @@ enum {
-       Opt_ignore, Opt_barrier,
+@@ -545,6 +546,7 @@ enum {
        Opt_err,
        Opt_iopen, Opt_noiopen, Opt_iopen_nopriv,
--      Opt_extents, Opt_extdebug,
-+      Opt_extents, Opt_extdebug, Opt_mballoc,
+       Opt_extents, Opt_noextents, Opt_extdebug,
++      Opt_mballoc, Opt_nomballoc, Opt_stripe,
  };
  
  static match_table_t tokens = {
-@@ -590,6 +591,7 @@ static match_table_t tokens = {
-       {Opt_iopen_nopriv, "iopen_nopriv"},
+@@ -591,6 +592,9 @@ static match_table_t tokens = {
        {Opt_extents, "extents"},
+       {Opt_noextents, "noextents"},
        {Opt_extdebug, "extdebug"},
 +      {Opt_mballoc, "mballoc"},
++      {Opt_nomballoc, "nomballoc"},
++      {Opt_stripe, "stripe=%u"},
        {Opt_barrier, "barrier=%u"},
        {Opt_err, NULL}
  };
-@@ -811,6 +813,9 @@ static int parse_options (char * options
+@@ -813,6 +815,19 @@ static int parse_options (char * options
                case Opt_extdebug:
                        set_opt (sbi->s_mount_opt, EXTDEBUG);
                        break;
 +              case Opt_mballoc:
-+                      set_opt (sbi->s_mount_opt, MBALLOC);
++                      set_opt(sbi->s_mount_opt, MBALLOC);
++                      break;
++              case Opt_nomballoc:
++                      clear_opt(sbi->s_mount_opt, MBALLOC);
++                      break;
++              case Opt_stripe:
++                      if (match_int(&args[0], &option))
++                              return 0;
++                      if (option < 0)
++                              return 0;
++                      sbi->s_stripe = option;
 +                      break;
                default:
                        printk (KERN_ERR
                                "EXT3-fs: Unrecognized mount option \"%s\" "
-@@ -1464,6 +1469,7 @@ static int ext3_fill_super (struct super
+@@ -1466,6 +1471,7 @@ static int ext3_fill_super (struct super
                ext3_count_dirs(sb));
  
        ext3_ext_init(sb);
@@ -160,7 +176,7 @@ Index: linux-2.6.5-7.201/fs/ext3/super.c
  
        return 0;
  
-@@ -2112,7 +2118,13 @@ static struct file_system_type ext3_fs_t
+@@ -2114,7 +2120,13 @@ static struct file_system_type ext3_fs_t
  
  static int __init init_ext3_fs(void)
  {
@@ -175,7 +191,7 @@ Index: linux-2.6.5-7.201/fs/ext3/super.c
        if (err)
                return err;
        err = init_inodecache();
-@@ -2141,6 +2153,7 @@ static void __exit exit_ext3_fs(void)
+@@ -2143,6 +2155,7 @@ static void __exit exit_ext3_fs(void)
        unregister_filesystem(&ext3_fs_type);
        destroy_inodecache();
        exit_ext3_xattr();
@@ -183,11 +199,11 @@ Index: linux-2.6.5-7.201/fs/ext3/super.c
  }
  
  int ext3_prep_san_write(struct inode *inode, long *blocks,
-Index: linux-2.6.5-7.201/fs/ext3/extents.c
+Index: linux-2.6.5-7.252-full/fs/ext3/extents.c
 ===================================================================
---- linux-2.6.5-7.201.orig/fs/ext3/extents.c   2005-12-17 02:53:29.000000000 +0300
-+++ linux-2.6.5-7.201/fs/ext3/extents.c        2005-12-17 03:10:23.000000000 +0300
-@@ -771,7 +771,7 @@ cleanup:
+--- linux-2.6.5-7.252-full.orig/fs/ext3/extents.c      2006-04-25 17:42:19.000000000 +0400
++++ linux-2.6.5-7.252-full/fs/ext3/extents.c   2006-04-26 23:40:28.000000000 +0400
+@@ -777,7 +777,7 @@ cleanup:
                for (i = 0; i < depth; i++) {
                        if (!ablocks[i])
                                continue;
@@ -196,7 +212,7 @@ Index: linux-2.6.5-7.201/fs/ext3/extents.c
                }
        }
        kfree(ablocks);
-@@ -1428,7 +1428,7 @@ int ext3_ext_rm_idx(handle_t *handle, st
+@@ -1434,7 +1434,7 @@ int ext3_ext_rm_idx(handle_t *handle, st
                  path->p_idx->ei_leaf);
        bh = sb_find_get_block(tree->inode->i_sb, path->p_idx->ei_leaf);
        ext3_forget(handle, 1, tree->inode, bh, path->p_idx->ei_leaf);
@@ -205,7 +221,7 @@ Index: linux-2.6.5-7.201/fs/ext3/extents.c
        return err;
  }
  
-@@ -1913,10 +1913,12 @@ ext3_remove_blocks(struct ext3_extents_t
+@@ -1919,10 +1919,12 @@ ext3_remove_blocks(struct ext3_extents_t
        int needed = ext3_remove_blocks_credits(tree, ex, from, to);
        handle_t *handle = ext3_journal_start(tree->inode, needed);
        struct buffer_head *bh;
@@ -219,7 +235,7 @@ Index: linux-2.6.5-7.201/fs/ext3/extents.c
        if (from >= ex->ee_block && to == ex->ee_block + ex->ee_len - 1) {
                /* tail removal */
                unsigned long num, start;
-@@ -1928,7 +1930,7 @@ ext3_remove_blocks(struct ext3_extents_t
+@@ -1934,7 +1936,7 @@ ext3_remove_blocks(struct ext3_extents_t
                        bh = sb_find_get_block(tree->inode->i_sb, start + i);
                        ext3_forget(handle, 0, tree->inode, bh, start + i);
                }
@@ -228,11 +244,11 @@ Index: linux-2.6.5-7.201/fs/ext3/extents.c
        } else if (from == ex->ee_block && to <= ex->ee_block + ex->ee_len - 1) {
                printk("strange request: removal %lu-%lu from %u:%u\n",
                       from, to, ex->ee_block, ex->ee_len);
-Index: linux-2.6.5-7.201/fs/ext3/inode.c
+Index: linux-2.6.5-7.252-full/fs/ext3/inode.c
 ===================================================================
---- linux-2.6.5-7.201.orig/fs/ext3/inode.c     2005-12-17 02:53:30.000000000 +0300
-+++ linux-2.6.5-7.201/fs/ext3/inode.c  2005-12-17 03:10:23.000000000 +0300
-@@ -572,7 +572,7 @@ static int ext3_alloc_branch(handle_t *h
+--- linux-2.6.5-7.252-full.orig/fs/ext3/inode.c        2006-04-25 17:42:19.000000000 +0400
++++ linux-2.6.5-7.252-full/fs/ext3/inode.c     2006-04-26 23:40:28.000000000 +0400
+@@ -574,7 +574,7 @@ static int ext3_alloc_branch(handle_t *h
                ext3_journal_forget(handle, branch[i].bh);
        }
        for (i = 0; i < keys; i++)
@@ -241,7 +257,7 @@ Index: linux-2.6.5-7.201/fs/ext3/inode.c
        return err;
  }
  
-@@ -673,7 +673,7 @@ err_out:
+@@ -675,7 +675,7 @@ err_out:
        if (err == -EAGAIN)
                for (i = 0; i < num; i++)
                        ext3_free_blocks(handle, inode, 
@@ -250,7 +266,7 @@ Index: linux-2.6.5-7.201/fs/ext3/inode.c
        return err;
  }
  
-@@ -1835,7 +1835,7 @@ ext3_clear_blocks(handle_t *handle, stru
+@@ -1837,7 +1837,7 @@ ext3_clear_blocks(handle_t *handle, stru
                }
        }
  
@@ -259,7 +275,7 @@ Index: linux-2.6.5-7.201/fs/ext3/inode.c
  }
  
  /**
-@@ -2006,7 +2006,7 @@ static void ext3_free_branches(handle_t 
+@@ -2008,7 +2008,7 @@ static void ext3_free_branches(handle_t 
                                ext3_journal_test_restart(handle, inode);
                        }
  
@@ -268,10 +284,10 @@ Index: linux-2.6.5-7.201/fs/ext3/inode.c
  
                        if (parent_bh) {
                                /*
-Index: linux-2.6.5-7.201/fs/ext3/balloc.c
+Index: linux-2.6.5-7.252-full/fs/ext3/balloc.c
 ===================================================================
---- linux-2.6.5-7.201.orig/fs/ext3/balloc.c    2005-10-11 00:12:45.000000000 +0400
-+++ linux-2.6.5-7.201/fs/ext3/balloc.c 2005-12-17 03:10:23.000000000 +0300
+--- linux-2.6.5-7.252-full.orig/fs/ext3/balloc.c       2006-02-14 15:26:58.000000000 +0300
++++ linux-2.6.5-7.252-full/fs/ext3/balloc.c    2006-04-26 23:40:28.000000000 +0400
 @@ -78,7 +78,7 @@ struct ext3_group_desc * ext3_get_group_
   *
   * Return buffer_head on success or NULL in case of failure.
@@ -299,10 +315,10 @@ Index: linux-2.6.5-7.201/fs/ext3/balloc.c
                        unsigned long goal, int *errp)
  {
        struct buffer_head *bitmap_bh = NULL;
-Index: linux-2.6.5-7.201/fs/ext3/xattr.c
+Index: linux-2.6.5-7.252-full/fs/ext3/xattr.c
 ===================================================================
---- linux-2.6.5-7.201.orig/fs/ext3/xattr.c     2005-12-17 02:53:26.000000000 +0300
-+++ linux-2.6.5-7.201/fs/ext3/xattr.c  2005-12-17 03:10:41.000000000 +0300
+--- linux-2.6.5-7.252-full.orig/fs/ext3/xattr.c        2006-04-25 17:42:19.000000000 +0400
++++ linux-2.6.5-7.252-full/fs/ext3/xattr.c     2006-04-26 23:40:28.000000000 +0400
 @@ -1371,7 +1371,7 @@ ext3_xattr_set_handle2(handle_t *handle,
                        new_bh = sb_getblk(sb, block);
                        if (!new_bh) {
@@ -330,11 +346,11 @@ Index: linux-2.6.5-7.201/fs/ext3/xattr.c
                get_bh(bh);
                ext3_forget(handle, 1, inode, bh, EXT3_I(inode)->i_file_acl);
        } else {
-Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
+Index: linux-2.6.5-7.252-full/fs/ext3/mballoc.c
 ===================================================================
---- linux-2.6.5-7.201.orig/fs/ext3/mballoc.c   2005-12-09 13:08:53.191437750 +0300
-+++ linux-2.6.5-7.201/fs/ext3/mballoc.c        2005-12-17 03:15:04.000000000 +0300
-@@ -0,0 +1,2430 @@
+--- linux-2.6.5-7.252-full.orig/fs/ext3/mballoc.c      2006-04-22 17:31:47.543334750 +0400
++++ linux-2.6.5-7.252-full/fs/ext3/mballoc.c   2006-04-26 23:42:45.000000000 +0400
+@@ -0,0 +1,2702 @@
 +/*
 + * Copyright (c) 2003-2005, Cluster File Systems, Inc, info@clusterfs.com
 + * Written by Alex Tomas <alex@clusterfs.com>
@@ -423,6 +439,12 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +
 +long ext3_mb_stats = 1;
 +
++/*
++ * for which requests use 2^N search using buddies
++ */
++long ext3_mb_order2_reqs = 8;
++
++
 +#ifdef EXT3_BB_MAX_BLOCKS
 +#undef EXT3_BB_MAX_BLOCKS
 +#endif
@@ -463,10 +485,10 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +
 +      /* search goals */
 +      struct ext3_free_extent ac_g_ex;
-+      
++
 +      /* the best found extent */
 +      struct ext3_free_extent ac_b_ex;
-+      
++
 +      /* number of iterations done. we have to track to limit searching */
 +      unsigned long ac_ex_scanned;
 +      __u16 ac_groups_scanned;
@@ -488,6 +510,8 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +struct ext3_mb_history {
 +      struct ext3_free_extent goal;   /* goal allocation */
 +      struct ext3_free_extent result; /* result allocation */
++      unsigned pid;
++      unsigned ino;
 +      __u16 found;    /* how many extents have been found */
 +      __u16 groups;   /* how many groups have been scanned */
 +      __u16 tail;     /* what tail broke some buddy */
@@ -510,9 +534,9 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +#define EXT3_MB_BUDDY(e3b)    ((e3b)->bd_buddy)
 +
 +#ifndef EXT3_MB_HISTORY
-+#define ext3_mb_store_history(sb,ac)
++#define ext3_mb_store_history(sb,ino,ac)
 +#else
-+static void ext3_mb_store_history(struct super_block *,
++static void ext3_mb_store_history(struct super_block *, unsigned ino,
 +                              struct ext3_allocation_context *ac);
 +#endif
 +
@@ -631,7 +655,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +              if (mb_check_counter++ % 300 != 0)
 +                      return;
 +      }
-+      
++
 +      while (order > 1) {
 +              buddy = mb_find_buddy(e3b, order, &max);
 +              J_ASSERT(buddy);
@@ -812,7 +836,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      sb = inode->i_sb;
 +      blocksize = 1 << inode->i_blkbits;
 +      blocks_per_page = PAGE_CACHE_SIZE / blocksize;
-+      
++
 +      groups_per_page = blocks_per_page >> 1;
 +      if (groups_per_page == 0)
 +              groups_per_page = 1;
@@ -827,9 +851,9 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +              memset(bh, 0, i);
 +      } else
 +              bh = &bhs;
-+      
++
 +      first_group = page->index * blocks_per_page / 2;
-+      
++
 +      /* read all groups the page covers into the cache */
 +      for (i = 0; i < groups_per_page; i++) {
 +              struct ext3_group_desc * desc;
@@ -884,11 +908,11 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +                      mb_debug("put buddy for group %u in page %lu/%x\n",
 +                              group, page->index, i * blocksize);
 +                      memset(data, 0xff, blocksize);
-+                      EXT3_SB(sb)->s_group_info[group]->bb_fragments = 0;
-+                      memset(EXT3_SB(sb)->s_group_info[group]->bb_counters, 0,
++                      EXT3_GROUP_INFO(sb, group)->bb_fragments = 0;
++                      memset(EXT3_GROUP_INFO(sb, group)->bb_counters, 0,
 +                              sizeof(unsigned short)*(sb->s_blocksize_bits+2));
 +                      ext3_mb_generate_buddy(sb, data, bitmap,
-+                                              EXT3_SB(sb)->s_group_info[group]);
++                                              EXT3_GROUP_INFO(sb, group));
 +              } else {
 +                      /* this is block of bitmap */
 +                      mb_debug("put bitmap for group %u in page %lu/%x\n",
@@ -921,7 +945,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      blocks_per_page = PAGE_CACHE_SIZE / sb->s_blocksize;
 +
 +      e3b->bd_blkbits = sb->s_blocksize_bits;
-+      e3b->bd_info = sbi->s_group_info[group];
++      e3b->bd_info = EXT3_GROUP_INFO(sb, group);
 +      e3b->bd_sb = sb;
 +      e3b->bd_group = group;
 +      e3b->bd_buddy_page = NULL;
@@ -997,14 +1021,14 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +ext3_lock_group(struct super_block *sb, int group)
 +{
 +      bit_spin_lock(EXT3_GROUP_INFO_LOCKED_BIT,
-+                      &EXT3_SB(sb)->s_group_info[group]->bb_state);
++                    &EXT3_GROUP_INFO(sb, group)->bb_state);
 +}
 +
 +static inline void
 +ext3_unlock_group(struct super_block *sb, int group)
 +{
 +      bit_spin_unlock(EXT3_GROUP_INFO_LOCKED_BIT,
-+                      &EXT3_SB(sb)->s_group_info[group]->bb_state);
++                      &EXT3_GROUP_INFO(sb, group)->bb_state);
 +}
 +
 +static int mb_find_order_for_block(struct ext3_buddy *e3b, int block)
@@ -1134,7 +1158,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +static int mb_find_extent(struct ext3_buddy *e3b, int order, int block,
 +                              int needed, struct ext3_free_extent *ex)
 +{
-+      int next, max, ord;
++      int next = block, max, ord;
 +      void *buddy;
 +
 +      J_ASSERT(ex != NULL);
@@ -1159,6 +1183,11 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      ex->fe_start = block << order;
 +      ex->fe_group = e3b->bd_group;
 +
++      /* calc difference from given start */
++      next = next - ex->fe_start;
++      ex->fe_len -= next;
++      ex->fe_start += next;
++
 +      while (needed > ex->fe_len && (buddy = mb_find_buddy(e3b, order, &max))) {
 +
 +              if (block + 1 >= max)
@@ -1354,7 +1383,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +
 +      ext3_lock_group(ac->ac_sb, group);
 +      max = mb_find_extent(e3b, 0, ex.fe_start, ex.fe_len, &ex);
-+      
++
 +      if (max > 0) {
 +              ac->ac_b_ex = ex;
 +              ext3_mb_use_best_found(ac, e3b);
@@ -1371,6 +1400,8 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +                              struct ext3_buddy *e3b)
 +{
 +      int group = ac->ac_g_ex.fe_group, max, err;
++      struct ext3_sb_info *sbi = EXT3_SB(ac->ac_sb);
++      struct ext3_super_block *es = sbi->s_es;
 +      struct ext3_free_extent ex;
 +
 +      err = ext3_mb_load_buddy(ac->ac_sb, group, e3b);
@@ -1379,9 +1410,27 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +
 +      ext3_lock_group(ac->ac_sb, group);
 +      max = mb_find_extent(e3b, 0, ac->ac_g_ex.fe_start,
-+                              ac->ac_g_ex.fe_len, &ex);
-+      
-+      if (max > 0) {
++                           ac->ac_g_ex.fe_len, &ex);
++
++      if (max >= ac->ac_g_ex.fe_len && ac->ac_g_ex.fe_len == sbi->s_stripe) {
++              unsigned long start;
++              start = (e3b->bd_group * EXT3_BLOCKS_PER_GROUP(ac->ac_sb) +
++                      ex.fe_start + le32_to_cpu(es->s_first_data_block));
++              if (start % sbi->s_stripe == 0) {
++                      ac->ac_found++;
++                      ac->ac_b_ex = ex;
++                      ext3_mb_use_best_found(ac, e3b);
++              }
++      } else if (max >= ac->ac_g_ex.fe_len) {
++              J_ASSERT(ex.fe_len > 0);
++              J_ASSERT(ex.fe_group == ac->ac_g_ex.fe_group);
++              J_ASSERT(ex.fe_start == ac->ac_g_ex.fe_start);
++              ac->ac_found++;
++              ac->ac_b_ex = ex;
++              ext3_mb_use_best_found(ac, e3b);
++      } else if (max > 0 && (ac->ac_flags & EXT3_MB_HINT_MERGE)) {
++              /* Sometimes, caller may want to merge even small
++               * number of blocks to an existing extent */
 +              J_ASSERT(ex.fe_len > 0);
 +              J_ASSERT(ex.fe_group == ac->ac_g_ex.fe_group);
 +              J_ASSERT(ex.fe_start == ac->ac_g_ex.fe_start);
@@ -1409,7 +1458,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      int i, k, max;
 +
 +      J_ASSERT(ac->ac_2order > 0);
-+      for (i = ac->ac_2order; i < sb->s_blocksize_bits + 1; i++) {
++      for (i = ac->ac_2order; i <= sb->s_blocksize_bits + 1; i++) {
 +              if (grp->bb_counters[i] == 0)
 +                      continue;
 +
@@ -1474,11 +1523,46 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      }
 +}
 +
++/*
++ * This is a special case for storages like raid5
++ * we try to find stripe-aligned chunks for stripe-size requests
++ */
++static void ext3_mb_scan_aligned(struct ext3_allocation_context *ac,
++                               struct ext3_buddy *e3b)
++{
++      struct super_block *sb = ac->ac_sb;
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      void *bitmap = EXT3_MB_BITMAP(e3b);
++      struct ext3_free_extent ex;
++      unsigned long i, max;
++
++      J_ASSERT(sbi->s_stripe != 0);
++
++      /* find first stripe-aligned block */
++      i = e3b->bd_group * EXT3_BLOCKS_PER_GROUP(sb)
++              + le32_to_cpu(sbi->s_es->s_first_data_block);
++      i = ((i + sbi->s_stripe - 1) / sbi->s_stripe) * sbi->s_stripe;
++      i = (i - le32_to_cpu(sbi->s_es->s_first_data_block))
++                      % EXT3_BLOCKS_PER_GROUP(sb);
++
++      while (i < sb->s_blocksize * 8) {
++              if (!mb_test_bit(i, bitmap)) {
++                      max = mb_find_extent(e3b, 0, i, sbi->s_stripe, &ex);
++                      if (max >= sbi->s_stripe) {
++                              ac->ac_found++;
++                              ac->ac_b_ex = ex;
++                              ext3_mb_use_best_found(ac, e3b);
++                              break;
++                      }
++              }
++              i += sbi->s_stripe;
++      }
++}
++
 +static int ext3_mb_good_group(struct ext3_allocation_context *ac,
 +                              int group, int cr)
 +{
-+      struct ext3_sb_info *sbi = EXT3_SB(ac->ac_sb);
-+      struct ext3_group_info *grp = sbi->s_group_info[group];
++      struct ext3_group_info *grp = EXT3_GROUP_INFO(ac->ac_sb, group);
 +      unsigned free, fragments, i, bits;
 +
 +      J_ASSERT(cr >= 0 && cr < 4);
@@ -1495,15 +1579,18 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +              case 0:
 +                      J_ASSERT(ac->ac_2order != 0);
 +                      bits = ac->ac_sb->s_blocksize_bits + 1;
-+                      for (i = ac->ac_2order; i < bits; i++)
++                      for (i = ac->ac_2order; i <= bits; i++)
 +                              if (grp->bb_counters[i] > 0)
 +                                      return 1;
++                      break;
 +              case 1:
 +                      if ((free / fragments) >= ac->ac_g_ex.fe_len)
 +                              return 1;
++                      break;
 +              case 2:
 +                      if (free >= ac->ac_g_ex.fe_len)
 +                              return 1;
++                      break;
 +              case 3:
 +                      return 1;
 +              default:
@@ -1604,23 +1691,27 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      ac.ac_2order = 0;
 +      ac.ac_criteria = 0;
 +
++      if (*len == 1 && sbi->s_stripe) {
++              /* looks like a metadata, let's use a dirty hack for raid5
++               * move all metadata in first groups in hope to hit cached
++               * sectors and thus avoid read-modify cycles in raid5 */
++              ac.ac_g_ex.fe_group = group = 0;
++      }
++
 +      /* probably, the request is for 2^8+ blocks (1/2/3/... MB) */
 +      i = ffs(*len);
-+      if (i >= 8) {
++      if (i >= ext3_mb_order2_reqs) {
 +              i--;
 +              if ((*len & (~(1 << i))) == 0)
 +                      ac.ac_2order = i;
 +      }
 +
-+      /* Sometimes, caller may want to merge even small
-+       * number of blocks to an existing extent */
-+      if (ac.ac_flags & EXT3_MB_HINT_MERGE) {
-+              err = ext3_mb_find_by_goal(&ac, &e3b);
-+              if (err)
-+                      goto out_err;
-+              if (ac.ac_status == AC_STATUS_FOUND)
-+                      goto found;
-+      }
++      /* first, try the goal */
++      err = ext3_mb_find_by_goal(&ac, &e3b);
++      if (err)
++              goto out_err;
++      if (ac.ac_status == AC_STATUS_FOUND)
++              goto found;
 +
 +      /* Let's just scan groups to find more-less suitable blocks */
 +      cr = ac.ac_2order ? 0 : 1;
@@ -1631,7 +1722,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +                      if (group == EXT3_SB(sb)->s_groups_count)
 +                              group = 0;
 +
-+                      if (EXT3_MB_GRP_NEED_INIT(sbi->s_group_info[group])) {
++                      if (EXT3_MB_GRP_NEED_INIT(EXT3_GROUP_INFO(sb, group))) {
 +                              /* we need full data about the group
 +                               * to make a good selection */
 +                              err = ext3_mb_load_buddy(ac.ac_sb, group, &e3b);
@@ -1659,6 +1750,8 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +                      ac.ac_groups_scanned++;
 +                      if (cr == 0)
 +                              ext3_mb_simple_scan_group(&ac, &e3b);
++                      else if (cr == 1 && *len == sbi->s_stripe) 
++                              ext3_mb_scan_aligned(&ac, &e3b);
 +                      else
 +                              ext3_mb_complex_scan_group(&ac, &e3b);
 +
@@ -1672,7 +1765,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      }
 +
 +      if (ac.ac_b_ex.fe_len > 0 && ac.ac_status != AC_STATUS_FOUND &&
-+                      !(ac.ac_flags & EXT3_MB_HINT_FIRST)) {
++          !(ac.ac_flags & EXT3_MB_HINT_FIRST)) {
 +              /*
 +               * We've been searching too long. Let's try to allocate
 +               * the best chunk we've found so far
@@ -1717,8 +1810,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +                      sbi->s_blocks_reserved, ac.ac_found);
 +              printk("EXT3-fs: groups: ");
 +              for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++)
-+                      printk("%d: %d ", i,
-+                              sbi->s_group_info[i]->bb_free);
++                      printk("%d: %d ", i, EXT3_GROUP_INFO(sb, i)->bb_free);
 +              printk("\n");
 +#endif
 +              goto out;
@@ -1756,7 +1848,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +              *errp = -EIO;
 +              goto out_err;
 +      }
-+      
++
 +      err = ext3_journal_get_write_access(handle, gdp_bh);
 +      if (err)
 +              goto out_err;
@@ -1825,7 +1917,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +               * path only, here is single block always */
 +              ext3_mb_release_blocks(sb, 1);
 +      }
-+      
++
 +      if (unlikely(ext3_mb_stats) && ac.ac_g_ex.fe_len > 1) {
 +              atomic_inc(&sbi->s_bal_reqs);
 +              atomic_add(*len, &sbi->s_bal_allocated);
@@ -1839,7 +1931,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +                      atomic_inc(&sbi->s_bal_breaks);
 +      }
 +
-+      ext3_mb_store_history(sb, &ac);
++      ext3_mb_store_history(sb, inode->i_ino, &ac);
 +
 +      return block;
 +}
@@ -1904,9 +1996,9 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      char buf[20], buf2[20];
 +
 +      if (v == SEQ_START_TOKEN) {
-+              seq_printf(seq, "%-17s %-17s %-5s %-5s %-2s %-5s %-5s %-6s\n",
-+                       "goal", "result", "found", "grps", "cr", "merge",
-+                       "tail", "broken");
++              seq_printf(seq, "%-5s %-8s %-17s %-17s %-5s %-5s %-2s %-5s %-5s %-6s\n",
++                       "pid", "inode", "goal", "result", "found", "grps", "cr",
++                       "merge", "tail", "broken");
 +              return 0;
 +      }
 +
@@ -1914,9 +2006,9 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +              hs->goal.fe_start, hs->goal.fe_len);
 +      sprintf(buf2, "%u/%u/%u", hs->result.fe_group,
 +              hs->result.fe_start, hs->result.fe_len);
-+      seq_printf(seq, "%-17s %-17s %-5u %-5u %-2u %-5s %-5u %-6u\n", buf,
-+                      buf2, hs->found, hs->groups, hs->cr, 
-+                      hs->merged ? "M" : "", hs->tail,
++      seq_printf(seq, "%-5u %-8u %-17s %-17s %-5u %-5u %-2u %-5s %-5u %-6u\n",
++                      hs->pid, hs->ino, buf, buf2, hs->found, hs->groups,
++                      hs->cr, hs->merged ? "M" : "", hs->tail,
 +                      hs->buddy ? 1 << hs->buddy : 0);
 +      return 0;
 +}
@@ -1950,7 +2042,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      s->max = sbi->s_mb_history_max;
 +      s->start = sbi->s_mb_history_cur % s->max;
 +      spin_unlock(&sbi->s_mb_history_lock);
-+      
++
 +      rc = seq_open(file, &ext3_mb_seq_history_ops);
 +      if (rc == 0) {
 +              struct seq_file *m = (struct seq_file *)file->private_data;
@@ -1974,10 +2066,104 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +
 +static struct file_operations ext3_mb_seq_history_fops = {
 +      .owner          = THIS_MODULE,
-+      .open           = ext3_mb_seq_history_open,
-+      .read           = seq_read,
-+      .llseek         = seq_lseek,
-+      .release        = ext3_mb_seq_history_release,
++      .open           = ext3_mb_seq_history_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = ext3_mb_seq_history_release,
++};
++
++static void *ext3_mb_seq_groups_start(struct seq_file *seq, loff_t *pos)
++{
++      struct super_block *sb = seq->private;
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      long group;
++
++      if (*pos < 0 || *pos >= sbi->s_groups_count)
++              return NULL;
++
++      group = *pos + 1;
++      return (void *) group;
++}
++
++static void *ext3_mb_seq_groups_next(struct seq_file *seq, void *v, loff_t *pos)
++{
++      struct super_block *sb = seq->private;
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      long group;
++
++      ++*pos;
++      if (*pos < 0 || *pos >= sbi->s_groups_count)
++              return NULL;
++      group = *pos + 1;
++      return (void *) group;;
++}
++
++static int ext3_mb_seq_groups_show(struct seq_file *seq, void *v)
++{
++      struct super_block *sb = seq->private;
++      long group = (long) v, i;
++      struct sg {
++              struct ext3_group_info info;
++              unsigned short counters[16];
++      } sg;
++
++      group--;
++      if (group == 0)
++              seq_printf(seq, "#%-5s: %-5s %-5s %-5s [ %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s ]\n",
++                       "group", "free", "frags", "first", "2^0", "2^1", "2^2", 
++                       "2^3", "2^4", "2^5", "2^6", "2^7", "2^8", "2^9", "2^10",
++                       "2^11", "2^12", "2^13");
++
++      i = (sb->s_blocksize_bits + 2) * sizeof(sg.info.bb_counters[0]) +
++              sizeof(struct ext3_group_info);
++      ext3_lock_group(sb, group);
++      memcpy(&sg, EXT3_GROUP_INFO(sb, group), i);
++      ext3_unlock_group(sb, group);
++
++      if (EXT3_MB_GRP_NEED_INIT(&sg.info))
++              return 0;
++
++      seq_printf(seq, "#%-5lu: %-5u %-5u %-5u [", group, sg.info.bb_free,
++                      sg.info.bb_fragments, sg.info.bb_first_free);
++      for (i = 0; i <= 13; i++)
++              seq_printf(seq, " %-5u", i <= sb->s_blocksize_bits + 1 ?
++                              sg.info.bb_counters[i] : 0);
++      seq_printf(seq, " ]\n");
++
++      return 0;
++}
++
++static void ext3_mb_seq_groups_stop(struct seq_file *seq, void *v)
++{
++}
++
++static struct seq_operations ext3_mb_seq_groups_ops = {
++      .start  = ext3_mb_seq_groups_start,
++      .next   = ext3_mb_seq_groups_next,
++      .stop   = ext3_mb_seq_groups_stop,
++      .show   = ext3_mb_seq_groups_show,
++};
++
++static int ext3_mb_seq_groups_open(struct inode *inode, struct file *file)
++{
++      struct super_block *sb = PDE(inode)->data;
++      int rc;
++
++      rc = seq_open(file, &ext3_mb_seq_groups_ops);
++      if (rc == 0) {
++              struct seq_file *m = (struct seq_file *)file->private_data;
++              m->private = sb;
++      }
++      return rc;
++
++}
++
++static struct file_operations ext3_mb_seq_groups_fops = {
++      .owner          = THIS_MODULE,
++      .open           = ext3_mb_seq_groups_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = seq_release,
 +};
 +
 +static void ext3_mb_history_release(struct super_block *sb)
@@ -1986,6 +2172,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      char name[64];
 +
 +      snprintf(name, sizeof(name) - 1, "%s", bdevname(sb->s_bdev, name));
++      remove_proc_entry("mb_groups", sbi->s_mb_proc);
 +      remove_proc_entry("mb_history", sbi->s_mb_proc);
 +      remove_proc_entry(name, proc_root_ext3);
 +
@@ -2008,6 +2195,11 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +                      p->proc_fops = &ext3_mb_seq_history_fops;
 +                      p->data = sb;
 +              }
++              p = create_proc_entry("mb_groups", S_IRUGO, sbi->s_mb_proc);
++              if (p) {
++                      p->proc_fops = &ext3_mb_seq_groups_fops;
++                      p->data = sb;
++              }
 +      }
 +
 +      sbi->s_mb_history_max = 1000;
@@ -2020,7 +2212,8 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +}
 +
 +static void
-+ext3_mb_store_history(struct super_block *sb, struct ext3_allocation_context *ac)
++ext3_mb_store_history(struct super_block *sb, unsigned ino,
++                      struct ext3_allocation_context *ac)
 +{
 +      struct ext3_sb_info *sbi = EXT3_SB(sb);
 +      struct ext3_mb_history h;
@@ -2028,6 +2221,8 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      if (likely(sbi->s_mb_history == NULL))
 +              return;
 +
++      h.pid = current->pid;
++      h.ino = ino;
 +      h.goal = ac->ac_g_ex;
 +      h.result = ac->ac_b_ex;
 +      h.found = ac->ac_found;
@@ -2055,21 +2250,40 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +int ext3_mb_init_backend(struct super_block *sb)
 +{
 +      struct ext3_sb_info *sbi = EXT3_SB(sb);
-+      int i, len;
-+
-+      len = sizeof(struct ext3_buddy_group_blocks *) * sbi->s_groups_count;
-+      sbi->s_group_info = kmalloc(len, GFP_KERNEL);
++      int i, j, len, metalen;
++      int num_meta_group_infos =
++              (sbi->s_groups_count + EXT3_DESC_PER_BLOCK(sb) - 1) >>
++                      EXT3_DESC_PER_BLOCK_BITS(sb);
++      struct ext3_group_info **meta_group_info;
++
++      /* An 8TB filesystem with 64-bit pointers requires a 4096 byte
++       * kmalloc. A 128kb malloc should suffice for a 256TB filesystem.
++       * So a two level scheme suffices for now. */
++      sbi->s_group_info = kmalloc(sizeof(*sbi->s_group_info) *
++                                  num_meta_group_infos, GFP_KERNEL);
 +      if (sbi->s_group_info == NULL) {
-+              printk(KERN_ERR "EXT3-fs: can't allocate mem for buddy\n");
++              printk(KERN_ERR "EXT3-fs: can't allocate buddy meta group\n");
 +              return -ENOMEM;
 +      }
-+      memset(sbi->s_group_info, 0, len);
-+
 +      sbi->s_buddy_cache = new_inode(sb);
 +      if (sbi->s_buddy_cache == NULL) {
 +              printk(KERN_ERR "EXT3-fs: can't get new inode\n");
-+              kfree(sbi->s_group_info);
-+              return -ENOMEM;
++              goto err_freesgi;
++      }
++
++      metalen = sizeof(*meta_group_info) << EXT3_DESC_PER_BLOCK_BITS(sb);
++      for (i = 0; i < num_meta_group_infos; i++) {
++              if ((i + 1) == num_meta_group_infos)
++                      metalen = sizeof(*meta_group_info) *
++                              (sbi->s_groups_count -
++                                      (i << EXT3_DESC_PER_BLOCK_BITS(sb)));
++              meta_group_info = kmalloc(metalen, GFP_KERNEL);
++              if (meta_group_info == NULL) {
++                      printk(KERN_ERR "EXT3-fs: can't allocate mem for a "
++                             "buddy group\n");
++                      goto err_freemeta;
++              }
++              sbi->s_group_info[i] = meta_group_info;
 +      }
 +
 +      /* 
@@ -2081,30 +2295,42 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      for (i = 0; i < sbi->s_groups_count; i++) {
 +              struct ext3_group_desc * desc;
 +
-+              sbi->s_group_info[i] = kmalloc(len, GFP_KERNEL);
-+              if (sbi->s_group_info[i] == NULL) {
++              meta_group_info =
++                      sbi->s_group_info[i >> EXT3_DESC_PER_BLOCK_BITS(sb)];
++              j = i & (EXT3_DESC_PER_BLOCK(sb) - 1);
++
++              meta_group_info[j] = kmalloc(len, GFP_KERNEL);
++              if (meta_group_info[j] == NULL) {
 +                      printk(KERN_ERR "EXT3-fs: can't allocate buddy mem\n");
-+                      goto err_out;
++                      i--;
++                      goto err_freebuddy;
 +              }
 +              desc = ext3_get_group_desc(sb, i, NULL);
 +              if (desc == NULL) {
 +                      printk(KERN_ERR"EXT3-fs: can't read descriptor %u\n",i);
-+                      goto err_out;
++                      goto err_freebuddy;
 +              }
-+              memset(sbi->s_group_info[i], 0, len);
++              memset(meta_group_info[j], 0, len);
 +              set_bit(EXT3_GROUP_INFO_NEED_INIT_BIT,
-+                      &sbi->s_group_info[i]->bb_state);
-+              sbi->s_group_info[i]->bb_free =
++                      &meta_group_info[j]->bb_state);
++              meta_group_info[j]->bb_free =
 +                      le16_to_cpu(desc->bg_free_blocks_count);
 +      }
 +
 +      return 0;
 +
-+err_out:
++err_freebuddy:
++      while (i >= 0) {
++              kfree(EXT3_GROUP_INFO(sb, i));
++              i--;
++      }
++      i = num_meta_group_infos;
++err_freemeta:
 +      while (--i >= 0)
 +              kfree(sbi->s_group_info[i]);
 +      iput(sbi->s_buddy_cache);
-+
++err_freesgi:
++      kfree(sbi->s_group_info);
 +      return -ENOMEM;
 +}
 +
@@ -2146,7 +2372,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +              max = max >> 1;
 +              i++;
 +      } while (i <= sb->s_blocksize_bits + 1);
-+      
++
 +
 +      /* init file for buddy data */
 +      if ((i = ext3_mb_init_backend(sb))) {
@@ -2183,8 +2409,8 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +int ext3_mb_release(struct super_block *sb)
 +{
 +      struct ext3_sb_info *sbi = EXT3_SB(sb);
-+      int i;
-+      
++      int i, num_meta_group_infos;
++
 +      if (!test_opt(sb, MBALLOC))
 +              return 0;
 +
@@ -2198,11 +2424,13 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      ext3_mb_free_committed_blocks(sb);
 +
 +      if (sbi->s_group_info) {
-+              for (i = 0; i < sbi->s_groups_count; i++) {
-+                      if (sbi->s_group_info[i] == NULL)
-+                              continue;
++              for (i = 0; i < sbi->s_groups_count; i++)
++                      kfree(EXT3_GROUP_INFO(sb, i));
++              num_meta_group_infos = (sbi->s_groups_count +
++                      EXT3_DESC_PER_BLOCK(sb) - 1) >>
++                      EXT3_DESC_PER_BLOCK_BITS(sb);
++              for (i = 0; i < num_meta_group_infos; i++)
 +                      kfree(sbi->s_group_info[i]);
-+              }
 +              kfree(sbi->s_group_info);
 +      }
 +      if (sbi->s_mb_offsets)
@@ -2496,7 +2724,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +              cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) + count);
 +      spin_unlock(sb_bgl_lock(sbi, block_group));
 +      percpu_counter_mod(&sbi->s_freeblocks_counter, count);
-+      
++
 +      ext3_mb_release_desc(&e3b);
 +
 +      *freed = count;
@@ -2580,10 +2808,11 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      return;
 +}
 +
-+#define EXT3_ROOT                 "ext3"
-+#define EXT3_MB_STATS_NAME        "mb_stats"
++#define EXT3_ROOT                "ext3"
++#define EXT3_MB_STATS_NAME       "mb_stats"
 +#define EXT3_MB_MAX_TO_SCAN_NAME  "mb_max_to_scan"
 +#define EXT3_MB_MIN_TO_SCAN_NAME  "mb_min_to_scan"
++#define EXT3_MB_ORDER2_REQ       "mb_order2_req"
 +
 +static int ext3_mb_stats_read(char *page, char **start, off_t off,
 +              int count, int *eof, void *data)
@@ -2671,6 +2900,45 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      return len;
 +}
 +
++static int ext3_mb_order2_req_write(struct file *file, const char *buffer,
++              unsigned long count, void *data)
++{
++      char str[32];
++      long value;
++
++      if (count >= sizeof(str)) {
++              printk(KERN_ERR "EXT3-fs: %s string too long, max %u bytes\n",
++                     EXT3_MB_MIN_TO_SCAN_NAME, (int)sizeof(str));
++              return -EOVERFLOW;
++      }
++
++      if (copy_from_user(str, buffer, count))
++              return -EFAULT;
++
++      /* Only set to 0 or 1 respectively; zero->0; non-zero->1 */
++      value = simple_strtol(str, NULL, 0);
++      if (value <= 0)
++              return -ERANGE;
++
++      ext3_mb_order2_reqs = value;    
++
++      return count;
++}
++
++static int ext3_mb_order2_req_read(char *page, char **start, off_t off,
++              int count, int *eof, void *data)
++{
++      int len;
++
++      *eof = 1;
++      if (off != 0)
++              return 0;
++
++      len = sprintf(page, "%ld\n", ext3_mb_order2_reqs);
++      *start = page;
++      return len;
++}
++
 +static int ext3_mb_min_to_scan_write(struct file *file, const char *buffer,
 +              unsigned long count, void *data)
 +{
@@ -2701,6 +2969,7 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      struct proc_dir_entry *proc_ext3_mb_stats;
 +      struct proc_dir_entry *proc_ext3_mb_max_to_scan;
 +      struct proc_dir_entry *proc_ext3_mb_min_to_scan;
++      struct proc_dir_entry *proc_ext3_mb_order2_req;
 +
 +      proc_root_ext3 = proc_mkdir(EXT3_ROOT, proc_root_fs);
 +      if (proc_root_ext3 == NULL) {
@@ -2755,6 +3024,24 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      proc_ext3_mb_min_to_scan->read_proc  = ext3_mb_min_to_scan_read;
 +      proc_ext3_mb_min_to_scan->write_proc = ext3_mb_min_to_scan_write;
 +
++      /* Initialize EXT3_ORDER2_REQ */
++      proc_ext3_mb_order2_req = create_proc_entry(
++                      EXT3_MB_ORDER2_REQ,
++                      S_IFREG | S_IRUGO | S_IWUSR, proc_root_ext3);
++      if (proc_ext3_mb_order2_req == NULL) {
++              printk(KERN_ERR "EXT3-fs: Unable to create %s\n",
++                              EXT3_MB_ORDER2_REQ);
++              remove_proc_entry(EXT3_MB_MIN_TO_SCAN_NAME, proc_root_ext3);
++              remove_proc_entry(EXT3_MB_MAX_TO_SCAN_NAME, proc_root_ext3);
++              remove_proc_entry(EXT3_MB_STATS_NAME, proc_root_ext3);
++              remove_proc_entry(EXT3_ROOT, proc_root_fs);
++              return -EIO;
++      }
++
++      proc_ext3_mb_order2_req->data = NULL;
++      proc_ext3_mb_order2_req->read_proc  = ext3_mb_order2_req_read;
++      proc_ext3_mb_order2_req->write_proc = ext3_mb_order2_req_write;
++
 +      return 0;
 +}
 +
@@ -2763,13 +3050,14 @@ Index: linux-2.6.5-7.201/fs/ext3/mballoc.c
 +      remove_proc_entry(EXT3_MB_STATS_NAME, proc_root_ext3);
 +      remove_proc_entry(EXT3_MB_MAX_TO_SCAN_NAME, proc_root_ext3);
 +      remove_proc_entry(EXT3_MB_MIN_TO_SCAN_NAME, proc_root_ext3);
++      remove_proc_entry(EXT3_MB_ORDER2_REQ, proc_root_ext3);
 +      remove_proc_entry(EXT3_ROOT, proc_root_fs);
 +}
-Index: linux-2.6.5-7.201/fs/ext3/Makefile
+Index: linux-2.6.5-7.252-full/fs/ext3/Makefile
 ===================================================================
---- linux-2.6.5-7.201.orig/fs/ext3/Makefile    2005-12-17 02:53:30.000000000 +0300
-+++ linux-2.6.5-7.201/fs/ext3/Makefile 2005-12-17 03:10:23.000000000 +0300
-@@ -6,7 +6,7 @@
+--- linux-2.6.5-7.252-full.orig/fs/ext3/Makefile       2006-04-25 17:42:19.000000000 +0400
++++ linux-2.6.5-7.252-full/fs/ext3/Makefile    2006-04-26 23:40:28.000000000 +0400
+@@ -6,7 +6,7 @@ obj-$(CONFIG_EXT3_FS) += ext3.o
  
  ext3-y        := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
           ioctl.o namei.o super.o symlink.o hash.o \
index 70f4f8a..fae9e30 100644 (file)
@@ -1,7 +1,7 @@
-Index: linux-2.6.12.6/include/linux/ext3_fs.h
+Index: linux-2.6.12.6-bull/include/linux/ext3_fs.h
 ===================================================================
---- linux-2.6.12.6.orig/include/linux/ext3_fs.h        2005-12-17 02:17:16.000000000 +0300
-+++ linux-2.6.12.6/include/linux/ext3_fs.h     2005-12-17 02:21:21.000000000 +0300
+--- linux-2.6.12.6-bull.orig/include/linux/ext3_fs.h   2006-04-29 20:39:09.000000000 +0400
++++ linux-2.6.12.6-bull/include/linux/ext3_fs.h        2006-04-29 20:39:10.000000000 +0400
 @@ -57,6 +57,14 @@ struct statfs;
  #define ext3_debug(f, a...)   do {} while (0)
  #endif
@@ -52,10 +52,10 @@ Index: linux-2.6.12.6/include/linux/ext3_fs.h
  #endif        /* __KERNEL__ */
  
  /* EXT3_IOC_CREATE_INUM at bottom of file (visible to kernel and user). */
-Index: linux-2.6.12.6/include/linux/ext3_fs_sb.h
+Index: linux-2.6.12.6-bull/include/linux/ext3_fs_sb.h
 ===================================================================
---- linux-2.6.12.6.orig/include/linux/ext3_fs_sb.h     2005-08-29 20:55:27.000000000 +0400
-+++ linux-2.6.12.6/include/linux/ext3_fs_sb.h  2005-12-17 02:21:21.000000000 +0300
+--- linux-2.6.12.6-bull.orig/include/linux/ext3_fs_sb.h        2005-08-29 20:55:27.000000000 +0400
++++ linux-2.6.12.6-bull/include/linux/ext3_fs_sb.h     2006-04-29 20:39:10.000000000 +0400
 @@ -21,8 +21,14 @@
  #include <linux/wait.h>
  #include <linux/blockgroup_lock.h>
@@ -71,13 +71,13 @@ Index: linux-2.6.12.6/include/linux/ext3_fs_sb.h
  
  /*
   * third extended-fs super-block data in memory
-@@ -78,6 +84,38 @@ struct ext3_sb_info {
+@@ -78,6 +84,43 @@ struct ext3_sb_info {
        char *s_qf_names[MAXQUOTAS];            /* Names of quota files with journalled quota */
        int s_jquota_fmt;                       /* Format of quota to use */
  #endif
 +
 +      /* for buddy allocator */
-+      struct ext3_group_info **s_group_info;
++      struct ext3_group_info ***s_group_info;
 +      struct inode *s_buddy_cache;
 +      long s_blocks_reserved;
 +      spinlock_t s_reserve_lock;
@@ -88,6 +88,7 @@ Index: linux-2.6.12.6/include/linux/ext3_fs_sb.h
 +      tid_t s_last_transaction;
 +      int s_mb_factor;
 +      unsigned short *s_mb_offsets, *s_mb_maxs;
++      unsigned long s_stripe;
 +
 +      /* history to debug policy */
 +      struct ext3_mb_history *s_mb_history;
@@ -108,12 +109,16 @@ Index: linux-2.6.12.6/include/linux/ext3_fs_sb.h
 +      unsigned long s_mb_buddies_generated;
 +      unsigned long long s_mb_generation_time;
  };
++
++#define EXT3_GROUP_INFO(sb, group)                                       \
++      EXT3_SB(sb)->s_group_info[(group) >> EXT3_DESC_PER_BLOCK_BITS(sb)] \
++                               [(group) & (EXT3_DESC_PER_BLOCK(sb) - 1)]
  
  #endif        /* _LINUX_EXT3_FS_SB */
-Index: linux-2.6.12.6/fs/ext3/super.c
+Index: linux-2.6.12.6-bull/fs/ext3/super.c
 ===================================================================
---- linux-2.6.12.6.orig/fs/ext3/super.c        2005-12-17 02:17:16.000000000 +0300
-+++ linux-2.6.12.6/fs/ext3/super.c     2005-12-17 02:21:21.000000000 +0300
+--- linux-2.6.12.6-bull.orig/fs/ext3/super.c   2006-04-29 20:39:09.000000000 +0400
++++ linux-2.6.12.6-bull/fs/ext3/super.c        2006-04-29 20:39:10.000000000 +0400
 @@ -387,6 +387,7 @@ static void ext3_put_super (struct super
        struct ext3_super_block *es = sbi->s_es;
        int i;
@@ -122,34 +127,45 @@ Index: linux-2.6.12.6/fs/ext3/super.c
        ext3_ext_release(sb);
        ext3_xattr_put_super(sb);
        journal_destroy(sbi->s_journal);
-@@ -597,7 +598,7 @@ enum {
-       Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0,
+@@ -597,6 +598,7 @@ enum {
        Opt_ignore, Opt_barrier, Opt_err, Opt_resize,
        Opt_iopen, Opt_noiopen, Opt_iopen_nopriv,
--      Opt_extents, Opt_extdebug,
-+      Opt_extents, Opt_extdebug, Opt_mballoc,
+       Opt_extents, Opt_noextents, Opt_extdebug,
++      Opt_mballoc, Opt_nomballoc, Opt_stripe,
  };
  
  static match_table_t tokens = {
-@@ -649,6 +651,7 @@ static match_table_t tokens = {
-       {Opt_iopen_nopriv, "iopen_nopriv"},
+@@ -650,6 +651,9 @@ static match_table_t tokens = {
        {Opt_extents, "extents"},
+       {Opt_noextents, "noextents"},
        {Opt_extdebug, "extdebug"},
 +      {Opt_mballoc, "mballoc"},
++      {Opt_nomballoc, "nomballoc"},
++      {Opt_stripe, "stripe=%u"},
        {Opt_barrier, "barrier=%u"},
        {Opt_err, NULL},
        {Opt_resize, "resize"},
-@@ -964,6 +967,9 @@ clear_qf_name:
+@@ -965,6 +967,19 @@ clear_qf_name:
                case Opt_extdebug:
                        set_opt (sbi->s_mount_opt, EXTDEBUG);
                        break;
 +              case Opt_mballoc:
-+                      set_opt (sbi->s_mount_opt, MBALLOC);
++                      set_opt(sbi->s_mount_opt, MBALLOC);
++                      break;
++              case Opt_nomballoc:
++                      clear_opt(sbi->s_mount_opt, MBALLOC);
++                      break;
++              case Opt_stripe:
++                      if (match_int(&args[0], &option))
++                              return 0;
++                      if (option < 0)
++                              return 0;
++                      sbi->s_stripe = option;
 +                      break;
                default:
                        printk (KERN_ERR
                                "EXT3-fs: Unrecognized mount option \"%s\" "
-@@ -1669,6 +1675,7 @@ static int ext3_fill_super (struct super
+@@ -1670,6 +1675,7 @@ static int ext3_fill_super (struct super
                ext3_count_dirs(sb));
  
        ext3_ext_init(sb);
@@ -157,7 +173,7 @@ Index: linux-2.6.12.6/fs/ext3/super.c
        lock_kernel();
        return 0;
  
-@@ -2548,7 +2555,13 @@ static struct file_system_type ext3_fs_t
+@@ -2549,7 +2555,13 @@ static struct file_system_type ext3_fs_t
  
  static int __init init_ext3_fs(void)
  {
@@ -172,7 +188,7 @@ Index: linux-2.6.12.6/fs/ext3/super.c
        if (err)
                return err;
        err = init_inodecache();
-@@ -2570,6 +2583,7 @@ static void __exit exit_ext3_fs(void)
+@@ -2571,6 +2583,7 @@ static void __exit exit_ext3_fs(void)
        unregister_filesystem(&ext3_fs_type);
        destroy_inodecache();
        exit_ext3_xattr();
@@ -180,11 +196,11 @@ Index: linux-2.6.12.6/fs/ext3/super.c
  }
  
  int ext3_prep_san_write(struct inode *inode, long *blocks,
-Index: linux-2.6.12.6/fs/ext3/extents.c
+Index: linux-2.6.12.6-bull/fs/ext3/extents.c
 ===================================================================
---- linux-2.6.12.6.orig/fs/ext3/extents.c      2005-12-17 02:17:16.000000000 +0300
-+++ linux-2.6.12.6/fs/ext3/extents.c   2005-12-17 02:21:21.000000000 +0300
-@@ -771,7 +771,7 @@ cleanup:
+--- linux-2.6.12.6-bull.orig/fs/ext3/extents.c 2006-04-29 20:39:09.000000000 +0400
++++ linux-2.6.12.6-bull/fs/ext3/extents.c      2006-04-29 20:39:10.000000000 +0400
+@@ -777,7 +777,7 @@ cleanup:
                for (i = 0; i < depth; i++) {
                        if (!ablocks[i])
                                continue;
@@ -193,7 +209,7 @@ Index: linux-2.6.12.6/fs/ext3/extents.c
                }
        }
        kfree(ablocks);
-@@ -1428,7 +1428,7 @@ int ext3_ext_rm_idx(handle_t *handle, st
+@@ -1434,7 +1434,7 @@ int ext3_ext_rm_idx(handle_t *handle, st
                  path->p_idx->ei_leaf);
        bh = sb_find_get_block(tree->inode->i_sb, path->p_idx->ei_leaf);
        ext3_forget(handle, 1, tree->inode, bh, path->p_idx->ei_leaf);
@@ -202,7 +218,7 @@ Index: linux-2.6.12.6/fs/ext3/extents.c
        return err;
  }
  
-@@ -1913,10 +1913,12 @@ ext3_remove_blocks(struct ext3_extents_t
+@@ -1919,10 +1919,12 @@ ext3_remove_blocks(struct ext3_extents_t
        int needed = ext3_remove_blocks_credits(tree, ex, from, to);
        handle_t *handle = ext3_journal_start(tree->inode, needed);
        struct buffer_head *bh;
@@ -216,7 +232,7 @@ Index: linux-2.6.12.6/fs/ext3/extents.c
        if (from >= ex->ee_block && to == ex->ee_block + ex->ee_len - 1) {
                /* tail removal */
                unsigned long num, start;
-@@ -1928,7 +1930,7 @@ ext3_remove_blocks(struct ext3_extents_t
+@@ -1934,7 +1936,7 @@ ext3_remove_blocks(struct ext3_extents_t
                        bh = sb_find_get_block(tree->inode->i_sb, start + i);
                        ext3_forget(handle, 0, tree->inode, bh, start + i);
                }
@@ -225,10 +241,10 @@ Index: linux-2.6.12.6/fs/ext3/extents.c
        } else if (from == ex->ee_block && to <= ex->ee_block + ex->ee_len - 1) {
                printk("strange request: removal %lu-%lu from %u:%u\n",
                       from, to, ex->ee_block, ex->ee_len);
-Index: linux-2.6.12.6/fs/ext3/inode.c
+Index: linux-2.6.12.6-bull/fs/ext3/inode.c
 ===================================================================
---- linux-2.6.12.6.orig/fs/ext3/inode.c        2005-12-17 02:17:16.000000000 +0300
-+++ linux-2.6.12.6/fs/ext3/inode.c     2005-12-17 02:21:21.000000000 +0300
+--- linux-2.6.12.6-bull.orig/fs/ext3/inode.c   2006-04-29 20:39:09.000000000 +0400
++++ linux-2.6.12.6-bull/fs/ext3/inode.c        2006-04-29 20:39:10.000000000 +0400
 @@ -564,7 +564,7 @@ static int ext3_alloc_branch(handle_t *h
                ext3_journal_forget(handle, branch[i].bh);
        }
@@ -256,10 +272,10 @@ Index: linux-2.6.12.6/fs/ext3/inode.c
  
                        if (parent_bh) {
                                /*
-Index: linux-2.6.12.6/fs/ext3/balloc.c
+Index: linux-2.6.12.6-bull/fs/ext3/balloc.c
 ===================================================================
---- linux-2.6.12.6.orig/fs/ext3/balloc.c       2005-08-29 20:55:27.000000000 +0400
-+++ linux-2.6.12.6/fs/ext3/balloc.c    2005-12-17 02:21:21.000000000 +0300
+--- linux-2.6.12.6-bull.orig/fs/ext3/balloc.c  2005-08-29 20:55:27.000000000 +0400
++++ linux-2.6.12.6-bull/fs/ext3/balloc.c       2006-04-29 20:39:10.000000000 +0400
 @@ -79,7 +79,7 @@ struct ext3_group_desc * ext3_get_group_
   *
   * Return buffer_head on success or NULL in case of failure.
@@ -303,10 +319,10 @@ Index: linux-2.6.12.6/fs/ext3/balloc.c
                        unsigned long goal, int *errp)
  {
        struct buffer_head *bitmap_bh = NULL;
-Index: linux-2.6.12.6/fs/ext3/xattr.c
+Index: linux-2.6.12.6-bull/fs/ext3/xattr.c
 ===================================================================
---- linux-2.6.12.6.orig/fs/ext3/xattr.c        2005-08-29 20:55:27.000000000 +0400
-+++ linux-2.6.12.6/fs/ext3/xattr.c     2005-12-17 02:21:33.000000000 +0300
+--- linux-2.6.12.6-bull.orig/fs/ext3/xattr.c   2005-08-29 20:55:27.000000000 +0400
++++ linux-2.6.12.6-bull/fs/ext3/xattr.c        2006-04-29 20:39:10.000000000 +0400
 @@ -484,7 +484,7 @@ ext3_xattr_release_block(handle_t *handl
                ea_bdebug(bh, "refcount now=0; freeing");
                if (ce)
@@ -325,11 +341,11 @@ Index: linux-2.6.12.6/fs/ext3/xattr.c
                                error = -EIO;
                                goto cleanup;
                        }
-Index: linux-2.6.12.6/fs/ext3/mballoc.c
+Index: linux-2.6.12.6-bull/fs/ext3/mballoc.c
 ===================================================================
---- linux-2.6.12.6.orig/fs/ext3/mballoc.c      2005-12-09 13:08:53.191437750 +0300
-+++ linux-2.6.12.6/fs/ext3/mballoc.c   2005-12-17 02:21:21.000000000 +0300
-@@ -0,0 +1,2429 @@
+--- linux-2.6.12.6-bull.orig/fs/ext3/mballoc.c 2006-04-22 17:31:47.543334750 +0400
++++ linux-2.6.12.6-bull/fs/ext3/mballoc.c      2006-04-30 01:24:11.000000000 +0400
+@@ -0,0 +1,2701 @@
 +/*
 + * Copyright (c) 2003-2005, Cluster File Systems, Inc, info@clusterfs.com
 + * Written by Alex Tomas <alex@clusterfs.com>
@@ -418,6 +434,12 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +
 +long ext3_mb_stats = 1;
 +
++/*
++ * for which requests use 2^N search using buddies
++ */
++long ext3_mb_order2_reqs = 8;
++
++
 +#ifdef EXT3_BB_MAX_BLOCKS
 +#undef EXT3_BB_MAX_BLOCKS
 +#endif
@@ -458,10 +480,10 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +
 +      /* search goals */
 +      struct ext3_free_extent ac_g_ex;
-+      
++
 +      /* the best found extent */
 +      struct ext3_free_extent ac_b_ex;
-+      
++
 +      /* number of iterations done. we have to track to limit searching */
 +      unsigned long ac_ex_scanned;
 +      __u16 ac_groups_scanned;
@@ -483,6 +505,8 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +struct ext3_mb_history {
 +      struct ext3_free_extent goal;   /* goal allocation */
 +      struct ext3_free_extent result; /* result allocation */
++      unsigned pid;
++      unsigned ino;
 +      __u16 found;    /* how many extents have been found */
 +      __u16 groups;   /* how many groups have been scanned */
 +      __u16 tail;     /* what tail broke some buddy */
@@ -505,9 +529,9 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +#define EXT3_MB_BUDDY(e3b)    ((e3b)->bd_buddy)
 +
 +#ifndef EXT3_MB_HISTORY
-+#define ext3_mb_store_history(sb,ac)
++#define ext3_mb_store_history(sb,ino,ac)
 +#else
-+static void ext3_mb_store_history(struct super_block *,
++static void ext3_mb_store_history(struct super_block *, unsigned ino,
 +                              struct ext3_allocation_context *ac);
 +#endif
 +
@@ -626,7 +650,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +              if (mb_check_counter++ % 300 != 0)
 +                      return;
 +      }
-+      
++
 +      while (order > 1) {
 +              buddy = mb_find_buddy(e3b, order, &max);
 +              J_ASSERT(buddy);
@@ -807,7 +831,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      sb = inode->i_sb;
 +      blocksize = 1 << inode->i_blkbits;
 +      blocks_per_page = PAGE_CACHE_SIZE / blocksize;
-+      
++
 +      groups_per_page = blocks_per_page >> 1;
 +      if (groups_per_page == 0)
 +              groups_per_page = 1;
@@ -822,9 +846,9 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +              memset(bh, 0, i);
 +      } else
 +              bh = &bhs;
-+      
++
 +      first_group = page->index * blocks_per_page / 2;
-+      
++
 +      /* read all groups the page covers into the cache */
 +      for (i = 0; i < groups_per_page; i++) {
 +              struct ext3_group_desc * desc;
@@ -879,11 +903,11 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +                      mb_debug("put buddy for group %u in page %lu/%x\n",
 +                              group, page->index, i * blocksize);
 +                      memset(data, 0xff, blocksize);
-+                      EXT3_SB(sb)->s_group_info[group]->bb_fragments = 0;
-+                      memset(EXT3_SB(sb)->s_group_info[group]->bb_counters, 0,
++                      EXT3_GROUP_INFO(sb, group)->bb_fragments = 0;
++                      memset(EXT3_GROUP_INFO(sb, group)->bb_counters, 0,
 +                              sizeof(unsigned short)*(sb->s_blocksize_bits+2));
 +                      ext3_mb_generate_buddy(sb, data, bitmap,
-+                                              EXT3_SB(sb)->s_group_info[group]);
++                                              EXT3_GROUP_INFO(sb, group));
 +              } else {
 +                      /* this is block of bitmap */
 +                      mb_debug("put bitmap for group %u in page %lu/%x\n",
@@ -916,7 +940,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      blocks_per_page = PAGE_CACHE_SIZE / sb->s_blocksize;
 +
 +      e3b->bd_blkbits = sb->s_blocksize_bits;
-+      e3b->bd_info = sbi->s_group_info[group];
++      e3b->bd_info = EXT3_GROUP_INFO(sb, group);
 +      e3b->bd_sb = sb;
 +      e3b->bd_group = group;
 +      e3b->bd_buddy_page = NULL;
@@ -992,14 +1016,14 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +ext3_lock_group(struct super_block *sb, int group)
 +{
 +      bit_spin_lock(EXT3_GROUP_INFO_LOCKED_BIT,
-+                      &EXT3_SB(sb)->s_group_info[group]->bb_state);
++                    &EXT3_GROUP_INFO(sb, group)->bb_state);
 +}
 +
 +static inline void
 +ext3_unlock_group(struct super_block *sb, int group)
 +{
 +      bit_spin_unlock(EXT3_GROUP_INFO_LOCKED_BIT,
-+                      &EXT3_SB(sb)->s_group_info[group]->bb_state);
++                      &EXT3_GROUP_INFO(sb, group)->bb_state);
 +}
 +
 +static int mb_find_order_for_block(struct ext3_buddy *e3b, int block)
@@ -1129,7 +1153,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +static int mb_find_extent(struct ext3_buddy *e3b, int order, int block,
 +                              int needed, struct ext3_free_extent *ex)
 +{
-+      int next, max, ord;
++      int next = block, max, ord;
 +      void *buddy;
 +
 +      J_ASSERT(ex != NULL);
@@ -1154,6 +1178,11 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      ex->fe_start = block << order;
 +      ex->fe_group = e3b->bd_group;
 +
++      /* calc difference from given start */
++      next = next - ex->fe_start;
++      ex->fe_len -= next;
++      ex->fe_start += next;
++
 +      while (needed > ex->fe_len && (buddy = mb_find_buddy(e3b, order, &max))) {
 +
 +              if (block + 1 >= max)
@@ -1349,7 +1378,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +
 +      ext3_lock_group(ac->ac_sb, group);
 +      max = mb_find_extent(e3b, 0, ex.fe_start, ex.fe_len, &ex);
-+      
++
 +      if (max > 0) {
 +              ac->ac_b_ex = ex;
 +              ext3_mb_use_best_found(ac, e3b);
@@ -1366,6 +1395,8 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +                              struct ext3_buddy *e3b)
 +{
 +      int group = ac->ac_g_ex.fe_group, max, err;
++      struct ext3_sb_info *sbi = EXT3_SB(ac->ac_sb);
++      struct ext3_super_block *es = sbi->s_es;
 +      struct ext3_free_extent ex;
 +
 +      err = ext3_mb_load_buddy(ac->ac_sb, group, e3b);
@@ -1374,9 +1405,27 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +
 +      ext3_lock_group(ac->ac_sb, group);
 +      max = mb_find_extent(e3b, 0, ac->ac_g_ex.fe_start,
-+                              ac->ac_g_ex.fe_len, &ex);
-+      
-+      if (max > 0) {
++                           ac->ac_g_ex.fe_len, &ex);
++
++      if (max >= ac->ac_g_ex.fe_len && ac->ac_g_ex.fe_len == sbi->s_stripe) {
++              unsigned long start;
++              start = (e3b->bd_group * EXT3_BLOCKS_PER_GROUP(ac->ac_sb) +
++                      ex.fe_start + le32_to_cpu(es->s_first_data_block));
++              if (start % sbi->s_stripe == 0) {
++                      ac->ac_found++;
++                      ac->ac_b_ex = ex;
++                      ext3_mb_use_best_found(ac, e3b);
++              }
++      } else if (max >= ac->ac_g_ex.fe_len) {
++              J_ASSERT(ex.fe_len > 0);
++              J_ASSERT(ex.fe_group == ac->ac_g_ex.fe_group);
++              J_ASSERT(ex.fe_start == ac->ac_g_ex.fe_start);
++              ac->ac_found++;
++              ac->ac_b_ex = ex;
++              ext3_mb_use_best_found(ac, e3b);
++      } else if (max > 0 && (ac->ac_flags & EXT3_MB_HINT_MERGE)) {
++              /* Sometimes, caller may want to merge even small
++               * number of blocks to an existing extent */
 +              J_ASSERT(ex.fe_len > 0);
 +              J_ASSERT(ex.fe_group == ac->ac_g_ex.fe_group);
 +              J_ASSERT(ex.fe_start == ac->ac_g_ex.fe_start);
@@ -1404,7 +1453,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      int i, k, max;
 +
 +      J_ASSERT(ac->ac_2order > 0);
-+      for (i = ac->ac_2order; i < sb->s_blocksize_bits + 1; i++) {
++      for (i = ac->ac_2order; i <= sb->s_blocksize_bits + 1; i++) {
 +              if (grp->bb_counters[i] == 0)
 +                      continue;
 +
@@ -1469,11 +1518,46 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      }
 +}
 +
++/*
++ * This is a special case for storages like raid5
++ * we try to find stripe-aligned chunks for stripe-size requests
++ */
++static void ext3_mb_scan_aligned(struct ext3_allocation_context *ac,
++                               struct ext3_buddy *e3b)
++{
++      struct super_block *sb = ac->ac_sb;
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      void *bitmap = EXT3_MB_BITMAP(e3b);
++      struct ext3_free_extent ex;
++      unsigned long i, max;
++
++      J_ASSERT(sbi->s_stripe != 0);
++
++      /* find first stripe-aligned block */
++      i = e3b->bd_group * EXT3_BLOCKS_PER_GROUP(sb)
++              + le32_to_cpu(sbi->s_es->s_first_data_block);
++      i = ((i + sbi->s_stripe - 1) / sbi->s_stripe) * sbi->s_stripe;
++      i = (i - le32_to_cpu(sbi->s_es->s_first_data_block))
++                      % EXT3_BLOCKS_PER_GROUP(sb);
++
++      while (i < sb->s_blocksize * 8) {
++              if (!mb_test_bit(i, bitmap)) {
++                      max = mb_find_extent(e3b, 0, i, sbi->s_stripe, &ex);
++                      if (max >= sbi->s_stripe) {
++                              ac->ac_found++;
++                              ac->ac_b_ex = ex;
++                              ext3_mb_use_best_found(ac, e3b);
++                              break;
++                      }
++              }
++              i += sbi->s_stripe;
++      }
++}
++
 +static int ext3_mb_good_group(struct ext3_allocation_context *ac,
 +                              int group, int cr)
 +{
-+      struct ext3_sb_info *sbi = EXT3_SB(ac->ac_sb);
-+      struct ext3_group_info *grp = sbi->s_group_info[group];
++      struct ext3_group_info *grp = EXT3_GROUP_INFO(ac->ac_sb, group);
 +      unsigned free, fragments, i, bits;
 +
 +      J_ASSERT(cr >= 0 && cr < 4);
@@ -1490,15 +1574,18 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +              case 0:
 +                      J_ASSERT(ac->ac_2order != 0);
 +                      bits = ac->ac_sb->s_blocksize_bits + 1;
-+                      for (i = ac->ac_2order; i < bits; i++)
++                      for (i = ac->ac_2order; i <= bits; i++)
 +                              if (grp->bb_counters[i] > 0)
 +                                      return 1;
++                      break;
 +              case 1:
 +                      if ((free / fragments) >= ac->ac_g_ex.fe_len)
 +                              return 1;
++                      break;
 +              case 2:
 +                      if (free >= ac->ac_g_ex.fe_len)
 +                              return 1;
++                      break;
 +              case 3:
 +                      return 1;
 +              default:
@@ -1599,23 +1686,27 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      ac.ac_2order = 0;
 +      ac.ac_criteria = 0;
 +
++      if (*len == 1 && sbi->s_stripe) {
++              /* looks like a metadata, let's use a dirty hack for raid5
++               * move all metadata in first groups in hope to hit cached
++               * sectors and thus avoid read-modify cycles in raid5 */
++              ac.ac_g_ex.fe_group = group = 0;
++      }
++
 +      /* probably, the request is for 2^8+ blocks (1/2/3/... MB) */
 +      i = ffs(*len);
-+      if (i >= 8) {
++      if (i >= ext3_mb_order2_reqs) {
 +              i--;
 +              if ((*len & (~(1 << i))) == 0)
 +                      ac.ac_2order = i;
 +      }
 +
-+      /* Sometimes, caller may want to merge even small
-+       * number of blocks to an existing extent */
-+      if (ac.ac_flags & EXT3_MB_HINT_MERGE) {
-+              err = ext3_mb_find_by_goal(&ac, &e3b);
-+              if (err)
-+                      goto out_err;
-+              if (ac.ac_status == AC_STATUS_FOUND)
-+                      goto found;
-+      }
++      /* first, try the goal */
++      err = ext3_mb_find_by_goal(&ac, &e3b);
++      if (err)
++              goto out_err;
++      if (ac.ac_status == AC_STATUS_FOUND)
++              goto found;
 +
 +      /* Let's just scan groups to find more-less suitable blocks */
 +      cr = ac.ac_2order ? 0 : 1;
@@ -1626,7 +1717,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +                      if (group == EXT3_SB(sb)->s_groups_count)
 +                              group = 0;
 +
-+                      if (EXT3_MB_GRP_NEED_INIT(sbi->s_group_info[group])) {
++                      if (EXT3_MB_GRP_NEED_INIT(EXT3_GROUP_INFO(sb, group))) {
 +                              /* we need full data about the group
 +                               * to make a good selection */
 +                              err = ext3_mb_load_buddy(ac.ac_sb, group, &e3b);
@@ -1654,6 +1745,8 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +                      ac.ac_groups_scanned++;
 +                      if (cr == 0)
 +                              ext3_mb_simple_scan_group(&ac, &e3b);
++                      else if (cr == 1 && *len == sbi->s_stripe) 
++                              ext3_mb_scan_aligned(&ac, &e3b);
 +                      else
 +                              ext3_mb_complex_scan_group(&ac, &e3b);
 +
@@ -1667,7 +1760,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      }
 +
 +      if (ac.ac_b_ex.fe_len > 0 && ac.ac_status != AC_STATUS_FOUND &&
-+                      !(ac.ac_flags & EXT3_MB_HINT_FIRST)) {
++          !(ac.ac_flags & EXT3_MB_HINT_FIRST)) {
 +              /*
 +               * We've been searching too long. Let's try to allocate
 +               * the best chunk we've found so far
@@ -1712,8 +1805,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +                      sbi->s_blocks_reserved, ac.ac_found);
 +              printk("EXT3-fs: groups: ");
 +              for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++)
-+                      printk("%d: %d ", i,
-+                              sbi->s_group_info[i]->bb_free);
++                      printk("%d: %d ", i, EXT3_GROUP_INFO(sb, i)->bb_free);
 +              printk("\n");
 +#endif
 +              goto out;
@@ -1751,7 +1843,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +              *errp = -EIO;
 +              goto out_err;
 +      }
-+      
++
 +      err = ext3_journal_get_write_access(handle, gdp_bh);
 +      if (err)
 +              goto out_err;
@@ -1820,7 +1912,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +               * path only, here is single block always */
 +              ext3_mb_release_blocks(sb, 1);
 +      }
-+      
++
 +      if (unlikely(ext3_mb_stats) && ac.ac_g_ex.fe_len > 1) {
 +              atomic_inc(&sbi->s_bal_reqs);
 +              atomic_add(*len, &sbi->s_bal_allocated);
@@ -1834,7 +1926,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +                      atomic_inc(&sbi->s_bal_breaks);
 +      }
 +
-+      ext3_mb_store_history(sb, &ac);
++      ext3_mb_store_history(sb, inode->i_ino, &ac);
 +
 +      return block;
 +}
@@ -1899,9 +1991,9 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      char buf[20], buf2[20];
 +
 +      if (v == SEQ_START_TOKEN) {
-+              seq_printf(seq, "%-17s %-17s %-5s %-5s %-2s %-5s %-5s %-6s\n",
-+                       "goal", "result", "found", "grps", "cr", "merge",
-+                       "tail", "broken");
++              seq_printf(seq, "%-5s %-8s %-17s %-17s %-5s %-5s %-2s %-5s %-5s %-6s\n",
++                       "pid", "inode", "goal", "result", "found", "grps", "cr",
++                       "merge", "tail", "broken");
 +              return 0;
 +      }
 +
@@ -1909,9 +2001,9 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +              hs->goal.fe_start, hs->goal.fe_len);
 +      sprintf(buf2, "%u/%u/%u", hs->result.fe_group,
 +              hs->result.fe_start, hs->result.fe_len);
-+      seq_printf(seq, "%-17s %-17s %-5u %-5u %-2u %-5s %-5u %-6u\n", buf,
-+                      buf2, hs->found, hs->groups, hs->cr, 
-+                      hs->merged ? "M" : "", hs->tail,
++      seq_printf(seq, "%-5u %-8u %-17s %-17s %-5u %-5u %-2u %-5s %-5u %-6u\n",
++                      hs->pid, hs->ino, buf, buf2, hs->found, hs->groups,
++                      hs->cr, hs->merged ? "M" : "", hs->tail,
 +                      hs->buddy ? 1 << hs->buddy : 0);
 +      return 0;
 +}
@@ -1945,7 +2037,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      s->max = sbi->s_mb_history_max;
 +      s->start = sbi->s_mb_history_cur % s->max;
 +      spin_unlock(&sbi->s_mb_history_lock);
-+      
++
 +      rc = seq_open(file, &ext3_mb_seq_history_ops);
 +      if (rc == 0) {
 +              struct seq_file *m = (struct seq_file *)file->private_data;
@@ -1969,10 +2061,104 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +
 +static struct file_operations ext3_mb_seq_history_fops = {
 +      .owner          = THIS_MODULE,
-+      .open           = ext3_mb_seq_history_open,
-+      .read           = seq_read,
-+      .llseek         = seq_lseek,
-+      .release        = ext3_mb_seq_history_release,
++      .open           = ext3_mb_seq_history_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = ext3_mb_seq_history_release,
++};
++
++static void *ext3_mb_seq_groups_start(struct seq_file *seq, loff_t *pos)
++{
++      struct super_block *sb = seq->private;
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      long group;
++
++      if (*pos < 0 || *pos >= sbi->s_groups_count)
++              return NULL;
++
++      group = *pos + 1;
++      return (void *) group;
++}
++
++static void *ext3_mb_seq_groups_next(struct seq_file *seq, void *v, loff_t *pos)
++{
++      struct super_block *sb = seq->private;
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      long group;
++
++      ++*pos;
++      if (*pos < 0 || *pos >= sbi->s_groups_count)
++              return NULL;
++      group = *pos + 1;
++      return (void *) group;;
++}
++
++static int ext3_mb_seq_groups_show(struct seq_file *seq, void *v)
++{
++      struct super_block *sb = seq->private;
++      long group = (long) v, i;
++      struct sg {
++              struct ext3_group_info info;
++              unsigned short counters[16];
++      } sg;
++
++      group--;
++      if (group == 0)
++              seq_printf(seq, "#%-5s: %-5s %-5s %-5s [ %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s ]\n",
++                       "group", "free", "frags", "first", "2^0", "2^1", "2^2", 
++                       "2^3", "2^4", "2^5", "2^6", "2^7", "2^8", "2^9", "2^10",
++                       "2^11", "2^12", "2^13");
++
++      i = (sb->s_blocksize_bits + 2) * sizeof(sg.info.bb_counters[0]) +
++              sizeof(struct ext3_group_info);
++      ext3_lock_group(sb, group);
++      memcpy(&sg, EXT3_GROUP_INFO(sb, group), i);
++      ext3_unlock_group(sb, group);
++
++      if (EXT3_MB_GRP_NEED_INIT(&sg.info))
++              return 0;
++
++      seq_printf(seq, "#%-5lu: %-5u %-5u %-5u [", group, sg.info.bb_free,
++                      sg.info.bb_fragments, sg.info.bb_first_free);
++      for (i = 0; i <= 13; i++)
++              seq_printf(seq, " %-5u", i <= sb->s_blocksize_bits + 1 ?
++                              sg.info.bb_counters[i] : 0);
++      seq_printf(seq, " ]\n");
++
++      return 0;
++}
++
++static void ext3_mb_seq_groups_stop(struct seq_file *seq, void *v)
++{
++}
++
++static struct seq_operations ext3_mb_seq_groups_ops = {
++      .start  = ext3_mb_seq_groups_start,
++      .next   = ext3_mb_seq_groups_next,
++      .stop   = ext3_mb_seq_groups_stop,
++      .show   = ext3_mb_seq_groups_show,
++};
++
++static int ext3_mb_seq_groups_open(struct inode *inode, struct file *file)
++{
++      struct super_block *sb = PDE(inode)->data;
++      int rc;
++
++      rc = seq_open(file, &ext3_mb_seq_groups_ops);
++      if (rc == 0) {
++              struct seq_file *m = (struct seq_file *)file->private_data;
++              m->private = sb;
++      }
++      return rc;
++
++}
++
++static struct file_operations ext3_mb_seq_groups_fops = {
++      .owner          = THIS_MODULE,
++      .open           = ext3_mb_seq_groups_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = seq_release,
 +};
 +
 +static void ext3_mb_history_release(struct super_block *sb)
@@ -1981,6 +2167,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      char name[64];
 +
 +      snprintf(name, sizeof(name) - 1, "%s", bdevname(sb->s_bdev, name));
++      remove_proc_entry("mb_groups", sbi->s_mb_proc);
 +      remove_proc_entry("mb_history", sbi->s_mb_proc);
 +      remove_proc_entry(name, proc_root_ext3);
 +
@@ -2003,6 +2190,11 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +                      p->proc_fops = &ext3_mb_seq_history_fops;
 +                      p->data = sb;
 +              }
++              p = create_proc_entry("mb_groups", S_IRUGO, sbi->s_mb_proc);
++              if (p) {
++                      p->proc_fops = &ext3_mb_seq_groups_fops;
++                      p->data = sb;
++              }
 +      }
 +
 +      sbi->s_mb_history_max = 1000;
@@ -2015,7 +2207,8 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +}
 +
 +static void
-+ext3_mb_store_history(struct super_block *sb, struct ext3_allocation_context *ac)
++ext3_mb_store_history(struct super_block *sb, unsigned ino,
++                      struct ext3_allocation_context *ac)
 +{
 +      struct ext3_sb_info *sbi = EXT3_SB(sb);
 +      struct ext3_mb_history h;
@@ -2023,6 +2216,8 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      if (likely(sbi->s_mb_history == NULL))
 +              return;
 +
++      h.pid = current->pid;
++      h.ino = ino;
 +      h.goal = ac->ac_g_ex;
 +      h.result = ac->ac_b_ex;
 +      h.found = ac->ac_found;
@@ -2050,21 +2245,40 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +int ext3_mb_init_backend(struct super_block *sb)
 +{
 +      struct ext3_sb_info *sbi = EXT3_SB(sb);
-+      int i, len;
-+
-+      len = sizeof(struct ext3_buddy_group_blocks *) * sbi->s_groups_count;
-+      sbi->s_group_info = kmalloc(len, GFP_KERNEL);
++      int i, j, len, metalen;
++      int num_meta_group_infos =
++              (sbi->s_groups_count + EXT3_DESC_PER_BLOCK(sb) - 1) >>
++                      EXT3_DESC_PER_BLOCK_BITS(sb);
++      struct ext3_group_info **meta_group_info;
++
++      /* An 8TB filesystem with 64-bit pointers requires a 4096 byte
++       * kmalloc. A 128kb malloc should suffice for a 256TB filesystem.
++       * So a two level scheme suffices for now. */
++      sbi->s_group_info = kmalloc(sizeof(*sbi->s_group_info) *
++                                  num_meta_group_infos, GFP_KERNEL);
 +      if (sbi->s_group_info == NULL) {
-+              printk(KERN_ERR "EXT3-fs: can't allocate mem for buddy\n");
++              printk(KERN_ERR "EXT3-fs: can't allocate buddy meta group\n");
 +              return -ENOMEM;
 +      }
-+      memset(sbi->s_group_info, 0, len);
-+
 +      sbi->s_buddy_cache = new_inode(sb);
 +      if (sbi->s_buddy_cache == NULL) {
 +              printk(KERN_ERR "EXT3-fs: can't get new inode\n");
-+              kfree(sbi->s_group_info);
-+              return -ENOMEM;
++              goto err_freesgi;
++      }
++
++      metalen = sizeof(*meta_group_info) << EXT3_DESC_PER_BLOCK_BITS(sb);
++      for (i = 0; i < num_meta_group_infos; i++) {
++              if ((i + 1) == num_meta_group_infos)
++                      metalen = sizeof(*meta_group_info) *
++                              (sbi->s_groups_count -
++                                      (i << EXT3_DESC_PER_BLOCK_BITS(sb)));
++              meta_group_info = kmalloc(metalen, GFP_KERNEL);
++              if (meta_group_info == NULL) {
++                      printk(KERN_ERR "EXT3-fs: can't allocate mem for a "
++                             "buddy group\n");
++                      goto err_freemeta;
++              }
++              sbi->s_group_info[i] = meta_group_info;
 +      }
 +
 +      /* 
@@ -2076,30 +2290,42 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      for (i = 0; i < sbi->s_groups_count; i++) {
 +              struct ext3_group_desc * desc;
 +
-+              sbi->s_group_info[i] = kmalloc(len, GFP_KERNEL);
-+              if (sbi->s_group_info[i] == NULL) {
++              meta_group_info =
++                      sbi->s_group_info[i >> EXT3_DESC_PER_BLOCK_BITS(sb)];
++              j = i & (EXT3_DESC_PER_BLOCK(sb) - 1);
++
++              meta_group_info[j] = kmalloc(len, GFP_KERNEL);
++              if (meta_group_info[j] == NULL) {
 +                      printk(KERN_ERR "EXT3-fs: can't allocate buddy mem\n");
-+                      goto err_out;
++                      i--;
++                      goto err_freebuddy;
 +              }
 +              desc = ext3_get_group_desc(sb, i, NULL);
 +              if (desc == NULL) {
 +                      printk(KERN_ERR"EXT3-fs: can't read descriptor %u\n",i);
-+                      goto err_out;
++                      goto err_freebuddy;
 +              }
-+              memset(sbi->s_group_info[i], 0, len);
++              memset(meta_group_info[j], 0, len);
 +              set_bit(EXT3_GROUP_INFO_NEED_INIT_BIT,
-+                      &sbi->s_group_info[i]->bb_state);
-+              sbi->s_group_info[i]->bb_free =
++                      &meta_group_info[j]->bb_state);
++              meta_group_info[j]->bb_free =
 +                      le16_to_cpu(desc->bg_free_blocks_count);
 +      }
 +
 +      return 0;
 +
-+err_out:
++err_freebuddy:
++      while (i >= 0) {
++              kfree(EXT3_GROUP_INFO(sb, i));
++              i--;
++      }
++      i = num_meta_group_infos;
++err_freemeta:
 +      while (--i >= 0)
 +              kfree(sbi->s_group_info[i]);
 +      iput(sbi->s_buddy_cache);
-+
++err_freesgi:
++      kfree(sbi->s_group_info);
 +      return -ENOMEM;
 +}
 +
@@ -2141,7 +2367,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +              max = max >> 1;
 +              i++;
 +      } while (i <= sb->s_blocksize_bits + 1);
-+      
++
 +
 +      /* init file for buddy data */
 +      if ((i = ext3_mb_init_backend(sb))) {
@@ -2178,8 +2404,8 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +int ext3_mb_release(struct super_block *sb)
 +{
 +      struct ext3_sb_info *sbi = EXT3_SB(sb);
-+      int i;
-+      
++      int i, num_meta_group_infos;
++
 +      if (!test_opt(sb, MBALLOC))
 +              return 0;
 +
@@ -2193,11 +2419,13 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      ext3_mb_free_committed_blocks(sb);
 +
 +      if (sbi->s_group_info) {
-+              for (i = 0; i < sbi->s_groups_count; i++) {
-+                      if (sbi->s_group_info[i] == NULL)
-+                              continue;
++              for (i = 0; i < sbi->s_groups_count; i++)
++                      kfree(EXT3_GROUP_INFO(sb, i));
++              num_meta_group_infos = (sbi->s_groups_count +
++                      EXT3_DESC_PER_BLOCK(sb) - 1) >>
++                      EXT3_DESC_PER_BLOCK_BITS(sb);
++              for (i = 0; i < num_meta_group_infos; i++)
 +                      kfree(sbi->s_group_info[i]);
-+              }
 +              kfree(sbi->s_group_info);
 +      }
 +      if (sbi->s_mb_offsets)
@@ -2491,7 +2719,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +              cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) + count);
 +      spin_unlock(sb_bgl_lock(sbi, block_group));
 +      percpu_counter_mod(&sbi->s_freeblocks_counter, count);
-+      
++
 +      ext3_mb_release_desc(&e3b);
 +
 +      *freed = count;
@@ -2574,10 +2802,11 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      return;
 +}
 +
-+#define EXT3_ROOT                 "ext3"
-+#define EXT3_MB_STATS_NAME        "mb_stats"
++#define EXT3_ROOT                "ext3"
++#define EXT3_MB_STATS_NAME       "mb_stats"
 +#define EXT3_MB_MAX_TO_SCAN_NAME  "mb_max_to_scan"
 +#define EXT3_MB_MIN_TO_SCAN_NAME  "mb_min_to_scan"
++#define EXT3_MB_ORDER2_REQ       "mb_order2_req"
 +
 +static int ext3_mb_stats_read(char *page, char **start, off_t off,
 +              int count, int *eof, void *data)
@@ -2665,6 +2894,45 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      return len;
 +}
 +
++static int ext3_mb_order2_req_write(struct file *file, const char *buffer,
++              unsigned long count, void *data)
++{
++      char str[32];
++      long value;
++
++      if (count >= sizeof(str)) {
++              printk(KERN_ERR "EXT3-fs: %s string too long, max %u bytes\n",
++                     EXT3_MB_MIN_TO_SCAN_NAME, (int)sizeof(str));
++              return -EOVERFLOW;
++      }
++
++      if (copy_from_user(str, buffer, count))
++              return -EFAULT;
++
++      /* Only set to 0 or 1 respectively; zero->0; non-zero->1 */
++      value = simple_strtol(str, NULL, 0);
++      if (value <= 0)
++              return -ERANGE;
++
++      ext3_mb_order2_reqs = value;    
++
++      return count;
++}
++
++static int ext3_mb_order2_req_read(char *page, char **start, off_t off,
++              int count, int *eof, void *data)
++{
++      int len;
++
++      *eof = 1;
++      if (off != 0)
++              return 0;
++
++      len = sprintf(page, "%ld\n", ext3_mb_order2_reqs);
++      *start = page;
++      return len;
++}
++
 +static int ext3_mb_min_to_scan_write(struct file *file, const char *buffer,
 +              unsigned long count, void *data)
 +{
@@ -2695,6 +2963,7 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      struct proc_dir_entry *proc_ext3_mb_stats;
 +      struct proc_dir_entry *proc_ext3_mb_max_to_scan;
 +      struct proc_dir_entry *proc_ext3_mb_min_to_scan;
++      struct proc_dir_entry *proc_ext3_mb_order2_req;
 +
 +      proc_root_ext3 = proc_mkdir(EXT3_ROOT, proc_root_fs);
 +      if (proc_root_ext3 == NULL) {
@@ -2749,6 +3018,24 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      proc_ext3_mb_min_to_scan->read_proc  = ext3_mb_min_to_scan_read;
 +      proc_ext3_mb_min_to_scan->write_proc = ext3_mb_min_to_scan_write;
 +
++      /* Initialize EXT3_ORDER2_REQ */
++      proc_ext3_mb_order2_req = create_proc_entry(
++                      EXT3_MB_ORDER2_REQ,
++                      S_IFREG | S_IRUGO | S_IWUSR, proc_root_ext3);
++      if (proc_ext3_mb_order2_req == NULL) {
++              printk(KERN_ERR "EXT3-fs: Unable to create %s\n",
++                              EXT3_MB_ORDER2_REQ);
++              remove_proc_entry(EXT3_MB_MIN_TO_SCAN_NAME, proc_root_ext3);
++              remove_proc_entry(EXT3_MB_MAX_TO_SCAN_NAME, proc_root_ext3);
++              remove_proc_entry(EXT3_MB_STATS_NAME, proc_root_ext3);
++              remove_proc_entry(EXT3_ROOT, proc_root_fs);
++              return -EIO;
++      }
++
++      proc_ext3_mb_order2_req->data = NULL;
++      proc_ext3_mb_order2_req->read_proc  = ext3_mb_order2_req_read;
++      proc_ext3_mb_order2_req->write_proc = ext3_mb_order2_req_write;
++
 +      return 0;
 +}
 +
@@ -2757,13 +3044,14 @@ Index: linux-2.6.12.6/fs/ext3/mballoc.c
 +      remove_proc_entry(EXT3_MB_STATS_NAME, proc_root_ext3);
 +      remove_proc_entry(EXT3_MB_MAX_TO_SCAN_NAME, proc_root_ext3);
 +      remove_proc_entry(EXT3_MB_MIN_TO_SCAN_NAME, proc_root_ext3);
++      remove_proc_entry(EXT3_MB_ORDER2_REQ, proc_root_ext3);
 +      remove_proc_entry(EXT3_ROOT, proc_root_fs);
 +}
-Index: linux-2.6.12.6/fs/ext3/Makefile
+Index: linux-2.6.12.6-bull/fs/ext3/Makefile
 ===================================================================
---- linux-2.6.12.6.orig/fs/ext3/Makefile       2005-12-17 02:17:16.000000000 +0300
-+++ linux-2.6.12.6/fs/ext3/Makefile    2005-12-17 02:21:21.000000000 +0300
-@@ -6,7 +6,7 @@
+--- linux-2.6.12.6-bull.orig/fs/ext3/Makefile  2006-04-29 20:39:09.000000000 +0400
++++ linux-2.6.12.6-bull/fs/ext3/Makefile       2006-04-29 20:39:10.000000000 +0400
+@@ -6,7 +6,7 @@ obj-$(CONFIG_EXT3_FS) += ext3.o
  
  ext3-y        := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
           ioctl.o namei.o super.o symlink.o hash.o resize.o \
diff --git a/lustre/kernel_patches/patches/ext3-mballoc2-2.6.18-vanilla.patch b/lustre/kernel_patches/patches/ext3-mballoc2-2.6.18-vanilla.patch
new file mode 100644 (file)
index 0000000..0040a6f
--- /dev/null
@@ -0,0 +1,2810 @@
+Index: linux-stage/fs/ext3/mballoc.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-stage/fs/ext3/mballoc.c      2006-07-16 02:29:49.000000000 +0800
+@@ -0,0 +1,2434 @@
++/*
++ * Copyright (c) 2003-2005, Cluster File Systems, Inc, info@clusterfs.com
++ * Written by Alex Tomas <alex@clusterfs.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public Licens
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-
++ */
++
++
++/*
++ * mballoc.c contains the multiblocks allocation routines
++ */
++
++#include <linux/config.h>
++#include <linux/time.h>
++#include <linux/fs.h>
++#include <linux/namei.h>
++#include <linux/jbd.h>
++#include <linux/ext3_fs.h>
++#include <linux/ext3_jbd.h>
++#include <linux/quotaops.h>
++#include <linux/buffer_head.h>
++#include <linux/module.h>
++#include <linux/swap.h>
++#include <linux/proc_fs.h>
++#include <linux/pagemap.h>
++#include <linux/seq_file.h>
++
++/*
++ * TODO:
++ *   - bitmap read-ahead (proposed by Oleg Drokin aka green)
++ *   - track min/max extents in each group for better group selection
++ *   - mb_mark_used() may allocate chunk right after splitting buddy
++ *   - special flag to advice allocator to look for requested + N blocks
++ *     this may improve interaction between extents and mballoc
++ *   - tree of groups sorted by number of free blocks
++ *   - percpu reservation code (hotpath)
++ *   - error handling
++ */
++
++/*
++ * with AGRESSIVE_CHECK allocator runs consistency checks over
++ * structures. these checks slow things down a lot
++ */
++#define AGGRESSIVE_CHECK__
++
++/*
++ */
++#define MB_DEBUG__
++#ifdef MB_DEBUG
++#define mb_debug(fmt,a...)    printk(fmt, ##a)
++#else
++#define mb_debug(fmt,a...)
++#endif
++
++/*
++ * with EXT3_MB_HISTORY mballoc stores last N allocations in memory
++ * and you can monitor it in /proc/fs/ext3/<dev>/mb_history
++ */
++#define EXT3_MB_HISTORY
++
++/*
++ * How long mballoc can look for a best extent (in found extents)
++ */
++long ext3_mb_max_to_scan = 500;
++
++/*
++ * How long mballoc must look for a best extent
++ */
++long ext3_mb_min_to_scan = 30;
++
++/*
++ * with 'ext3_mb_stats' allocator will collect stats that will be
++ * shown at umount. The collecting costs though!
++ */
++
++long ext3_mb_stats = 1;
++
++#ifdef EXT3_BB_MAX_BLOCKS
++#undef EXT3_BB_MAX_BLOCKS
++#endif
++#define EXT3_BB_MAX_BLOCKS    30
++
++struct ext3_free_metadata {
++      unsigned short group;
++      unsigned short num;
++      unsigned short blocks[EXT3_BB_MAX_BLOCKS];
++      struct list_head list;
++};
++
++struct ext3_group_info {
++      unsigned long   bb_state;
++      unsigned long   bb_tid;
++      struct ext3_free_metadata *bb_md_cur;
++      unsigned short  bb_first_free;
++      unsigned short  bb_free;
++      unsigned short  bb_fragments;
++      unsigned short  bb_counters[];
++};
++
++
++#define EXT3_GROUP_INFO_NEED_INIT_BIT 0
++#define EXT3_GROUP_INFO_LOCKED_BIT    1
++
++#define EXT3_MB_GRP_NEED_INIT(grp)    \
++      (test_bit(EXT3_GROUP_INFO_NEED_INIT_BIT, &(grp)->bb_state))
++
++struct ext3_free_extent {
++      __u16 fe_start;
++      __u16 fe_len;
++      __u16 fe_group;
++};
++
++struct ext3_allocation_context {
++      struct super_block *ac_sb;
++
++      /* search goals */
++      struct ext3_free_extent ac_g_ex;
++      
++      /* the best found extent */
++      struct ext3_free_extent ac_b_ex;
++      
++      /* number of iterations done. we have to track to limit searching */
++      unsigned long ac_ex_scanned;
++      __u16 ac_groups_scanned;
++      __u16 ac_found;
++      __u16 ac_tail;
++      __u16 ac_buddy;
++      __u8 ac_status; 
++      __u8 ac_flags;          /* allocation hints */
++      __u8 ac_criteria;
++      __u8 ac_repeats;
++      __u8 ac_2order;         /* if request is to allocate 2^N blocks and
++                               * N > 0, the field stores N, otherwise 0 */
++};
++
++#define AC_STATUS_CONTINUE    1
++#define AC_STATUS_FOUND               2
++#define AC_STATUS_BREAK               3
++
++struct ext3_mb_history {
++      struct ext3_free_extent goal;   /* goal allocation */
++      struct ext3_free_extent result; /* result allocation */
++      __u16 found;    /* how many extents have been found */
++      __u16 groups;   /* how many groups have been scanned */
++      __u16 tail;     /* what tail broke some buddy */
++      __u16 buddy;    /* buddy the tail ^^^ broke */
++      __u8 cr;        /* which phase the result extent was found at */
++      __u8 merged;
++};
++
++struct ext3_buddy {
++      struct page *bd_buddy_page;
++      void *bd_buddy;
++      struct page *bd_bitmap_page;
++      void *bd_bitmap;
++      struct ext3_group_info *bd_info;
++      struct super_block *bd_sb;
++      __u16 bd_blkbits;
++      __u16 bd_group;
++};
++#define EXT3_MB_BITMAP(e3b)   ((e3b)->bd_bitmap)
++#define EXT3_MB_BUDDY(e3b)    ((e3b)->bd_buddy)
++
++#ifndef EXT3_MB_HISTORY
++#define ext3_mb_store_history(sb,ac)
++#else
++static void ext3_mb_store_history(struct super_block *,
++                              struct ext3_allocation_context *ac);
++#endif
++
++#define in_range(b, first, len)       ((b) >= (first) && (b) <= (first) + (len) - 1)
++
++static struct proc_dir_entry *proc_root_ext3;
++
++int ext3_create (struct inode *, struct dentry *, int, struct nameidata *);
++struct buffer_head * read_block_bitmap(struct super_block *, unsigned int);
++int ext3_new_block_old(handle_t *, struct inode *, unsigned long, int *);
++int ext3_mb_reserve_blocks(struct super_block *, int);
++void ext3_mb_release_blocks(struct super_block *, int);
++void ext3_mb_poll_new_transaction(struct super_block *, handle_t *);
++void ext3_mb_free_committed_blocks(struct super_block *);
++
++#if BITS_PER_LONG == 64
++#define mb_correct_addr_and_bit(bit,addr)             \
++{                                                     \
++      bit += ((unsigned long) addr & 7UL) << 3;       \
++      addr = (void *) ((unsigned long) addr & ~7UL);  \
++}
++#elif BITS_PER_LONG == 32
++#define mb_correct_addr_and_bit(bit,addr)             \
++{                                                     \
++      bit += ((unsigned long) addr & 3UL) << 3;       \
++      addr = (void *) ((unsigned long) addr & ~3UL);  \
++}
++#else
++#error "how many bits you are?!"
++#endif
++
++static inline int mb_test_bit(int bit, void *addr)
++{
++      mb_correct_addr_and_bit(bit,addr);
++      return ext2_test_bit(bit, addr);
++}
++
++static inline void mb_set_bit(int bit, void *addr)
++{
++      mb_correct_addr_and_bit(bit,addr);
++      ext2_set_bit(bit, addr);
++}
++
++static inline void mb_set_bit_atomic(int bit, void *addr)
++{
++      mb_correct_addr_and_bit(bit,addr);
++      ext2_set_bit_atomic(NULL, bit, addr);
++}
++
++static inline void mb_clear_bit(int bit, void *addr)
++{
++      mb_correct_addr_and_bit(bit,addr);
++      ext2_clear_bit(bit, addr);
++}
++
++static inline void mb_clear_bit_atomic(int bit, void *addr)
++{
++      mb_correct_addr_and_bit(bit,addr);
++      ext2_clear_bit_atomic(NULL, bit, addr);
++}
++
++static inline int mb_find_next_zero_bit(void *addr, int max, int start)
++{
++      int fix;
++#if BITS_PER_LONG == 64
++      fix = ((unsigned long) addr & 7UL) << 3;
++      addr = (void *) ((unsigned long) addr & ~7UL);
++#elif BITS_PER_LONG == 32
++      fix = ((unsigned long) addr & 3UL) << 3;
++      addr = (void *) ((unsigned long) addr & ~3UL);
++#else
++#error "how many bits you are?!"
++#endif
++      max += fix;
++      start += fix;
++      return ext2_find_next_zero_bit(addr, max, start) - fix;
++}
++
++static inline void *mb_find_buddy(struct ext3_buddy *e3b, int order, int *max)
++{
++      char *bb;
++
++      J_ASSERT(EXT3_MB_BITMAP(e3b) != EXT3_MB_BUDDY(e3b));
++      J_ASSERT(max != NULL);
++
++      if (order > e3b->bd_blkbits + 1) {
++              *max = 0;
++              return NULL;
++      }
++
++      /* at order 0 we see each particular block */
++      *max = 1 << (e3b->bd_blkbits + 3);
++      if (order == 0)
++              return EXT3_MB_BITMAP(e3b);
++
++      bb = EXT3_MB_BUDDY(e3b) + EXT3_SB(e3b->bd_sb)->s_mb_offsets[order];
++      *max = EXT3_SB(e3b->bd_sb)->s_mb_maxs[order];
++
++      return bb;
++}
++
++#ifdef AGGRESSIVE_CHECK
++
++static void mb_check_buddy(struct ext3_buddy *e3b)
++{
++      int order = e3b->bd_blkbits + 1;
++      int max, max2, i, j, k, count;
++      int fragments = 0, fstart;
++      void *buddy, *buddy2;
++
++      if (!test_opt(e3b->bd_sb, MBALLOC))
++              return;
++
++      {
++              static int mb_check_counter = 0;
++              if (mb_check_counter++ % 300 != 0)
++                      return;
++      }
++      
++      while (order > 1) {
++              buddy = mb_find_buddy(e3b, order, &max);
++              J_ASSERT(buddy);
++              buddy2 = mb_find_buddy(e3b, order - 1, &max2);
++              J_ASSERT(buddy2);
++              J_ASSERT(buddy != buddy2);
++              J_ASSERT(max * 2 == max2);
++
++              count = 0;
++              for (i = 0; i < max; i++) {
++
++                      if (mb_test_bit(i, buddy)) {
++                              /* only single bit in buddy2 may be 1 */
++                              if (!mb_test_bit(i << 1, buddy2))
++                                      J_ASSERT(mb_test_bit((i<<1)+1, buddy2));
++                              else if (!mb_test_bit((i << 1) + 1, buddy2))
++                                      J_ASSERT(mb_test_bit(i << 1, buddy2));
++                              continue;
++                      }
++
++                      /* both bits in buddy2 must be 0 */
++                      J_ASSERT(mb_test_bit(i << 1, buddy2));
++                      J_ASSERT(mb_test_bit((i << 1) + 1, buddy2));
++
++                      for (j = 0; j < (1 << order); j++) {
++                              k = (i * (1 << order)) + j;
++                              J_ASSERT(!mb_test_bit(k, EXT3_MB_BITMAP(e3b)));
++                      }
++                      count++;
++              }
++              J_ASSERT(e3b->bd_info->bb_counters[order] == count);
++              order--;
++      }
++
++      fstart = -1;
++      buddy = mb_find_buddy(e3b, 0, &max);
++      for (i = 0; i < max; i++) {
++              if (!mb_test_bit(i, buddy)) {
++                      J_ASSERT(i >= e3b->bd_info->bb_first_free);
++                      if (fstart == -1) {
++                              fragments++;
++                              fstart = i;
++                      }
++                      continue;
++              }
++              fstart = -1;
++              /* check used bits only */
++              for (j = 0; j < e3b->bd_blkbits + 1; j++) {
++                      buddy2 = mb_find_buddy(e3b, j, &max2);
++                      k = i >> j;
++                      J_ASSERT(k < max2);
++                      J_ASSERT(mb_test_bit(k, buddy2));
++              }
++      }
++      J_ASSERT(!EXT3_MB_GRP_NEED_INIT(e3b->bd_info));
++      J_ASSERT(e3b->bd_info->bb_fragments == fragments);
++}
++
++#else
++#define mb_check_buddy(e3b)
++#endif
++
++/* find most significant bit */
++static int inline fmsb(unsigned short word)
++{
++      int order;
++
++      if (word > 255) {
++              order = 7;
++              word >>= 8;
++      } else {
++              order = -1;
++      }
++
++      do {
++              order++;
++              word >>= 1;
++      } while (word != 0);
++
++      return order;
++}
++
++static void inline
++ext3_mb_mark_free_simple(struct super_block *sb, void *buddy, unsigned first,
++                              int len, struct ext3_group_info *grp)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      unsigned short min, max, chunk, border;
++
++      mb_debug("mark %u/%u free\n", first, len);
++      J_ASSERT(len < EXT3_BLOCKS_PER_GROUP(sb));
++
++      border = 2 << sb->s_blocksize_bits;
++
++      while (len > 0) {
++              /* find how many blocks can be covered since this position */
++              max = ffs(first | border) - 1;
++
++              /* find how many blocks of power 2 we need to mark */
++              min = fmsb(len);
++
++              mb_debug("  %u/%u -> max %u, min %u\n",
++                      first & ((2 << sb->s_blocksize_bits) - 1),
++                      len, max, min);
++
++              if (max < min)
++                      min = max;
++              chunk = 1 << min;
++
++              /* mark multiblock chunks only */
++              grp->bb_counters[min]++;
++              if (min > 0) {
++                      mb_debug("    set %u at %u \n", first >> min,
++                              sbi->s_mb_offsets[min]);
++                      mb_clear_bit(first >> min, buddy + sbi->s_mb_offsets[min]);
++              }
++
++              len -= chunk;
++              first += chunk;
++      }
++}
++
++static void
++ext3_mb_generate_buddy(struct super_block *sb, void *buddy, void *bitmap,
++                      struct ext3_group_info *grp)
++{
++      unsigned short max = EXT3_BLOCKS_PER_GROUP(sb);
++      unsigned short i = 0, first, len;
++      unsigned free = 0, fragments = 0;
++      unsigned long long period = get_cycles();
++
++      i = mb_find_next_zero_bit(bitmap, max, 0);
++      grp->bb_first_free = i;
++      while (i < max) {
++              fragments++;
++              first = i;
++              i = find_next_bit(bitmap, max, i);
++              len = i - first;
++              free += len;
++              if (len > 1) 
++                      ext3_mb_mark_free_simple(sb, buddy, first, len, grp);
++              else
++                      grp->bb_counters[0]++;
++              if (i < max)
++                      i = mb_find_next_zero_bit(bitmap, max, i);
++      }
++      grp->bb_fragments = fragments;
++
++      /* bb_state shouldn't being modified because all
++       * others waits for init completion on page lock */
++      clear_bit(EXT3_GROUP_INFO_NEED_INIT_BIT, &grp->bb_state);
++      if (free != grp->bb_free) {
++              printk("EXT3-fs: %u blocks in bitmap, %u in group descriptor\n",
++                      free, grp->bb_free);
++              grp->bb_free = free;
++      }
++
++      period = get_cycles() - period;
++      spin_lock(&EXT3_SB(sb)->s_bal_lock);
++      EXT3_SB(sb)->s_mb_buddies_generated++;
++      EXT3_SB(sb)->s_mb_generation_time += period;
++      spin_unlock(&EXT3_SB(sb)->s_bal_lock);
++}
++
++static int ext3_mb_init_cache(struct page *page)
++{
++      int blocksize, blocks_per_page, groups_per_page;
++      int err = 0, i, first_group, first_block;
++      struct super_block *sb;
++      struct buffer_head *bhs;
++      struct buffer_head **bh;
++      struct inode *inode;
++      char *data, *bitmap;
++
++      mb_debug("init page %lu\n", page->index);
++
++      inode = page->mapping->host;
++      sb = inode->i_sb;
++      blocksize = 1 << inode->i_blkbits;
++      blocks_per_page = PAGE_CACHE_SIZE / blocksize;
++      
++      groups_per_page = blocks_per_page >> 1;
++      if (groups_per_page == 0)
++              groups_per_page = 1;
++
++      /* allocate buffer_heads to read bitmaps */
++      if (groups_per_page > 1) {
++              err = -ENOMEM;
++              i = sizeof(struct buffer_head *) * groups_per_page;
++              bh = kmalloc(i, GFP_NOFS);
++              if (bh == NULL)
++                      goto out;
++              memset(bh, 0, i);
++      } else
++              bh = &bhs;
++      
++      first_group = page->index * blocks_per_page / 2;
++      
++      /* read all groups the page covers into the cache */
++      for (i = 0; i < groups_per_page; i++) {
++              struct ext3_group_desc * desc;
++
++              if (first_group + i >= EXT3_SB(sb)->s_groups_count)
++                      break;
++
++              err = -EIO;
++              desc = ext3_get_group_desc(sb, first_group + i, NULL);
++              if (desc == NULL)
++                      goto out;
++
++              err = -ENOMEM;
++              bh[i] = sb_getblk(sb, le32_to_cpu(desc->bg_block_bitmap));
++              if (bh[i] == NULL)
++                      goto out;
++
++              if (buffer_uptodate(bh[i]))
++                      continue;
++
++              lock_buffer(bh[i]);
++              if (buffer_uptodate(bh[i])) {
++                      unlock_buffer(bh[i]);
++                      continue;
++              }
++
++              get_bh(bh[i]);
++              bh[i]->b_end_io = end_buffer_read_sync;
++              submit_bh(READ, bh[i]);
++              mb_debug("read bitmap for group %u\n", first_group + i);
++      }
++
++      /* wait for I/O completion */
++      for (i = 0; i < groups_per_page && bh[i]; i++)
++              wait_on_buffer(bh[i]);
++
++      /* XXX: I/O error handling here */
++
++      first_block = page->index * blocks_per_page;
++      for (i = 0; i < blocks_per_page; i++) {
++              int group;
++
++              group = (first_block + i) >> 1;
++              if (group >= EXT3_SB(sb)->s_groups_count)
++                      break;
++
++              data = page_address(page) + (i * blocksize);
++              bitmap = bh[group - first_group]->b_data;
++
++              if ((first_block + i) & 1) {
++                      /* this is block of buddy */
++                      mb_debug("put buddy for group %u in page %lu/%x\n",
++                              group, page->index, i * blocksize);
++                      memset(data, 0xff, blocksize);
++                      EXT3_SB(sb)->s_group_info[group]->bb_fragments = 0;
++                      memset(EXT3_SB(sb)->s_group_info[group]->bb_counters, 0,
++                              sizeof(unsigned short)*(sb->s_blocksize_bits+2));
++                      ext3_mb_generate_buddy(sb, data, bitmap,
++                                              EXT3_SB(sb)->s_group_info[group]);
++              } else {
++                      /* this is block of bitmap */
++                      mb_debug("put bitmap for group %u in page %lu/%x\n",
++                              group, page->index, i * blocksize);
++                      memcpy(data, bitmap, blocksize);
++              }
++      }
++      SetPageUptodate(page);
++
++out:
++      for (i = 0; i < groups_per_page && bh[i]; i++)
++              brelse(bh[i]);
++      if (bh && bh != &bhs)
++              kfree(bh);
++      return err;
++}
++
++static int ext3_mb_load_buddy(struct super_block *sb, int group,
++              struct ext3_buddy *e3b)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      struct inode *inode = sbi->s_buddy_cache;
++      int blocks_per_page, block, pnum, poff;
++      struct page *page;
++
++      mb_debug("load group %u\n", group);
++
++      blocks_per_page = PAGE_CACHE_SIZE / sb->s_blocksize;
++
++      e3b->bd_blkbits = sb->s_blocksize_bits;
++      e3b->bd_info = sbi->s_group_info[group];
++      e3b->bd_sb = sb;
++      e3b->bd_group = group;
++      e3b->bd_buddy_page = NULL;
++      e3b->bd_bitmap_page = NULL;
++
++      block = group * 2;
++      pnum = block / blocks_per_page;
++      poff = block % blocks_per_page;
++
++      page = find_get_page(inode->i_mapping, pnum);
++      if (page == NULL || !PageUptodate(page)) {
++              if (page)
++                      page_cache_release(page);
++              page = find_or_create_page(inode->i_mapping, pnum, GFP_NOFS);
++              if (page) {
++                      if (!PageUptodate(page))
++                              ext3_mb_init_cache(page);
++                      unlock_page(page);
++              }
++      }
++      if (page == NULL || !PageUptodate(page))
++              goto err;
++      e3b->bd_bitmap_page = page;
++      e3b->bd_bitmap = page_address(page) + (poff * sb->s_blocksize);
++      mark_page_accessed(page);
++
++      block++;
++      pnum = block / blocks_per_page;
++      poff = block % blocks_per_page;
++
++      page = find_get_page(inode->i_mapping, pnum);
++      if (page == NULL || !PageUptodate(page)) {
++              if (page)
++                      page_cache_release(page);
++              page = find_or_create_page(inode->i_mapping, pnum, GFP_NOFS);
++              if (page) {
++                      if (!PageUptodate(page))
++                              ext3_mb_init_cache(page);
++                      unlock_page(page);
++              }
++      }
++      if (page == NULL || !PageUptodate(page))
++              goto err;
++      e3b->bd_buddy_page = page;
++      e3b->bd_buddy = page_address(page) + (poff * sb->s_blocksize);
++      mark_page_accessed(page);
++
++      J_ASSERT(e3b->bd_bitmap_page != NULL);
++      J_ASSERT(e3b->bd_buddy_page != NULL);
++
++      return 0;
++
++err:
++      if (e3b->bd_bitmap_page)
++              page_cache_release(e3b->bd_bitmap_page);
++      if (e3b->bd_buddy_page)
++              page_cache_release(e3b->bd_buddy_page);
++      e3b->bd_buddy = NULL;
++      e3b->bd_bitmap = NULL;
++      return -EIO;
++}
++
++static void ext3_mb_release_desc(struct ext3_buddy *e3b)
++{
++      if (e3b->bd_bitmap_page)
++              page_cache_release(e3b->bd_bitmap_page);
++      if (e3b->bd_buddy_page)
++              page_cache_release(e3b->bd_buddy_page);
++}
++
++
++static inline void
++ext3_lock_group(struct super_block *sb, int group)
++{
++      bit_spin_lock(EXT3_GROUP_INFO_LOCKED_BIT,
++                      &EXT3_SB(sb)->s_group_info[group]->bb_state);
++}
++
++static inline void
++ext3_unlock_group(struct super_block *sb, int group)
++{
++      bit_spin_unlock(EXT3_GROUP_INFO_LOCKED_BIT,
++                      &EXT3_SB(sb)->s_group_info[group]->bb_state);
++}
++
++static int mb_find_order_for_block(struct ext3_buddy *e3b, int block)
++{
++      int order = 1;
++      void *bb;
++
++      J_ASSERT(EXT3_MB_BITMAP(e3b) != EXT3_MB_BUDDY(e3b));
++      J_ASSERT(block < (1 << (e3b->bd_blkbits + 3)));
++
++      bb = EXT3_MB_BUDDY(e3b);
++      while (order <= e3b->bd_blkbits + 1) {
++              block = block >> 1;
++              if (!mb_test_bit(block, bb)) {
++                      /* this block is part of buddy of order 'order' */
++                      return order;
++              }
++              bb += 1 << (e3b->bd_blkbits - order);
++              order++;
++      }
++      return 0;
++}
++
++static inline void mb_clear_bits(void *bm, int cur, int len)
++{
++      __u32 *addr;
++
++      len = cur + len;
++      while (cur < len) {
++              if ((cur & 31) == 0 && (len - cur) >= 32) {
++                      /* fast path: clear whole word at once */
++                      addr = bm + (cur >> 3);
++                      *addr = 0;
++                      cur += 32;
++                      continue;
++              }
++              mb_clear_bit_atomic(cur, bm);
++              cur++;
++      }
++}
++
++static inline void mb_set_bits(void *bm, int cur, int len)
++{
++      __u32 *addr;
++
++      len = cur + len;
++      while (cur < len) {
++              if ((cur & 31) == 0 && (len - cur) >= 32) {
++                      /* fast path: clear whole word at once */
++                      addr = bm + (cur >> 3);
++                      *addr = 0xffffffff;
++                      cur += 32;
++                      continue;
++              }
++              mb_set_bit_atomic(cur, bm);
++              cur++;
++      }
++}
++
++static int mb_free_blocks(struct ext3_buddy *e3b, int first, int count)
++{
++      int block = 0, max = 0, order;
++      void *buddy, *buddy2;
++
++      mb_check_buddy(e3b);
++
++      e3b->bd_info->bb_free += count;
++      if (first < e3b->bd_info->bb_first_free)
++              e3b->bd_info->bb_first_free = first;
++
++      /* let's maintain fragments counter */
++      if (first != 0)
++              block = !mb_test_bit(first - 1, EXT3_MB_BITMAP(e3b));
++      if (first + count < EXT3_SB(e3b->bd_sb)->s_mb_maxs[0])
++              max = !mb_test_bit(first + count, EXT3_MB_BITMAP(e3b));
++      if (block && max)
++              e3b->bd_info->bb_fragments--;
++      else if (!block && !max)
++              e3b->bd_info->bb_fragments++;
++
++      /* let's maintain buddy itself */
++      while (count-- > 0) {
++              block = first++;
++              order = 0;
++
++              J_ASSERT(mb_test_bit(block, EXT3_MB_BITMAP(e3b)));
++              mb_clear_bit(block, EXT3_MB_BITMAP(e3b));
++              e3b->bd_info->bb_counters[order]++;
++
++              /* start of the buddy */
++              buddy = mb_find_buddy(e3b, order, &max);
++
++              do {
++                      block &= ~1UL;
++                      if (mb_test_bit(block, buddy) ||
++                                      mb_test_bit(block + 1, buddy))
++                              break;
++
++                      /* both the buddies are free, try to coalesce them */
++                      buddy2 = mb_find_buddy(e3b, order + 1, &max);
++
++                      if (!buddy2)
++                              break;
++
++                      if (order > 0) {
++                              /* for special purposes, we don't set
++                               * free bits in bitmap */
++                              mb_set_bit(block, buddy);
++                              mb_set_bit(block + 1, buddy);
++                      }
++                      e3b->bd_info->bb_counters[order]--;
++                      e3b->bd_info->bb_counters[order]--;
++
++                      block = block >> 1;
++                      order++;
++                      e3b->bd_info->bb_counters[order]++;
++
++                      mb_clear_bit(block, buddy2);
++                      buddy = buddy2;
++              } while (1);
++      }
++      mb_check_buddy(e3b);
++
++      return 0;
++}
++
++static int mb_find_extent(struct ext3_buddy *e3b, int order, int block,
++                              int needed, struct ext3_free_extent *ex)
++{
++      int next, max, ord;
++      void *buddy;
++
++      J_ASSERT(ex != NULL);
++
++      buddy = mb_find_buddy(e3b, order, &max);
++      J_ASSERT(buddy);
++      J_ASSERT(block < max);
++      if (mb_test_bit(block, buddy)) {
++              ex->fe_len = 0;
++              ex->fe_start = 0;
++              ex->fe_group = 0;
++              return 0;
++      }
++
++      if (likely(order == 0)) {
++              /* find actual order */
++              order = mb_find_order_for_block(e3b, block);
++              block = block >> order;
++      }
++
++      ex->fe_len = 1 << order;
++      ex->fe_start = block << order;
++      ex->fe_group = e3b->bd_group;
++
++      while (needed > ex->fe_len && (buddy = mb_find_buddy(e3b, order, &max))) {
++
++              if (block + 1 >= max)
++                      break;
++
++              next = (block + 1) * (1 << order);
++              if (mb_test_bit(next, EXT3_MB_BITMAP(e3b)))
++                      break;
++
++              ord = mb_find_order_for_block(e3b, next);
++
++              order = ord;
++              block = next >> order;
++              ex->fe_len += 1 << order;
++      }
++
++      J_ASSERT(ex->fe_start + ex->fe_len <= (1 << (e3b->bd_blkbits + 3)));
++      return ex->fe_len;
++}
++
++static int mb_mark_used(struct ext3_buddy *e3b, struct ext3_free_extent *ex)
++{
++      int ord, mlen = 0, max = 0, cur;
++      int start = ex->fe_start;
++      int len = ex->fe_len;
++      unsigned ret = 0;
++      int len0 = len;
++      void *buddy;
++
++      mb_check_buddy(e3b);
++
++      e3b->bd_info->bb_free -= len;
++      if (e3b->bd_info->bb_first_free == start)
++              e3b->bd_info->bb_first_free += len;
++
++      /* let's maintain fragments counter */
++      if (start != 0)
++              mlen = !mb_test_bit(start - 1, EXT3_MB_BITMAP(e3b));
++      if (start + len < EXT3_SB(e3b->bd_sb)->s_mb_maxs[0])
++              max = !mb_test_bit(start + len, EXT3_MB_BITMAP(e3b));
++      if (mlen && max)
++              e3b->bd_info->bb_fragments++;
++      else if (!mlen && !max)
++              e3b->bd_info->bb_fragments--;
++
++      /* let's maintain buddy itself */
++      while (len) {
++              ord = mb_find_order_for_block(e3b, start);
++
++              if (((start >> ord) << ord) == start && len >= (1 << ord)) {
++                      /* the whole chunk may be allocated at once! */
++                      mlen = 1 << ord;
++                      buddy = mb_find_buddy(e3b, ord, &max);
++                      J_ASSERT((start >> ord) < max);
++                      mb_set_bit(start >> ord, buddy);
++                      e3b->bd_info->bb_counters[ord]--;
++                      start += mlen;
++                      len -= mlen;
++                      J_ASSERT(len >= 0);
++                      continue;
++              }
++
++              /* store for history */
++              if (ret == 0)
++                      ret = len | (ord << 16);
++
++              /* we have to split large buddy */
++              J_ASSERT(ord > 0);
++              buddy = mb_find_buddy(e3b, ord, &max);
++              mb_set_bit(start >> ord, buddy);
++              e3b->bd_info->bb_counters[ord]--;
++
++              ord--;
++              cur = (start >> ord) & ~1U;
++              buddy = mb_find_buddy(e3b, ord, &max);
++              mb_clear_bit(cur, buddy);
++              mb_clear_bit(cur + 1, buddy);
++              e3b->bd_info->bb_counters[ord]++;
++              e3b->bd_info->bb_counters[ord]++;
++      }
++
++      /* now drop all the bits in bitmap */
++      mb_set_bits(EXT3_MB_BITMAP(e3b), ex->fe_start, len0);
++
++      mb_check_buddy(e3b);
++
++      return ret;
++}
++
++/*
++ * Must be called under group lock!
++ */
++static void ext3_mb_use_best_found(struct ext3_allocation_context *ac,
++                                      struct ext3_buddy *e3b)
++{
++      unsigned long ret;
++
++      ac->ac_b_ex.fe_len = min(ac->ac_b_ex.fe_len, ac->ac_g_ex.fe_len);
++      ret = mb_mark_used(e3b, &ac->ac_b_ex);
++
++      ac->ac_status = AC_STATUS_FOUND;
++      ac->ac_tail = ret & 0xffff;
++      ac->ac_buddy = ret >> 16;
++}
++
++/*
++ * The routine checks whether found extent is good enough. If it is,
++ * then the extent gets marked used and flag is set to the context
++ * to stop scanning. Otherwise, the extent is compared with the
++ * previous found extent and if new one is better, then it's stored
++ * in the context. Later, the best found extent will be used, if
++ * mballoc can't find good enough extent.
++ *
++ * FIXME: real allocation policy is to be designed yet!
++ */
++static void ext3_mb_measure_extent(struct ext3_allocation_context *ac,
++                                      struct ext3_free_extent *ex,
++                                      struct ext3_buddy *e3b)
++{
++      struct ext3_free_extent *bex = &ac->ac_b_ex;
++      struct ext3_free_extent *gex = &ac->ac_g_ex;
++
++      J_ASSERT(ex->fe_len > 0);
++      J_ASSERT(ex->fe_len < (1 << ac->ac_sb->s_blocksize_bits) * 8);
++      J_ASSERT(ex->fe_start < (1 << ac->ac_sb->s_blocksize_bits) * 8);
++
++      ac->ac_found++;
++
++      /*
++       * The special case - take what you catch first
++       */
++      if (unlikely(ac->ac_flags & EXT3_MB_HINT_FIRST)) {
++              *bex = *ex;
++              ext3_mb_use_best_found(ac, e3b);
++              return;
++      }
++
++      /*
++       * Let's check whether the chuck is good enough
++       */
++      if (ex->fe_len == gex->fe_len) {
++              *bex = *ex;
++              ext3_mb_use_best_found(ac, e3b);
++              return;
++      }
++
++      /*
++       * If this is first found extent, just store it in the context
++       */
++      if (bex->fe_len == 0) {
++              *bex = *ex;
++              return;
++      }
++
++      /*
++       * If new found extent is better, store it in the context
++       */
++      if (bex->fe_len < gex->fe_len) {
++              /* if the request isn't satisfied, any found extent
++               * larger than previous best one is better */
++              if (ex->fe_len > bex->fe_len)
++                      *bex = *ex;
++      } else if (ex->fe_len > gex->fe_len) {
++              /* if the request is satisfied, then we try to find
++               * an extent that still satisfy the request, but is
++               * smaller than previous one */
++              *bex = *ex;
++      }
++
++      /*
++       * Let's scan at least few extents and don't pick up a first one
++       */
++      if (bex->fe_len > gex->fe_len && ac->ac_found > ext3_mb_min_to_scan)
++              ac->ac_status = AC_STATUS_BREAK;
++
++      /*
++       * We don't want to scan for a whole year
++       */
++      if (ac->ac_found > ext3_mb_max_to_scan)
++              ac->ac_status = AC_STATUS_BREAK;
++}
++
++static int ext3_mb_try_best_found(struct ext3_allocation_context *ac,
++                                      struct ext3_buddy *e3b)
++{
++      struct ext3_free_extent ex = ac->ac_b_ex;
++      int group = ex.fe_group, max, err;
++
++      J_ASSERT(ex.fe_len > 0);
++      err = ext3_mb_load_buddy(ac->ac_sb, group, e3b);
++      if (err)
++              return err;
++
++      ext3_lock_group(ac->ac_sb, group);
++      max = mb_find_extent(e3b, 0, ex.fe_start, ex.fe_len, &ex);
++      
++      if (max > 0) {
++              ac->ac_b_ex = ex;
++              ext3_mb_use_best_found(ac, e3b);
++      }
++
++      ext3_unlock_group(ac->ac_sb, group);
++
++      ext3_mb_release_desc(e3b);
++
++      return 0;
++}
++
++static int ext3_mb_find_by_goal(struct ext3_allocation_context *ac,
++                              struct ext3_buddy *e3b)
++{
++      int group = ac->ac_g_ex.fe_group, max, err;
++      struct ext3_free_extent ex;
++
++      err = ext3_mb_load_buddy(ac->ac_sb, group, e3b);
++      if (err)
++              return err;
++
++      ext3_lock_group(ac->ac_sb, group);
++      max = mb_find_extent(e3b, 0, ac->ac_g_ex.fe_start,
++                              ac->ac_g_ex.fe_len, &ex);
++      
++      if (max > 0) {
++              J_ASSERT(ex.fe_len > 0);
++              J_ASSERT(ex.fe_group == ac->ac_g_ex.fe_group);
++              J_ASSERT(ex.fe_start == ac->ac_g_ex.fe_start);
++              ac->ac_found++;
++              ac->ac_b_ex = ex;
++              ext3_mb_use_best_found(ac, e3b);
++      }
++      ext3_unlock_group(ac->ac_sb, group);
++
++      ext3_mb_release_desc(e3b);
++
++      return 0;
++}
++
++/*
++ * The routine scans buddy structures (not bitmap!) from given order
++ * to max order and tries to find big enough chunk to satisfy the req
++ */
++static void ext3_mb_simple_scan_group(struct ext3_allocation_context *ac,
++                                      struct ext3_buddy *e3b)
++{
++      struct super_block *sb = ac->ac_sb;
++      struct ext3_group_info *grp = e3b->bd_info;
++      void *buddy;
++      int i, k, max;
++
++      J_ASSERT(ac->ac_2order > 0);
++      for (i = ac->ac_2order; i < sb->s_blocksize_bits + 1; i++) {
++              if (grp->bb_counters[i] == 0)
++                      continue;
++
++              buddy = mb_find_buddy(e3b, i, &max);
++              if (buddy == NULL) {
++                      printk(KERN_ALERT "looking for wrong order?\n");
++                      break;
++              }
++
++              k = mb_find_next_zero_bit(buddy, max, 0);
++              J_ASSERT(k < max);
++
++              ac->ac_found++;
++
++              ac->ac_b_ex.fe_len = 1 << i;
++              ac->ac_b_ex.fe_start = k << i;
++              ac->ac_b_ex.fe_group = e3b->bd_group;
++              
++              ext3_mb_use_best_found(ac, e3b);
++              J_ASSERT(ac->ac_b_ex.fe_len == ac->ac_g_ex.fe_len);
++
++              if (unlikely(ext3_mb_stats))
++                      atomic_inc(&EXT3_SB(sb)->s_bal_2orders);
++
++              break;
++      }
++}
++
++/*
++ * The routine scans the group and measures all found extents.
++ * In order to optimize scanning, caller must pass number of
++ * free blocks in the group, so the routine can know upper limit.
++ */
++static void ext3_mb_complex_scan_group(struct ext3_allocation_context *ac,
++                                      struct ext3_buddy *e3b)
++{
++      struct super_block *sb = ac->ac_sb;
++      void *bitmap = EXT3_MB_BITMAP(e3b);
++      struct ext3_free_extent ex;
++      int i, free;
++
++      free = e3b->bd_info->bb_free;
++      J_ASSERT(free > 0);
++
++      i = e3b->bd_info->bb_first_free;
++
++      while (free && ac->ac_status == AC_STATUS_CONTINUE) {
++              i = mb_find_next_zero_bit(bitmap, sb->s_blocksize * 8, i);
++              if (i >= sb->s_blocksize * 8) {
++                      J_ASSERT(free == 0);
++                      break;
++              }
++
++              mb_find_extent(e3b, 0, i, ac->ac_g_ex.fe_len, &ex);
++              J_ASSERT(ex.fe_len > 0);
++              J_ASSERT(free >= ex.fe_len);
++
++              ext3_mb_measure_extent(ac, &ex, e3b);
++
++              i += ex.fe_len;
++              free -= ex.fe_len;
++      }
++}
++
++static int ext3_mb_good_group(struct ext3_allocation_context *ac,
++                              int group, int cr)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(ac->ac_sb);
++      struct ext3_group_info *grp = sbi->s_group_info[group];
++      unsigned free, fragments, i, bits;
++
++      J_ASSERT(cr >= 0 && cr < 4);
++      J_ASSERT(!EXT3_MB_GRP_NEED_INIT(grp));
++
++      free = grp->bb_free;
++      fragments = grp->bb_fragments;
++      if (free == 0)
++              return 0;
++      if (fragments == 0)
++              return 0;
++
++      switch (cr) {
++              case 0:
++                      J_ASSERT(ac->ac_2order != 0);
++                      bits = ac->ac_sb->s_blocksize_bits + 1;
++                      for (i = ac->ac_2order; i < bits; i++)
++                              if (grp->bb_counters[i] > 0)
++                                      return 1;
++              case 1:
++                      if ((free / fragments) >= ac->ac_g_ex.fe_len)
++                              return 1;
++              case 2:
++                      if (free >= ac->ac_g_ex.fe_len)
++                              return 1;
++              case 3:
++                      return 1;
++              default:
++                      BUG();
++      }
++
++      return 0;
++}
++
++int ext3_mb_new_blocks(handle_t *handle, struct inode *inode,
++                     unsigned long goal, int *len, int flags, int *errp)
++{
++      struct buffer_head *bitmap_bh = NULL;
++      struct ext3_allocation_context ac;
++      int i, group, block, cr, err = 0;
++      struct ext3_group_desc *gdp;
++      struct ext3_super_block *es;
++      struct buffer_head *gdp_bh;
++      struct ext3_sb_info *sbi;
++      struct super_block *sb;
++      struct ext3_buddy e3b;
++
++      J_ASSERT(len != NULL);
++      J_ASSERT(*len > 0);
++
++      sb = inode->i_sb;
++      if (!sb) {
++              printk("ext3_mb_new_nblocks: nonexistent device");
++              return 0;
++      }
++
++      if (!test_opt(sb, MBALLOC)) {
++              static int ext3_mballoc_warning = 0;
++              if (ext3_mballoc_warning == 0) {
++                      printk(KERN_ERR "EXT3-fs: multiblock request with "
++                              "mballoc disabled!\n");
++                      ext3_mballoc_warning++;
++              }
++              *len = 1;
++              err = ext3_new_block_old(handle, inode, goal, errp);
++              return err;
++      }
++
++      ext3_mb_poll_new_transaction(sb, handle);
++
++      sbi = EXT3_SB(sb);
++      es = EXT3_SB(sb)->s_es;
++
++      /*
++       * We can't allocate > group size
++       */
++      if (*len >= EXT3_BLOCKS_PER_GROUP(sb) - 10)
++              *len = EXT3_BLOCKS_PER_GROUP(sb) - 10;
++
++      if (!(flags & EXT3_MB_HINT_RESERVED)) {
++              /* someone asks for non-reserved blocks */
++              BUG_ON(*len > 1);
++              err = ext3_mb_reserve_blocks(sb, 1);
++              if (err) {
++                      *errp = err;
++                      return 0;
++              }
++      }
++
++      /*
++       * Check quota for allocation of this blocks.
++       */
++      while (*len && DQUOT_ALLOC_BLOCK(inode, *len))
++              *len -= 1;
++      if (*len == 0) {
++              *errp = -EDQUOT;
++              block = 0;
++              goto out;
++      }
++
++      /* start searching from the goal */
++      if (goal < le32_to_cpu(es->s_first_data_block) ||
++          goal >= le32_to_cpu(es->s_blocks_count))
++              goal = le32_to_cpu(es->s_first_data_block);
++      group = (goal - le32_to_cpu(es->s_first_data_block)) /
++                      EXT3_BLOCKS_PER_GROUP(sb);
++      block = ((goal - le32_to_cpu(es->s_first_data_block)) %
++                      EXT3_BLOCKS_PER_GROUP(sb));
++
++      /* set up allocation goals */
++      ac.ac_b_ex.fe_group = 0;
++      ac.ac_b_ex.fe_start = 0;
++      ac.ac_b_ex.fe_len = 0;
++      ac.ac_status = AC_STATUS_CONTINUE;
++      ac.ac_groups_scanned = 0;
++      ac.ac_ex_scanned = 0;
++      ac.ac_found = 0;
++      ac.ac_sb = inode->i_sb;
++      ac.ac_g_ex.fe_group = group;
++      ac.ac_g_ex.fe_start = block;
++      ac.ac_g_ex.fe_len = *len;
++      ac.ac_flags = flags;
++      ac.ac_2order = 0;
++      ac.ac_criteria = 0;
++
++      /* probably, the request is for 2^8+ blocks (1/2/3/... MB) */
++      i = ffs(*len);
++      if (i >= 8) {
++              i--;
++              if ((*len & (~(1 << i))) == 0)
++                      ac.ac_2order = i;
++      }
++
++      /* Sometimes, caller may want to merge even small
++       * number of blocks to an existing extent */
++      if (ac.ac_flags & EXT3_MB_HINT_MERGE) {
++              err = ext3_mb_find_by_goal(&ac, &e3b);
++              if (err)
++                      goto out_err;
++              if (ac.ac_status == AC_STATUS_FOUND)
++                      goto found;
++      }
++
++      /* Let's just scan groups to find more-less suitable blocks */
++      cr = ac.ac_2order ? 0 : 1;
++repeat:
++      for (; cr < 4 && ac.ac_status == AC_STATUS_CONTINUE; cr++) {
++              ac.ac_criteria = cr;
++              for (i = 0; i < EXT3_SB(sb)->s_groups_count; group++, i++) {
++                      if (group == EXT3_SB(sb)->s_groups_count)
++                              group = 0;
++
++                      if (EXT3_MB_GRP_NEED_INIT(sbi->s_group_info[group])) {
++                              /* we need full data about the group
++                               * to make a good selection */
++                              err = ext3_mb_load_buddy(ac.ac_sb, group, &e3b);
++                              if (err)
++                                      goto out_err;
++                              ext3_mb_release_desc(&e3b);
++                      }
++                              
++                      /* check is group good for our criteries */
++                      if (!ext3_mb_good_group(&ac, group, cr))
++                              continue;
++
++                      err = ext3_mb_load_buddy(ac.ac_sb, group, &e3b);
++                      if (err)
++                              goto out_err;
++
++                      ext3_lock_group(sb, group);
++                      if (!ext3_mb_good_group(&ac, group, cr)) {
++                              /* someone did allocation from this group */
++                              ext3_unlock_group(sb, group);
++                              ext3_mb_release_desc(&e3b);
++                              continue;
++                      }
++
++                      ac.ac_groups_scanned++;
++                      if (cr == 0)
++                              ext3_mb_simple_scan_group(&ac, &e3b);
++                      else
++                              ext3_mb_complex_scan_group(&ac, &e3b);
++
++                      ext3_unlock_group(sb, group);
++
++                      ext3_mb_release_desc(&e3b);
++
++                      if (err)
++                              goto out_err;
++                      if (ac.ac_status != AC_STATUS_CONTINUE)
++                              break;
++              }
++      }
++
++      if (ac.ac_b_ex.fe_len > 0 && ac.ac_status != AC_STATUS_FOUND &&
++                      !(ac.ac_flags & EXT3_MB_HINT_FIRST)) {
++              /*
++               * We've been searching too long. Let's try to allocate
++               * the best chunk we've found so far
++               */
++
++              /*if (ac.ac_found > ext3_mb_max_to_scan)
++                      printk(KERN_ERR "EXT3-fs: too long searching at "
++                              "%u (%d/%d)\n", cr, ac.ac_b_ex.fe_len,
++                              ac.ac_g_ex.fe_len);*/
++              ext3_mb_try_best_found(&ac, &e3b);
++              if (ac.ac_status != AC_STATUS_FOUND) {
++                      /*
++                       * Someone more lucky has already allocated it.
++                       * The only thing we can do is just take first
++                       * found block(s)
++                       */
++                      printk(KERN_ERR "EXT3-fs: and someone won our chunk\n");
++                      ac.ac_b_ex.fe_group = 0;
++                      ac.ac_b_ex.fe_start = 0;
++                      ac.ac_b_ex.fe_len = 0;
++                      ac.ac_status = AC_STATUS_CONTINUE;
++                      ac.ac_flags |= EXT3_MB_HINT_FIRST;
++                      cr = 3;
++                      goto repeat;
++              }
++      }
++
++      if (ac.ac_status != AC_STATUS_FOUND) {
++              /*
++               * We aren't lucky definitely
++               */
++              DQUOT_FREE_BLOCK(inode, *len);
++              *errp = -ENOSPC;
++              block = 0;
++#if 1
++              printk(KERN_ERR "EXT3-fs: cant allocate: status %d, flags %d\n",
++                      ac.ac_status, ac.ac_flags);
++              printk(KERN_ERR "EXT3-fs: goal %d, best found %d/%d/%d, cr %d\n",
++                      ac.ac_g_ex.fe_len, ac.ac_b_ex.fe_group,
++                      ac.ac_b_ex.fe_start, ac.ac_b_ex.fe_len, cr);
++              printk(KERN_ERR "EXT3-fs: %lu block reserved, %d found\n",
++                      sbi->s_blocks_reserved, ac.ac_found);
++              printk("EXT3-fs: groups: ");
++              for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++)
++                      printk("%d: %d ", i,
++                              sbi->s_group_info[i]->bb_free);
++              printk("\n");
++#endif
++              goto out;
++      }
++
++found:
++      J_ASSERT(ac.ac_b_ex.fe_len > 0);
++
++      /* good news - free block(s) have been found. now it's time
++       * to mark block(s) in good old journaled bitmap */
++      block = ac.ac_b_ex.fe_group * EXT3_BLOCKS_PER_GROUP(sb)
++                      + ac.ac_b_ex.fe_start
++                      + le32_to_cpu(es->s_first_data_block);
++
++      /* we made a desicion, now mark found blocks in good old
++       * bitmap to be journaled */
++
++      ext3_debug("using block group %d(%d)\n",
++                      ac.ac_b_group.group, gdp->bg_free_blocks_count);
++
++      bitmap_bh = read_block_bitmap(sb, ac.ac_b_ex.fe_group);
++      if (!bitmap_bh) {
++              *errp = -EIO;
++              goto out_err;
++      }
++
++      err = ext3_journal_get_write_access(handle, bitmap_bh);
++      if (err) {
++              *errp = err;
++              goto out_err;
++      }
++
++      gdp = ext3_get_group_desc(sb, ac.ac_b_ex.fe_group, &gdp_bh);
++      if (!gdp) {
++              *errp = -EIO;
++              goto out_err;
++      }
++      
++      err = ext3_journal_get_write_access(handle, gdp_bh);
++      if (err)
++              goto out_err;
++
++      block = ac.ac_b_ex.fe_group * EXT3_BLOCKS_PER_GROUP(sb)
++                      + ac.ac_b_ex.fe_start
++                      + le32_to_cpu(es->s_first_data_block);
++
++      if (block == le32_to_cpu(gdp->bg_block_bitmap) ||
++          block == le32_to_cpu(gdp->bg_inode_bitmap) ||
++          in_range(block, le32_to_cpu(gdp->bg_inode_table),
++                    EXT3_SB(sb)->s_itb_per_group))
++              ext3_error(sb, "ext3_new_block",
++                          "Allocating block in system zone - "
++                          "block = %u", block);
++#ifdef AGGRESSIVE_CHECK
++      for (i = 0; i < ac.ac_b_ex.fe_len; i++)
++              J_ASSERT(!mb_test_bit(ac.ac_b_ex.fe_start + i, bitmap_bh->b_data));
++#endif
++      mb_set_bits(bitmap_bh->b_data, ac.ac_b_ex.fe_start, ac.ac_b_ex.fe_len);
++
++      spin_lock(sb_bgl_lock(sbi, ac.ac_b_ex.fe_group));
++      gdp->bg_free_blocks_count =
++                      cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count)
++                                      - ac.ac_b_ex.fe_len);
++      spin_unlock(sb_bgl_lock(sbi, ac.ac_b_ex.fe_group));
++      percpu_counter_mod(&sbi->s_freeblocks_counter, - ac.ac_b_ex.fe_len);
++
++      err = ext3_journal_dirty_metadata(handle, bitmap_bh);
++      if (err)
++              goto out_err;
++      err = ext3_journal_dirty_metadata(handle, gdp_bh);
++      if (err)
++              goto out_err;
++
++      sb->s_dirt = 1;
++      *errp = 0;
++      brelse(bitmap_bh);
++
++      /* drop non-allocated, but dquote'd blocks */
++      J_ASSERT(*len >= ac.ac_b_ex.fe_len);
++      DQUOT_FREE_BLOCK(inode, *len - ac.ac_b_ex.fe_len);
++
++      *len = ac.ac_b_ex.fe_len;
++      J_ASSERT(*len > 0);
++      J_ASSERT(block != 0);
++      goto out;
++
++out_err:
++      /* if we've already allocated something, roll it back */
++      if (ac.ac_status == AC_STATUS_FOUND) {
++              /* FIXME: free blocks here */
++      }
++
++      DQUOT_FREE_BLOCK(inode, *len);
++      brelse(bitmap_bh);
++      *errp = err;
++      block = 0;
++out:
++      if (!(flags & EXT3_MB_HINT_RESERVED)) {
++              /* block wasn't reserved before and we reserved it
++               * at the beginning of allocation. it doesn't matter
++               * whether we allocated anything or we failed: time
++               * to release reservation. NOTE: because I expect
++               * any multiblock request from delayed allocation
++               * path only, here is single block always */
++              ext3_mb_release_blocks(sb, 1);
++      }
++      
++      if (unlikely(ext3_mb_stats) && ac.ac_g_ex.fe_len > 1) {
++              atomic_inc(&sbi->s_bal_reqs);
++              atomic_add(*len, &sbi->s_bal_allocated);
++              if (*len >= ac.ac_g_ex.fe_len)
++                      atomic_inc(&sbi->s_bal_success);
++              atomic_add(ac.ac_found, &sbi->s_bal_ex_scanned);
++              if (ac.ac_g_ex.fe_start == ac.ac_b_ex.fe_start &&
++                              ac.ac_g_ex.fe_group == ac.ac_b_ex.fe_group)
++                      atomic_inc(&sbi->s_bal_goals);
++              if (ac.ac_found > ext3_mb_max_to_scan)
++                      atomic_inc(&sbi->s_bal_breaks);
++      }
++
++      ext3_mb_store_history(sb, &ac);
++
++      return block;
++}
++EXPORT_SYMBOL(ext3_mb_new_blocks);
++
++#ifdef EXT3_MB_HISTORY
++struct ext3_mb_proc_session {
++      struct ext3_mb_history *history;
++      struct super_block *sb;
++      int start;
++      int max;
++};
++
++static void *ext3_mb_history_skip_empty(struct ext3_mb_proc_session *s,
++                                      struct ext3_mb_history *hs,
++                                      int first)
++{
++      if (hs == s->history + s->max)
++              hs = s->history;
++      if (!first && hs == s->history + s->start)
++              return NULL;
++      while (hs->goal.fe_len == 0) {
++              hs++;
++              if (hs == s->history + s->max)
++                      hs = s->history;
++              if (hs == s->history + s->start)
++                      return NULL;
++      }
++      return hs;
++}
++
++static void *ext3_mb_seq_history_start(struct seq_file *seq, loff_t *pos)
++{
++      struct ext3_mb_proc_session *s = seq->private;
++      struct ext3_mb_history *hs;
++      int l = *pos;
++
++      if (l == 0)
++              return SEQ_START_TOKEN;
++      hs = ext3_mb_history_skip_empty(s, s->history + s->start, 1);
++      if (!hs)
++              return NULL;
++      while (--l && (hs = ext3_mb_history_skip_empty(s, ++hs, 0)) != NULL);
++      return hs;
++}
++
++static void *ext3_mb_seq_history_next(struct seq_file *seq, void *v, loff_t *pos)
++{
++      struct ext3_mb_proc_session *s = seq->private;
++      struct ext3_mb_history *hs = v;
++
++      ++*pos;
++      if (v == SEQ_START_TOKEN)
++              return ext3_mb_history_skip_empty(s, s->history + s->start, 1);
++      else
++              return ext3_mb_history_skip_empty(s, ++hs, 0);
++}
++
++static int ext3_mb_seq_history_show(struct seq_file *seq, void *v)
++{
++      struct ext3_mb_history *hs = v;
++      char buf[20], buf2[20];
++
++      if (v == SEQ_START_TOKEN) {
++              seq_printf(seq, "%-17s %-17s %-5s %-5s %-2s %-5s %-5s %-6s\n",
++                       "goal", "result", "found", "grps", "cr", "merge",
++                       "tail", "broken");
++              return 0;
++      }
++
++      sprintf(buf, "%u/%u/%u", hs->goal.fe_group,
++              hs->goal.fe_start, hs->goal.fe_len);
++      sprintf(buf2, "%u/%u/%u", hs->result.fe_group,
++              hs->result.fe_start, hs->result.fe_len);
++      seq_printf(seq, "%-17s %-17s %-5u %-5u %-2u %-5s %-5u %-6u\n", buf,
++                      buf2, hs->found, hs->groups, hs->cr, 
++                      hs->merged ? "M" : "", hs->tail,
++                      hs->buddy ? 1 << hs->buddy : 0);
++      return 0;
++}
++
++static void ext3_mb_seq_history_stop(struct seq_file *seq, void *v)
++{
++}
++
++static struct seq_operations ext3_mb_seq_history_ops = {
++      .start  = ext3_mb_seq_history_start,
++      .next   = ext3_mb_seq_history_next,
++      .stop   = ext3_mb_seq_history_stop,
++      .show   = ext3_mb_seq_history_show,
++};
++
++static int ext3_mb_seq_history_open(struct inode *inode, struct file *file)
++{
++      struct super_block *sb = PDE(inode)->data;
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      struct ext3_mb_proc_session *s;
++      int rc, size;
++
++      s = kmalloc(sizeof(*s), GFP_KERNEL);
++      if (s == NULL)
++              return -EIO;
++      size = sizeof(struct ext3_mb_history) * sbi->s_mb_history_max;
++      s->history = kmalloc(size, GFP_KERNEL);
++      if (s == NULL) {
++              kfree(s);
++              return -EIO;
++      }
++
++      spin_lock(&sbi->s_mb_history_lock);
++      memcpy(s->history, sbi->s_mb_history, size);
++      s->max = sbi->s_mb_history_max;
++      s->start = sbi->s_mb_history_cur % s->max;
++      spin_unlock(&sbi->s_mb_history_lock);
++      
++      rc = seq_open(file, &ext3_mb_seq_history_ops);
++      if (rc == 0) {
++              struct seq_file *m = (struct seq_file *)file->private_data;
++              m->private = s;
++      } else {
++              kfree(s->history);
++              kfree(s);
++      }
++      return rc;
++
++}
++
++static int ext3_mb_seq_history_release(struct inode *inode, struct file *file)
++{
++      struct seq_file *seq = (struct seq_file *)file->private_data;
++      struct ext3_mb_proc_session *s = seq->private;
++      kfree(s->history);
++      kfree(s);
++      return seq_release(inode, file);
++}
++
++static struct file_operations ext3_mb_seq_history_fops = {
++      .owner          = THIS_MODULE,
++      .open           = ext3_mb_seq_history_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = ext3_mb_seq_history_release,
++};
++
++static void ext3_mb_history_release(struct super_block *sb)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      char name[64];
++
++      snprintf(name, sizeof(name) - 1, "%s", bdevname(sb->s_bdev, name));
++      remove_proc_entry("mb_history", sbi->s_mb_proc);
++      remove_proc_entry(name, proc_root_ext3);
++
++      if (sbi->s_mb_history)
++              kfree(sbi->s_mb_history);
++}
++
++static void ext3_mb_history_init(struct super_block *sb)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      char name[64];
++      int i;
++
++      snprintf(name, sizeof(name) - 1, "%s", bdevname(sb->s_bdev, name));
++      sbi->s_mb_proc = proc_mkdir(name, proc_root_ext3);
++      if (sbi->s_mb_proc != NULL) {
++              struct proc_dir_entry *p;
++              p = create_proc_entry("mb_history", S_IRUGO, sbi->s_mb_proc);
++              if (p) {
++                      p->proc_fops = &ext3_mb_seq_history_fops;
++                      p->data = sb;
++              }
++      }
++
++      sbi->s_mb_history_max = 1000;
++      sbi->s_mb_history_cur = 0;
++      spin_lock_init(&sbi->s_mb_history_lock);
++      i = sbi->s_mb_history_max * sizeof(struct ext3_mb_history);
++      sbi->s_mb_history = kmalloc(i, GFP_KERNEL);
++      memset(sbi->s_mb_history, 0, i);
++      /* if we can't allocate history, then we simple won't use it */
++}
++
++static void
++ext3_mb_store_history(struct super_block *sb, struct ext3_allocation_context *ac)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      struct ext3_mb_history h;
++
++      if (likely(sbi->s_mb_history == NULL))
++              return;
++
++      h.goal = ac->ac_g_ex;
++      h.result = ac->ac_b_ex;
++      h.found = ac->ac_found;
++      h.cr = ac->ac_criteria;
++      h.groups = ac->ac_groups_scanned;
++      h.tail = ac->ac_tail;
++      h.buddy = ac->ac_buddy;
++      h.merged = 0;
++      if (ac->ac_g_ex.fe_start == ac->ac_b_ex.fe_start &&
++                      ac->ac_g_ex.fe_group == ac->ac_b_ex.fe_group)
++              h.merged = 1;
++
++      spin_lock(&sbi->s_mb_history_lock);
++      memcpy(sbi->s_mb_history + sbi->s_mb_history_cur, &h, sizeof(h));
++      if (++sbi->s_mb_history_cur >= sbi->s_mb_history_max)
++              sbi->s_mb_history_cur = 0;
++      spin_unlock(&sbi->s_mb_history_lock);
++}
++
++#else
++#define ext3_mb_history_release(sb)
++#define ext3_mb_history_init(sb)
++#endif
++
++int ext3_mb_init_backend(struct super_block *sb)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      int i, len;
++
++      len = sizeof(struct ext3_buddy_group_blocks *) * sbi->s_groups_count;
++      sbi->s_group_info = kmalloc(len, GFP_KERNEL);
++      if (sbi->s_group_info == NULL) {
++              printk(KERN_ERR "EXT3-fs: can't allocate mem for buddy\n");
++              return -ENOMEM;
++      }
++      memset(sbi->s_group_info, 0, len);
++
++      sbi->s_buddy_cache = new_inode(sb);
++      if (sbi->s_buddy_cache == NULL) {
++              printk(KERN_ERR "EXT3-fs: can't get new inode\n");
++              kfree(sbi->s_group_info);
++              return -ENOMEM;
++      }
++
++      /* 
++       * calculate needed size. if change bb_counters size,
++       * don't forget about ext3_mb_generate_buddy()
++       */
++      len = sizeof(struct ext3_group_info);
++      len += sizeof(unsigned short) * (sb->s_blocksize_bits + 2);
++      for (i = 0; i < sbi->s_groups_count; i++) {
++              struct ext3_group_desc * desc;
++
++              sbi->s_group_info[i] = kmalloc(len, GFP_KERNEL);
++              if (sbi->s_group_info[i] == NULL) {
++                      printk(KERN_ERR "EXT3-fs: cant allocate mem for buddy\n");
++                      goto err_out;
++              }
++              desc = ext3_get_group_desc(sb, i, NULL);
++              if (desc == NULL) {
++                      printk(KERN_ERR "EXT3-fs: cant read descriptor %u\n", i);
++                      goto err_out;
++              }
++              memset(sbi->s_group_info[i], 0, len);
++              set_bit(EXT3_GROUP_INFO_NEED_INIT_BIT,
++                      &sbi->s_group_info[i]->bb_state);
++              sbi->s_group_info[i]->bb_free =
++                      le16_to_cpu(desc->bg_free_blocks_count);
++      }
++
++      return 0;
++
++err_out:
++      while (--i >= 0)
++              kfree(sbi->s_group_info[i]);
++      iput(sbi->s_buddy_cache);
++
++      return -ENOMEM;
++}
++
++int ext3_mb_init(struct super_block *sb, int needs_recovery)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      struct inode *root = sb->s_root->d_inode;
++      unsigned i, offset, max;
++      struct dentry *dentry;
++
++      if (!test_opt(sb, MBALLOC))
++              return 0;
++
++      i = (sb->s_blocksize_bits + 2) * sizeof(unsigned short);
++
++      sbi->s_mb_offsets = kmalloc(i, GFP_KERNEL);
++      if (sbi->s_mb_offsets == NULL) {
++              clear_opt(sbi->s_mount_opt, MBALLOC);
++              return -ENOMEM;
++      }
++      sbi->s_mb_maxs = kmalloc(i, GFP_KERNEL);
++      if (sbi->s_mb_maxs == NULL) {
++              clear_opt(sbi->s_mount_opt, MBALLOC);
++              kfree(sbi->s_mb_maxs);
++              return -ENOMEM;
++      }
++
++       /* order 0 is regular bitmap */
++      sbi->s_mb_maxs[0] = sb->s_blocksize << 3;
++      sbi->s_mb_offsets[0] = 0;
++
++      i = 1;
++      offset = 0;
++      max = sb->s_blocksize << 2;
++      do {
++              sbi->s_mb_offsets[i] = offset;
++              sbi->s_mb_maxs[i] = max;
++              offset += 1 << (sb->s_blocksize_bits - i);
++              max = max >> 1;
++              i++;
++      } while (i <= sb->s_blocksize_bits + 1);
++      
++
++      /* init file for buddy data */
++      if ((i = ext3_mb_init_backend(sb))) {
++              clear_opt(sbi->s_mount_opt, MBALLOC);
++              kfree(sbi->s_mb_offsets);
++              kfree(sbi->s_mb_maxs);
++              return i;
++      }
++
++      spin_lock_init(&sbi->s_reserve_lock);
++      spin_lock_init(&sbi->s_md_lock);
++      INIT_LIST_HEAD(&sbi->s_active_transaction);
++      INIT_LIST_HEAD(&sbi->s_closed_transaction);
++      INIT_LIST_HEAD(&sbi->s_committed_transaction);
++      spin_lock_init(&sbi->s_bal_lock);
++
++      /* remove old on-disk buddy file */
++      mutex_lock(&root->i_mutex);
++      dentry = lookup_one_len(".buddy", sb->s_root, strlen(".buddy"));
++      if (dentry->d_inode != NULL) {
++              i = vfs_unlink(root, dentry);
++              if (i != 0)
++                      printk("EXT3-fs: can't remove .buddy file: %d\n", i);
++      }
++      dput(dentry);
++      mutex_unlock(&root->i_mutex);
++
++      ext3_mb_history_init(sb);
++
++      printk("EXT3-fs: mballoc enabled\n");
++      return 0;
++}
++
++int ext3_mb_release(struct super_block *sb)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      int i;
++      
++      if (!test_opt(sb, MBALLOC))
++              return 0;
++
++      /* release freed, non-committed blocks */
++      spin_lock(&sbi->s_md_lock);
++      list_splice_init(&sbi->s_closed_transaction,
++                      &sbi->s_committed_transaction);
++      list_splice_init(&sbi->s_active_transaction,
++                      &sbi->s_committed_transaction);
++      spin_unlock(&sbi->s_md_lock);
++      ext3_mb_free_committed_blocks(sb);
++
++      if (sbi->s_group_info) {
++              for (i = 0; i < sbi->s_groups_count; i++) {
++                      if (sbi->s_group_info[i] == NULL)
++                              continue;
++                      kfree(sbi->s_group_info[i]);
++              }
++              kfree(sbi->s_group_info);
++      }
++      if (sbi->s_mb_offsets)
++              kfree(sbi->s_mb_offsets);
++      if (sbi->s_mb_maxs)
++              kfree(sbi->s_mb_maxs);
++      if (sbi->s_buddy_cache)
++              iput(sbi->s_buddy_cache);
++      if (sbi->s_blocks_reserved)
++              printk("ext3-fs: %ld blocks being reserved at umount!\n",
++                              sbi->s_blocks_reserved);
++      if (ext3_mb_stats) {
++              printk("EXT3-fs: mballoc: %u blocks %u reqs (%u success)\n",
++                      atomic_read(&sbi->s_bal_allocated),
++                      atomic_read(&sbi->s_bal_reqs),
++                      atomic_read(&sbi->s_bal_success));
++              printk("EXT3-fs: mballoc: %u extents scanned, %u goal hits, "
++                      "%u 2^N hits, %u breaks\n",
++                      atomic_read(&sbi->s_bal_ex_scanned),
++                      atomic_read(&sbi->s_bal_goals),
++                      atomic_read(&sbi->s_bal_2orders),
++                      atomic_read(&sbi->s_bal_breaks));
++              printk("EXT3-fs: mballoc: %lu generated and it took %Lu\n",
++                      sbi->s_mb_buddies_generated++,
++                      sbi->s_mb_generation_time);
++      }
++
++      ext3_mb_history_release(sb);
++
++      return 0;
++}
++
++void ext3_mb_free_committed_blocks(struct super_block *sb)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      int err, i, count = 0, count2 = 0;
++      struct ext3_free_metadata *md;
++      struct ext3_buddy e3b;
++
++      if (list_empty(&sbi->s_committed_transaction))
++              return;
++
++      /* there is committed blocks to be freed yet */
++      do {
++              /* get next array of blocks */
++              md = NULL;
++              spin_lock(&sbi->s_md_lock);
++              if (!list_empty(&sbi->s_committed_transaction)) {
++                      md = list_entry(sbi->s_committed_transaction.next,
++                                      struct ext3_free_metadata, list);
++                      list_del(&md->list);
++              }
++              spin_unlock(&sbi->s_md_lock);
++
++              if (md == NULL)
++                      break;
++
++              mb_debug("gonna free %u blocks in group %u (0x%p):",
++                              md->num, md->group, md);
++
++              err = ext3_mb_load_buddy(sb, md->group, &e3b);
++              BUG_ON(err != 0);
++
++              /* there are blocks to put in buddy to make them really free */
++              count += md->num;
++              count2++;
++              ext3_lock_group(sb, md->group);
++              for (i = 0; i < md->num; i++) {
++                      mb_debug(" %u", md->blocks[i]);
++                      mb_free_blocks(&e3b, md->blocks[i], 1);
++              }
++              mb_debug("\n");
++              ext3_unlock_group(sb, md->group);
++
++              /* balance refcounts from ext3_mb_free_metadata() */
++              page_cache_release(e3b.bd_buddy_page);
++              page_cache_release(e3b.bd_bitmap_page);
++
++              kfree(md);
++              ext3_mb_release_desc(&e3b);
++
++      } while (md);
++      mb_debug("freed %u blocks in %u structures\n", count, count2);
++}
++
++void ext3_mb_poll_new_transaction(struct super_block *sb, handle_t *handle)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++
++      if (sbi->s_last_transaction == handle->h_transaction->t_tid)
++              return;
++
++      /* new transaction! time to close last one and free blocks for
++       * committed transaction. we know that only transaction can be
++       * active, so previos transaction can be being logged and we
++       * know that transaction before previous is known to be already
++       * logged. this means that now we may free blocks freed in all
++       * transactions before previous one. hope I'm clear enough ... */
++
++      spin_lock(&sbi->s_md_lock);
++      if (sbi->s_last_transaction != handle->h_transaction->t_tid) {
++              mb_debug("new transaction %lu, old %lu\n",
++                              (unsigned long) handle->h_transaction->t_tid,
++                              (unsigned long) sbi->s_last_transaction);
++              list_splice_init(&sbi->s_closed_transaction,
++                                      &sbi->s_committed_transaction);
++              list_splice_init(&sbi->s_active_transaction,
++                                      &sbi->s_closed_transaction);
++              sbi->s_last_transaction = handle->h_transaction->t_tid;
++      }
++      spin_unlock(&sbi->s_md_lock);
++
++      ext3_mb_free_committed_blocks(sb);
++}
++
++int ext3_mb_free_metadata(handle_t *handle, struct ext3_buddy *e3b,
++                              int group, int block, int count)
++{
++      struct ext3_group_info *db = e3b->bd_info;
++      struct super_block *sb = e3b->bd_sb;
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      struct ext3_free_metadata *md;
++      int i;
++
++      J_ASSERT(e3b->bd_bitmap_page != NULL);
++      J_ASSERT(e3b->bd_buddy_page != NULL);
++
++      ext3_lock_group(sb, group);
++      for (i = 0; i < count; i++) {
++              md = db->bb_md_cur;
++              if (md && db->bb_tid != handle->h_transaction->t_tid) {
++                      db->bb_md_cur = NULL;
++                      md = NULL;
++              }
++
++              if (md == NULL) {
++                      ext3_unlock_group(sb, group);
++                      md = kmalloc(sizeof(*md), GFP_KERNEL);
++                      if (md == NULL)
++                              return -ENOMEM;
++                      md->num = 0;
++                      md->group = group;
++
++                      ext3_lock_group(sb, group);
++                      if (db->bb_md_cur == NULL) {
++                              spin_lock(&sbi->s_md_lock);
++                              list_add(&md->list, &sbi->s_active_transaction);
++                              spin_unlock(&sbi->s_md_lock);
++                              /* protect buddy cache from being freed,
++                               * otherwise we'll refresh it from
++                               * on-disk bitmap and lose not-yet-available
++                               * blocks */
++                              page_cache_get(e3b->bd_buddy_page);
++                              page_cache_get(e3b->bd_bitmap_page);
++                              db->bb_md_cur = md;
++                              db->bb_tid = handle->h_transaction->t_tid;
++                              mb_debug("new md 0x%p for group %u\n",
++                                                      md, md->group);
++                      } else {
++                              kfree(md);
++                              md = db->bb_md_cur;
++                      }
++              }
++
++              BUG_ON(md->num >= EXT3_BB_MAX_BLOCKS);
++              md->blocks[md->num] = block + i;
++              md->num++;
++              if (md->num == EXT3_BB_MAX_BLOCKS) {
++                      /* no more space, put full container on a sb's list */
++                      db->bb_md_cur = NULL;
++              }
++      }
++      ext3_unlock_group(sb, group);
++      return 0;
++}
++
++void ext3_mb_free_blocks(handle_t *handle, struct inode *inode,
++                      unsigned long block, unsigned long count,
++                      int metadata, int *freed)
++{
++      struct buffer_head *bitmap_bh = NULL;
++      struct ext3_group_desc *gdp;
++      struct ext3_super_block *es;
++      unsigned long bit, overflow;
++      struct buffer_head *gd_bh;
++      unsigned long block_group;
++      struct ext3_sb_info *sbi;
++      struct super_block *sb;
++      struct ext3_buddy e3b;
++      int err = 0, ret;
++
++      *freed = 0;
++      sb = inode->i_sb;
++      if (!sb) {
++              printk ("ext3_free_blocks: nonexistent device");
++              return;
++      }
++
++      ext3_mb_poll_new_transaction(sb, handle);
++
++      sbi = EXT3_SB(sb);
++      es = EXT3_SB(sb)->s_es;
++      if (block < le32_to_cpu(es->s_first_data_block) ||
++          block + count < block ||
++          block + count > le32_to_cpu(es->s_blocks_count)) {
++              ext3_error (sb, "ext3_free_blocks",
++                          "Freeing blocks not in datazone - "
++                          "block = %lu, count = %lu", block, count);
++              goto error_return;
++      }
++
++      ext3_debug("freeing block %lu\n", block);
++
++do_more:
++      overflow = 0;
++      block_group = (block - le32_to_cpu(es->s_first_data_block)) /
++                    EXT3_BLOCKS_PER_GROUP(sb);
++      bit = (block - le32_to_cpu(es->s_first_data_block)) %
++                    EXT3_BLOCKS_PER_GROUP(sb);
++      /*
++       * Check to see if we are freeing blocks across a group
++       * boundary.
++       */
++      if (bit + count > EXT3_BLOCKS_PER_GROUP(sb)) {
++              overflow = bit + count - EXT3_BLOCKS_PER_GROUP(sb);
++              count -= overflow;
++      }
++      brelse(bitmap_bh);
++      bitmap_bh = read_block_bitmap(sb, block_group);
++      if (!bitmap_bh)
++              goto error_return;
++      gdp = ext3_get_group_desc (sb, block_group, &gd_bh);
++      if (!gdp)
++              goto error_return;
++
++      if (in_range (le32_to_cpu(gdp->bg_block_bitmap), block, count) ||
++          in_range (le32_to_cpu(gdp->bg_inode_bitmap), block, count) ||
++          in_range (block, le32_to_cpu(gdp->bg_inode_table),
++                    EXT3_SB(sb)->s_itb_per_group) ||
++          in_range (block + count - 1, le32_to_cpu(gdp->bg_inode_table),
++                    EXT3_SB(sb)->s_itb_per_group))
++              ext3_error (sb, "ext3_free_blocks",
++                          "Freeing blocks in system zones - "
++                          "Block = %lu, count = %lu",
++                          block, count);
++
++      BUFFER_TRACE(bitmap_bh, "getting write access");
++      err = ext3_journal_get_write_access(handle, bitmap_bh);
++      if (err)
++              goto error_return;
++
++      /*
++       * We are about to modify some metadata.  Call the journal APIs
++       * to unshare ->b_data if a currently-committing transaction is
++       * using it
++       */
++      BUFFER_TRACE(gd_bh, "get_write_access");
++      err = ext3_journal_get_write_access(handle, gd_bh);
++      if (err)
++              goto error_return;
++
++      err = ext3_mb_load_buddy(sb, block_group, &e3b);
++      if (err)
++              goto error_return;
++
++#ifdef AGGRESSIVE_CHECK
++      {
++              int i;
++              for (i = 0; i < count; i++)
++                      J_ASSERT(mb_test_bit(bit + i, bitmap_bh->b_data));
++      }
++#endif
++      mb_clear_bits(bitmap_bh->b_data, bit, count);
++
++      /* We dirtied the bitmap block */
++      BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");
++      err = ext3_journal_dirty_metadata(handle, bitmap_bh);
++
++      if (metadata) {
++              /* blocks being freed are metadata. these blocks shouldn't
++               * be used until this transaction is committed */
++              ext3_mb_free_metadata(handle, &e3b, block_group, bit, count);
++      } else { 
++              ext3_lock_group(sb, block_group);
++              mb_free_blocks(&e3b, bit, count);
++              ext3_unlock_group(sb, block_group);
++      }
++
++      spin_lock(sb_bgl_lock(sbi, block_group));
++      gdp->bg_free_blocks_count =
++              cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) + count);
++      spin_unlock(sb_bgl_lock(sbi, block_group));
++      percpu_counter_mod(&sbi->s_freeblocks_counter, count);
++      
++      ext3_mb_release_desc(&e3b);
++
++      *freed = count;
++
++      /* And the group descriptor block */
++      BUFFER_TRACE(gd_bh, "dirtied group descriptor block");
++      ret = ext3_journal_dirty_metadata(handle, gd_bh);
++      if (!err) err = ret;
++
++      if (overflow && !err) {
++              block += count;
++              count = overflow;
++              goto do_more;
++      }
++      sb->s_dirt = 1;
++error_return:
++      brelse(bitmap_bh);
++      ext3_std_error(sb, err);
++      return;
++}
++
++int ext3_mb_reserve_blocks(struct super_block *sb, int blocks)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      int free, ret = -ENOSPC;
++
++      BUG_ON(blocks < 0);
++      spin_lock(&sbi->s_reserve_lock);
++      free = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
++      if (blocks <= free - sbi->s_blocks_reserved) {
++              sbi->s_blocks_reserved += blocks;
++              ret = 0;
++      }
++      spin_unlock(&sbi->s_reserve_lock);
++      return ret;
++}
++
++void ext3_mb_release_blocks(struct super_block *sb, int blocks)
++{
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++
++      BUG_ON(blocks < 0);
++      spin_lock(&sbi->s_reserve_lock);
++      sbi->s_blocks_reserved -= blocks;
++      WARN_ON(sbi->s_blocks_reserved < 0);
++      if (sbi->s_blocks_reserved < 0)
++              sbi->s_blocks_reserved = 0;
++      spin_unlock(&sbi->s_reserve_lock);
++}
++
++int ext3_new_block(handle_t *handle, struct inode *inode,
++              unsigned long goal, int *errp)
++{
++      int ret, len;
++
++      if (!test_opt(inode->i_sb, MBALLOC)) {
++              ret = ext3_new_block_old(handle, inode, goal, errp);
++              goto out;
++      }
++      len = 1;
++      ret = ext3_mb_new_blocks(handle, inode, goal, &len, 0, errp);
++out:
++      return ret;
++}
++
++
++void ext3_free_blocks(handle_t *handle, struct inode * inode,
++                      unsigned long block, unsigned long count, int metadata)
++{
++      struct super_block *sb;
++      int freed;
++
++      sb = inode->i_sb;
++      if (!test_opt(sb, MBALLOC))
++              ext3_free_blocks_sb(handle, sb, block, count, &freed);
++      else
++              ext3_mb_free_blocks(handle, inode, block, count, metadata, &freed);
++      if (freed)
++              DQUOT_FREE_BLOCK(inode, freed);
++      return;
++}
++
++#define EXT3_ROOT                 "ext3"
++#define EXT3_MB_STATS_NAME        "mb_stats"
++#define EXT3_MB_MAX_TO_SCAN_NAME  "mb_max_to_scan"
++#define EXT3_MB_MIN_TO_SCAN_NAME  "mb_min_to_scan"
++
++static int ext3_mb_stats_read(char *page, char **start, off_t off,
++              int count, int *eof, void *data)
++{
++      int len;
++
++      *eof = 1;
++      if (off != 0)
++              return 0;
++
++      len = sprintf(page, "%ld\n", ext3_mb_stats);
++      *start = page;
++      return len;
++}
++
++static int ext3_mb_stats_write(struct file *file, const char *buffer,
++              unsigned long count, void *data)
++{
++      char str[32];
++
++      if (count >= sizeof(str)) {
++              printk(KERN_ERR "EXT3: %s string to long, max %u bytes\n",
++                     EXT3_MB_STATS_NAME, (int)sizeof(str));
++              return -EOVERFLOW;
++      }
++
++      if (copy_from_user(str, buffer, count))
++              return -EFAULT;
++
++      /* Only set to 0 or 1 respectively; zero->0; non-zero->1 */
++      ext3_mb_stats = (simple_strtol(str, NULL, 0) != 0);
++      return count;
++}
++
++static int ext3_mb_max_to_scan_read(char *page, char **start, off_t off,
++              int count, int *eof, void *data)
++{
++      int len;
++
++      *eof = 1;
++      if (off != 0)
++              return 0;
++
++      len = sprintf(page, "%ld\n", ext3_mb_max_to_scan);
++      *start = page;
++      return len;
++}
++
++static int ext3_mb_max_to_scan_write(struct file *file, const char *buffer,
++              unsigned long count, void *data)
++{
++      char str[32];
++      long value;
++
++      if (count >= sizeof(str)) {
++              printk(KERN_ERR "EXT3: %s string to long, max %u bytes\n",
++                     EXT3_MB_MAX_TO_SCAN_NAME, (int)sizeof(str));
++              return -EOVERFLOW;
++      }
++
++      if (copy_from_user(str, buffer, count))
++              return -EFAULT;
++
++      /* Only set to 0 or 1 respectively; zero->0; non-zero->1 */
++      value = simple_strtol(str, NULL, 0);
++      if (value <= 0)
++              return -ERANGE;
++
++      ext3_mb_max_to_scan = value;    
++
++      return count;
++}
++
++static int ext3_mb_min_to_scan_read(char *page, char **start, off_t off,
++              int count, int *eof, void *data)
++{
++      int len;
++
++      *eof = 1;
++      if (off != 0)
++              return 0;
++
++      len = sprintf(page, "%ld\n", ext3_mb_min_to_scan);
++      *start = page;
++      return len;
++}
++
++static int ext3_mb_min_to_scan_write(struct file *file, const char *buffer,
++              unsigned long count, void *data)
++{
++      char str[32];
++      long value;
++
++      if (count >= sizeof(str)) {
++              printk(KERN_ERR "EXT3: %s string to long, max %u bytes\n",
++                     EXT3_MB_MIN_TO_SCAN_NAME, (int)sizeof(str));
++              return -EOVERFLOW;
++      }
++
++      if (copy_from_user(str, buffer, count))
++              return -EFAULT;
++
++      /* Only set to 0 or 1 respectively; zero->0; non-zero->1 */
++      value = simple_strtol(str, NULL, 0);
++      if (value <= 0)
++              return -ERANGE;
++
++      ext3_mb_min_to_scan = value;    
++
++      return count;
++}
++
++int __init init_ext3_proc(void)
++{
++      struct proc_dir_entry *proc_ext3_mb_stats;
++      struct proc_dir_entry *proc_ext3_mb_max_to_scan;
++      struct proc_dir_entry *proc_ext3_mb_min_to_scan;
++
++      proc_root_ext3 = proc_mkdir(EXT3_ROOT, proc_root_fs);
++      if (proc_root_ext3 == NULL) {
++              printk(KERN_ERR "EXT3: Unable to create %s\n", EXT3_ROOT);
++              return -EIO;
++      }
++
++      /* Initialize EXT3_MB_STATS_NAME */
++      proc_ext3_mb_stats = create_proc_entry(EXT3_MB_STATS_NAME,
++                      S_IFREG | S_IRUGO | S_IWUSR, proc_root_ext3);
++      if (proc_ext3_mb_stats == NULL) {
++              printk(KERN_ERR "EXT3: Unable to create %s\n",
++                              EXT3_MB_STATS_NAME);
++              remove_proc_entry(EXT3_ROOT, proc_root_fs);
++              return -EIO;
++      }
++
++      proc_ext3_mb_stats->data = NULL;
++      proc_ext3_mb_stats->read_proc  = ext3_mb_stats_read;
++      proc_ext3_mb_stats->write_proc = ext3_mb_stats_write;
++
++      /* Initialize EXT3_MAX_TO_SCAN_NAME */
++      proc_ext3_mb_max_to_scan = create_proc_entry(
++                      EXT3_MB_MAX_TO_SCAN_NAME,
++                      S_IFREG | S_IRUGO | S_IWUSR, proc_root_ext3);
++      if (proc_ext3_mb_max_to_scan == NULL) {
++              printk(KERN_ERR "EXT3: Unable to create %s\n",
++                              EXT3_MB_MAX_TO_SCAN_NAME);
++              remove_proc_entry(EXT3_MB_STATS_NAME, proc_root_ext3);
++              remove_proc_entry(EXT3_ROOT, proc_root_fs);
++              return -EIO;
++      }
++
++      proc_ext3_mb_max_to_scan->data = NULL;
++      proc_ext3_mb_max_to_scan->read_proc  = ext3_mb_max_to_scan_read;
++      proc_ext3_mb_max_to_scan->write_proc = ext3_mb_max_to_scan_write;
++
++      /* Initialize EXT3_MIN_TO_SCAN_NAME */
++      proc_ext3_mb_min_to_scan = create_proc_entry(
++                      EXT3_MB_MIN_TO_SCAN_NAME,
++                      S_IFREG | S_IRUGO | S_IWUSR, proc_root_ext3);
++      if (proc_ext3_mb_min_to_scan == NULL) {
++              printk(KERN_ERR "EXT3: Unable to create %s\n",
++                              EXT3_MB_MIN_TO_SCAN_NAME);
++              remove_proc_entry(EXT3_MB_MAX_TO_SCAN_NAME, proc_root_ext3);
++              remove_proc_entry(EXT3_MB_STATS_NAME, proc_root_ext3);
++              remove_proc_entry(EXT3_ROOT, proc_root_fs);
++              return -EIO;
++      }
++
++      proc_ext3_mb_min_to_scan->data = NULL;
++      proc_ext3_mb_min_to_scan->read_proc  = ext3_mb_min_to_scan_read;
++      proc_ext3_mb_min_to_scan->write_proc = ext3_mb_min_to_scan_write;
++
++      return 0;
++}
++
++void exit_ext3_proc(void)
++{
++      remove_proc_entry(EXT3_MB_STATS_NAME, proc_root_ext3);
++      remove_proc_entry(EXT3_MB_MAX_TO_SCAN_NAME, proc_root_ext3);
++      remove_proc_entry(EXT3_MB_MIN_TO_SCAN_NAME, proc_root_ext3);
++      remove_proc_entry(EXT3_ROOT, proc_root_fs);
++}
++
+Index: linux-stage/fs/ext3/extents.c
+===================================================================
+--- linux-stage.orig/fs/ext3/extents.c 2006-07-16 02:29:43.000000000 +0800
++++ linux-stage/fs/ext3/extents.c      2006-07-16 02:29:49.000000000 +0800
+@@ -771,7 +771,7 @@ cleanup:
+               for (i = 0; i < depth; i++) {
+                       if (!ablocks[i])
+                               continue;
+-                      ext3_free_blocks(handle, tree->inode, ablocks[i], 1);
++                      ext3_free_blocks(handle, tree->inode, ablocks[i], 1, 1);
+               }
+       }
+       kfree(ablocks);
+@@ -1428,7 +1428,7 @@ int ext3_ext_rm_idx(handle_t *handle, st
+                 path->p_idx->ei_leaf);
+       bh = sb_find_get_block(tree->inode->i_sb, path->p_idx->ei_leaf);
+       ext3_forget(handle, 1, tree->inode, bh, path->p_idx->ei_leaf);
+-      ext3_free_blocks(handle, tree->inode, path->p_idx->ei_leaf, 1);
++      ext3_free_blocks(handle, tree->inode, path->p_idx->ei_leaf, 1, 1);
+       return err;
+ }
+@@ -1913,10 +1913,12 @@ ext3_remove_blocks(struct ext3_extents_t
+       int needed = ext3_remove_blocks_credits(tree, ex, from, to);
+       handle_t *handle = ext3_journal_start(tree->inode, needed);
+       struct buffer_head *bh;
+-      int i;
++      int i, metadata = 0;
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
++      if (S_ISDIR(tree->inode->i_mode) || S_ISLNK(tree->inode->i_mode))
++              metadata = 1;
+       if (from >= ex->ee_block && to == ex->ee_block + ex->ee_len - 1) {
+               /* tail removal */
+               unsigned long num, start;
+@@ -1928,7 +1930,7 @@ ext3_remove_blocks(struct ext3_extents_t
+                       bh = sb_find_get_block(tree->inode->i_sb, start + i);
+                       ext3_forget(handle, 0, tree->inode, bh, start + i);
+               }
+-              ext3_free_blocks(handle, tree->inode, start, num);
++              ext3_free_blocks(handle, tree->inode, start, num, metadata);
+       } else if (from == ex->ee_block && to <= ex->ee_block + ex->ee_len - 1) {
+               printk("strange request: removal %lu-%lu from %u:%u\n",
+                      from, to, ex->ee_block, ex->ee_len);
+Index: linux-stage/fs/ext3/xattr.c
+===================================================================
+--- linux-stage.orig/fs/ext3/xattr.c   2006-07-16 02:29:43.000000000 +0800
++++ linux-stage/fs/ext3/xattr.c        2006-07-16 02:29:49.000000000 +0800
+@@ -484,7 +484,7 @@ ext3_xattr_release_block(handle_t *handl
+               ea_bdebug(bh, "refcount now=0; freeing");
+               if (ce)
+                       mb_cache_entry_free(ce);
+-              ext3_free_blocks(handle, inode, bh->b_blocknr, 1);
++              ext3_free_blocks(handle, inode, bh->b_blocknr, 1, 1);
+               get_bh(bh);
+               ext3_forget(handle, 1, inode, bh, bh->b_blocknr);
+       } else {
+@@ -805,7 +805,7 @@ inserted:
+                       new_bh = sb_getblk(sb, block);
+                       if (!new_bh) {
+ getblk_failed:
+-                              ext3_free_blocks(handle, inode, block, 1);
++                              ext3_free_blocks(handle, inode, block, 1, 1);
+                               error = -EIO;
+                               goto cleanup;
+                       }
+Index: linux-stage/fs/ext3/balloc.c
+===================================================================
+--- linux-stage.orig/fs/ext3/balloc.c  2006-07-16 02:29:43.000000000 +0800
++++ linux-stage/fs/ext3/balloc.c       2006-07-16 02:33:13.000000000 +0800
+@@ -79,7 +79,7 @@ struct ext3_group_desc * ext3_get_group_
+  *
+  * Return buffer_head on success or NULL in case of failure.
+  */
+-static struct buffer_head *
++struct buffer_head *
+ read_block_bitmap(struct super_block *sb, unsigned int block_group)
+ {
+       struct ext3_group_desc * desc;
+@@ -490,24 +490,6 @@ error_return:
+       return;
+ }
+-/* Free given blocks, update quota and i_blocks field */
+-void ext3_free_blocks(handle_t *handle, struct inode *inode,
+-                      ext3_fsblk_t block, unsigned long count)
+-{
+-      struct super_block * sb;
+-      unsigned long dquot_freed_blocks;
+-
+-      sb = inode->i_sb;
+-      if (!sb) {
+-              printk ("ext3_free_blocks: nonexistent device");
+-              return;
+-      }
+-      ext3_free_blocks_sb(handle, sb, block, count, &dquot_freed_blocks);
+-      if (dquot_freed_blocks)
+-              DQUOT_FREE_BLOCK(inode, dquot_freed_blocks);
+-      return;
+-}
+-
+ /*
+  * For ext3 allocations, we must not reuse any blocks which are
+  * allocated in the bitmap buffer's "last committed data" copy.  This
+@@ -1463,7 +1445,7 @@ out:
+       return 0;
+ }
+-ext3_fsblk_t ext3_new_block(handle_t *handle, struct inode *inode,
++ext3_fsblk_t ext3_new_block_old(handle_t *handle, struct inode *inode,
+                       ext3_fsblk_t goal, int *errp)
+ {
+       unsigned long count = 1;
+Index: linux-stage/fs/ext3/super.c
+===================================================================
+--- linux-stage.orig/fs/ext3/super.c   2006-07-16 02:29:43.000000000 +0800
++++ linux-stage/fs/ext3/super.c        2006-07-16 02:29:49.000000000 +0800
+@@ -391,6 +391,7 @@ static void ext3_put_super (struct super
+       struct ext3_super_block *es = sbi->s_es;
+       int i;
++      ext3_mb_release(sb);
+       ext3_ext_release(sb);
+       ext3_xattr_put_super(sb);
+       journal_destroy(sbi->s_journal);
+@@ -641,7 +642,7 @@ enum {
+       Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
+       Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
+       Opt_iopen, Opt_noiopen, Opt_iopen_nopriv,
+-      Opt_extents, Opt_extdebug,
++      Opt_extents, Opt_extdebug, Opt_mballoc,
+       Opt_grpquota
+ };
+@@ -696,6 +697,7 @@ static match_table_t tokens = {
+       {Opt_iopen_nopriv, "iopen_nopriv"},
+       {Opt_extents, "extents"},
+       {Opt_extdebug, "extdebug"},
++      {Opt_mballoc, "mballoc"},
+       {Opt_barrier, "barrier=%u"},
+       {Opt_err, NULL},
+       {Opt_resize, "resize"},
+@@ -1047,6 +1049,9 @@ clear_qf_name:
+               case Opt_extdebug:
+                       set_opt (sbi->s_mount_opt, EXTDEBUG);
+                       break;
++              case Opt_mballoc:
++                      set_opt (sbi->s_mount_opt, MBALLOC);
++                      break;
+               default:
+                       printk (KERN_ERR
+                               "EXT3-fs: Unrecognized mount option \"%s\" "
+@@ -1773,6 +1778,7 @@ static int ext3_fill_super (struct super
+               "writeback");
+       ext3_ext_init(sb);
++      ext3_mb_init(sb, needs_recovery);
+       lock_kernel();
+       return 0;
+@@ -2712,7 +2718,13 @@ static struct file_system_type ext3_fs_t
+ static int __init init_ext3_fs(void)
+ {
+-      int err = init_ext3_xattr();
++      int err;
++
++      err = init_ext3_proc();
++      if (err)
++              return err;
++
++      err = init_ext3_xattr();
+       if (err)
+               return err;
+       err = init_inodecache();
+@@ -2734,6 +2746,7 @@ static void __exit exit_ext3_fs(void)
+       unregister_filesystem(&ext3_fs_type);
+       destroy_inodecache();
+       exit_ext3_xattr();
++      exit_ext3_proc();
+ }
+ int ext3_prep_san_write(struct inode *inode, long *blocks,
+Index: linux-stage/fs/ext3/Makefile
+===================================================================
+--- linux-stage.orig/fs/ext3/Makefile  2006-07-16 02:29:43.000000000 +0800
++++ linux-stage/fs/ext3/Makefile       2006-07-16 02:29:49.000000000 +0800
+@@ -6,7 +6,7 @@ obj-$(CONFIG_EXT3_FS) += ext3.o
+ ext3-y        := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
+          ioctl.o namei.o super.o symlink.o hash.o resize.o \
+-         extents.o
++         extents.o mballoc.o
+ ext3-$(CONFIG_EXT3_FS_XATTR)   += xattr.o xattr_user.o xattr_trusted.o
+ ext3-$(CONFIG_EXT3_FS_POSIX_ACL) += acl.o
+Index: linux-stage/include/linux/ext3_fs.h
+===================================================================
+--- linux-stage.orig/include/linux/ext3_fs.h   2006-07-16 02:29:43.000000000 +0800
++++ linux-stage/include/linux/ext3_fs.h        2006-07-16 02:29:49.000000000 +0800
+@@ -53,6 +53,14 @@
+ #define ext3_debug(f, a...)   do {} while (0)
+ #endif
++#define EXT3_MULTIBLOCK_ALLOCATOR     1
++
++#define EXT3_MB_HINT_MERGE            1
++#define EXT3_MB_HINT_RESERVED         2
++#define EXT3_MB_HINT_METADATA         4
++#define EXT3_MB_HINT_FIRST            8
++#define EXT3_MB_HINT_BEST             16
++
+ /*
+  * Special inodes numbers
+  */
+@@ -379,6 +387,7 @@ struct ext3_inode {
+ #define EXT3_MOUNT_IOPEN_NOPRIV               0x800000/* Make iopen world-readable */
+ #define EXT3_MOUNT_EXTENTS            0x1000000/* Extents support */
+ #define EXT3_MOUNT_EXTDEBUG           0x2000000/* Extents debug */
++#define EXT3_MOUNT_MBALLOC            0x800000/* Buddy allocation support */
+ /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
+ #ifndef clear_opt
+@@ -749,12 +758,12 @@ ext3_group_first_block_no(struct super_b
+ /* balloc.c */
+ extern int ext3_bg_has_super(struct super_block *sb, int group);
+ extern unsigned long ext3_bg_num_gdb(struct super_block *sb, int group);
+-extern ext3_fsblk_t ext3_new_block (handle_t *handle, struct inode *inode,
+-                      ext3_fsblk_t goal, int *errp);
++//extern ext3_fsblk_t ext3_new_block (handle_t *handle, struct inode *inode,
++//                    ext3_fsblk_t goal, int *errp);
+ extern ext3_fsblk_t ext3_new_blocks (handle_t *handle, struct inode *inode,
+                       ext3_fsblk_t goal, unsigned long *count, int *errp);
+ extern void ext3_free_blocks (handle_t *handle, struct inode *inode,
+-                      ext3_fsblk_t block, unsigned long count);
++                      ext3_fsblk_t block, unsigned long count, int metadata);
+ extern void ext3_free_blocks_sb (handle_t *handle, struct super_block *sb,
+                                ext3_fsblk_t block, unsigned long count,
+                               unsigned long *pdquot_freed_blocks);
+@@ -881,6 +890,17 @@ extern void ext3_extents_initialize_bloc
+ extern int ext3_ext_ioctl(struct inode *inode, struct file *filp,
+                         unsigned int cmd, unsigned long arg);
++/* mballoc.c */
++extern long ext3_mb_stats;
++extern long ext3_mb_max_to_scan;
++extern int ext3_mb_init(struct super_block *, int);
++extern int ext3_mb_release(struct super_block *);
++extern int ext3_mb_new_blocks(handle_t *, struct inode *, unsigned long, int *, int, int *);
++extern int ext3_mb_reserve_blocks(struct super_block *, int);
++extern void ext3_mb_release_blocks(struct super_block *, int);
++int __init init_ext3_proc(void);
++void exit_ext3_proc(void);
++
+ #endif        /* __KERNEL__ */
+ /* EXT3_IOC_CREATE_INUM at bottom of file (visible to kernel and user). */
+Index: linux-stage/include/linux/ext3_fs_sb.h
+===================================================================
+--- linux-stage.orig/include/linux/ext3_fs_sb.h        2006-07-16 02:29:43.000000000 +0800
++++ linux-stage/include/linux/ext3_fs_sb.h     2006-07-16 02:29:49.000000000 +0800
+@@ -21,8 +21,14 @@
+ #include <linux/wait.h>
+ #include <linux/blockgroup_lock.h>
+ #include <linux/percpu_counter.h>
++#include <linux/list.h>
+ #endif
+ #include <linux/rbtree.h>
++#include <linux/proc_fs.h>
++
++struct ext3_buddy_group_blocks;
++struct ext3_mb_history;
++#define EXT3_BB_MAX_BLOCKS
+ /*
+  * third extended-fs super-block data in memory
+@@ -78,6 +84,38 @@ struct ext3_sb_info {
+       char *s_qf_names[MAXQUOTAS];            /* Names of quota files with journalled quota */
+       int s_jquota_fmt;                       /* Format of quota to use */
+ #endif
++
++      /* for buddy allocator */
++      struct ext3_group_info **s_group_info;
++      struct inode *s_buddy_cache;
++      long s_blocks_reserved;
++      spinlock_t s_reserve_lock;
++      struct list_head s_active_transaction;
++      struct list_head s_closed_transaction;
++      struct list_head s_committed_transaction;
++      spinlock_t s_md_lock;
++      tid_t s_last_transaction;
++      int s_mb_factor;
++      unsigned short *s_mb_offsets, *s_mb_maxs;
++
++      /* history to debug policy */
++      struct ext3_mb_history *s_mb_history;
++      int s_mb_history_cur;
++      int s_mb_history_max;
++      struct proc_dir_entry *s_mb_proc;
++      spinlock_t s_mb_history_lock;
++
++      /* stats for buddy allocator */
++      atomic_t s_bal_reqs;    /* number of reqs with len > 1 */
++      atomic_t s_bal_success; /* we found long enough chunks */
++      atomic_t s_bal_allocated;       /* in blocks */
++      atomic_t s_bal_ex_scanned;      /* total extents scanned */
++      atomic_t s_bal_goals;   /* goal hits */
++      atomic_t s_bal_breaks;  /* too long searches */
++      atomic_t s_bal_2orders; /* 2^order hits */
++      spinlock_t s_bal_lock;
++      unsigned long s_mb_buddies_generated;
++      unsigned long long s_mb_generation_time;
+ };
+ #endif        /* _LINUX_EXT3_FS_SB */
+Index: linux-stage/fs/ext3/inode.c
+===================================================================
+--- linux-stage.orig/fs/ext3/inode.c   2006-07-16 02:29:43.000000000 +0800
++++ linux-stage/fs/ext3/inode.c        2006-07-16 02:29:49.000000000 +0800
+@@ -562,7 +562,7 @@ static int ext3_alloc_blocks(handle_t *h
+       return ret;
+ failed_out:
+       for (i = 0; i <index; i++)
+-              ext3_free_blocks(handle, inode, new_blocks[i], 1);
++              ext3_free_blocks(handle, inode, new_blocks[i], 1, 1);
+       return ret;
+ }
+@@ -661,9 +661,9 @@ failed:
+               ext3_journal_forget(handle, branch[i].bh);
+       }
+       for (i = 0; i <indirect_blks; i++)
+-              ext3_free_blocks(handle, inode, new_blocks[i], 1);
++              ext3_free_blocks(handle, inode, new_blocks[i], 1, 1);
+-      ext3_free_blocks(handle, inode, new_blocks[i], num);
++      ext3_free_blocks(handle, inode, new_blocks[i], num, 1);
+       return err;
+ }
+@@ -760,9 +760,9 @@ err_out:
+       for (i = 1; i <= num; i++) {
+               BUFFER_TRACE(where[i].bh, "call journal_forget");
+               ext3_journal_forget(handle, where[i].bh);
+-              ext3_free_blocks(handle,inode,le32_to_cpu(where[i-1].key),1);
++              ext3_free_blocks(handle,inode,le32_to_cpu(where[i-1].key),1,1);
+       }
+-      ext3_free_blocks(handle, inode, le32_to_cpu(where[num].key), blks);
++      ext3_free_blocks(handle, inode, le32_to_cpu(where[num].key), blks, 1);
+       return err;
+ }
+@@ -2007,7 +2007,7 @@ static void ext3_clear_blocks(handle_t *
+               }
+       }
+-      ext3_free_blocks(handle, inode, block_to_free, count);
++      ext3_free_blocks(handle, inode, block_to_free, count, 1);
+ }
+ /**
+@@ -2180,7 +2180,7 @@ static void ext3_free_branches(handle_t 
+                               ext3_journal_test_restart(handle, inode);
+                       }
+-                      ext3_free_blocks(handle, inode, nr, 1);
++                      ext3_free_blocks(handle, inode, nr, 1, 1);
+                       if (parent_bh) {
+                               /*
index 01e7387..e34c411 100644 (file)
@@ -1,7 +1,7 @@
-Index: linux-2.6.9-full/include/linux/ext3_fs.h
+Index: linux-stage/include/linux/ext3_fs.h
 ===================================================================
---- linux-2.6.9-full.orig/include/linux/ext3_fs.h      2005-12-16 23:16:41.000000000 +0300
-+++ linux-2.6.9-full/include/linux/ext3_fs.h   2005-12-16 23:16:42.000000000 +0300
+--- linux-stage.orig/include/linux/ext3_fs.h   2006-05-25 10:36:04.000000000 -0600
++++ linux-stage/include/linux/ext3_fs.h        2006-05-25 10:36:04.000000000 -0600
 @@ -57,6 +57,14 @@ struct statfs;
  #define ext3_debug(f, a...)   do {} while (0)
  #endif
@@ -52,10 +52,10 @@ Index: linux-2.6.9-full/include/linux/ext3_fs.h
  #endif        /* __KERNEL__ */
  
  /* EXT3_IOC_CREATE_INUM at bottom of file (visible to kernel and user). */
-Index: linux-2.6.9-full/include/linux/ext3_fs_sb.h
+Index: linux-stage/include/linux/ext3_fs_sb.h
 ===================================================================
---- linux-2.6.9-full.orig/include/linux/ext3_fs_sb.h   2005-12-16 23:16:39.000000000 +0300
-+++ linux-2.6.9-full/include/linux/ext3_fs_sb.h        2005-12-16 23:16:42.000000000 +0300
+--- linux-stage.orig/include/linux/ext3_fs_sb.h        2006-05-25 10:36:04.000000000 -0600
++++ linux-stage/include/linux/ext3_fs_sb.h     2006-05-25 10:59:14.000000000 -0600
 @@ -23,9 +23,15 @@
  #define EXT_INCLUDE
  #include <linux/blockgroup_lock.h>
@@ -72,13 +72,13 @@ Index: linux-2.6.9-full/include/linux/ext3_fs_sb.h
  
  /*
   * third extended-fs super-block data in memory
-@@ -81,6 +87,38 @@ struct ext3_sb_info {
+@@ -81,6 +87,43 @@ struct ext3_sb_info {
        char *s_qf_names[MAXQUOTAS];            /* Names of quota files with journalled quota */
        int s_jquota_fmt;                       /* Format of quota to use */
  #endif
 +
 +      /* for buddy allocator */
-+      struct ext3_group_info **s_group_info;
++      struct ext3_group_info ***s_group_info;
 +      struct inode *s_buddy_cache;
 +      long s_blocks_reserved;
 +      spinlock_t s_reserve_lock;
@@ -89,6 +89,7 @@ Index: linux-2.6.9-full/include/linux/ext3_fs_sb.h
 +      tid_t s_last_transaction;
 +      int s_mb_factor;
 +      unsigned short *s_mb_offsets, *s_mb_maxs;
++      unsigned long s_stripe;
 +
 +      /* history to debug policy */
 +      struct ext3_mb_history *s_mb_history;
@@ -109,13 +110,17 @@ Index: linux-2.6.9-full/include/linux/ext3_fs_sb.h
 +      unsigned long s_mb_buddies_generated;
 +      unsigned long long s_mb_generation_time;
  };
++
++#define EXT3_GROUP_INFO(sb, group)                                       \
++      EXT3_SB(sb)->s_group_info[(group) >> EXT3_DESC_PER_BLOCK_BITS(sb)] \
++                               [(group) & (EXT3_DESC_PER_BLOCK(sb) - 1)]
  
  #endif        /* _LINUX_EXT3_FS_SB */
-Index: linux-2.6.9-full/fs/ext3/super.c
+Index: linux-stage/fs/ext3/super.c
 ===================================================================
---- linux-2.6.9-full.orig/fs/ext3/super.c      2005-12-16 23:16:41.000000000 +0300
-+++ linux-2.6.9-full/fs/ext3/super.c   2005-12-16 23:16:42.000000000 +0300
-@@ -394,6 +394,7 @@ void ext3_put_super (struct super_block 
+--- linux-stage.orig/fs/ext3/super.c   2006-05-25 10:36:04.000000000 -0600
++++ linux-stage/fs/ext3/super.c        2006-05-25 10:36:04.000000000 -0600
+@@ -394,6 +394,7 @@ void ext3_put_super (struct super_block
        struct ext3_super_block *es = sbi->s_es;
        int i;
  
@@ -123,34 +128,45 @@ Index: linux-2.6.9-full/fs/ext3/super.c
        ext3_ext_release(sb);
        ext3_xattr_put_super(sb);
        journal_destroy(sbi->s_journal);
-@@ -596,7 +597,7 @@ enum {
-       Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0,
+@@ -597,6 +598,7 @@ enum {
        Opt_ignore, Opt_barrier, Opt_err, Opt_resize,
        Opt_iopen, Opt_noiopen, Opt_iopen_nopriv,
--      Opt_extents, Opt_extdebug,
-+      Opt_extents, Opt_extdebug, Opt_mballoc,
+       Opt_extents, Opt_noextents, Opt_extdebug,
++      Opt_mballoc, Opt_nomballoc, Opt_stripe,
  };
  
  static match_table_t tokens = {
-@@ -647,6 +649,7 @@ static match_table_t tokens = {
-       {Opt_iopen_nopriv, "iopen_nopriv"},
+@@ -649,6 +651,9 @@ static match_table_t tokens = {
        {Opt_extents, "extents"},
+       {Opt_noextents, "noextents"},
        {Opt_extdebug, "extdebug"},
 +      {Opt_mballoc, "mballoc"},
++      {Opt_nomballoc, "nomballoc"},
++      {Opt_stripe, "stripe=%u"},
        {Opt_barrier, "barrier=%u"},
        {Opt_err, NULL},
        {Opt_resize, "resize"},
-@@ -957,6 +960,9 @@ clear_qf_name:
+@@ -962,6 +967,19 @@ static int parse_options (char * options
                case Opt_extdebug:
                        set_opt (sbi->s_mount_opt, EXTDEBUG);
                        break;
 +              case Opt_mballoc:
-+                      set_opt (sbi->s_mount_opt, MBALLOC);
++                      set_opt(sbi->s_mount_opt, MBALLOC);
++                      break;
++              case Opt_nomballoc:
++                      clear_opt(sbi->s_mount_opt, MBALLOC);
++                      break;
++              case Opt_stripe:
++                      if (match_int(&args[0], &option))
++                              return 0;
++                      if (option < 0)
++                              return 0;
++                      sbi->s_stripe = option;
 +                      break;
                default:
                        printk (KERN_ERR
                                "EXT3-fs: Unrecognized mount option \"%s\" "
-@@ -1646,6 +1652,7 @@ static int ext3_fill_super (struct super
+@@ -1651,6 +1669,7 @@ static int ext3_fill_super (struct super
                ext3_count_dirs(sb));
  
        ext3_ext_init(sb);
@@ -158,7 +174,7 @@ Index: linux-2.6.9-full/fs/ext3/super.c
  
        return 0;
  
-@@ -2428,7 +2435,13 @@ static struct file_system_type ext3_fs_t
+@@ -2433,7 +2452,13 @@ static struct file_system_type ext3_fs_t
  
  static int __init init_ext3_fs(void)
  {
@@ -173,7 +189,7 @@ Index: linux-2.6.9-full/fs/ext3/super.c
        if (err)
                return err;
        err = init_inodecache();
-@@ -2450,6 +2463,7 @@ static void __exit exit_ext3_fs(void)
+@@ -2455,6 +2480,7 @@ static void __exit exit_ext3_fs(void)
        unregister_filesystem(&ext3_fs_type);
        destroy_inodecache();
        exit_ext3_xattr();
@@ -181,11 +197,11 @@ Index: linux-2.6.9-full/fs/ext3/super.c
  }
  
  int ext3_prep_san_write(struct inode *inode, long *blocks,
-Index: linux-2.6.9-full/fs/ext3/extents.c
+Index: linux-stage/fs/ext3/extents.c
 ===================================================================
---- linux-2.6.9-full.orig/fs/ext3/extents.c    2005-12-16 23:16:41.000000000 +0300
-+++ linux-2.6.9-full/fs/ext3/extents.c 2005-12-16 23:16:42.000000000 +0300
-@@ -771,7 +771,7 @@ cleanup:
+--- linux-stage.orig/fs/ext3/extents.c 2006-05-25 10:36:04.000000000 -0600
++++ linux-stage/fs/ext3/extents.c      2006-05-25 10:36:04.000000000 -0600
+@@ -777,7 +777,7 @@ cleanup:
                for (i = 0; i < depth; i++) {
                        if (!ablocks[i])
                                continue;
@@ -194,7 +210,7 @@ Index: linux-2.6.9-full/fs/ext3/extents.c
                }
        }
        kfree(ablocks);
-@@ -1428,7 +1428,7 @@ int ext3_ext_rm_idx(handle_t *handle, st
+@@ -1434,7 +1434,7 @@ int ext3_ext_rm_idx(handle_t *handle, st
                  path->p_idx->ei_leaf);
        bh = sb_find_get_block(tree->inode->i_sb, path->p_idx->ei_leaf);
        ext3_forget(handle, 1, tree->inode, bh, path->p_idx->ei_leaf);
@@ -203,7 +219,7 @@ Index: linux-2.6.9-full/fs/ext3/extents.c
        return err;
  }
  
-@@ -1913,10 +1913,12 @@ ext3_remove_blocks(struct ext3_extents_t
+@@ -1919,10 +1919,12 @@ ext3_remove_blocks(struct ext3_extents_t
        int needed = ext3_remove_blocks_credits(tree, ex, from, to);
        handle_t *handle = ext3_journal_start(tree->inode, needed);
        struct buffer_head *bh;
@@ -217,7 +233,7 @@ Index: linux-2.6.9-full/fs/ext3/extents.c
        if (from >= ex->ee_block && to == ex->ee_block + ex->ee_len - 1) {
                /* tail removal */
                unsigned long num, start;
-@@ -1928,7 +1930,7 @@ ext3_remove_blocks(struct ext3_extents_t
+@@ -1934,7 +1936,7 @@ ext3_remove_blocks(struct ext3_extents_t
                        bh = sb_find_get_block(tree->inode->i_sb, start + i);
                        ext3_forget(handle, 0, tree->inode, bh, start + i);
                }
@@ -226,10 +242,10 @@ Index: linux-2.6.9-full/fs/ext3/extents.c
        } else if (from == ex->ee_block && to <= ex->ee_block + ex->ee_len - 1) {
                printk("strange request: removal %lu-%lu from %u:%u\n",
                       from, to, ex->ee_block, ex->ee_len);
-Index: linux-2.6.9-full/fs/ext3/inode.c
+Index: linux-stage/fs/ext3/inode.c
 ===================================================================
---- linux-2.6.9-full.orig/fs/ext3/inode.c      2005-12-16 23:16:41.000000000 +0300
-+++ linux-2.6.9-full/fs/ext3/inode.c   2005-12-16 23:16:42.000000000 +0300
+--- linux-stage.orig/fs/ext3/inode.c   2006-05-25 10:36:04.000000000 -0600
++++ linux-stage/fs/ext3/inode.c        2006-05-25 10:36:04.000000000 -0600
 @@ -572,7 +572,7 @@ static int ext3_alloc_branch(handle_t *h
                ext3_journal_forget(handle, branch[i].bh);
        }
@@ -257,7 +273,7 @@ Index: linux-2.6.9-full/fs/ext3/inode.c
  }
  
  /**
-@@ -2004,7 +2004,7 @@ static void ext3_free_branches(handle_t 
+@@ -2004,7 +2004,7 @@ static void ext3_free_branches(handle_t
                                ext3_journal_test_restart(handle, inode);
                        }
  
@@ -266,10 +282,10 @@ Index: linux-2.6.9-full/fs/ext3/inode.c
  
                        if (parent_bh) {
                                /*
-Index: linux-2.6.9-full/fs/ext3/balloc.c
+Index: linux-stage/fs/ext3/balloc.c
 ===================================================================
---- linux-2.6.9-full.orig/fs/ext3/balloc.c     2005-10-27 21:44:24.000000000 +0400
-+++ linux-2.6.9-full/fs/ext3/balloc.c  2005-12-16 23:16:42.000000000 +0300
+--- linux-stage.orig/fs/ext3/balloc.c  2006-05-25 10:36:02.000000000 -0600
++++ linux-stage/fs/ext3/balloc.c       2006-05-25 10:36:04.000000000 -0600
 @@ -79,7 +79,7 @@ struct ext3_group_desc * ext3_get_group_
   *
   * Return buffer_head on success or NULL in case of failure.
@@ -279,7 +295,7 @@ Index: linux-2.6.9-full/fs/ext3/balloc.c
  read_block_bitmap(struct super_block *sb, unsigned int block_group)
  {
        struct ext3_group_desc * desc;
-@@ -450,24 +450,6 @@ error_return:
+@@ -451,24 +451,6 @@
        return;
  }
  
@@ -304,7 +320,7 @@ Index: linux-2.6.9-full/fs/ext3/balloc.c
  /*
   * For ext3 allocations, we must not reuse any blocks which are
   * allocated in the bitmap buffer's "last committed data" copy.  This
-@@ -1140,7 +1122,7 @@ int ext3_should_retry_alloc(struct super
+@@ -1131,7 +1113,7 @@
   * bitmap, and then for any free bit if that fails.
   * This function also updates quota and i_blocks field.
   */
@@ -313,10 +329,10 @@ Index: linux-2.6.9-full/fs/ext3/balloc.c
                        unsigned long goal, int *errp)
  {
        struct buffer_head *bitmap_bh = NULL;
-Index: linux-2.6.9-full/fs/ext3/xattr.c
+Index: linux-stage/fs/ext3/xattr.c
 ===================================================================
---- linux-2.6.9-full.orig/fs/ext3/xattr.c      2005-12-16 23:16:40.000000000 +0300
-+++ linux-2.6.9-full/fs/ext3/xattr.c   2005-12-16 23:16:42.000000000 +0300
+--- linux-stage.orig/fs/ext3/xattr.c   2006-05-25 10:36:04.000000000 -0600
++++ linux-stage/fs/ext3/xattr.c        2006-05-25 10:36:04.000000000 -0600
 @@ -1281,7 +1281,7 @@ ext3_xattr_set_handle2(handle_t *handle,
                        new_bh = sb_getblk(sb, block);
                        if (!new_bh) {
@@ -344,11 +360,11 @@ Index: linux-2.6.9-full/fs/ext3/xattr.c
                get_bh(bh);
                ext3_forget(handle, 1, inode, bh, EXT3_I(inode)->i_file_acl);
        } else {
-Index: linux-2.6.9-full/fs/ext3/mballoc.c
+Index: linux-stage/fs/ext3/mballoc.c
 ===================================================================
---- linux-2.6.9-full.orig/fs/ext3/mballoc.c    2005-12-16 17:46:19.148560250 +0300
-+++ linux-2.6.9-full/fs/ext3/mballoc.c 2005-12-17 00:10:15.000000000 +0300
-@@ -0,0 +1,2429 @@
+--- linux-stage.orig/fs/ext3/mballoc.c 2006-05-23 17:33:37.579436680 -0600
++++ linux-stage/fs/ext3/mballoc.c      2006-05-25 10:59:14.000000000 -0600
+@@ -0,0 +1,2701 @@
 +/*
 + * Copyright (c) 2003-2005, Cluster File Systems, Inc, info@clusterfs.com
 + * Written by Alex Tomas <alex@clusterfs.com>
@@ -437,6 +453,12 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +
 +long ext3_mb_stats = 1;
 +
++/*
++ * for which requests use 2^N search using buddies
++ */
++long ext3_mb_order2_reqs = 8;
++
++
 +#ifdef EXT3_BB_MAX_BLOCKS
 +#undef EXT3_BB_MAX_BLOCKS
 +#endif
@@ -477,10 +499,10 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +
 +      /* search goals */
 +      struct ext3_free_extent ac_g_ex;
-+      
++
 +      /* the best found extent */
 +      struct ext3_free_extent ac_b_ex;
-+      
++
 +      /* number of iterations done. we have to track to limit searching */
 +      unsigned long ac_ex_scanned;
 +      __u16 ac_groups_scanned;
@@ -502,6 +524,8 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +struct ext3_mb_history {
 +      struct ext3_free_extent goal;   /* goal allocation */
 +      struct ext3_free_extent result; /* result allocation */
++      unsigned pid;
++      unsigned ino;
 +      __u16 found;    /* how many extents have been found */
 +      __u16 groups;   /* how many groups have been scanned */
 +      __u16 tail;     /* what tail broke some buddy */
@@ -524,9 +548,9 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +#define EXT3_MB_BUDDY(e3b)    ((e3b)->bd_buddy)
 +
 +#ifndef EXT3_MB_HISTORY
-+#define ext3_mb_store_history(sb,ac)
++#define ext3_mb_store_history(sb,ino,ac)
 +#else
-+static void ext3_mb_store_history(struct super_block *,
++static void ext3_mb_store_history(struct super_block *, unsigned ino,
 +                              struct ext3_allocation_context *ac);
 +#endif
 +
@@ -645,7 +669,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +              if (mb_check_counter++ % 300 != 0)
 +                      return;
 +      }
-+      
++
 +      while (order > 1) {
 +              buddy = mb_find_buddy(e3b, order, &max);
 +              J_ASSERT(buddy);
@@ -826,7 +850,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      sb = inode->i_sb;
 +      blocksize = 1 << inode->i_blkbits;
 +      blocks_per_page = PAGE_CACHE_SIZE / blocksize;
-+      
++
 +      groups_per_page = blocks_per_page >> 1;
 +      if (groups_per_page == 0)
 +              groups_per_page = 1;
@@ -841,9 +865,9 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +              memset(bh, 0, i);
 +      } else
 +              bh = &bhs;
-+      
++
 +      first_group = page->index * blocks_per_page / 2;
-+      
++
 +      /* read all groups the page covers into the cache */
 +      for (i = 0; i < groups_per_page; i++) {
 +              struct ext3_group_desc * desc;
@@ -898,11 +922,11 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +                      mb_debug("put buddy for group %u in page %lu/%x\n",
 +                              group, page->index, i * blocksize);
 +                      memset(data, 0xff, blocksize);
-+                      EXT3_SB(sb)->s_group_info[group]->bb_fragments = 0;
-+                      memset(EXT3_SB(sb)->s_group_info[group]->bb_counters, 0,
++                      EXT3_GROUP_INFO(sb, group)->bb_fragments = 0;
++                      memset(EXT3_GROUP_INFO(sb, group)->bb_counters, 0,
 +                              sizeof(unsigned short)*(sb->s_blocksize_bits+2));
 +                      ext3_mb_generate_buddy(sb, data, bitmap,
-+                                              EXT3_SB(sb)->s_group_info[group]);
++                                              EXT3_GROUP_INFO(sb, group));
 +              } else {
 +                      /* this is block of bitmap */
 +                      mb_debug("put bitmap for group %u in page %lu/%x\n",
@@ -935,7 +959,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      blocks_per_page = PAGE_CACHE_SIZE / sb->s_blocksize;
 +
 +      e3b->bd_blkbits = sb->s_blocksize_bits;
-+      e3b->bd_info = sbi->s_group_info[group];
++      e3b->bd_info = EXT3_GROUP_INFO(sb, group);
 +      e3b->bd_sb = sb;
 +      e3b->bd_group = group;
 +      e3b->bd_buddy_page = NULL;
@@ -1011,14 +1035,14 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +ext3_lock_group(struct super_block *sb, int group)
 +{
 +      bit_spin_lock(EXT3_GROUP_INFO_LOCKED_BIT,
-+                      &EXT3_SB(sb)->s_group_info[group]->bb_state);
++                    &EXT3_GROUP_INFO(sb, group)->bb_state);
 +}
 +
 +static inline void
 +ext3_unlock_group(struct super_block *sb, int group)
 +{
 +      bit_spin_unlock(EXT3_GROUP_INFO_LOCKED_BIT,
-+                      &EXT3_SB(sb)->s_group_info[group]->bb_state);
++                      &EXT3_GROUP_INFO(sb, group)->bb_state);
 +}
 +
 +static int mb_find_order_for_block(struct ext3_buddy *e3b, int block)
@@ -1148,7 +1172,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +static int mb_find_extent(struct ext3_buddy *e3b, int order, int block,
 +                              int needed, struct ext3_free_extent *ex)
 +{
-+      int next, max, ord;
++      int next = block, max, ord;
 +      void *buddy;
 +
 +      J_ASSERT(ex != NULL);
@@ -1173,6 +1197,11 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      ex->fe_start = block << order;
 +      ex->fe_group = e3b->bd_group;
 +
++      /* calc difference from given start */
++      next = next - ex->fe_start;
++      ex->fe_len -= next;
++      ex->fe_start += next;
++
 +      while (needed > ex->fe_len && (buddy = mb_find_buddy(e3b, order, &max))) {
 +
 +              if (block + 1 >= max)
@@ -1368,7 +1397,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +
 +      ext3_lock_group(ac->ac_sb, group);
 +      max = mb_find_extent(e3b, 0, ex.fe_start, ex.fe_len, &ex);
-+      
++
 +      if (max > 0) {
 +              ac->ac_b_ex = ex;
 +              ext3_mb_use_best_found(ac, e3b);
@@ -1385,6 +1414,8 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +                              struct ext3_buddy *e3b)
 +{
 +      int group = ac->ac_g_ex.fe_group, max, err;
++      struct ext3_sb_info *sbi = EXT3_SB(ac->ac_sb);
++      struct ext3_super_block *es = sbi->s_es;
 +      struct ext3_free_extent ex;
 +
 +      err = ext3_mb_load_buddy(ac->ac_sb, group, e3b);
@@ -1393,9 +1424,27 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +
 +      ext3_lock_group(ac->ac_sb, group);
 +      max = mb_find_extent(e3b, 0, ac->ac_g_ex.fe_start,
-+                              ac->ac_g_ex.fe_len, &ex);
-+      
-+      if (max > 0) {
++                           ac->ac_g_ex.fe_len, &ex);
++
++      if (max >= ac->ac_g_ex.fe_len && ac->ac_g_ex.fe_len == sbi->s_stripe) {
++              unsigned long start;
++              start = (e3b->bd_group * EXT3_BLOCKS_PER_GROUP(ac->ac_sb) +
++                      ex.fe_start + le32_to_cpu(es->s_first_data_block));
++              if (start % sbi->s_stripe == 0) {
++                      ac->ac_found++;
++                      ac->ac_b_ex = ex;
++                      ext3_mb_use_best_found(ac, e3b);
++              }
++      } else if (max >= ac->ac_g_ex.fe_len) {
++              J_ASSERT(ex.fe_len > 0);
++              J_ASSERT(ex.fe_group == ac->ac_g_ex.fe_group);
++              J_ASSERT(ex.fe_start == ac->ac_g_ex.fe_start);
++              ac->ac_found++;
++              ac->ac_b_ex = ex;
++              ext3_mb_use_best_found(ac, e3b);
++      } else if (max > 0 && (ac->ac_flags & EXT3_MB_HINT_MERGE)) {
++              /* Sometimes, caller may want to merge even small
++               * number of blocks to an existing extent */
 +              J_ASSERT(ex.fe_len > 0);
 +              J_ASSERT(ex.fe_group == ac->ac_g_ex.fe_group);
 +              J_ASSERT(ex.fe_start == ac->ac_g_ex.fe_start);
@@ -1423,7 +1472,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      int i, k, max;
 +
 +      J_ASSERT(ac->ac_2order > 0);
-+      for (i = ac->ac_2order; i < sb->s_blocksize_bits + 1; i++) {
++      for (i = ac->ac_2order; i <= sb->s_blocksize_bits + 1; i++) {
 +              if (grp->bb_counters[i] == 0)
 +                      continue;
 +
@@ -1488,11 +1537,46 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      }
 +}
 +
++/*
++ * This is a special case for storages like raid5
++ * we try to find stripe-aligned chunks for stripe-size requests
++ */
++static void ext3_mb_scan_aligned(struct ext3_allocation_context *ac,
++                               struct ext3_buddy *e3b)
++{
++      struct super_block *sb = ac->ac_sb;
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      void *bitmap = EXT3_MB_BITMAP(e3b);
++      struct ext3_free_extent ex;
++      unsigned long i, max;
++
++      J_ASSERT(sbi->s_stripe != 0);
++
++      /* find first stripe-aligned block */
++      i = e3b->bd_group * EXT3_BLOCKS_PER_GROUP(sb)
++              + le32_to_cpu(sbi->s_es->s_first_data_block);
++      i = ((i + sbi->s_stripe - 1) / sbi->s_stripe) * sbi->s_stripe;
++      i = (i - le32_to_cpu(sbi->s_es->s_first_data_block))
++                      % EXT3_BLOCKS_PER_GROUP(sb);
++
++      while (i < sb->s_blocksize * 8) {
++              if (!mb_test_bit(i, bitmap)) {
++                      max = mb_find_extent(e3b, 0, i, sbi->s_stripe, &ex);
++                      if (max >= sbi->s_stripe) {
++                              ac->ac_found++;
++                              ac->ac_b_ex = ex;
++                              ext3_mb_use_best_found(ac, e3b);
++                              break;
++                      }
++              }
++              i += sbi->s_stripe;
++      }
++}
++
 +static int ext3_mb_good_group(struct ext3_allocation_context *ac,
 +                              int group, int cr)
 +{
-+      struct ext3_sb_info *sbi = EXT3_SB(ac->ac_sb);
-+      struct ext3_group_info *grp = sbi->s_group_info[group];
++      struct ext3_group_info *grp = EXT3_GROUP_INFO(ac->ac_sb, group);
 +      unsigned free, fragments, i, bits;
 +
 +      J_ASSERT(cr >= 0 && cr < 4);
@@ -1509,15 +1593,18 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +              case 0:
 +                      J_ASSERT(ac->ac_2order != 0);
 +                      bits = ac->ac_sb->s_blocksize_bits + 1;
-+                      for (i = ac->ac_2order; i < bits; i++)
++                      for (i = ac->ac_2order; i <= bits; i++)
 +                              if (grp->bb_counters[i] > 0)
 +                                      return 1;
++                      break;
 +              case 1:
 +                      if ((free / fragments) >= ac->ac_g_ex.fe_len)
 +                              return 1;
++                      break;
 +              case 2:
 +                      if (free >= ac->ac_g_ex.fe_len)
 +                              return 1;
++                      break;
 +              case 3:
 +                      return 1;
 +              default:
@@ -1618,23 +1705,27 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      ac.ac_2order = 0;
 +      ac.ac_criteria = 0;
 +
++      if (*len == 1 && sbi->s_stripe) {
++              /* looks like a metadata, let's use a dirty hack for raid5
++               * move all metadata in first groups in hope to hit cached
++               * sectors and thus avoid read-modify cycles in raid5 */
++              ac.ac_g_ex.fe_group = group = 0;
++      }
++
 +      /* probably, the request is for 2^8+ blocks (1/2/3/... MB) */
 +      i = ffs(*len);
-+      if (i >= 8) {
++      if (i >= ext3_mb_order2_reqs) {
 +              i--;
 +              if ((*len & (~(1 << i))) == 0)
 +                      ac.ac_2order = i;
 +      }
 +
-+      /* Sometimes, caller may want to merge even small
-+       * number of blocks to an existing extent */
-+      if (ac.ac_flags & EXT3_MB_HINT_MERGE) {
-+              err = ext3_mb_find_by_goal(&ac, &e3b);
-+              if (err)
-+                      goto out_err;
-+              if (ac.ac_status == AC_STATUS_FOUND)
-+                      goto found;
-+      }
++      /* first, try the goal */
++      err = ext3_mb_find_by_goal(&ac, &e3b);
++      if (err)
++              goto out_err;
++      if (ac.ac_status == AC_STATUS_FOUND)
++              goto found;
 +
 +      /* Let's just scan groups to find more-less suitable blocks */
 +      cr = ac.ac_2order ? 0 : 1;
@@ -1645,7 +1736,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +                      if (group == EXT3_SB(sb)->s_groups_count)
 +                              group = 0;
 +
-+                      if (EXT3_MB_GRP_NEED_INIT(sbi->s_group_info[group])) {
++                      if (EXT3_MB_GRP_NEED_INIT(EXT3_GROUP_INFO(sb, group))) {
 +                              /* we need full data about the group
 +                               * to make a good selection */
 +                              err = ext3_mb_load_buddy(ac.ac_sb, group, &e3b);
@@ -1673,6 +1764,8 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +                      ac.ac_groups_scanned++;
 +                      if (cr == 0)
 +                              ext3_mb_simple_scan_group(&ac, &e3b);
++                      else if (cr == 1 && *len == sbi->s_stripe) 
++                              ext3_mb_scan_aligned(&ac, &e3b);
 +                      else
 +                              ext3_mb_complex_scan_group(&ac, &e3b);
 +
@@ -1686,7 +1779,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      }
 +
 +      if (ac.ac_b_ex.fe_len > 0 && ac.ac_status != AC_STATUS_FOUND &&
-+                      !(ac.ac_flags & EXT3_MB_HINT_FIRST)) {
++          !(ac.ac_flags & EXT3_MB_HINT_FIRST)) {
 +              /*
 +               * We've been searching too long. Let's try to allocate
 +               * the best chunk we've found so far
@@ -1731,8 +1824,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +                      sbi->s_blocks_reserved, ac.ac_found);
 +              printk("EXT3-fs: groups: ");
 +              for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++)
-+                      printk("%d: %d ", i,
-+                              sbi->s_group_info[i]->bb_free);
++                      printk("%d: %d ", i, EXT3_GROUP_INFO(sb, i)->bb_free);
 +              printk("\n");
 +#endif
 +              goto out;
@@ -1770,7 +1862,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +              *errp = -EIO;
 +              goto out_err;
 +      }
-+      
++
 +      err = ext3_journal_get_write_access(handle, gdp_bh);
 +      if (err)
 +              goto out_err;
@@ -1839,7 +1931,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +               * path only, here is single block always */
 +              ext3_mb_release_blocks(sb, 1);
 +      }
-+      
++
 +      if (unlikely(ext3_mb_stats) && ac.ac_g_ex.fe_len > 1) {
 +              atomic_inc(&sbi->s_bal_reqs);
 +              atomic_add(*len, &sbi->s_bal_allocated);
@@ -1853,7 +1945,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +                      atomic_inc(&sbi->s_bal_breaks);
 +      }
 +
-+      ext3_mb_store_history(sb, &ac);
++      ext3_mb_store_history(sb, inode->i_ino, &ac);
 +
 +      return block;
 +}
@@ -1918,9 +2010,9 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      char buf[20], buf2[20];
 +
 +      if (v == SEQ_START_TOKEN) {
-+              seq_printf(seq, "%-17s %-17s %-5s %-5s %-2s %-5s %-5s %-6s\n",
-+                       "goal", "result", "found", "grps", "cr", "merge",
-+                       "tail", "broken");
++              seq_printf(seq, "%-5s %-8s %-17s %-17s %-5s %-5s %-2s %-5s %-5s %-6s\n",
++                       "pid", "inode", "goal", "result", "found", "grps", "cr",
++                       "merge", "tail", "broken");
 +              return 0;
 +      }
 +
@@ -1928,9 +2020,9 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +              hs->goal.fe_start, hs->goal.fe_len);
 +      sprintf(buf2, "%u/%u/%u", hs->result.fe_group,
 +              hs->result.fe_start, hs->result.fe_len);
-+      seq_printf(seq, "%-17s %-17s %-5u %-5u %-2u %-5s %-5u %-6u\n", buf,
-+                      buf2, hs->found, hs->groups, hs->cr, 
-+                      hs->merged ? "M" : "", hs->tail,
++      seq_printf(seq, "%-5u %-8u %-17s %-17s %-5u %-5u %-2u %-5s %-5u %-6u\n",
++                      hs->pid, hs->ino, buf, buf2, hs->found, hs->groups,
++                      hs->cr, hs->merged ? "M" : "", hs->tail,
 +                      hs->buddy ? 1 << hs->buddy : 0);
 +      return 0;
 +}
@@ -1964,7 +2056,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      s->max = sbi->s_mb_history_max;
 +      s->start = sbi->s_mb_history_cur % s->max;
 +      spin_unlock(&sbi->s_mb_history_lock);
-+      
++
 +      rc = seq_open(file, &ext3_mb_seq_history_ops);
 +      if (rc == 0) {
 +              struct seq_file *m = (struct seq_file *)file->private_data;
@@ -1988,10 +2080,104 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +
 +static struct file_operations ext3_mb_seq_history_fops = {
 +      .owner          = THIS_MODULE,
-+      .open           = ext3_mb_seq_history_open,
-+      .read           = seq_read,
-+      .llseek         = seq_lseek,
-+      .release        = ext3_mb_seq_history_release,
++      .open           = ext3_mb_seq_history_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = ext3_mb_seq_history_release,
++};
++
++static void *ext3_mb_seq_groups_start(struct seq_file *seq, loff_t *pos)
++{
++      struct super_block *sb = seq->private;
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      long group;
++
++      if (*pos < 0 || *pos >= sbi->s_groups_count)
++              return NULL;
++
++      group = *pos + 1;
++      return (void *) group;
++}
++
++static void *ext3_mb_seq_groups_next(struct seq_file *seq, void *v, loff_t *pos)
++{
++      struct super_block *sb = seq->private;
++      struct ext3_sb_info *sbi = EXT3_SB(sb);
++      long group;
++
++      ++*pos;
++      if (*pos < 0 || *pos >= sbi->s_groups_count)
++              return NULL;
++      group = *pos + 1;
++      return (void *) group;;
++}
++
++static int ext3_mb_seq_groups_show(struct seq_file *seq, void *v)
++{
++      struct super_block *sb = seq->private;
++      long group = (long) v, i;
++      struct sg {
++              struct ext3_group_info info;
++              unsigned short counters[16];
++      } sg;
++
++      group--;
++      if (group == 0)
++              seq_printf(seq, "#%-5s: %-5s %-5s %-5s [ %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s ]\n",
++                       "group", "free", "frags", "first", "2^0", "2^1", "2^2", 
++                       "2^3", "2^4", "2^5", "2^6", "2^7", "2^8", "2^9", "2^10",
++                       "2^11", "2^12", "2^13");
++
++      i = (sb->s_blocksize_bits + 2) * sizeof(sg.info.bb_counters[0]) +
++              sizeof(struct ext3_group_info);
++      ext3_lock_group(sb, group);
++      memcpy(&sg, EXT3_GROUP_INFO(sb, group), i);
++      ext3_unlock_group(sb, group);
++
++      if (EXT3_MB_GRP_NEED_INIT(&sg.info))
++              return 0;
++
++      seq_printf(seq, "#%-5lu: %-5u %-5u %-5u [", group, sg.info.bb_free,
++                      sg.info.bb_fragments, sg.info.bb_first_free);
++      for (i = 0; i <= 13; i++)
++              seq_printf(seq, " %-5u", i <= sb->s_blocksize_bits + 1 ?
++                              sg.info.bb_counters[i] : 0);
++      seq_printf(seq, " ]\n");
++
++      return 0;
++}
++
++static void ext3_mb_seq_groups_stop(struct seq_file *seq, void *v)
++{
++}
++
++static struct seq_operations ext3_mb_seq_groups_ops = {
++      .start  = ext3_mb_seq_groups_start,
++      .next   = ext3_mb_seq_groups_next,
++      .stop   = ext3_mb_seq_groups_stop,
++      .show   = ext3_mb_seq_groups_show,
++};
++
++static int ext3_mb_seq_groups_open(struct inode *inode, struct file *file)
++{
++      struct super_block *sb = PDE(inode)->data;
++      int rc;
++
++      rc = seq_open(file, &ext3_mb_seq_groups_ops);
++      if (rc == 0) {
++              struct seq_file *m = (struct seq_file *)file->private_data;
++              m->private = sb;
++      }
++      return rc;
++
++}
++
++static struct file_operations ext3_mb_seq_groups_fops = {
++      .owner          = THIS_MODULE,
++      .open           = ext3_mb_seq_groups_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = seq_release,
 +};
 +
 +static void ext3_mb_history_release(struct super_block *sb)
@@ -2000,6 +2186,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      char name[64];
 +
 +      snprintf(name, sizeof(name) - 1, "%s", bdevname(sb->s_bdev, name));
++      remove_proc_entry("mb_groups", sbi->s_mb_proc);
 +      remove_proc_entry("mb_history", sbi->s_mb_proc);
 +      remove_proc_entry(name, proc_root_ext3);
 +
@@ -2022,6 +2209,11 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +                      p->proc_fops = &ext3_mb_seq_history_fops;
 +                      p->data = sb;
 +              }
++              p = create_proc_entry("mb_groups", S_IRUGO, sbi->s_mb_proc);
++              if (p) {
++                      p->proc_fops = &ext3_mb_seq_groups_fops;
++                      p->data = sb;
++              }
 +      }
 +
 +      sbi->s_mb_history_max = 1000;
@@ -2034,7 +2226,8 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +}
 +
 +static void
-+ext3_mb_store_history(struct super_block *sb, struct ext3_allocation_context *ac)
++ext3_mb_store_history(struct super_block *sb, unsigned ino,
++                      struct ext3_allocation_context *ac)
 +{
 +      struct ext3_sb_info *sbi = EXT3_SB(sb);
 +      struct ext3_mb_history h;
@@ -2042,6 +2235,8 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      if (likely(sbi->s_mb_history == NULL))
 +              return;
 +
++      h.pid = current->pid;
++      h.ino = ino;
 +      h.goal = ac->ac_g_ex;
 +      h.result = ac->ac_b_ex;
 +      h.found = ac->ac_found;
@@ -2069,21 +2264,40 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +int ext3_mb_init_backend(struct super_block *sb)
 +{
 +      struct ext3_sb_info *sbi = EXT3_SB(sb);
-+      int i, len;
-+
-+      len = sizeof(struct ext3_buddy_group_blocks *) * sbi->s_groups_count;
-+      sbi->s_group_info = kmalloc(len, GFP_KERNEL);
++      int i, j, len, metalen;
++      int num_meta_group_infos =
++              (sbi->s_groups_count + EXT3_DESC_PER_BLOCK(sb) - 1) >>
++                      EXT3_DESC_PER_BLOCK_BITS(sb);
++      struct ext3_group_info **meta_group_info;
++
++      /* An 8TB filesystem with 64-bit pointers requires a 4096 byte
++       * kmalloc. A 128kb malloc should suffice for a 256TB filesystem.
++       * So a two level scheme suffices for now. */
++      sbi->s_group_info = kmalloc(sizeof(*sbi->s_group_info) *
++                                  num_meta_group_infos, GFP_KERNEL);
 +      if (sbi->s_group_info == NULL) {
-+              printk(KERN_ERR "EXT3-fs: can't allocate mem for buddy\n");
++              printk(KERN_ERR "EXT3-fs: can't allocate buddy meta group\n");
 +              return -ENOMEM;
 +      }
-+      memset(sbi->s_group_info, 0, len);
-+
 +      sbi->s_buddy_cache = new_inode(sb);
 +      if (sbi->s_buddy_cache == NULL) {
 +              printk(KERN_ERR "EXT3-fs: can't get new inode\n");
-+              kfree(sbi->s_group_info);
-+              return -ENOMEM;
++              goto err_freesgi;
++      }
++
++      metalen = sizeof(*meta_group_info) << EXT3_DESC_PER_BLOCK_BITS(sb);
++      for (i = 0; i < num_meta_group_infos; i++) {
++              if ((i + 1) == num_meta_group_infos)
++                      metalen = sizeof(*meta_group_info) *
++                              (sbi->s_groups_count -
++                                      (i << EXT3_DESC_PER_BLOCK_BITS(sb)));
++              meta_group_info = kmalloc(metalen, GFP_KERNEL);
++              if (meta_group_info == NULL) {
++                      printk(KERN_ERR "EXT3-fs: can't allocate mem for a "
++                             "buddy group\n");
++                      goto err_freemeta;
++              }
++              sbi->s_group_info[i] = meta_group_info;
 +      }
 +
 +      /* 
@@ -2095,30 +2309,42 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      for (i = 0; i < sbi->s_groups_count; i++) {
 +              struct ext3_group_desc * desc;
 +
-+              sbi->s_group_info[i] = kmalloc(len, GFP_KERNEL);
-+              if (sbi->s_group_info[i] == NULL) {
++              meta_group_info =
++                      sbi->s_group_info[i >> EXT3_DESC_PER_BLOCK_BITS(sb)];
++              j = i & (EXT3_DESC_PER_BLOCK(sb) - 1);
++
++              meta_group_info[j] = kmalloc(len, GFP_KERNEL);
++              if (meta_group_info[j] == NULL) {
 +                      printk(KERN_ERR "EXT3-fs: can't allocate buddy mem\n");
-+                      goto err_out;
++                      i--;
++                      goto err_freebuddy;
 +              }
 +              desc = ext3_get_group_desc(sb, i, NULL);
 +              if (desc == NULL) {
 +                      printk(KERN_ERR"EXT3-fs: can't read descriptor %u\n",i);
-+                      goto err_out;
++                      goto err_freebuddy;
 +              }
-+              memset(sbi->s_group_info[i], 0, len);
++              memset(meta_group_info[j], 0, len);
 +              set_bit(EXT3_GROUP_INFO_NEED_INIT_BIT,
-+                      &sbi->s_group_info[i]->bb_state);
-+              sbi->s_group_info[i]->bb_free =
++                      &meta_group_info[j]->bb_state);
++              meta_group_info[j]->bb_free =
 +                      le16_to_cpu(desc->bg_free_blocks_count);
 +      }
 +
 +      return 0;
 +
-+err_out:
++err_freebuddy:
++      while (i >= 0) {
++              kfree(EXT3_GROUP_INFO(sb, i));
++              i--;
++      }
++      i = num_meta_group_infos;
++err_freemeta:
 +      while (--i >= 0)
 +              kfree(sbi->s_group_info[i]);
 +      iput(sbi->s_buddy_cache);
-+
++err_freesgi:
++      kfree(sbi->s_group_info);
 +      return -ENOMEM;
 +}
 +
@@ -2160,7 +2386,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +              max = max >> 1;
 +              i++;
 +      } while (i <= sb->s_blocksize_bits + 1);
-+      
++
 +
 +      /* init file for buddy data */
 +      if ((i = ext3_mb_init_backend(sb))) {
@@ -2197,8 +2423,8 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +int ext3_mb_release(struct super_block *sb)
 +{
 +      struct ext3_sb_info *sbi = EXT3_SB(sb);
-+      int i;
-+      
++      int i, num_meta_group_infos;
++
 +      if (!test_opt(sb, MBALLOC))
 +              return 0;
 +
@@ -2212,11 +2438,13 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      ext3_mb_free_committed_blocks(sb);
 +
 +      if (sbi->s_group_info) {
-+              for (i = 0; i < sbi->s_groups_count; i++) {
-+                      if (sbi->s_group_info[i] == NULL)
-+                              continue;
++              for (i = 0; i < sbi->s_groups_count; i++)
++                      kfree(EXT3_GROUP_INFO(sb, i));
++              num_meta_group_infos = (sbi->s_groups_count +
++                      EXT3_DESC_PER_BLOCK(sb) - 1) >>
++                      EXT3_DESC_PER_BLOCK_BITS(sb);
++              for (i = 0; i < num_meta_group_infos; i++)
 +                      kfree(sbi->s_group_info[i]);
-+              }
 +              kfree(sbi->s_group_info);
 +      }
 +      if (sbi->s_mb_offsets)
@@ -2510,7 +2738,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +              cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) + count);
 +      spin_unlock(sb_bgl_lock(sbi, block_group));
 +      percpu_counter_mod(&sbi->s_freeblocks_counter, count);
-+      
++
 +      ext3_mb_release_desc(&e3b);
 +
 +      *freed = count;
@@ -2593,10 +2821,11 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      return;
 +}
 +
-+#define EXT3_ROOT                 "ext3"
-+#define EXT3_MB_STATS_NAME        "mb_stats"
++#define EXT3_ROOT                "ext3"
++#define EXT3_MB_STATS_NAME       "mb_stats"
 +#define EXT3_MB_MAX_TO_SCAN_NAME  "mb_max_to_scan"
 +#define EXT3_MB_MIN_TO_SCAN_NAME  "mb_min_to_scan"
++#define EXT3_MB_ORDER2_REQ       "mb_order2_req"
 +
 +static int ext3_mb_stats_read(char *page, char **start, off_t off,
 +              int count, int *eof, void *data)
@@ -2684,6 +2913,45 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      return len;
 +}
 +
++static int ext3_mb_order2_req_write(struct file *file, const char *buffer,
++              unsigned long count, void *data)
++{
++      char str[32];
++      long value;
++
++      if (count >= sizeof(str)) {
++              printk(KERN_ERR "EXT3-fs: %s string too long, max %u bytes\n",
++                     EXT3_MB_MIN_TO_SCAN_NAME, (int)sizeof(str));
++              return -EOVERFLOW;
++      }
++
++      if (copy_from_user(str, buffer, count))
++              return -EFAULT;
++
++      /* Only set to 0 or 1 respectively; zero->0; non-zero->1 */
++      value = simple_strtol(str, NULL, 0);
++      if (value <= 0)
++              return -ERANGE;
++
++      ext3_mb_order2_reqs = value;    
++
++      return count;
++}
++
++static int ext3_mb_order2_req_read(char *page, char **start, off_t off,
++              int count, int *eof, void *data)
++{
++      int len;
++
++      *eof = 1;
++      if (off != 0)
++              return 0;
++
++      len = sprintf(page, "%ld\n", ext3_mb_order2_reqs);
++      *start = page;
++      return len;
++}
++
 +static int ext3_mb_min_to_scan_write(struct file *file, const char *buffer,
 +              unsigned long count, void *data)
 +{
@@ -2691,7 +2959,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      long value;
 +
 +      if (count >= sizeof(str)) {
-+              printk(KERN_ERR "EXT3: %s string too long, max %u bytes\n",
++              printk(KERN_ERR "EXT3-fs: %s string too long, max %u bytes\n",
 +                     EXT3_MB_MIN_TO_SCAN_NAME, (int)sizeof(str));
 +              return -EOVERFLOW;
 +      }
@@ -2714,10 +2982,11 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      struct proc_dir_entry *proc_ext3_mb_stats;
 +      struct proc_dir_entry *proc_ext3_mb_max_to_scan;
 +      struct proc_dir_entry *proc_ext3_mb_min_to_scan;
++      struct proc_dir_entry *proc_ext3_mb_order2_req;
 +
 +      proc_root_ext3 = proc_mkdir(EXT3_ROOT, proc_root_fs);
 +      if (proc_root_ext3 == NULL) {
-+              printk(KERN_ERR "EXT3: Unable to create %s\n", EXT3_ROOT);
++              printk(KERN_ERR "EXT3-fs: Unable to create %s\n", EXT3_ROOT);
 +              return -EIO;
 +      }
 +
@@ -2725,7 +2994,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      proc_ext3_mb_stats = create_proc_entry(EXT3_MB_STATS_NAME,
 +                      S_IFREG | S_IRUGO | S_IWUSR, proc_root_ext3);
 +      if (proc_ext3_mb_stats == NULL) {
-+              printk(KERN_ERR "EXT3: Unable to create %s\n",
++              printk(KERN_ERR "EXT3-fs: Unable to create %s\n",
 +                              EXT3_MB_STATS_NAME);
 +              remove_proc_entry(EXT3_ROOT, proc_root_fs);
 +              return -EIO;
@@ -2740,7 +3009,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +                      EXT3_MB_MAX_TO_SCAN_NAME,
 +                      S_IFREG | S_IRUGO | S_IWUSR, proc_root_ext3);
 +      if (proc_ext3_mb_max_to_scan == NULL) {
-+              printk(KERN_ERR "EXT3: Unable to create %s\n",
++              printk(KERN_ERR "EXT3-fs: Unable to create %s\n",
 +                              EXT3_MB_MAX_TO_SCAN_NAME);
 +              remove_proc_entry(EXT3_MB_STATS_NAME, proc_root_ext3);
 +              remove_proc_entry(EXT3_ROOT, proc_root_fs);
@@ -2756,7 +3025,7 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +                      EXT3_MB_MIN_TO_SCAN_NAME,
 +                      S_IFREG | S_IRUGO | S_IWUSR, proc_root_ext3);
 +      if (proc_ext3_mb_min_to_scan == NULL) {
-+              printk(KERN_ERR "EXT3: Unable to create %s\n",
++              printk(KERN_ERR "EXT3-fs: Unable to create %s\n",
 +                              EXT3_MB_MIN_TO_SCAN_NAME);
 +              remove_proc_entry(EXT3_MB_MAX_TO_SCAN_NAME, proc_root_ext3);
 +              remove_proc_entry(EXT3_MB_STATS_NAME, proc_root_ext3);
@@ -2768,6 +3037,24 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      proc_ext3_mb_min_to_scan->read_proc  = ext3_mb_min_to_scan_read;
 +      proc_ext3_mb_min_to_scan->write_proc = ext3_mb_min_to_scan_write;
 +
++      /* Initialize EXT3_ORDER2_REQ */
++      proc_ext3_mb_order2_req = create_proc_entry(
++                      EXT3_MB_ORDER2_REQ,
++                      S_IFREG | S_IRUGO | S_IWUSR, proc_root_ext3);
++      if (proc_ext3_mb_order2_req == NULL) {
++              printk(KERN_ERR "EXT3-fs: Unable to create %s\n",
++                              EXT3_MB_ORDER2_REQ);
++              remove_proc_entry(EXT3_MB_MIN_TO_SCAN_NAME, proc_root_ext3);
++              remove_proc_entry(EXT3_MB_MAX_TO_SCAN_NAME, proc_root_ext3);
++              remove_proc_entry(EXT3_MB_STATS_NAME, proc_root_ext3);
++              remove_proc_entry(EXT3_ROOT, proc_root_fs);
++              return -EIO;
++      }
++
++      proc_ext3_mb_order2_req->data = NULL;
++      proc_ext3_mb_order2_req->read_proc  = ext3_mb_order2_req_read;
++      proc_ext3_mb_order2_req->write_proc = ext3_mb_order2_req_write;
++
 +      return 0;
 +}
 +
@@ -2776,12 +3063,13 @@ Index: linux-2.6.9-full/fs/ext3/mballoc.c
 +      remove_proc_entry(EXT3_MB_STATS_NAME, proc_root_ext3);
 +      remove_proc_entry(EXT3_MB_MAX_TO_SCAN_NAME, proc_root_ext3);
 +      remove_proc_entry(EXT3_MB_MIN_TO_SCAN_NAME, proc_root_ext3);
++      remove_proc_entry(EXT3_MB_ORDER2_REQ, proc_root_ext3);
 +      remove_proc_entry(EXT3_ROOT, proc_root_fs);
 +}
-Index: linux-2.6.9-full/fs/ext3/Makefile
+Index: linux-stage/fs/ext3/Makefile
 ===================================================================
---- linux-2.6.9-full.orig/fs/ext3/Makefile     2005-12-16 23:16:41.000000000 +0300
-+++ linux-2.6.9-full/fs/ext3/Makefile  2005-12-16 23:16:42.000000000 +0300
+--- linux-stage.orig/fs/ext3/Makefile  2006-05-25 10:36:04.000000000 -0600
++++ linux-stage/fs/ext3/Makefile       2006-05-25 10:36:04.000000000 -0600
 @@ -6,7 +6,7 @@
  
  ext3-y        := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
diff --git a/lustre/kernel_patches/patches/ext3-multi-mount-protection-2.6-fc5.patch b/lustre/kernel_patches/patches/ext3-multi-mount-protection-2.6-fc5.patch
new file mode 100644 (file)
index 0000000..0c41b47
--- /dev/null
@@ -0,0 +1,381 @@
+Index: mmp/fs/ext3/al.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ mmp/fs/ext3/al.h   2006-07-24 10:39:26.000000000 +0800
+@@ -0,0 +1,11 @@
++/*
++ * (C) 2006  Qi Yong <qiyong@clusterfs.com>
++ */
++
++#define       ALIVE_MAGIC     0xA1153C29
++struct alive_struct {
++      __le32  al_magic;
++      __le32  al_seq;
++      __le32  al_time;
++      char    al_nodename[65];
++};
+Index: mmp/fs/ext3/namei.c
+===================================================================
+--- mmp.orig/fs/ext3/namei.c   2006-07-24 10:34:41.000000000 +0800
++++ mmp/fs/ext3/namei.c        2006-07-24 10:39:26.000000000 +0800
+@@ -805,7 +805,7 @@ static inline int search_dirblock(struct
+  * The returned buffer_head has ->b_count elevated.  The caller is expected
+  * to brelse() it when appropriate.
+  */
+-static struct buffer_head * ext3_find_entry (struct dentry *dentry,
++struct buffer_head * ext3_find_entry (struct dentry *dentry,
+                                       struct ext3_dir_entry_2 ** res_dir)
+ {
+       struct super_block * sb;
+Index: mmp/fs/ext3/super.c
+===================================================================
+--- mmp.orig/fs/ext3/super.c   2006-07-24 10:34:41.000000000 +0800
++++ mmp/fs/ext3/super.c        2006-07-24 10:45:19.000000000 +0800
+@@ -36,12 +36,14 @@
+ #include <linux/namei.h>
+ #include <linux/quotaops.h>
+ #include <linux/seq_file.h>
++#include <linux/kthread.h>
+ #include <asm/uaccess.h>
+ #include "xattr.h"
+ #include "acl.h"
+ #include "namei.h"
++#include "al.h"
+ static int ext3_load_journal(struct super_block *, struct ext3_super_block *,
+                            unsigned long journal_devnum);
+@@ -62,6 +64,8 @@ static int ext3_statfs (struct super_blo
+ static void ext3_unlockfs(struct super_block *sb);
+ static void ext3_write_super (struct super_block * sb);
+ static void ext3_write_super_lockfs(struct super_block *sb);
++struct buffer_head * ext3_find_entry (struct dentry *dentry,
++                                      struct ext3_dir_entry_2 ** res_dir);
+ /* 
+  * Wrappers for journal_start/end.
+@@ -435,6 +439,9 @@ static void ext3_put_super (struct super
+               invalidate_bdev(sbi->journal_bdev, 0);
+               ext3_blkdev_remove(sbi);
+       }
++      if (sbi->s_alive_tsk)
++              kthread_stop(sbi->s_alive_tsk);
++
+       sb->s_fs_info = NULL;
+       kfree(sbi);
+       return;
+@@ -1369,6 +1376,261 @@ static unsigned long descriptor_loc(stru
+       return (first_data_block + has_super + (bg * sbi->s_blocks_per_group));
+ }
++static int write_alive(struct buffer_head * bh)
++{
++      lock_buffer(bh);
++      bh->b_end_io = end_buffer_write_sync;
++      get_bh(bh);
++      submit_bh(WRITE, bh);
++      wait_on_buffer(bh);
++      if (unlikely(!buffer_uptodate(bh)))
++              return 1;
++      return 0;
++}
++
++static int read_alive_again(struct buffer_head * bh)
++{
++      lock_buffer(bh);
++      bh->b_end_io = end_buffer_read_sync;
++      get_bh(bh);
++      submit_bh(READ, bh);
++      wait_on_buffer(bh);
++      if (!buffer_uptodate(bh)) {
++              brelse(bh);
++              return 1;
++      }
++      return 0;
++}
++
++/*
++ * The caller must have a ref on the buffer_head.
++ */
++static int kalived(void *data)
++{
++      struct buffer_head * bh;
++      struct alive_struct * alive;
++      char b[BDEVNAME_SIZE];
++      u32 seq = 0;
++
++      bh = (struct buffer_head *)data;
++      bdevname(bh->b_bdev, b);
++
++      alive = (struct alive_struct *)(bh->b_data);
++      alive->al_magic = cpu_to_le32(ALIVE_MAGIC);
++      alive->al_time = cpu_to_le32(get_seconds());
++
++      down_read(&uts_sem);
++      memcpy(alive->al_nodename, system_utsname.nodename, 65);
++      up_read(&uts_sem);
++
++      while (!kthread_should_stop()) {
++              if (++seq == 0)
++                      ++seq;
++
++              alive->al_seq = cpu_to_le32(seq);
++              alive->al_time = cpu_to_le32(get_seconds());
++
++              if (unlikely(write_alive(bh))) {
++                      /* panic here? */
++                      printk(KERN_ERR "Alive (device %s): "
++                              "can't write alive block\n", b);
++                      continue;
++              }
++
++              schedule_timeout_interruptible(5 * HZ);
++      }
++
++      alive->al_seq = 0;
++      alive->al_time = cpu_to_le32(get_seconds());
++
++      if (unlikely(write_alive(bh)))
++              printk(KERN_ERR "Alive (device %s): "
++                      "can't reset alive block\n", b);
++      brelse(bh);
++      return 0;
++}
++
++static unsigned long get_alive_ino(struct super_block *sb)
++{
++      unsigned long   ino = 0;
++      struct dentry   alive;
++      struct dentry   * root;
++      struct inode    * root_inode;
++      struct ext3_dir_entry_2 * de;
++      struct buffer_head      * bh;
++
++      root_inode = iget(sb, EXT3_ROOT_INO);
++      root = d_alloc_root(root_inode);
++      if (!root) {
++              printk(KERN_ERR "Alive (device %s): get root inode failed\n",
++                      sb->s_id);
++              iput(root_inode);
++              goto out;
++      }
++
++      alive.d_name.name = ".alive";
++      alive.d_name.len = 6;
++      alive.d_parent = root;
++
++      bh = ext3_find_entry(&alive, &de);
++      dput(root);
++
++      if (!bh) {
++              printk(KERN_WARNING "Alive (device %s): alive lookup failed\n",
++                      sb->s_id);
++              goto out;
++      }
++
++      ino = le32_to_cpu(de->inode);
++      brelse (bh);
++      pr_debug("Alive (device %s): alive_ino=%lu\n", sb->s_id, ino);
++out:
++      return ino;
++}
++
++/* check alive file */
++static int check_alive(struct super_block *sb, struct ext3_sb_info *sbi)
++{
++      unsigned long           ino;
++      struct buffer_head      * bh;
++      struct ext3_inode_info  * ei;
++      struct inode            * alive_inode;
++      struct alive_struct     * alive;
++      u32 alive_block;
++      u32 seq;
++
++      ino = get_alive_ino(sb);
++      if (!ino)
++              goto failed;
++
++      alive_inode = iget(sb, ino);
++      if (!alive_inode) {
++              iput(alive_inode);
++              printk(KERN_ERR "Alive (device %s): get alive inode failed\n",
++                      sb->s_id);
++              goto failed;
++      }
++      if (!alive_inode->i_nlink) {
++              make_bad_inode(alive_inode);
++              iput(alive_inode);
++              printk(KERN_ERR "Alive (device %s): alive inode is deleted\n",
++                      sb->s_id);
++              goto failed;
++      }
++      if (!S_ISREG(alive_inode->i_mode)) {
++              iput(alive_inode);
++              printk(KERN_ERR "Alive (device %s): invalid alive inode\n",
++                      sb->s_id);
++              goto failed;
++      }
++      if (EXT3_I(alive_inode)->i_flags & EXT3_EXTENTS_FL) {
++              iput(alive_inode);
++              printk(KERN_ERR "Alive (device %s): invalid alive inode, "
++                      "in extents format\n", sb->s_id);
++              goto failed;
++      }
++
++      ei = EXT3_I(alive_inode);
++      alive_block = ei->i_data[0];
++      iput(alive_inode);
++
++      pr_debug("Alive (device %s): read in alive block #%u\n",
++                      sb->s_id, alive_block);
++
++      /* first read */
++      bh = sb_bread(sb, alive_block);
++      if (!bh) {
++              printk(KERN_ERR "Alive (device %s): "
++                      "can't read alive block #%u\n", sb->s_id, alive_block);
++              goto failed;
++      }
++
++      alive = (struct alive_struct *)(bh->b_data);
++      if (le32_to_cpu(alive->al_magic) != ALIVE_MAGIC) {
++              printk(KERN_ERR "Alive (device %s): "
++                      "magic mismatch\n", sb->s_id);
++              brelse(bh);
++              goto failed;
++      }
++
++      seq = le32_to_cpu(alive->al_seq);
++      pr_debug("Alive (device %s): seq=%u\n", sb->s_id, seq);
++      pr_info ("Alive (device %s): last touched by node: %s, "
++              "%li seconds ago\n", sb->s_id, alive->al_nodename,
++              get_seconds() - le32_to_cpu(alive->al_time));
++
++      if (seq == 0)
++              goto skip;
++
++      /* wait 8s */
++      pr_info("Alive (device %s): wait for 8 seconds...\n", sb->s_id);
++      schedule_timeout_uninterruptible(HZ * 8);
++
++      /* read again */
++      if (read_alive_again(bh)) {
++              printk(KERN_ERR "Alive (device %s): "
++                      "can't read alive block #%u\n",
++                      sb->s_id, alive_block);
++              goto failed;
++      }
++
++      alive = (struct alive_struct *)(bh->b_data);
++      pr_debug("Alive (device %s): seq=%u\n",
++              sb->s_id, le32_to_cpu(alive->al_seq));
++
++      if (seq != le32_to_cpu(alive->al_seq)) {
++              printk(KERN_WARNING "Alive (device %s): "
++                      "still active on node %s\n",
++                      sb->s_id, alive->al_nodename);
++              brelse(bh);
++              goto failed;
++      }
++skip:
++      /* write a new random seq */
++      get_random_bytes(&seq, sizeof(u32));
++      alive->al_seq = cpu_to_le32(seq);
++      if (unlikely(write_alive(bh))) {
++              printk(KERN_ERR "Alive (device %s): "
++                      "can't write alive block\n", sb->s_id);
++              goto failed;
++      }
++      pr_debug("Alive (device %s): write random seq=%u\n", sb->s_id, seq);
++
++      /* wait 6s */
++      pr_info("Alive (device %s): wait for 6 seconds...\n", sb->s_id);
++      schedule_timeout_uninterruptible(HZ * 6);
++
++      /* read again */
++      if (read_alive_again(bh)) {
++              printk(KERN_ERR "Alive (device %s): "
++                      "can't read alive block #%u\n",
++                      sb->s_id, alive_block);
++              goto failed;
++      }
++
++      alive = (struct alive_struct *)(bh->b_data);
++      pr_debug("Alive (device %s): seq=%u\n",
++              sb->s_id, le32_to_cpu(alive->al_seq));
++
++      if (seq != le32_to_cpu(alive->al_seq)) {
++              printk(KERN_WARNING "Alive (device %s): "
++                      "still active on node %s\n",
++                      sb->s_id, alive->al_nodename);
++              brelse(bh);
++              goto failed;
++      }
++
++      /* succeed */
++      pr_info("Alive (device %s): alive check passed!\n", sb->s_id);
++      sbi->s_alive_tsk = kthread_run(kalived, bh, "kalived");
++      return 0;
++
++failed:
++      printk(KERN_WARNING "Alive (device %s): alive check failed!\n",
++              sb->s_id);
++      return 1;
++}
++
+ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
+ {
+@@ -1668,6 +1930,10 @@ static int ext3_fill_super (struct super
+                         EXT3_HAS_INCOMPAT_FEATURE(sb,
+                                   EXT3_FEATURE_INCOMPAT_RECOVER));
++      if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_ALIVE))
++              if (check_alive(sb, sbi))
++                      goto failed_mount2;
++
+       /*
+        * The first inode we look at is the journal inode.  Don't try
+        * root first: it may be modified in the journal!
+@@ -1785,6 +2051,8 @@ cantfind_ext3:
+ failed_mount3:
+       journal_destroy(sbi->s_journal);
++      if (sbi->s_alive_tsk)
++              kthread_stop(sbi->s_alive_tsk);
+ failed_mount2:
+       for (i = 0; i < db_count; i++)
+               brelse(sbi->s_group_desc[i]);
+Index: mmp/include/linux/ext3_fs.h
+===================================================================
+--- mmp.orig/include/linux/ext3_fs.h   2006-07-24 10:34:41.000000000 +0800
++++ mmp/include/linux/ext3_fs.h        2006-07-24 10:39:26.000000000 +0800
+@@ -581,12 +581,14 @@ static inline struct ext3_inode_info *EX
+ #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV     0x0008 /* Journal device */
+ #define EXT3_FEATURE_INCOMPAT_META_BG         0x0010
+ #define EXT3_FEATURE_INCOMPAT_EXTENTS         0x0040 /* extents support */
++#define EXT3_FEATURE_INCOMPAT_ALIVE           0x0080
+ #define EXT3_FEATURE_COMPAT_SUPP      EXT2_FEATURE_COMPAT_EXT_ATTR
+ #define EXT3_FEATURE_INCOMPAT_SUPP    (EXT3_FEATURE_INCOMPAT_FILETYPE| \
+                                        EXT3_FEATURE_INCOMPAT_RECOVER| \
+                                        EXT3_FEATURE_INCOMPAT_META_BG| \
+-                                       EXT3_FEATURE_INCOMPAT_EXTENTS)
++                                       EXT3_FEATURE_INCOMPAT_EXTENTS| \
++                                       EXT3_FEATURE_INCOMPAT_ALIVE)
+ #define EXT3_FEATURE_RO_COMPAT_SUPP   (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
+                                        EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \
+                                        EXT3_FEATURE_RO_COMPAT_BTREE_DIR)
+Index: mmp/include/linux/ext3_fs_sb.h
+===================================================================
+--- mmp.orig/include/linux/ext3_fs_sb.h        2006-07-24 10:34:41.000000000 +0800
++++ mmp/include/linux/ext3_fs_sb.h     2006-07-24 10:39:26.000000000 +0800
+@@ -86,6 +86,7 @@ struct ext3_sb_info {
+       char *s_qf_names[MAXQUOTAS];            /* Names of quota files with journalled quota */
+       int s_jquota_fmt;                       /* Format of quota to use */
+ #endif
++      struct task_struct * s_alive_tsk;
+       /* for buddy allocator */
+       struct ext3_group_info **s_group_info;
diff --git a/lustre/kernel_patches/patches/ext3-multi-mount-protection-2.6.18-vanilla.patch b/lustre/kernel_patches/patches/ext3-multi-mount-protection-2.6.18-vanilla.patch
new file mode 100644 (file)
index 0000000..989ca26
--- /dev/null
@@ -0,0 +1,381 @@
+Index: mmp/fs/ext3/al.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ mmp/fs/ext3/al.h   2006-07-18 20:43:51.000000000 +0800
+@@ -0,0 +1,11 @@
++/*
++ * (C) 2006  Qi Yong <qiyong@clusterfs.com>
++ */
++
++#define       ALIVE_MAGIC     0xA1153C29
++struct alive_struct {
++      __le32  al_magic;
++      __le32  al_seq;
++      __le32  al_time;
++      char    al_nodename[65];
++};
+Index: mmp/fs/ext3/namei.c
+===================================================================
+--- mmp.orig/fs/ext3/namei.c   2006-07-18 20:43:51.000000000 +0800
++++ mmp/fs/ext3/namei.c        2006-07-18 20:43:51.000000000 +0800
+@@ -805,7 +805,7 @@ static inline int search_dirblock(struct
+  * The returned buffer_head has ->b_count elevated.  The caller is expected
+  * to brelse() it when appropriate.
+  */
+-static struct buffer_head * ext3_find_entry (struct dentry *dentry,
++struct buffer_head * ext3_find_entry (struct dentry *dentry,
+                                       struct ext3_dir_entry_2 ** res_dir)
+ {
+       struct super_block * sb;
+Index: mmp/fs/ext3/super.c
+===================================================================
+--- mmp.orig/fs/ext3/super.c   2006-07-18 20:43:51.000000000 +0800
++++ mmp/fs/ext3/super.c        2006-07-18 23:49:54.000000000 +0800
+@@ -35,12 +35,14 @@
+ #include <linux/namei.h>
+ #include <linux/quotaops.h>
+ #include <linux/seq_file.h>
++#include <linux/kthread.h>
+ #include <asm/uaccess.h>
+ #include "xattr.h"
+ #include "acl.h"
+ #include "namei.h"
++#include "al.h"
+ static int ext3_load_journal(struct super_block *, struct ext3_super_block *,
+                            unsigned long journal_devnum);
+@@ -61,6 +63,8 @@ static int ext3_statfs (struct dentry * 
+ static void ext3_unlockfs(struct super_block *sb);
+ static void ext3_write_super (struct super_block * sb);
+ static void ext3_write_super_lockfs(struct super_block *sb);
++struct buffer_head * ext3_find_entry (struct dentry *dentry,
++                                      struct ext3_dir_entry_2 ** res_dir);
+ /* 
+  * Wrappers for journal_start/end.
+@@ -434,6 +438,9 @@ static void ext3_put_super (struct super
+               invalidate_bdev(sbi->journal_bdev, 0);
+               ext3_blkdev_remove(sbi);
+       }
++      if (sbi->s_alive_tsk)
++              kthread_stop(sbi->s_alive_tsk);
++
+       sb->s_fs_info = NULL;
+       kfree(sbi);
+       return;
+@@ -1374,6 +1381,261 @@ static ext3_fsblk_t descriptor_loc(struc
+       return (has_super + ext3_group_first_block_no(sb, bg));
+ }
++static int write_alive(struct buffer_head * bh)
++{
++      lock_buffer(bh);
++      bh->b_end_io = end_buffer_write_sync;
++      get_bh(bh);
++      submit_bh(WRITE, bh);
++      wait_on_buffer(bh);
++      if (unlikely(!buffer_uptodate(bh)))
++              return 1;
++      return 0;
++}
++
++static int read_alive_again(struct buffer_head * bh)
++{
++      lock_buffer(bh);
++      bh->b_end_io = end_buffer_read_sync;
++      get_bh(bh);
++      submit_bh(READ, bh);
++      wait_on_buffer(bh);
++      if (!buffer_uptodate(bh)) {
++              brelse(bh);
++              return 1;
++      }
++      return 0;
++}
++
++/*
++ * The caller must have a ref on the buffer_head.
++ */
++static int kalived(void *data)
++{
++      struct buffer_head * bh;
++      struct alive_struct * alive;
++      char b[BDEVNAME_SIZE];
++      u32 seq = 0;
++
++      bh = (struct buffer_head *)data;
++      bdevname(bh->b_bdev, b);
++
++      alive = (struct alive_struct *)(bh->b_data);
++      alive->al_magic = cpu_to_le32(ALIVE_MAGIC);
++      alive->al_time = cpu_to_le32(get_seconds());
++
++      down_read(&uts_sem);
++      memcpy(alive->al_nodename, system_utsname.nodename, 65);
++      up_read(&uts_sem);
++
++      while (!kthread_should_stop()) {
++              if (++seq == 0)
++                      ++seq;
++
++              alive->al_seq = cpu_to_le32(seq);
++              alive->al_time = cpu_to_le32(get_seconds());
++
++              if (unlikely(write_alive(bh))) {
++                      /* panic here? */
++                      printk(KERN_ERR "Alive (device %s): "
++                              "can't write alive block\n", b);
++                      continue;
++              }
++
++              schedule_timeout_interruptible(5 * HZ);
++      }
++
++      alive->al_seq = 0;
++      alive->al_time = cpu_to_le32(get_seconds());
++
++      if (unlikely(write_alive(bh)))
++              printk(KERN_ERR "Alive (device %s): "
++                      "can't reset alive block\n", b);
++      brelse(bh);
++      return 0;
++}
++
++static unsigned long get_alive_ino(struct super_block *sb)
++{
++      unsigned long   ino = 0;
++      struct dentry   alive;
++      struct dentry   * root;
++      struct inode    * root_inode;
++      struct ext3_dir_entry_2 * de;
++      struct buffer_head      * bh;
++
++      root_inode = iget(sb, EXT3_ROOT_INO);
++      root = d_alloc_root(root_inode);
++      if (!root) {
++              printk(KERN_ERR "Alive (device %s): get root inode failed\n",
++                      sb->s_id);
++              iput(root_inode);
++              goto out;
++      }
++
++      alive.d_name.name = ".alive";
++      alive.d_name.len = 6;
++      alive.d_parent = root;
++
++      bh = ext3_find_entry(&alive, &de);
++      dput(root);
++
++      if (!bh) {
++              printk(KERN_WARNING "Alive (device %s): alive lookup failed\n",
++                      sb->s_id);
++              goto out;
++      }
++
++      ino = le32_to_cpu(de->inode);
++      brelse (bh);
++      pr_debug("Alive (device %s): alive_ino=%lu\n", sb->s_id, ino);
++out:
++      return ino;
++}
++
++/* check alive file */
++static int check_alive(struct super_block *sb, struct ext3_sb_info *sbi)
++{
++      unsigned long           ino;
++      struct buffer_head      * bh;
++      struct ext3_inode_info  * ei;
++      struct inode            * alive_inode;
++      struct alive_struct     * alive;
++      u32 alive_block;
++      u32 seq;
++
++      ino = get_alive_ino(sb);
++      if (!ino)
++              goto failed;
++
++      alive_inode = iget(sb, ino);
++      if (!alive_inode) {
++              iput(alive_inode);
++              printk(KERN_ERR "Alive (device %s): get alive inode failed\n",
++                      sb->s_id);
++              goto failed;
++      }
++      if (!alive_inode->i_nlink) {
++              make_bad_inode(alive_inode);
++              iput(alive_inode);
++              printk(KERN_ERR "Alive (device %s): alive inode is deleted\n",
++                      sb->s_id);
++              goto failed;
++      }
++      if (!S_ISREG(alive_inode->i_mode)) {
++              iput(alive_inode);
++              printk(KERN_ERR "Alive (device %s): invalid alive inode\n",
++                      sb->s_id);
++              goto failed;
++      }
++      if (EXT3_I(alive_inode)->i_flags & EXT3_EXTENTS_FL) {
++              iput(alive_inode);
++              printk(KERN_ERR "Alive (device %s): invalid alive inode, "
++                      "in extents format\n", sb->s_id);
++              goto failed;
++      }
++
++      ei = EXT3_I(alive_inode);
++      alive_block = ei->i_data[0];
++      iput(alive_inode);
++
++      pr_debug("Alive (device %s): read in alive block #%u\n",
++                      sb->s_id, alive_block);
++
++      /* first read */
++      bh = sb_bread(sb, alive_block);
++      if (!bh) {
++              printk(KERN_ERR "Alive (device %s): "
++                      "can't read alive block #%u\n", sb->s_id, alive_block);
++              goto failed;
++      }
++
++      alive = (struct alive_struct *)(bh->b_data);
++      if (le32_to_cpu(alive->al_magic) != ALIVE_MAGIC) {
++              printk(KERN_ERR "Alive (device %s): "
++                      "magic mismatch\n", sb->s_id);
++              brelse(bh);
++              goto failed;
++      }
++
++      seq = le32_to_cpu(alive->al_seq);
++      pr_debug("Alive (device %s): seq=%u\n", sb->s_id, seq);
++      pr_info ("Alive (device %s): last touched by node: %s, "
++              "%li seconds ago\n", sb->s_id, alive->al_nodename,
++              get_seconds() - le32_to_cpu(alive->al_time));
++
++      if (seq == 0)
++              goto skip;
++
++      /* wait 8s */
++      pr_info("Alive (device %s): wait for 8 seconds...\n", sb->s_id);
++      schedule_timeout_uninterruptible(HZ * 8);
++
++      /* read again */
++      if (read_alive_again(bh)) {
++              printk(KERN_ERR "Alive (device %s): "
++                      "can't read alive block #%u\n",
++                      sb->s_id, alive_block);
++              goto failed;
++      }
++
++      alive = (struct alive_struct *)(bh->b_data);
++      pr_debug("Alive (device %s): seq=%u\n",
++              sb->s_id, le32_to_cpu(alive->al_seq));
++
++      if (seq != le32_to_cpu(alive->al_seq)) {
++              printk(KERN_WARNING "Alive (device %s): "
++                      "still active on node %s\n",
++                      sb->s_id, alive->al_nodename);
++              brelse(bh);
++              goto failed;
++      }
++skip:
++      /* write a new random seq */
++      get_random_bytes(&seq, sizeof(u32));
++      alive->al_seq = cpu_to_le32(seq);
++      if (unlikely(write_alive(bh))) {
++              printk(KERN_ERR "Alive (device %s): "
++                      "can't write alive block\n", sb->s_id);
++              goto failed;
++      }
++      pr_debug("Alive (device %s): write random seq=%u\n", sb->s_id, seq);
++
++      /* wait 6s */
++      pr_info("Alive (device %s): wait for 6 seconds...\n", sb->s_id);
++      schedule_timeout_uninterruptible(HZ * 6);
++
++      /* read again */
++      if (read_alive_again(bh)) {
++              printk(KERN_ERR "Alive (device %s): "
++                      "can't read alive block #%u\n",
++                      sb->s_id, alive_block);
++              goto failed;
++      }
++
++      alive = (struct alive_struct *)(bh->b_data);
++      pr_debug("Alive (device %s): seq=%u\n",
++              sb->s_id, le32_to_cpu(alive->al_seq));
++
++      if (seq != le32_to_cpu(alive->al_seq)) {
++              printk(KERN_WARNING "Alive (device %s): "
++                      "still active on node %s\n",
++                      sb->s_id, alive->al_nodename);
++              brelse(bh);
++              goto failed;
++      }
++
++      /* succeed */
++      pr_info("Alive (device %s): alive check passed!\n", sb->s_id);
++      sbi->s_alive_tsk = kthread_run(kalived, bh, "kalived");
++      return 0;
++
++failed:
++      printk(KERN_WARNING "Alive (device %s): alive check failed!\n",
++              sb->s_id);
++      return 1;
++}
++
+ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
+ {
+@@ -1688,6 +1950,10 @@ static int ext3_fill_super (struct super
+                         EXT3_HAS_INCOMPAT_FEATURE(sb,
+                                   EXT3_FEATURE_INCOMPAT_RECOVER));
++      if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_ALIVE))
++              if (check_alive(sb, sbi))
++                      goto failed_mount2;
++
+       /*
+        * The first inode we look at is the journal inode.  Don't try
+        * root first: it may be modified in the journal!
+@@ -1796,6 +2062,8 @@ failed_mount3:
+       percpu_counter_destroy(&sbi->s_freeblocks_counter);
+       percpu_counter_destroy(&sbi->s_freeinodes_counter);
+       percpu_counter_destroy(&sbi->s_dirs_counter);
++      if (sbi->s_alive_tsk)
++              kthread_stop(sbi->s_alive_tsk);
+ failed_mount2:
+       for (i = 0; i < db_count; i++)
+               brelse(sbi->s_group_desc[i]);
+Index: mmp/include/linux/ext3_fs.h
+===================================================================
+--- mmp.orig/include/linux/ext3_fs.h   2006-07-18 20:43:51.000000000 +0800
++++ mmp/include/linux/ext3_fs.h        2006-07-18 20:43:52.000000000 +0800
+@@ -579,12 +579,14 @@ static inline struct ext3_inode_info *EX
+ #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV     0x0008 /* Journal device */
+ #define EXT3_FEATURE_INCOMPAT_META_BG         0x0010
+ #define EXT3_FEATURE_INCOMPAT_EXTENTS         0x0040 /* extents support */
++#define EXT3_FEATURE_INCOMPAT_ALIVE           0x0080
+ #define EXT3_FEATURE_COMPAT_SUPP      EXT2_FEATURE_COMPAT_EXT_ATTR
+ #define EXT3_FEATURE_INCOMPAT_SUPP    (EXT3_FEATURE_INCOMPAT_FILETYPE| \
+                                        EXT3_FEATURE_INCOMPAT_RECOVER| \
+                                        EXT3_FEATURE_INCOMPAT_META_BG| \
+-                                       EXT3_FEATURE_INCOMPAT_EXTENTS)
++                                       EXT3_FEATURE_INCOMPAT_EXTENTS| \
++                                       EXT3_FEATURE_INCOMPAT_ALIVE)
+ #define EXT3_FEATURE_RO_COMPAT_SUPP   (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
+                                        EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \
+                                        EXT3_FEATURE_RO_COMPAT_BTREE_DIR)
+Index: mmp/include/linux/ext3_fs_sb.h
+===================================================================
+--- mmp.orig/include/linux/ext3_fs_sb.h        2006-07-18 20:43:51.000000000 +0800
++++ mmp/include/linux/ext3_fs_sb.h     2006-07-18 20:43:52.000000000 +0800
+@@ -86,6 +86,7 @@ struct ext3_sb_info {
+       char *s_qf_names[MAXQUOTAS];            /* Names of quota files with journalled quota */
+       int s_jquota_fmt;                       /* Format of quota to use */
+ #endif
++      struct task_struct * s_alive_tsk;
+       /* for buddy allocator */
+       struct ext3_group_info **s_group_info;
diff --git a/lustre/kernel_patches/patches/ext3-sector_t-overflow-2.4.patch b/lustre/kernel_patches/patches/ext3-sector_t-overflow-2.4.patch
new file mode 100644 (file)
index 0000000..950ec9a
--- /dev/null
@@ -0,0 +1,41 @@
+Subject: Avoid disk sector_t overflow for >2TB ext3 filesystem
+From: Mingming Cao <cmm@us.ibm.com>
+
+
+If ext3 filesystem is larger than 2TB, and sector_t is a u32 (i.e. 
+CONFIG_LBD not defined in the kernel), the calculation of the disk sector
+will overflow.  Add check at ext3_fill_super() and ext3_group_extend() to
+prevent mount/remount/resize >2TB ext3 filesystem if sector_t size is 4
+bytes.
+
+Verified this patch on a 32 bit platform without CONFIG_LBD defined
+(sector_t is 32 bits long), mount refuse to mount a 10TB ext3.
+
+Signed-off-by: Mingming Cao<cmm@us.ibm.com>
+Acked-by: Andreas Dilger <adilger@clusterfs.com>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+---
+
+ fs/ext3/resize.c |   10 ++++++++++
+ fs/ext3/super.c  |   10 ++++++++++
+ 2 files changed, 20 insertions(+)
+
+diff -puN fs/ext3/super.c~avoid-disk-sector_t-overflow-for-2tb-ext3-filesystem fs/ext3/super.c
+--- devel/fs/ext3/super.c~avoid-disk-sector_t-overflow-for-2tb-ext3-filesystem 2006-05-22 14:09:53.000000000 -0700
++++ devel-akpm/fs/ext3/super.c 2006-05-22 14:11:10.000000000 -0700
+@@ -1565,6 +1565,14 @@ static int ext3_fill_super (struct super
+               goto failed_mount;
+       }
++      if (le32_to_cpu(es->s_blocks_count) >
++          (unsigned long)(~0ULL) >> (sb->s_blocksize_bits - 9)) {
++              printk(KERN_ERR "EXT3-fs: filesystem on %s: "
++                     "too large to mount safely - %u blocks\n",
++                     bdevname(sb->s_dev), le32_to_cpu(es->s_blocks_count));
++              goto failed_mount;
++      }
++
+       sbi->s_groups_count = (le32_to_cpu(es->s_blocks_count) -
+                              le32_to_cpu(es->s_first_data_block) +
+                              EXT3_BLOCKS_PER_GROUP(sb) - 1) /
+_
diff --git a/lustre/kernel_patches/patches/ext3-sector_t-overflow-2.6.12.patch b/lustre/kernel_patches/patches/ext3-sector_t-overflow-2.6.12.patch
new file mode 100644 (file)
index 0000000..ef0f4a4
--- /dev/null
@@ -0,0 +1,64 @@
+Subject: Avoid disk sector_t overflow for >2TB ext3 filesystem
+From: Mingming Cao <cmm@us.ibm.com>
+
+
+If ext3 filesystem is larger than 2TB, and sector_t is a u32 (i.e.
+CONFIG_LBD not defined in the kernel), the calculation of the disk sector
+will overflow.  Add check at ext3_fill_super() and ext3_group_extend() to
+prevent mount/remount/resize >2TB ext3 filesystem if sector_t size is 4
+bytes.
+
+Verified this patch on a 32 bit platform without CONFIG_LBD defined
+(sector_t is 32 bits long), mount refuse to mount a 10TB ext3.
+
+Signed-off-by: Mingming Cao<cmm@us.ibm.com>
+Acked-by: Andreas Dilger <adilger@clusterfs.com>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+---
+
+ fs/ext3/resize.c |   10 ++++++++++
+ fs/ext3/super.c  |   10 ++++++++++
+ 2 files changed, 20 insertions(+)
+
+diff -puN fs/ext3/resize.c~avoid-disk-sector_t-overflow-for-2tb-ext3-filesystem fs/ext3/resize.c
+--- devel/fs/ext3/resize.c~avoid-disk-sector_t-overflow-for-2tb-ext3-filesystem        2006-05-22 14:09:53.000000000 -0700
++++ devel-akpm/fs/ext3/resize.c        2006-05-22 14:10:56.000000000 -0700
+@@ -926,6 +926,16 @@ int ext3_group_extend(struct super_block
+       if (n_blocks_count == 0 || n_blocks_count == o_blocks_count)
+               return 0;
++      if (n_blocks_count > (sector_t)(~0ULL) >> (sb->s_blocksize_bits - 9)) {
++              printk(KERN_ERR "EXT3-fs: filesystem on %s: "
++                     "too large to resize to %lu blocks safely\n",
++                     sb->s_id, n_blocks_count);
++              if (sizeof(sector_t) < 8)
++                      ext3_warning(sb, __FUNCTION__,
++                                   "CONFIG_LBD not enabled\n");
++              return -EINVAL;
++      }
++
+       if (n_blocks_count < o_blocks_count) {
+               ext3_warning(sb, __FUNCTION__,
+                            "can't shrink FS - resize aborted");
+diff -puN fs/ext3/super.c~avoid-disk-sector_t-overflow-for-2tb-ext3-filesystem fs/ext3/super.c
+--- devel/fs/ext3/super.c~avoid-disk-sector_t-overflow-for-2tb-ext3-filesystem 2006-05-22 14:09:53.000000000 -0700
++++ devel-akpm/fs/ext3/super.c 2006-05-22 14:11:10.000000000 -0700
+@@ -1565,6 +1565,17 @@ static int ext3_fill_super (struct super
+               goto failed_mount;
+       }
++      if (le32_to_cpu(es->s_blocks_count) >
++          (sector_t)(~0ULL) >> (sb->s_blocksize_bits - 9)) {
++              printk(KERN_ERR "EXT3-fs: filesystem on %s: "
++                     "too large to mount safely - %u blocks\n", sb->s_id,
++                     le32_to_cpu(es->s_blocks_count));
++              if (sizeof(sector_t) < 8)
++                      printk(KERN_WARNING
++                             "EXT3-fs: CONFIG_LBD not enabled\n");
++              goto failed_mount;
++      }
++
+       if (EXT3_BLOCKS_PER_GROUP(sb) == 0)
+               goto cantfind_ext3;
+       sbi->s_groups_count = (le32_to_cpu(es->s_blocks_count) -
+_
diff --git a/lustre/kernel_patches/patches/ext3-sector_t-overflow-2.6.5-suse.patch b/lustre/kernel_patches/patches/ext3-sector_t-overflow-2.6.5-suse.patch
new file mode 100644 (file)
index 0000000..fe655da
--- /dev/null
@@ -0,0 +1,44 @@
+Subject: Avoid disk sector_t overflow for >2TB ext3 filesystem
+From: Mingming Cao <cmm@us.ibm.com>
+
+
+If ext3 filesystem is larger than 2TB, and sector_t is a u32 (i.e. 
+CONFIG_LBD not defined in the kernel), the calculation of the disk sector
+will overflow.  Add check at ext3_fill_super() and ext3_group_extend() to
+prevent mount/remount/resize >2TB ext3 filesystem if sector_t size is 4
+bytes.
+
+Verified this patch on a 32 bit platform without CONFIG_LBD defined
+(sector_t is 32 bits long), mount refuse to mount a 10TB ext3.
+
+Signed-off-by: Mingming Cao<cmm@us.ibm.com>
+Acked-by: Andreas Dilger <adilger@clusterfs.com>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+---
+
+ fs/ext3/resize.c |   10 ++++++++++
+ fs/ext3/super.c  |   10 ++++++++++
+ 2 files changed, 20 insertions(+)
+
+diff -puN fs/ext3/super.c~avoid-disk-sector_t-overflow-for-2tb-ext3-filesystem fs/ext3/super.c
+--- devel/fs/ext3/super.c~avoid-disk-sector_t-overflow-for-2tb-ext3-filesystem 2006-05-22 14:09:53.000000000 -0700
++++ devel-akpm/fs/ext3/super.c 2006-05-22 14:11:10.000000000 -0700
+@@ -1565,6 +1565,17 @@ static int ext3_fill_super (struct super
+               goto failed_mount;
+       }
++      if (le32_to_cpu(es->s_blocks_count) >
++          (sector_t)(~0ULL) >> (sb->s_blocksize_bits - 9)) {
++              printk(KERN_ERR "EXT3-fs: filesystem on %s: "
++                     "too large to mount safely - %u blocks\n", sb->s_id,
++                     le32_to_cpu(es->s_blocks_count));
++              if (sizeof(sector_t) < 8)
++                      printk(KERN_WARNING
++                             "EXT3-fs: CONFIG_LBD not enabled\n");
++              goto failed_mount;
++      }
++
+       sbi->s_groups_count = (le32_to_cpu(es->s_blocks_count) -
+                              le32_to_cpu(es->s_first_data_block) +
+                              EXT3_BLOCKS_PER_GROUP(sb) - 1) /
+_
diff --git a/lustre/kernel_patches/patches/ext3-sector_t-overflow-2.6.9-rhel4.patch b/lustre/kernel_patches/patches/ext3-sector_t-overflow-2.6.9-rhel4.patch
new file mode 100644 (file)
index 0000000..9bfdf80
--- /dev/null
@@ -0,0 +1,64 @@
+Subject: Avoid disk sector_t overflow for >2TB ext3 filesystem
+From: Mingming Cao <cmm@us.ibm.com>
+
+
+If ext3 filesystem is larger than 2TB, and sector_t is a u32 (i.e. 
+CONFIG_LBD not defined in the kernel), the calculation of the disk sector
+will overflow.  Add check at ext3_fill_super() and ext3_group_extend() to
+prevent mount/remount/resize >2TB ext3 filesystem if sector_t size is 4
+bytes.
+
+Verified this patch on a 32 bit platform without CONFIG_LBD defined
+(sector_t is 32 bits long), mount refuse to mount a 10TB ext3.
+
+Signed-off-by: Mingming Cao<cmm@us.ibm.com>
+Acked-by: Andreas Dilger <adilger@clusterfs.com>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+---
+
+ fs/ext3/resize.c |   10 ++++++++++
+ fs/ext3/super.c  |   10 ++++++++++
+ 2 files changed, 20 insertions(+)
+
+diff -puN fs/ext3/resize.c~avoid-disk-sector_t-overflow-for-2tb-ext3-filesystem fs/ext3/resize.c
+--- devel/fs/ext3/resize.c~avoid-disk-sector_t-overflow-for-2tb-ext3-filesystem        2006-05-22 14:09:53.000000000 -0700
++++ devel-akpm/fs/ext3/resize.c        2006-05-22 14:10:56.000000000 -0700
+@@ -926,6 +926,16 @@ int ext3_group_extend(struct super_block
+       if (n_blocks_count == 0 || n_blocks_count == o_blocks_count)
+               return 0;
++      if (n_blocks_count > (sector_t)(~0ULL) >> (sb->s_blocksize_bits - 9)) {
++              printk(KERN_ERR "EXT3-fs: filesystem on %s: "
++                     "too large to resize to %lu blocks safely\n",
++                     sb->s_id, n_blocks_count);
++              if (sizeof(sector_t) < 8)
++                      ext3_warning(sb, __FUNCTION__,
++                                   "CONFIG_LBD not enabled\n");
++              return -EINVAL;
++      }
++
+       if (n_blocks_count < o_blocks_count) {
+               ext3_warning(sb, __FUNCTION__,
+                            "can't shrink FS - resize aborted");
+diff -puN fs/ext3/super.c~avoid-disk-sector_t-overflow-for-2tb-ext3-filesystem fs/ext3/super.c
+--- devel/fs/ext3/super.c~avoid-disk-sector_t-overflow-for-2tb-ext3-filesystem 2006-05-22 14:09:53.000000000 -0700
++++ devel-akpm/fs/ext3/super.c 2006-05-22 14:11:10.000000000 -0700
+@@ -1565,6 +1565,17 @@ static int ext3_fill_super (struct super
+               goto failed_mount;
+       }
++      if (le32_to_cpu(es->s_blocks_count) >
++          (sector_t)(~0ULL) >> (sb->s_blocksize_bits - 9)) {
++              printk(KERN_ERR "EXT3-fs: filesystem on %s: "
++                     "too large to mount safely - %u blocks\n", sb->s_id,
++                     le32_to_cpu(es->s_blocks_count));
++              if (sizeof(sector_t) < 8)
++                      printk(KERN_WARNING
++                             "EXT3-fs: CONFIG_LBD not enabled\n");
++              goto failed_mount;
++      }
++
+       sbi->s_groups_count = (le32_to_cpu(es->s_blocks_count) -
+                              le32_to_cpu(es->s_first_data_block) +
+                              EXT3_BLOCKS_PER_GROUP(sb) - 1) /
+_
index 1c5c6ab..b586a2f 100644 (file)
@@ -19,16 +19,19 @@ Index: uml-2.6.3/fs/ext3/ialloc.c
  {
        struct super_block *sb;
        struct buffer_head *bitmap_bh = NULL;
-@@ -448,6 +449,38 @@
+@@ -448,6 +449,41 @@
  
        sbi = EXT3_SB(sb);
        es = sbi->s_es;
 +      if (goal) {
 +              group = (goal - 1) / EXT3_INODES_PER_GROUP(sb);
 +              ino = (goal - 1) % EXT3_INODES_PER_GROUP(sb);
++              err = -EIO;
++
 +              gdp = ext3_get_group_desc(sb, group, &bh2);
++              if (!gdp)
++                      goto fail;
 +
-+              err = -EIO;
 +              bitmap_bh = read_inode_bitmap (sb, group);
 +              if (!bitmap_bh)
 +                      goto fail;
index a4867a5..33535dc 100644 (file)
@@ -19,16 +19,19 @@ Index: uml-2.6.3/fs/ext3/ialloc.c
  {
        struct super_block *sb;
        struct buffer_head *bitmap_bh = NULL;
-@@ -448,6 +449,38 @@
+@@ -448,6 +449,41 @@
  
        sbi = EXT3_SB(sb);
        es = sbi->s_es;
 +      if (goal) {
 +              group = (goal - 1) / EXT3_INODES_PER_GROUP(sb);
 +              ino = (goal - 1) % EXT3_INODES_PER_GROUP(sb);
++              err = -EIO;
++
 +              gdp = ext3_get_group_desc(sb, group, &bh2);
++              if (!gdp)
++                      goto fail;
 +
-+              err = -EIO;
 +              bitmap_bh = read_inode_bitmap (sb, group);
 +              if (!bitmap_bh)
 +                      goto fail;
diff --git a/lustre/kernel_patches/patches/ext3-wantedi-2.6.15.patch b/lustre/kernel_patches/patches/ext3-wantedi-2.6.15.patch
new file mode 100644 (file)
index 0000000..9ed150e
--- /dev/null
@@ -0,0 +1,174 @@
+ fs/ext3/ialloc.c        |   35 ++++++++++++++++++++++++++++++++++-
+ fs/ext3/ioctl.c         |   25 +++++++++++++++++++++++++
+ fs/ext3/namei.c         |   21 +++++++++++++++++----
+ include/linux/dcache.h  |    5 +++++
+ include/linux/ext3_fs.h |    5 ++++-
+ 5 files changed, 85 insertions(+), 6 deletions(-)
+
+Index: linux-2.6.15/fs/ext3/ialloc.c
+===================================================================
+--- linux-2.6.15.orig/fs/ext3/ialloc.c 2006-02-19 15:23:12.000000000 +0300
++++ linux-2.6.15/fs/ext3/ialloc.c      2006-02-21 00:26:52.000000000 +0300
+@@ -420,7 +420,8 @@ static int find_group_other(struct super
+  * For other inodes, search forward from the parent directory's block
+  * group to find a free inode.
+  */
+-struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, int mode)
++struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, int mode,
++                              unsigned long goal)
+ {
+       struct super_block *sb;
+       struct buffer_head *bitmap_bh = NULL;
+@@ -448,6 +449,38 @@ struct inode *ext3_new_inode(handle_t *h
+       sbi = EXT3_SB(sb);
+       es = sbi->s_es;
++      if (goal) {
++              group = (goal - 1) / EXT3_INODES_PER_GROUP(sb);
++              ino = (goal - 1) % EXT3_INODES_PER_GROUP(sb);
++              gdp = ext3_get_group_desc(sb, group, &bh2);
++
++              err = -EIO;
++              bitmap_bh = read_inode_bitmap (sb, group);
++              if (!bitmap_bh)
++                      goto fail;
++
++              BUFFER_TRACE(bh, "get_write_access");
++              err = ext3_journal_get_write_access(handle, bitmap_bh);
++              if (err) goto fail;
++
++              if (ext3_set_bit_atomic(sb_bgl_lock(sbi, group),
++                                      ino, bitmap_bh->b_data)) {
++                      printk(KERN_ERR "goal inode %lu unavailable\n", goal);
++                      /* Oh well, we tried. */
++                      goto continue_allocation;
++              }
++
++              BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
++              err = ext3_journal_dirty_metadata(handle, bitmap_bh);
++              if (err) goto fail;
++
++              /* We've shortcircuited the allocation system successfully,
++               * now finish filling in the inode.
++               */
++              goto got;
++      }
++
++continue_allocation:
+       if (S_ISDIR(mode)) {
+               if (test_opt (sb, OLDALLOC))
+                       group = find_group_dir(sb, dir);
+Index: linux-2.6.15/fs/ext3/ioctl.c
+===================================================================
+--- linux-2.6.15.orig/fs/ext3/ioctl.c  2005-11-11 08:33:12.000000000 +0300
++++ linux-2.6.15/fs/ext3/ioctl.c       2006-02-21 00:26:52.000000000 +0300
+@@ -25,6 +25,31 @@ int ext3_ioctl (struct inode * inode, st
+       ext3_debug ("cmd = %u, arg = %lu\n", cmd, arg);
+       switch (cmd) {
++      case EXT3_IOC_CREATE_INUM: {
++              char name[32];
++              struct dentry *dchild, *dparent;
++              int rc = 0;
++
++              dparent = list_entry(inode->i_dentry.next, struct dentry,
++                                   d_alias);
++              snprintf(name, sizeof name, "%lu", arg);
++              dchild = lookup_one_len(name, dparent, strlen(name));
++              if (dchild->d_inode) {
++                      printk(KERN_ERR "%*s/%lu already exists (ino %lu)\n",
++                             dparent->d_name.len, dparent->d_name.name, arg,
++                             dchild->d_inode->i_ino);
++                      rc = -EEXIST;
++              } else {
++                      dchild->d_fsdata = (void *)arg;
++                      rc = vfs_create(inode, dchild, 0644, NULL);
++                      if (rc)
++                              printk(KERN_ERR "vfs_create: %d\n", rc);
++                      else if (dchild->d_inode->i_ino != arg)
++                              rc = -EEXIST;
++              }
++              dput(dchild);
++              return rc;
++      }
+       case EXT3_IOC_GETFLAGS:
+               flags = ei->i_flags & EXT3_FL_USER_VISIBLE;
+               return put_user(flags, (int __user *) arg);
+Index: linux-2.6.15/fs/ext3/namei.c
+===================================================================
+--- linux-2.6.15.orig/fs/ext3/namei.c  2006-02-19 15:23:12.000000000 +0300
++++ linux-2.6.15/fs/ext3/namei.c       2006-02-21 00:28:17.000000000 +0300
+@@ -1631,6 +1631,16 @@ static int ext3_add_nondir(handle_t *han
+       return err;
+ }
++static struct inode * ext3_new_inode_wantedi(handle_t *handle, struct inode *dir,
++                                              int mode, struct dentry *dentry)
++{
++      unsigned long inum = 0;
++
++      if (dentry->d_fsdata != NULL)
++              inum = (unsigned long) dentry->d_fsdata;
++      return ext3_new_inode(handle, dir, mode, inum);
++}
++
+ /*
+  * By the time this is called, we already have created
+  * the directory cache entry for the new file, but it
+@@ -1656,7 +1666,7 @@ retry:
+       if (IS_DIRSYNC(dir))
+               handle->h_sync = 1;
+-      inode = ext3_new_inode (handle, dir, mode);
++      inode = ext3_new_inode_wantedi (handle, dir, mode, dentry);
+       err = PTR_ERR(inode);
+       if (!IS_ERR(inode)) {
+               inode->i_op = &ext3_file_inode_operations;
+@@ -1690,7 +1700,7 @@ retry:
+       if (IS_DIRSYNC(dir))
+               handle->h_sync = 1;
+-      inode = ext3_new_inode (handle, dir, mode);
++      inode = ext3_new_inode_wantedi (handle, dir, mode, dentry);
+       err = PTR_ERR(inode);
+       if (!IS_ERR(inode)) {
+               init_special_inode(inode, inode->i_mode, rdev);
+@@ -1726,7 +1736,7 @@ retry:
+       if (IS_DIRSYNC(dir))
+               handle->h_sync = 1;
+-      inode = ext3_new_inode (handle, dir, S_IFDIR | mode);
++      inode = ext3_new_inode_wantedi (handle, dir, S_IFDIR | mode, dentry);
+       err = PTR_ERR(inode);
+       if (IS_ERR(inode))
+               goto out_stop;
+@@ -2131,7 +2141,7 @@ retry:
+       if (IS_DIRSYNC(dir))
+               handle->h_sync = 1;
+-      inode = ext3_new_inode (handle, dir, S_IFLNK|S_IRWXUGO);
++      inode = ext3_new_inode_wantedi (handle, dir, S_IFLNK|S_IRWXUGO, dentry);
+       err = PTR_ERR(inode);
+       if (IS_ERR(inode))
+               goto out_stop;
+Index: linux-2.6.15/include/linux/ext3_fs.h
+===================================================================
+--- linux-2.6.15.orig/include/linux/ext3_fs.h  2005-11-11 08:33:12.000000000 +0300
++++ linux-2.6.15/include/linux/ext3_fs.h       2006-02-21 00:26:52.000000000 +0300
+@@ -762,7 +762,8 @@ extern int ext3fs_dirhash(const char *na
+                         dx_hash_info *hinfo);
+ /* ialloc.c */
+-extern struct inode * ext3_new_inode (handle_t *, struct inode *, int);
++extern struct inode * ext3_new_inode (handle_t *, struct inode *, int,
++                                    unsigned long);
+ extern void ext3_free_inode (handle_t *, struct inode *);
+ extern struct inode * ext3_orphan_get (struct super_block *, unsigned long);
+ extern unsigned long ext3_count_free_inodes (struct super_block *);
+@@ -844,4 +845,6 @@ extern struct inode_operations ext3_fast
+ #endif        /* __KERNEL__ */
++/* EXT3_IOC_CREATE_INUM at bottom of file (visible to kernel and user). */
++#define EXT3_IOC_CREATE_INUM                  _IOW('f', 5, long)
+ #endif        /* _LINUX_EXT3_FS_H */
diff --git a/lustre/kernel_patches/patches/ext3-wantedi-misc-2.6.18-vanilla.patch b/lustre/kernel_patches/patches/ext3-wantedi-misc-2.6.18-vanilla.patch
new file mode 100644 (file)
index 0000000..11c6ada
--- /dev/null
@@ -0,0 +1,16 @@
+Index: linux-2.6/include/linux/dcache.h
+===================================================================
+--- linux-2.6.orig/include/linux/dcache.h      2006-07-15 16:11:52.000000000 +0800
++++ linux-2.6/include/linux/dcache.h   2006-07-15 16:12:04.000000000 +0800
+@@ -24,6 +24,11 @@ struct vfsmount;
+ #define IS_ROOT(x) ((x) == (x)->d_parent)
++struct dentry_params {
++      unsigned long   p_inum;
++      void            *p_ptr;
++};
++
+ /*
+  * "quick string" -- eases parameter passing, but more importantly
+  * saves "metadata" about the string (ie length and the hash).
diff --git a/lustre/kernel_patches/patches/iopen-2.6-fc5.patch b/lustre/kernel_patches/patches/iopen-2.6-fc5.patch
new file mode 100644 (file)
index 0000000..6bbcec5
--- /dev/null
@@ -0,0 +1,448 @@
+Index: linux-2.6.16.i686/fs/ext3/iopen.c
+===================================================================
+--- linux-2.6.16.i686.orig/fs/ext3/iopen.c     2006-05-31 04:14:15.752410384 +0800
++++ linux-2.6.16.i686/fs/ext3/iopen.c  2006-05-30 22:52:38.000000000 +0800
+@@ -0,0 +1,259 @@
++/*
++ * linux/fs/ext3/iopen.c
++ *
++ * Special support for open by inode number
++ *
++ * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu).
++ *
++ * This file may be redistributed under the terms of the GNU General
++ * Public License.
++ *
++ *
++ * Invariants:
++ *   - there is only ever a single DCACHE_NFSD_DISCONNECTED dentry alias
++ *     for an inode at one time.
++ *   - there are never both connected and DCACHE_NFSD_DISCONNECTED dentry
++ *     aliases on an inode at the same time.
++ *
++ * If we have any connected dentry aliases for an inode, use one of those
++ * in iopen_lookup().  Otherwise, we instantiate a single NFSD_DISCONNECTED
++ * dentry for this inode, which thereafter will be found by the dcache
++ * when looking up this inode number in __iopen__, so we don't return here
++ * until it is gone.
++ *
++ * If we get an inode via a regular name lookup, then we "rename" the
++ * NFSD_DISCONNECTED dentry to the proper name and parent.  This ensures
++ * existing users of the disconnected dentry will continue to use the same
++ * dentry as the connected users, and there will never be both kinds of
++ * dentry aliases at one time.
++ */
++
++#include <linux/sched.h>
++#include <linux/fs.h>
++#include <linux/ext3_jbd.h>
++#include <linux/jbd.h>
++#include <linux/ext3_fs.h>
++#include <linux/smp_lock.h>
++#include <linux/dcache.h>
++#include <linux/security.h>
++#include "iopen.h"
++
++#ifndef assert
++#define assert(test) J_ASSERT(test)
++#endif
++
++#define IOPEN_NAME_LEN        32
++
++/*
++ * This implements looking up an inode by number.
++ */
++static struct dentry *iopen_lookup(struct inode * dir, struct dentry *dentry,
++                                 struct nameidata *nd)
++{
++      struct inode *inode;
++      unsigned long ino;
++      struct list_head *lp;
++      struct dentry *alternate;
++      char buf[IOPEN_NAME_LEN];
++
++      if (dentry->d_name.len >= IOPEN_NAME_LEN)
++              return ERR_PTR(-ENAMETOOLONG);
++
++      memcpy(buf, dentry->d_name.name, dentry->d_name.len);
++      buf[dentry->d_name.len] = 0;
++
++      if (strcmp(buf, ".") == 0)
++              ino = dir->i_ino;
++      else if (strcmp(buf, "..") == 0)
++              ino = EXT3_ROOT_INO;
++      else
++              ino = simple_strtoul(buf, 0, 0);
++
++      if ((ino != EXT3_ROOT_INO &&
++           //ino != EXT3_ACL_IDX_INO &&
++           //ino != EXT3_ACL_DATA_INO &&
++           ino < EXT3_FIRST_INO(dir->i_sb)) ||
++          ino > le32_to_cpu(EXT3_SB(dir->i_sb)->s_es->s_inodes_count))
++              return ERR_PTR(-ENOENT);
++
++      inode = iget(dir->i_sb, ino);
++      if (!inode)
++              return ERR_PTR(-EACCES);
++      if (is_bad_inode(inode)) {
++              iput(inode);
++              return ERR_PTR(-ENOENT);
++      }
++
++      assert(list_empty(&dentry->d_alias));           /* d_instantiate */
++      assert(d_unhashed(dentry));                     /* d_rehash */
++
++      /* preferrably return a connected dentry */
++      spin_lock(&dcache_lock);
++      list_for_each(lp, &inode->i_dentry) {
++              alternate = list_entry(lp, struct dentry, d_alias);
++              assert(!(alternate->d_flags & DCACHE_DISCONNECTED));
++      }
++
++      if (!list_empty(&inode->i_dentry)) {
++              alternate = list_entry(inode->i_dentry.next,
++                                     struct dentry, d_alias);
++              dget_locked(alternate);
++              spin_lock(&alternate->d_lock);
++              alternate->d_flags |= DCACHE_REFERENCED;
++              spin_unlock(&alternate->d_lock);
++              iput(inode);
++              spin_unlock(&dcache_lock);
++              return alternate;
++      }
++      dentry->d_flags |= DCACHE_DISCONNECTED;
++
++      /* d_add(), but don't drop dcache_lock before adding dentry to inode */
++      list_add(&dentry->d_alias, &inode->i_dentry);   /* d_instantiate */
++      dentry->d_inode = inode;
++      spin_unlock(&dcache_lock);
++
++      d_rehash(dentry);
++
++      return NULL;
++}
++
++/* This function is spliced into ext3_lookup and does the move of a
++ * disconnected dentry (if it exists) to a connected dentry.
++ */
++struct dentry *iopen_connect_dentry(struct dentry *dentry, struct inode *inode,
++                                  int rehash)
++{
++      struct dentry *tmp, *goal = NULL;
++      struct list_head *lp;
++
++      /* verify this dentry is really new */
++      assert(dentry->d_inode == NULL);
++      assert(list_empty(&dentry->d_alias));           /* d_instantiate */
++      if (rehash)
++              assert(d_unhashed(dentry));             /* d_rehash */
++      assert(list_empty(&dentry->d_subdirs));
++
++      spin_lock(&dcache_lock);
++      if (!inode)
++              goto do_rehash;
++
++      if (!test_opt(inode->i_sb, IOPEN))
++              goto do_instantiate;
++
++      /* preferrably return a connected dentry */
++      list_for_each(lp, &inode->i_dentry) {
++              tmp = list_entry(lp, struct dentry, d_alias);
++              if (tmp->d_flags & DCACHE_DISCONNECTED) {
++                      assert(tmp->d_alias.next == &inode->i_dentry);
++                      assert(tmp->d_alias.prev == &inode->i_dentry);
++                      goal = tmp;
++                      dget_locked(goal);
++                      break;
++              }
++      }
++
++      if (!goal)
++              goto do_instantiate;
++
++      /* Move the goal to the de hash queue */
++      goal->d_flags &= ~DCACHE_DISCONNECTED;
++      security_d_instantiate(goal, inode);
++      __d_drop(dentry);
++      spin_unlock(&dcache_lock);
++      d_rehash(dentry);
++      d_move(goal, dentry);
++      iput(inode);
++
++      return goal;
++
++      /* d_add(), but don't drop dcache_lock before adding dentry to inode */
++do_instantiate:
++      list_add(&dentry->d_alias, &inode->i_dentry);   /* d_instantiate */
++      dentry->d_inode = inode;
++do_rehash:
++      spin_unlock(&dcache_lock);
++      if (rehash)
++              d_rehash(dentry);
++
++      return NULL;
++}
++
++/*
++ * These are the special structures for the iopen pseudo directory.
++ */
++
++static struct inode_operations iopen_inode_operations = {
++      lookup:         iopen_lookup,           /* BKL held */
++};
++
++static struct file_operations iopen_file_operations = {
++      read:           generic_read_dir,
++};
++
++static int match_dentry(struct dentry *dentry, const char *name)
++{
++      int     len;
++
++      len = strlen(name);
++      if (dentry->d_name.len != len)
++              return 0;
++      if (strncmp(dentry->d_name.name, name, len))
++              return 0;
++      return 1;
++}
++
++/*
++ * This function is spliced into ext3_lookup and returns 1 the file
++ * name is __iopen__ and dentry has been filled in appropriately.
++ */
++int ext3_check_for_iopen(struct inode *dir, struct dentry *dentry)
++{
++      struct inode *inode;
++
++      if (dir->i_ino != EXT3_ROOT_INO ||
++          !test_opt(dir->i_sb, IOPEN) ||
++          !match_dentry(dentry, "__iopen__"))
++              return 0;
++
++      inode = iget(dir->i_sb, EXT3_BAD_INO);
++
++      if (!inode)
++              return 0;
++      d_add(dentry, inode);
++      return 1;
++}
++
++/*
++ * This function is spliced into read_inode; it returns 1 if inode
++ * number is the one for /__iopen__, in which case the inode is filled
++ * in appropriately.  Otherwise, this fuction returns 0.
++ */
++int ext3_iopen_get_inode(struct inode *inode)
++{
++      if (inode->i_ino != EXT3_BAD_INO)
++              return 0;
++
++      inode->i_mode = S_IFDIR | S_IRUSR | S_IXUSR;
++      if (test_opt(inode->i_sb, IOPEN_NOPRIV))
++              inode->i_mode |= 0777;
++      inode->i_uid = 0;
++      inode->i_gid = 0;
++      inode->i_nlink = 1;
++      inode->i_size = 4096;
++      inode->i_atime = CURRENT_TIME;
++      inode->i_ctime = CURRENT_TIME;
++      inode->i_mtime = CURRENT_TIME;
++      EXT3_I(inode)->i_dtime = 0;
++      inode->i_blksize = PAGE_SIZE;   /* This is the optimal IO size
++                                       * (for stat), not the fs block
++                                       * size */
++      inode->i_blocks = 0;
++      inode->i_version = 1;
++      inode->i_generation = 0;
++
++      inode->i_op = &iopen_inode_operations;
++      inode->i_fop = &iopen_file_operations;
++      inode->i_mapping->a_ops = 0;
++
++      return 1;
++}
+Index: linux-2.6.16.i686/fs/ext3/iopen.h
+===================================================================
+--- linux-2.6.16.i686.orig/fs/ext3/iopen.h     2006-05-31 04:14:15.752410384 +0800
++++ linux-2.6.16.i686/fs/ext3/iopen.h  2006-05-30 22:52:38.000000000 +0800
+@@ -0,0 +1,15 @@
++/*
++ * iopen.h
++ *
++ * Special support for opening files by inode number.
++ *
++ * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu).
++ *
++ * This file may be redistributed under the terms of the GNU General
++ * Public License.
++ */
++
++extern int ext3_check_for_iopen(struct inode *dir, struct dentry *dentry);
++extern int ext3_iopen_get_inode(struct inode *inode);
++extern struct dentry *iopen_connect_dentry(struct dentry *dentry,
++                                         struct inode *inode, int rehash);
+Index: linux-2.6.16.i686/fs/ext3/inode.c
+===================================================================
+--- linux-2.6.16.i686.orig/fs/ext3/inode.c     2006-05-30 22:52:03.000000000 +0800
++++ linux-2.6.16.i686/fs/ext3/inode.c  2006-05-30 22:52:38.000000000 +0800
+@@ -37,6 +37,7 @@
+ #include <linux/mpage.h>
+ #include <linux/uio.h>
+ #include "xattr.h"
++#include "iopen.h"
+ #include "acl.h"
+ static int ext3_writepage_trans_blocks(struct inode *inode);
+@@ -2448,6 +2449,8 @@
+       ei->i_default_acl = EXT3_ACL_NOT_CACHED;
+ #endif
+       ei->i_block_alloc_info = NULL;
++      if (ext3_iopen_get_inode(inode))
++              return;
+       if (__ext3_get_inode_loc(inode, &iloc, 0))
+               goto bad_inode;
+Index: linux-2.6.16.i686/fs/ext3/super.c
+===================================================================
+--- linux-2.6.16.i686.orig/fs/ext3/super.c     2006-05-30 22:52:03.000000000 +0800
++++ linux-2.6.16.i686/fs/ext3/super.c  2006-05-30 22:52:38.000000000 +0800
+@@ -634,6 +634,7 @@
+       Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
+       Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
+       Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
++      Opt_iopen, Opt_noiopen, Opt_iopen_nopriv,
+       Opt_grpquota
+ };
+@@ -682,6 +683,9 @@
+       {Opt_noquota, "noquota"},
+       {Opt_quota, "quota"},
+       {Opt_usrquota, "usrquota"},
++      {Opt_iopen, "iopen"},
++      {Opt_noiopen, "noiopen"},
++      {Opt_iopen_nopriv, "iopen_nopriv"},
+       {Opt_barrier, "barrier=%u"},
+       {Opt_err, NULL},
+       {Opt_resize, "resize"},
+@@ -996,6 +1000,18 @@
+                       else
+                               clear_opt(sbi->s_mount_opt, BARRIER);
+                       break;
++              case Opt_iopen:
++                      set_opt (sbi->s_mount_opt, IOPEN);
++                      clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
++                      break;
++              case Opt_noiopen:
++                      clear_opt (sbi->s_mount_opt, IOPEN);
++                      clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
++                      break;
++              case Opt_iopen_nopriv:
++                      set_opt (sbi->s_mount_opt, IOPEN);
++                      set_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
++                      break;
+               case Opt_ignore:
+                       break;
+               case Opt_resize:
+Index: linux-2.6.16.i686/fs/ext3/namei.c
+===================================================================
+--- linux-2.6.16.i686.orig/fs/ext3/namei.c     2006-05-30 22:52:00.000000000 +0800
++++ linux-2.6.16.i686/fs/ext3/namei.c  2006-05-30 22:55:19.000000000 +0800
+@@ -39,6 +39,7 @@
+ #include "namei.h"
+ #include "xattr.h"
++#include "iopen.h"
+ #include "acl.h"
+ /*
+@@ -995,6 +996,9 @@
+       if (dentry->d_name.len > EXT3_NAME_LEN)
+               return ERR_PTR(-ENAMETOOLONG);
++      if (ext3_check_for_iopen(dir, dentry))
++              return NULL;
++
+       bh = ext3_find_entry(dentry, &de);
+       inode = NULL;
+       if (bh) {
+@@ -1005,7 +1009,7 @@
+               if (!inode)
+                       return ERR_PTR(-EACCES);
+       }
+-      return d_splice_alias(inode, dentry);
++      return iopen_connect_dentry(dentry, inode, 1);
+ }
+@@ -2046,10 +2050,6 @@
+                             inode->i_nlink);
+       inode->i_version++;
+       inode->i_nlink = 0;
+-      /* There's no need to set i_disksize: the fact that i_nlink is
+-       * zero will ensure that the right thing happens during any
+-       * recovery. */
+-      inode->i_size = 0;
+       ext3_orphan_add(handle, inode);
+       inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
+       ext3_mark_inode_dirty(handle, inode);
+@@ -2173,6 +2173,23 @@
+       return err;
+ }
++/* Like ext3_add_nondir() except for call to iopen_connect_dentry */
++static int ext3_add_link(handle_t *handle, struct dentry *dentry,
++                       struct inode *inode)
++{
++      int err = ext3_add_entry(handle, dentry, inode);
++      if (!err) {
++              err = ext3_mark_inode_dirty(handle, inode);
++              if (err == 0) {
++                      dput(iopen_connect_dentry(dentry, inode, 0));
++                      return 0;
++              }
++      }
++      ext3_dec_count(handle, inode);
++      iput(inode);
++      return err;
++}
++
+ static int ext3_link (struct dentry * old_dentry,
+               struct inode * dir, struct dentry *dentry)
+ {
+@@ -2196,7 +2213,8 @@
+       ext3_inc_count(handle, inode);
+       atomic_inc(&inode->i_count);
+-      err = ext3_add_nondir(handle, dentry, inode);
++      err = ext3_add_link(handle, dentry, inode);
++      ext3_orphan_del(handle, inode);
+       ext3_journal_stop(handle);
+       if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries))
+               goto retry;
+Index: linux-2.6.16.i686/fs/ext3/Makefile
+===================================================================
+--- linux-2.6.16.i686.orig/fs/ext3/Makefile    2006-03-20 13:53:29.000000000 +0800
++++ linux-2.6.16.i686/fs/ext3/Makefile 2006-05-30 22:52:38.000000000 +0800
+@@ -4,7 +4,7 @@
+ obj-$(CONFIG_EXT3_FS) += ext3.o
+-ext3-y        := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
++ext3-y        := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
+          ioctl.o namei.o super.o symlink.o hash.o resize.o
+ ext3-$(CONFIG_EXT3_FS_XATTR)   += xattr.o xattr_user.o xattr_trusted.o
+Index: linux-2.6.16.i686/include/linux/ext3_fs.h
+===================================================================
+--- linux-2.6.16.i686.orig/include/linux/ext3_fs.h     2006-05-30 22:52:00.000000000 +0800
++++ linux-2.6.16.i686/include/linux/ext3_fs.h  2006-05-30 22:52:38.000000000 +0800
+@@ -375,6 +375,8 @@
+ #define EXT3_MOUNT_QUOTA              0x80000 /* Some quota option set */
+ #define EXT3_MOUNT_USRQUOTA           0x100000 /* "old" user quota */
+ #define EXT3_MOUNT_GRPQUOTA           0x200000 /* "old" group quota */
++#define EXT3_MOUNT_IOPEN              0x400000        /* Allow access via iopen */
++#define EXT3_MOUNT_IOPEN_NOPRIV               0x800000/* Make iopen world-readable */
+ /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
+ #ifndef _LINUX_EXT2_FS_H
diff --git a/lustre/kernel_patches/patches/iopen-misc-2.6.18-vanilla.patch b/lustre/kernel_patches/patches/iopen-misc-2.6.18-vanilla.patch
new file mode 100644 (file)
index 0000000..89927c3
--- /dev/null
@@ -0,0 +1,82 @@
+Index: linux-2.6/Documentation/filesystems/ext2.txt
+===================================================================
+--- linux-2.6.orig/Documentation/filesystems/ext2.txt  2006-04-03 22:46:38.000000000 +0800
++++ linux-2.6/Documentation/filesystems/ext2.txt       2006-07-15 12:54:06.000000000 +0800
+@@ -58,6 +58,22 @@ nobh                                Do not attach buffer_heads to fi
+ xip                           Use execute in place (no caching) if possible
++iopen                         Makes an invisible pseudo-directory called 
++                              __iopen__ available in the root directory
++                              of the filesystem.  Allows open-by-inode-
++                              number.  i.e., inode 3145 can be accessed
++                              via /mntpt/__iopen__/3145
++
++iopen_nopriv                  This option makes the iopen directory be
++                              world-readable.  This may be safer since it
++                              allows daemons to run as an unprivileged user,
++                              however it significantly changes the security
++                              model of a Unix filesystem, since previously
++                              all files under a mode 700 directory were not
++                              generally avilable even if the
++                              permissions on the file itself is
++                              world-readable.
++
+ grpquota,noquota,quota,usrquota       Quota options are silently ignored by ext2.
+Index: linux-2.6/fs/dcache.c
+===================================================================
+--- linux-2.6.orig/fs/dcache.c 2006-07-15 12:48:18.000000000 +0800
++++ linux-2.6/fs/dcache.c      2006-07-15 12:54:06.000000000 +0800
+@@ -1341,14 +1341,13 @@ static void switch_names(struct dentry *
+  * dcache entries should not be moved in this way.
+  */
+-void d_move(struct dentry * dentry, struct dentry * target)
++void __d_move(struct dentry * dentry, struct dentry * target)
+ {
+       struct hlist_head *list;
+       if (!dentry->d_inode)
+               printk(KERN_WARNING "VFS: moving negative dcache entry\n");
+-      spin_lock(&dcache_lock);
+       write_seqlock(&rename_lock);
+       /*
+        * XXXX: do we really need to take target->d_lock?
+@@ -1399,6 +1398,14 @@ already_unhashed:
+       fsnotify_d_move(dentry);
+       spin_unlock(&dentry->d_lock);
+       write_sequnlock(&rename_lock);
++}
++
++EXPORT_SYMBOL(__d_move);
++
++void d_move(struct dentry *dentry, struct dentry *target)
++{
++      spin_lock(&dcache_lock);
++      __d_move(dentry, target);
+       spin_unlock(&dcache_lock);
+ }
+Index: linux-2.6/include/linux/dcache.h
+===================================================================
+--- linux-2.6.orig/include/linux/dcache.h      2006-07-15 12:48:41.000000000 +0800
++++ linux-2.6/include/linux/dcache.h   2006-07-15 12:54:06.000000000 +0800
+@@ -257,6 +257,7 @@ extern int have_submounts(struct dentry 
+  * This adds the entry to the hash queues.
+  */
+ extern void d_rehash(struct dentry *);
++extern void d_rehash_cond(struct dentry *, int lock);
+ /**
+  * d_add - add dentry to hash queues
+@@ -292,6 +293,7 @@ static inline struct dentry *d_add_uniqu
+ /* used for rename() and baskets */
+ extern void d_move(struct dentry *, struct dentry *);
++extern void __d_move(struct dentry *, struct dentry *);
+ /* appendix may either be NULL or be used for transname suffixes */
+ extern struct dentry * d_lookup(struct dentry *, struct qstr *);
diff --git a/lustre/kernel_patches/patches/jbd-jcberr-2.6.18-vanilla.patch b/lustre/kernel_patches/patches/jbd-jcberr-2.6.18-vanilla.patch
new file mode 100644 (file)
index 0000000..867d41c
--- /dev/null
@@ -0,0 +1,228 @@
+Index: linux-2.6/include/linux/jbd.h
+===================================================================
+--- linux-2.6.orig/include/linux/jbd.h 2006-07-15 16:08:35.000000000 +0800
++++ linux-2.6/include/linux/jbd.h      2006-07-15 16:13:01.000000000 +0800
+@@ -356,6 +356,27 @@ static inline void jbd_unlock_bh_journal
+       bit_spin_unlock(BH_JournalHead, &bh->b_state);
+ }
++#define HAVE_JOURNAL_CALLBACK_STATUS
++/**
++ *   struct journal_callback - Base structure for callback information.
++ *   @jcb_list: list information for other callbacks attached to the same handle.
++ *   @jcb_func: Function to call with this callback structure. 
++ *
++ *   This struct is a 'seed' structure for a using with your own callback
++ *   structs. If you are using callbacks you must allocate one of these
++ *   or another struct of your own definition which has this struct 
++ *   as it's first element and pass it to journal_callback_set().
++ *
++ *   This is used internally by jbd to maintain callback information.
++ *
++ *   See journal_callback_set for more information.
++ **/
++struct journal_callback {
++      struct list_head jcb_list;              /* t_jcb_lock */
++      void (*jcb_func)(struct journal_callback *jcb, int error);
++      /* user data goes here */
++};
++
+ struct jbd_revoke_table_s;
+ /**
+@@ -364,6 +385,7 @@ struct jbd_revoke_table_s;
+  * @h_transaction: Which compound transaction is this update a part of?
+  * @h_buffer_credits: Number of remaining buffers we are allowed to dirty.
+  * @h_ref: Reference count on this handle
++ * @h_jcb: List of application registered callbacks for this handle.
+  * @h_err: Field for caller's use to track errors through large fs operations
+  * @h_sync: flag for sync-on-close
+  * @h_jdata: flag to force data journaling
+@@ -389,6 +411,13 @@ struct handle_s 
+       /* operations */
+       int                     h_err;
++      /*
++       * List of application registered callbacks for this handle. The
++       * function(s) will be called after the transaction that this handle is
++       * part of has been committed to disk. [t_jcb_lock]
++       */
++      struct list_head        h_jcb;
++
+       /* Flags [no locking] */
+       unsigned int    h_sync:         1;      /* sync-on-close */
+       unsigned int    h_jdata:        1;      /* force data journaling */
+@@ -430,6 +459,8 @@ struct handle_s 
+  *    j_state_lock
+  *    ->j_list_lock                   (journal_unmap_buffer)
+  *
++ *    t_handle_lock
++ *    ->t_jcb_lock
+  */
+ struct transaction_s 
+@@ -559,6 +590,15 @@ struct transaction_s 
+        */
+       int t_handle_count;
++      /*
++       * Protects the callback list
++       */
++      spinlock_t              t_jcb_lock;
++      /*
++       * List of registered callback functions for this transaction.
++       * Called when the transaction is committed. [t_jcb_lock]
++       */
++      struct list_head        t_jcb;
+ };
+ /**
+@@ -906,6 +946,10 @@ extern void        journal_invalidatepage(jour
+ extern int     journal_try_to_free_buffers(journal_t *, struct page *, gfp_t);
+ extern int     journal_stop(handle_t *);
+ extern int     journal_flush (journal_t *);
++extern void    journal_callback_set(handle_t *handle,
++                                    void (*fn)(struct journal_callback *,int),
++                                    struct journal_callback *jcb);
++
+ extern void    journal_lock_updates (journal_t *);
+ extern void    journal_unlock_updates (journal_t *);
+Index: linux-2.6/fs/jbd/checkpoint.c
+===================================================================
+--- linux-2.6.orig/fs/jbd/checkpoint.c 2006-07-15 16:08:36.000000000 +0800
++++ linux-2.6/fs/jbd/checkpoint.c      2006-07-15 16:13:01.000000000 +0800
+@@ -688,6 +688,7 @@ void __journal_drop_transaction(journal_
+       J_ASSERT(transaction->t_checkpoint_list == NULL);
+       J_ASSERT(transaction->t_checkpoint_io_list == NULL);
+       J_ASSERT(transaction->t_updates == 0);
++      J_ASSERT(list_empty(&transaction->t_jcb));
+       J_ASSERT(journal->j_committing_transaction != transaction);
+       J_ASSERT(journal->j_running_transaction != transaction);
+Index: linux-2.6/fs/jbd/commit.c
+===================================================================
+--- linux-2.6.orig/fs/jbd/commit.c     2006-07-15 16:08:36.000000000 +0800
++++ linux-2.6/fs/jbd/commit.c  2006-07-15 16:13:01.000000000 +0800
+@@ -708,6 +708,30 @@ wait_for_iobuf:
+            transaction can be removed from any checkpoint list it was on
+            before. */
++      /*
++       * Call any callbacks that had been registered for handles in this
++       * transaction.  It is up to the callback to free any allocated
++       * memory.
++       *
++       * The spinlocking (t_jcb_lock) here is surely unnecessary...
++       */
++      spin_lock(&commit_transaction->t_jcb_lock);
++      if (!list_empty(&commit_transaction->t_jcb)) {
++              struct list_head *p, *n;
++              int error = is_journal_aborted(journal);
++
++              list_for_each_safe(p, n, &commit_transaction->t_jcb) {
++                      struct journal_callback *jcb;
++
++                      jcb = list_entry(p, struct journal_callback, jcb_list);
++                      list_del(p);
++                      spin_unlock(&commit_transaction->t_jcb_lock);
++                      jcb->jcb_func(jcb, error);
++                      spin_lock(&commit_transaction->t_jcb_lock);
++              }
++      }
++      spin_unlock(&commit_transaction->t_jcb_lock);
++
+       jbd_debug(3, "JBD: commit phase 7\n");
+       J_ASSERT(commit_transaction->t_sync_datalist == NULL);
+Index: linux-2.6/fs/jbd/journal.c
+===================================================================
+--- linux-2.6.orig/fs/jbd/journal.c    2006-07-15 16:08:36.000000000 +0800
++++ linux-2.6/fs/jbd/journal.c 2006-07-15 16:13:01.000000000 +0800
+@@ -58,6 +58,7 @@ EXPORT_SYMBOL(journal_sync_buffer);
+ #endif
+ EXPORT_SYMBOL(journal_flush);
+ EXPORT_SYMBOL(journal_revoke);
++EXPORT_SYMBOL(journal_callback_set);
+ EXPORT_SYMBOL(journal_init_dev);
+ EXPORT_SYMBOL(journal_init_inode);
+@@ -80,6 +81,7 @@ EXPORT_SYMBOL(journal_wipe);
+ EXPORT_SYMBOL(journal_blocks_per_page);
+ EXPORT_SYMBOL(journal_invalidatepage);
+ EXPORT_SYMBOL(journal_try_to_free_buffers);
++EXPORT_SYMBOL(journal_bmap);
+ EXPORT_SYMBOL(journal_force_commit);
+ static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *);
+Index: linux-2.6/fs/jbd/transaction.c
+===================================================================
+--- linux-2.6.orig/fs/jbd/transaction.c        2006-07-15 16:08:35.000000000 +0800
++++ linux-2.6/fs/jbd/transaction.c     2006-07-15 16:13:01.000000000 +0800
+@@ -50,7 +50,9 @@ get_transaction(journal_t *journal, tran
+       transaction->t_state = T_RUNNING;
+       transaction->t_tid = journal->j_transaction_sequence++;
+       transaction->t_expires = jiffies + journal->j_commit_interval;
++      INIT_LIST_HEAD(&transaction->t_jcb);
+       spin_lock_init(&transaction->t_handle_lock);
++      spin_lock_init(&transaction->t_jcb_lock);
+       /* Set up the commit timer for the new transaction. */
+       journal->j_commit_timer.expires = transaction->t_expires;
+@@ -241,6 +243,7 @@ static handle_t *new_handle(int nblocks)
+       memset(handle, 0, sizeof(*handle));
+       handle->h_buffer_credits = nblocks;
+       handle->h_ref = 1;
++      INIT_LIST_HEAD(&handle->h_jcb);
+       return handle;
+ }
+@@ -1291,6 +1294,36 @@ drop:
+ }
+ /**
++ * void journal_callback_set() -  Register a callback function for this handle.
++ * @handle: handle to attach the callback to.
++ * @func: function to callback.
++ * @jcb:  structure with additional information required by func() , and
++ *        some space for jbd internal information.
++ * 
++ * The function will be
++ * called when the transaction that this handle is part of has been
++ * committed to disk with the original callback data struct and the
++ * error status of the journal as parameters.  There is no guarantee of
++ * ordering between handles within a single transaction, nor between
++ * callbacks registered on the same handle.
++ *
++ * The caller is responsible for allocating the journal_callback struct.
++ * This is to allow the caller to add as much extra data to the callback
++ * as needed, but reduce the overhead of multiple allocations.  The caller
++ * allocated struct must start with a struct journal_callback at offset 0,
++ * and has the caller-specific data afterwards.
++ */
++void journal_callback_set(handle_t *handle,
++                      void (*func)(struct journal_callback *jcb, int error),
++                      struct journal_callback *jcb)
++{
++      spin_lock(&handle->h_transaction->t_jcb_lock);
++      list_add_tail(&jcb->jcb_list, &handle->h_jcb);
++      spin_unlock(&handle->h_transaction->t_jcb_lock);
++      jcb->jcb_func = func;
++}
++
++/**
+  * int journal_stop() - complete a transaction
+  * @handle: tranaction to complete.
+  * 
+@@ -1363,6 +1396,11 @@ int journal_stop(handle_t *handle)
+                       wake_up(&journal->j_wait_transaction_locked);
+       }
++      /* Move callbacks from the handle to the transaction. */
++      spin_lock(&transaction->t_jcb_lock);
++      list_splice(&handle->h_jcb, &transaction->t_jcb);
++      spin_unlock(&transaction->t_jcb_lock);
++
+       /*
+        * If the handle is marked SYNC, we need to set another commit
+        * going!  We also want to force a commit if the current
index 57b0e37..4d234af 100644 (file)
@@ -1,12 +1,7 @@
-Index: linux/arch/i386/kernel/traps.c
-===================================================================
-RCS file: /chaos/cvs/kernel-rh/linux/arch/i386/kernel/traps.c,v
-retrieving revision 1.3.6.4
-retrieving revision 1.3.6.2.2.5
-diff -u -r1.3.6.4 -r1.3.6.2.2.5
---- linux/arch/i386/kernel/traps.c     3 Dec 2003 21:39:03 -0000       1.3.6.4
-+++ linux/arch/i386/kernel/traps.c     3 Oct 2003 22:45:43 -0000       1.3.6.2.2.5
-@@ -133,6 +137,80 @@
+diff -X dontdiff -urp kern_oldest/arch/i386/kernel/traps.c kern_fix/arch/i386/kernel/traps.c
+--- kern_oldest/arch/i386/kernel/traps.c       2006-05-01 11:56:31.000000000 -0700
++++ kern_fix/arch/i386/kernel/traps.c  2006-05-01 14:56:40.000000000 -0700
+@@ -133,6 +133,80 @@ static inline int kernel_text_address(un
  
  #endif
  
@@ -87,14 +82,7 @@ diff -u -r1.3.6.4 -r1.3.6.2.2.5
  void show_trace(unsigned long * stack)
  {
  #if !CONFIG_FRAME_POINTER
-@@ -145,29 +223,20 @@
-       if (!stack)
-               stack = (unsigned long*)&stack;
--      printk("Call Trace:   ");
-+      printk("Call Trace:\n");
-       /*
-        * If we have frame pointers then use them to get
+@@ -151,16 +225,7 @@ void show_trace(unsigned long * stack)
         * a 100% exact backtrace, up until the entry frame:
         */
  #if CONFIG_FRAME_POINTER
@@ -111,7 +99,8 @@ diff -u -r1.3.6.4 -r1.3.6.2.2.5
 +      frame_pointer_walk(stack);
  #else
        i = 1;
-       while (((long) stack & (THREAD_SIZE-1)) != 0) {
+       limit = ((unsigned long)stack & ~(THREAD_SIZE - 1)) + THREAD_SIZE - 3;
+@@ -168,7 +233,7 @@ out:
                addr = *stack++;
                if (kernel_text_address(addr)) {
                        lookup_symbol(addr, buffer, 512);
@@ -120,7 +109,7 @@ diff -u -r1.3.6.4 -r1.3.6.2.2.5
                        i++;
                }
        }
-@@ -242,7 +305,7 @@
+@@ -244,7 +309,7 @@ void show_registers(struct pt_regs *regs
        lookup_symbol(regs->eip, buffer, 512);
        printk("CPU:    %d\nEIP:    %04x:[<%08lx>]    %s\nEFLAGS: %08lx\n",
                smp_processor_id(), 0xffff & regs->xcs, regs->eip, print_tainted(), regs->eflags);
index 11416e6..64d652a 100644 (file)
@@ -1,11 +1,7 @@
-Index: linux/arch/i386/kernel/traps.c===================================================================
-RCS file: /chaos/cvs/kernel-rh/linux/arch/i386/kernel/traps.c,v
-retrieving revision 1.3.6.2.2.11
-retrieving revision 1.3.6.2.2.12
-Index: linux-2.4.21/arch/i386/kernel/traps.c
+Index: kernel/arch/i386/kernel/traps.c
 ===================================================================
---- linux-2.4.21.orig/arch/i386/kernel/traps.c 2004-11-01 22:00:55.000000000 -0500
-+++ linux-2.4.21/arch/i386/kernel/traps.c      2004-11-02 14:20:54.000000000 -0500
+--- kernel.orig/arch/i386/kernel/traps.c       2006-05-26 16:12:28.000000000 -0700
++++ kernel/arch/i386/kernel/traps.c    2006-05-26 16:15:54.000000000 -0700
 @@ -133,6 +133,30 @@
  
  #endif
@@ -75,7 +71,7 @@ Index: linux-2.4.21/arch/i386/kernel/traps.c
  
        for (; ; ) {
                next_frame_ptr = (unsigned long *) (*frame_ptr);
-@@ -196,50 +216,58 @@
+@@ -196,9 +216,9 @@
                eip = *eip_ptr;
  
                if (kernel_text_address(eip)) {
@@ -87,19 +83,19 @@ Index: linux-2.4.21/arch/i386/kernel/traps.c
                               eip_ptr);
                }
  
-               frame_ptr = next_frame_ptr;
-       }
+@@ -207,40 +227,49 @@
  }
--#endif
-+
-+typedef void (*stack_trace_fn_t) (unsigned long *stack);
+ #endif
  
++typedef void (*stack_trace_fn_t) (unsigned long *stack);
++
++#if CONFIG_FRAME_POINTER
  void show_trace(unsigned long * stack)
  {
 -#if !CONFIG_FRAME_POINTER
 -      int i;
 -#endif
--      unsigned long addr;
+-      unsigned long addr, limit;
 -      /* static to not take up stackspace; if we race here too bad */
 -      static char buffer[512];
 +      static const stack_trace_fn_t trace_fn_vector[] =
@@ -110,25 +106,17 @@ Index: linux-2.4.21/arch/i386/kernel/traps.c
        if (!stack)
                stack = (unsigned long*)&stack;
  
-       printk("Call Trace:\n");
+       printk("Call Trace:   ");
 -      /*
 -       * If we have frame pointers then use them to get
 -       * a 100% exact backtrace, up until the entry frame:
-+      addr = (unsigned long) stack;
-+      task_addr = (unsigned long) current;
-+      stack_base = task_addr + THREAD_SIZE - 1;
-+      task_is_current = (addr >= task_addr) && (addr <= stack_base);
-+
-+      /* We may use frame pointers to do a stack trace only if the current
-+       * task is being traced.  Tracing some other task in this manner
-+       * would require a saved %ebp register value.  Perhaps in the future
-+       * I'll consider providing a means of obtaining this.
-        */
+-       */
 -#if CONFIG_FRAME_POINTER
 -      frame_pointer_walk(stack);
 -#else
 -      i = 1;
--      while (((long) stack & (THREAD_SIZE-1)) != 0) {
+-      limit = ((unsigned long)stack & ~(THREAD_SIZE - 1)) + THREAD_SIZE - 3;
+-      while ((unsigned long)stack < limit) {
 -              addr = *stack++;
 -              if (kernel_text_address(addr)) {
 -                      lookup_symbol(addr, buffer, 512);
@@ -137,11 +125,21 @@ Index: linux-2.4.21/arch/i386/kernel/traps.c
 -              }
 -      }
 -#endif
++      addr = (unsigned long) stack;
++      task_addr = (unsigned long) current;
++      stack_base = task_addr + THREAD_SIZE - 1;
++      task_is_current = (addr >= task_addr) && (addr <= stack_base);
++      
++      /* We may use frame pointers to do a stack trace only if the current
++       * task is being traced.  Tracing some other task in this manner
++       * would require a saved %ebp register value.  Perhaps in the future
++       * I'll consider providing a means of obtaining this.
++       */
 +      trace_fn_vector[task_is_current](stack);
 +
-       printk("\n");
- }
++      printk("\n");
++}
++
 +#else /* CONFIG_FRAME_POINTER */
 +
 +void show_trace(unsigned long * stack)
@@ -151,18 +149,18 @@ Index: linux-2.4.21/arch/i386/kernel/traps.c
 +
 +      printk("Call Trace:\n");
 +      scan_stack(stack);
-+      printk("\n");
-+}
-+
+       printk("\n");
+ }
 +#endif /* CONFIG_FRAME_POINTER */
 +
  void show_trace_task(struct task_struct *tsk)
  {
        unsigned long esp = tsk->thread.esp;
-Index: linux-2.4.21/include/asm-i386/hw_irq.h
+Index: kernel/include/asm-i386/hw_irq.h
 ===================================================================
---- linux-2.4.21.orig/include/asm-i386/hw_irq.h        2004-11-01 21:59:54.000000000 -0500
-+++ linux-2.4.21/include/asm-i386/hw_irq.h     2004-11-02 14:20:03.000000000 -0500
+--- kernel.orig/include/asm-i386/hw_irq.h      2006-05-26 16:11:33.000000000 -0700
++++ kernel/include/asm-i386/hw_irq.h   2006-05-26 16:13:51.000000000 -0700
 @@ -153,6 +153,9 @@
        /* there is a second layer of macro just to get the symbolic
           name for the vector evaluated. This change is for RTLinux */
diff --git a/lustre/kernel_patches/patches/nfs-cifs-intent-2.6-fc5.patch b/lustre/kernel_patches/patches/nfs-cifs-intent-2.6-fc5.patch
new file mode 100644 (file)
index 0000000..f445efe
--- /dev/null
@@ -0,0 +1,116 @@
+Index: linux-2.6.16.i686/fs/cifs/dir.c
+===================================================================
+--- linux-2.6.16.i686.orig/fs/cifs/dir.c       2006-05-30 15:47:03.000000000 +0800
++++ linux-2.6.16.i686/fs/cifs/dir.c    2006-05-30 21:11:39.000000000 +0800
+@@ -147,7 +147,7 @@
+       }
+       if(nd && (nd->flags & LOOKUP_OPEN)) {
+-              int oflags = nd->intent.open.flags;
++              int oflags = nd->intent.flags;
+               desiredAccess = 0;
+               if (oflags & FMODE_READ)
+Index: linux-2.6.16.i686/fs/nfs/dir.c
+===================================================================
+--- linux-2.6.16.i686.orig/fs/nfs/dir.c        2006-03-20 13:53:29.000000000 +0800
++++ linux-2.6.16.i686/fs/nfs/dir.c     2006-05-30 21:10:01.000000000 +0800
+@@ -831,7 +831,7 @@
+               return 0;
+       if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_CREATE) == 0)
+               return 0;
+-      return (nd->intent.open.flags & O_EXCL) != 0;
++      return (nd->intent.it_flags & O_EXCL) != 0;
+ }
+ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
+@@ -902,7 +902,7 @@
+       if (nd->flags & LOOKUP_DIRECTORY)
+               return 0;
+       /* Are we trying to write to a read only partition? */
+-      if (IS_RDONLY(dir) && (nd->intent.open.flags & (O_CREAT|O_TRUNC|FMODE_WRITE)))
++      if (IS_RDONLY(dir) && (nd->intent.it_flags & (O_CREAT|O_TRUNC|FMODE_WRITE)))
+               return 0;
+       return 1;
+ }
+@@ -923,7 +923,7 @@
+       dentry->d_op = NFS_PROTO(dir)->dentry_ops;
+       /* Let vfs_create() deal with O_EXCL */
+-      if (nd->intent.open.flags & O_EXCL) {
++      if (nd->intent.it_flags & O_EXCL) {
+               d_add(dentry, NULL);
+               goto out;
+       }
+@@ -938,7 +938,7 @@
+               goto out;
+       }
+-      if (nd->intent.open.flags & O_CREAT) {
++      if (nd->intent.it_flags & O_CREAT) {
+               nfs_begin_data_update(dir);
+               res = nfs4_atomic_open(dir, dentry, nd);
+               nfs_end_data_update(dir);
+@@ -957,7 +957,7 @@
+                       case -ENOTDIR:
+                               goto no_open;
+                       case -ELOOP:
+-                              if (!(nd->intent.open.flags & O_NOFOLLOW))
++                              if (!(nd->intent.it_flags & O_NOFOLLOW))
+                                       goto no_open;
+                       /* case -EINVAL: */
+                       default:
+@@ -993,7 +993,7 @@
+       /* NFS only supports OPEN on regular files */
+       if (!S_ISREG(inode->i_mode))
+               goto no_open;
+-      openflags = nd->intent.open.flags;
++      openflags = nd->intent.it_flags;
+       /* We cannot do exclusive creation on a positive dentry */
+       if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
+               goto no_open;
+@@ -1126,7 +1126,7 @@
+       attr.ia_valid = ATTR_MODE;
+       if (nd && (nd->flags & LOOKUP_CREATE))
+-              open_flags = nd->intent.open.flags;
++              open_flags = nd->intent.it_flags;
+       lock_kernel();
+       nfs_begin_data_update(dir);
+Index: linux-2.6.16.i686/fs/nfs/nfs4proc.c
+===================================================================
+--- linux-2.6.16.i686.orig/fs/nfs/nfs4proc.c   2006-03-20 13:53:29.000000000 +0800
++++ linux-2.6.16.i686/fs/nfs/nfs4proc.c        2006-05-30 21:11:00.000000000 +0800
+@@ -1220,7 +1220,7 @@
+               ctx = (struct nfs_open_context *)filp->private_data;
+               ctx->state = state;
+       } else
+-              nfs4_close_state(state, nd->intent.open.flags);
++              nfs4_close_state(state, nd->intent.flags);
+ }
+ struct dentry *
+@@ -1232,19 +1232,19 @@
+       struct dentry *res;
+       if (nd->flags & LOOKUP_CREATE) {
+-              attr.ia_mode = nd->intent.open.create_mode;
++              attr.ia_mode = nd->intent.create_mode;
+               attr.ia_valid = ATTR_MODE;
+               if (!IS_POSIXACL(dir))
+                       attr.ia_mode &= ~current->fs->umask;
+       } else {
+               attr.ia_valid = 0;
+-              BUG_ON(nd->intent.open.flags & O_CREAT);
++              BUG_ON(nd->intent.flags & O_CREAT);
+       }
+       cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0);
+       if (IS_ERR(cred))
+               return (struct dentry *)cred;
+-      state = nfs4_do_open(dir, dentry, nd->intent.open.flags, &attr, cred);
++      state = nfs4_do_open(dir, dentry, nd->intent.flags, &attr, cred);
+       put_rpccred(cred);
+       if (IS_ERR(state)) {
+               if (PTR_ERR(state) == -ENOENT)
diff --git a/lustre/kernel_patches/patches/nfs-cifs-intent-2.6.18-vanilla.patch b/lustre/kernel_patches/patches/nfs-cifs-intent-2.6.18-vanilla.patch
new file mode 100644 (file)
index 0000000..5639fe4
--- /dev/null
@@ -0,0 +1,120 @@
+Index: linux-2.6/fs/cifs/dir.c
+===================================================================
+--- linux-2.6.orig/fs/cifs/dir.c       2006-07-15 21:04:01.000000000 +0800
++++ linux-2.6/fs/cifs/dir.c    2006-07-15 21:04:47.000000000 +0800
+@@ -146,7 +146,7 @@ cifs_create(struct inode *inode, struct 
+       }
+       if(nd && (nd->flags & LOOKUP_OPEN)) {
+-              int oflags = nd->intent.open.flags;
++              int oflags = nd->intent.flags;
+               desiredAccess = 0;
+               if (oflags & FMODE_READ)
+Index: linux-2.6/fs/nfs/dir.c
+===================================================================
+--- linux-2.6.orig/fs/nfs/dir.c        2006-07-15 21:04:01.000000000 +0800
++++ linux-2.6/fs/nfs/dir.c     2006-07-15 21:04:47.000000000 +0800
+@@ -867,7 +867,7 @@ int nfs_is_exclusive_create(struct inode
+               return 0;
+       if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_CREATE) == 0)
+               return 0;
+-      return (nd->intent.open.flags & O_EXCL) != 0;
++      return (nd->intent.it_flags & O_EXCL) != 0;
+ }
+ static inline int nfs_reval_fsid(struct inode *dir,
+@@ -955,7 +955,7 @@ static int is_atomic_open(struct inode *
+       if (nd->flags & LOOKUP_DIRECTORY)
+               return 0;
+       /* Are we trying to write to a read only partition? */
+-      if (IS_RDONLY(dir) && (nd->intent.open.flags & (O_CREAT|O_TRUNC|FMODE_WRITE)))
++      if (IS_RDONLY(dir) && (nd->intent.it_flags & (O_CREAT|O_TRUNC|FMODE_WRITE)))
+               return 0;
+       return 1;
+ }
+@@ -979,7 +979,7 @@ static struct dentry *nfs_atomic_lookup(
+       dentry->d_op = NFS_PROTO(dir)->dentry_ops;
+       /* Let vfs_create() deal with O_EXCL */
+-      if (nd->intent.open.flags & O_EXCL) {
++      if (nd->intent.it_flags & O_EXCL) {
+               d_add(dentry, NULL);
+               goto out;
+       }
+@@ -994,7 +994,7 @@ static struct dentry *nfs_atomic_lookup(
+               goto out;
+       }
+-      if (nd->intent.open.flags & O_CREAT) {
++      if (nd->intent.it_flags & O_CREAT) {
+               nfs_begin_data_update(dir);
+               res = nfs4_atomic_open(dir, dentry, nd);
+               nfs_end_data_update(dir);
+@@ -1013,7 +1013,7 @@ static struct dentry *nfs_atomic_lookup(
+                       case -ENOTDIR:
+                               goto no_open;
+                       case -ELOOP:
+-                              if (!(nd->intent.open.flags & O_NOFOLLOW))
++                              if (!(nd->intent.it_flags & O_NOFOLLOW))
+                                       goto no_open;
+                       /* case -EINVAL: */
+                       default:
+@@ -1049,7 +1049,7 @@ static int nfs_open_revalidate(struct de
+       /* NFS only supports OPEN on regular files */
+       if (!S_ISREG(inode->i_mode))
+               goto no_open;
+-      openflags = nd->intent.open.flags;
++      openflags = nd->intent.it_flags;
+       /* We cannot do exclusive creation on a positive dentry */
+       if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
+               goto no_open;
+@@ -1182,7 +1182,7 @@ static int nfs_create(struct inode *dir,
+       attr.ia_valid = ATTR_MODE;
+       if (nd && (nd->flags & LOOKUP_CREATE))
+-              open_flags = nd->intent.open.flags;
++              open_flags = nd->intent.it_flags;
+       lock_kernel();
+       nfs_begin_data_update(dir);
+Index: linux-2.6/fs/nfs/nfs4proc.c
+===================================================================
+--- linux-2.6.orig/fs/nfs/nfs4proc.c   2006-07-15 21:04:01.000000000 +0800
++++ linux-2.6/fs/nfs/nfs4proc.c        2006-07-15 21:09:29.000000000 +0800
+@@ -1246,7 +1246,7 @@ static int nfs4_intent_set_file(struct n
+               ctx->state = state;
+               return 0;
+       }
+-      nfs4_close_state(state, nd->intent.open.flags);
++      nfs4_close_state(state, nd->intent.flags);
+       return PTR_ERR(filp);
+ }
+@@ -1259,22 +1259,22 @@ nfs4_atomic_open(struct inode *dir, stru
+       struct dentry *res;
+       if (nd->flags & LOOKUP_CREATE) {
+-              attr.ia_mode = nd->intent.open.create_mode;
++              attr.ia_mode = nd->intent.create_mode;
+               attr.ia_valid = ATTR_MODE;
+               if (!IS_POSIXACL(dir))
+                       attr.ia_mode &= ~current->fs->umask;
+       } else {
+               attr.ia_valid = 0;
+-              BUG_ON(nd->intent.open.flags & O_CREAT);
++              BUG_ON(nd->intent.flags & O_CREAT);
+       }
+       cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0);
+       if (IS_ERR(cred))
+               return (struct dentry *)cred;
+-      state = nfs4_do_open(dir, dentry, nd->intent.open.flags, &attr, cred);
++      state = nfs4_do_open(dir, dentry, nd->intent.flags, &attr, cred);
+       put_rpccred(cred);
+       if (IS_ERR(state)) {
+-              if (PTR_ERR(state) == -ENOENT)
++              ose_statef (PTR_ERR(state) == -ENOENT);
+                       d_add(dentry, NULL);
+               return (struct dentry *)state;
+       }
diff --git a/lustre/kernel_patches/patches/raid5-configurable-cachesize.patch b/lustre/kernel_patches/patches/raid5-configurable-cachesize.patch
new file mode 100644 (file)
index 0000000..7045872
--- /dev/null
@@ -0,0 +1,50 @@
+Adds a module parameter to control raid5's internal cache size.
+
+Index: linux-2.6.9/drivers/md/raid5.c
+===================================================================
+--- linux-2.6.9.orig/drivers/md/raid5.c        2006-05-21 17:57:25.000000000 +0400
++++ linux-2.6.9/drivers/md/raid5.c     2006-05-22 00:01:30.000000000 +0400
+@@ -28,7 +28,8 @@
+  * Stripe cache
+  */
+-#define NR_STRIPES            256
++static int raid5_nr_stripes = 256 * 8;
++
+ #define STRIPE_SIZE           PAGE_SIZE
+ #define STRIPE_SHIFT          (PAGE_SHIFT - 9)
+ #define STRIPE_SECTORS                (STRIPE_SIZE>>9)
+@@ -92,7 +93,7 @@ static inline void __release_stripe(raid
+                       list_add_tail(&sh->lru, &conf->inactive_list);
+                       atomic_dec(&conf->active_stripes);
+                       if (!conf->inactive_blocked ||
+-                          atomic_read(&conf->active_stripes) < (NR_STRIPES*3/4))
++                          atomic_read(&conf->active_stripes) < (conf->max_nr_stripes*3/4))
+                               wake_up(&conf->wait_for_stripe);
+               }
+       }
+@@ -255,7 +256,7 @@ static struct stripe_head *get_active_st
+                               conf->inactive_blocked = 1;
+                               wait_event_lock_irq(conf->wait_for_stripe,
+                                                   !list_empty(&conf->inactive_list) &&
+-                                                  (atomic_read(&conf->active_stripes) < (NR_STRIPES *3/4)
++                                                  (atomic_read(&conf->active_stripes) < (conf->max_nr_stripes *3/4)
+                                                    || !conf->inactive_blocked),
+                                                   conf->device_lock,
+                                                   unplug_slaves(conf->mddev);
+@@ -1637,7 +1638,7 @@ static int run (mddev_t *mddev)
+       conf->chunk_size = mddev->chunk_size;
+       conf->level = mddev->level;
+       conf->algorithm = mddev->layout;
+-      conf->max_nr_stripes = NR_STRIPES;
++      conf->max_nr_stripes = raid5_nr_stripes;
+       /* device size must be a multiple of chunk size */
+       mddev->size &= ~(mddev->chunk_size/1024 -1);
+@@ -1957,5 +1958,6 @@ static void raid5_exit (void)
+ module_init(raid5_init);
+ module_exit(raid5_exit);
++module_param(raid5_nr_stripes, int, 0644);
+ MODULE_LICENSE("GPL");
+ MODULE_ALIAS("md-personality-4"); /* RAID5 */
diff --git a/lustre/kernel_patches/patches/raid5-large-io.patch b/lustre/kernel_patches/patches/raid5-large-io.patch
new file mode 100644 (file)
index 0000000..591e6c4
--- /dev/null
@@ -0,0 +1,20 @@
+This patch changes max request size to <chunk size> * <disks>
+in order to allow Lustre to submit large I/Os and avoid
+unnecessary reads.
+
+Index: linux-2.6.9/drivers/md/raid5.c
+===================================================================
+--- linux-2.6.9.orig/drivers/md/raid5.c        2006-05-22 00:01:30.000000000 +0400
++++ linux-2.6.9/drivers/md/raid5.c     2006-05-22 00:09:56.000000000 +0400
+@@ -1609,6 +1609,11 @@ static int run (mddev_t *mddev)
+       mddev->queue->unplug_fn = raid5_unplug_device;
+       mddev->queue->issue_flush_fn = raid5_issue_flush;
++      /* in order to support large I/Os */
++      blk_queue_max_sectors(mddev->queue, mddev->chunk_size * mddev->raid_disks >> 9);
++      mddev->queue->max_phys_segments = mddev->chunk_size * mddev->raid_disks >> PAGE_SHIFT;
++      mddev->queue->max_hw_segments = mddev->chunk_size * mddev->raid_disks >> PAGE_SHIFT;;
++
+       PRINTK("raid5: run(%s) called.\n", mdname(mddev));
+       ITERATE_RDEV(mddev,rdev,tmp) {
diff --git a/lustre/kernel_patches/patches/raid5-merge-ios.patch b/lustre/kernel_patches/patches/raid5-merge-ios.patch
new file mode 100644 (file)
index 0000000..3f5cbbc
--- /dev/null
@@ -0,0 +1,129 @@
+Merge IO requests to try and get larger requests on underlying drives.
+
+Index: linux-2.6.9/drivers/md/raid5.c
+===================================================================
+--- linux-2.6.9.orig/drivers/md/raid5.c        2006-05-22 00:10:04.000000000 +0400
++++ linux-2.6.9/drivers/md/raid5.c     2006-05-22 00:10:06.000000000 +0400
+@@ -934,6 +934,26 @@ static void add_stripe_bio (struct strip
+       }
+ }
++/*
++ * The whole idea is to collect all bio's and then issue them
++ * disk by disk to assist merging a bit -bzzz
++ */
++static void raid5_flush_bios(raid5_conf_t *conf, struct bio *bios[], int raid_disks)
++{
++      struct bio *bio, *nbio;
++      int i;
++
++      for (i = 0; i < raid_disks; i++) {
++              bio = bios[i];
++              while (bio) {
++                      nbio = bio->bi_next;
++                      bio->bi_next = NULL;
++                      generic_make_request(bio);
++                      bio = nbio;
++              }
++              bios[i] = NULL;
++      }
++}
+ /*
+  * handle_stripe - do things to a stripe.
+@@ -953,7 +973,7 @@ static void add_stripe_bio (struct strip
+  *
+  */
+  
+-static void handle_stripe(struct stripe_head *sh)
++static void handle_stripe(struct stripe_head *sh, struct bio *bios[])
+ {
+       raid5_conf_t *conf = sh->raid_conf;
+       int disks = conf->raid_disks;
+@@ -1376,7 +1396,11 @@ static void handle_stripe(struct stripe_
+                       bi->bi_size = STRIPE_SIZE;
+                       bi->bi_next = NULL;
+                       atomic_inc(&conf->out_reqs_in_queue);
+-                      generic_make_request(bi);
++                      if (bios) {
++                              bi->bi_next = bios[i];
++                              bios[i] = bi;
++                      } else
++                              generic_make_request(bi);
+               } else {
+                       PRINTK("skip op %ld on disc %d for sector %llu\n",
+                               bi->bi_rw, i, (unsigned long long)sh->sector);
+@@ -1501,6 +1525,7 @@ static int make_request (request_queue_t
+       int sectors_per_chunk = conf->chunk_size >> 9;
+       int stripes_per_chunk, sectors_per_block;
+       int sectors_per_stripe;
++      struct bio *bios[MD_SB_DISKS];
+       int i, j;
+       atomic_inc(&conf->in_reqs_in_queue);
+@@ -1530,6 +1555,7 @@ static int make_request (request_queue_t
+       sector_div(block, sectors_per_block);
+       sectors = bi->bi_size >> 9;
++      memset(&bios, 0, sizeof(bios));
+ repeat:
+       stripe = block * sectors_per_block / data_disks;
+       b_sector = stripe * data_disks;
+@@ -1549,9 +1575,17 @@ repeat:
+                       new_sector = raid5_compute_sector(r_sector, raid_disks,
+                                                       data_disks, &dd_idx, 
+                                                       &pd_idx, conf);
+-                      if (sh == NULL)
+-                              sh = get_active_stripe(conf, new_sector, pd_idx,
+-                                                      (bi->bi_rw&RWA_MASK));
++                      if (sh == NULL) {
++                              /* first, try to get stripe w/o blocking
++                               * if we can't, then it's time to submit
++                               * all collected bio's in order to free
++                               * some space in the cache -bzzz */
++                              sh = get_active_stripe(conf, new_sector, pd_idx, 1);
++                              if (!sh && !(bi->bi_rw&RWA_MASK)) {
++                                      raid5_flush_bios(conf, bios, raid_disks);
++                                      sh = get_active_stripe(conf, new_sector, pd_idx, 0);
++                              }
++                      }
+                       if (sh) {
+                               add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK));
+                       } else {
+@@ -1571,7 +1605,7 @@ repeat:
+               }
+               if (sh) {
+                       raid5_plug_device(conf);
+-                      handle_stripe(sh);
++                      handle_stripe(sh, bios);
+                       release_stripe(sh);
+                       sh = NULL;
+               }
+@@ -1581,6 +1615,9 @@ repeat:
+       if (sectors > 0)
+               goto repeat;
++      /* now flush all bio's */
++      raid5_flush_bios(conf, bios, raid_disks);
++
+       spin_lock_irq(&conf->device_lock);
+       if (--bi->bi_phys_segments == 0) {
+               int bytes = bi->bi_size;
+@@ -1636,7 +1673,7 @@ static int sync_request (mddev_t *mddev,
+       clear_bit(STRIPE_INSYNC, &sh->state);
+       spin_unlock(&sh->lock);
+-      handle_stripe(sh);
++      handle_stripe(sh, NULL);
+       release_stripe(sh);
+       return STRIPE_SECTORS;
+@@ -1685,7 +1722,7 @@ static void raid5d (mddev_t *mddev)
+               
+               handled++;
+               atomic_inc(&conf->handled_in_raid5d);
+-              handle_stripe(sh);
++              handle_stripe(sh, NULL);
+               release_stripe(sh);
+               spin_lock_irq(&conf->device_lock);
diff --git a/lustre/kernel_patches/patches/raid5-optimize-memcpy.patch b/lustre/kernel_patches/patches/raid5-optimize-memcpy.patch
new file mode 100644 (file)
index 0000000..4e0d20e
--- /dev/null
@@ -0,0 +1,226 @@
+In case of full-stripe writes don't copy data into internal cache.
+This optimization reduces CPU load by 30% rougly.
+
+Index: linux-2.6.9/include/linux/raid/raid5.h
+===================================================================
+--- linux-2.6.9.orig/include/linux/raid/raid5.h        2006-05-21 17:57:25.000000000 +0400
++++ linux-2.6.9/include/linux/raid/raid5.h     2006-05-22 00:10:04.000000000 +0400
+@@ -152,6 +152,7 @@ struct stripe_head {
+ #define       R5_Wantread     4       /* want to schedule a read */
+ #define       R5_Wantwrite    5
+ #define       R5_Syncio       6       /* this io need to be accounted as resync io */
++#define       R5_Direct       7       /* use page fom passed bio to avoid memcpy */
+ /*
+  * Write method
+Index: linux-2.6.9/drivers/md/raid5.c
+===================================================================
+--- linux-2.6.9.orig/drivers/md/raid5.c        2006-05-22 00:10:01.000000000 +0400
++++ linux-2.6.9/drivers/md/raid5.c     2006-05-22 00:10:04.000000000 +0400
+@@ -411,6 +411,8 @@ static int raid5_end_read_request (struc
+               clear_buffer_uptodate(bh);
+       }
+ #endif
++      if (test_bit(R5_Direct, &sh->dev[i].flags))
++              printk("R5_Direct for READ ?!\n");
+       clear_bit(R5_LOCKED, &sh->dev[i].flags);
+       set_bit(STRIPE_HANDLE, &sh->state);
+       release_stripe(sh);
+@@ -449,6 +451,10 @@ static int raid5_end_write_request (stru
+       rdev_dec_pending(conf->disks[i].rdev, conf->mddev);
+       
++      if (test_bit(R5_Direct, &sh->dev[i].flags)) {
++              BUG_ON(sh->dev[i].req.bi_io_vec[0].bv_page == sh->dev[i].page);
++              sh->dev[i].req.bi_io_vec[0].bv_page = sh->dev[i].page;
++      }
+       clear_bit(R5_LOCKED, &sh->dev[i].flags);
+       set_bit(STRIPE_HANDLE, &sh->state);
+       __release_stripe(conf, sh);
+@@ -673,6 +679,49 @@ static void copy_data(int frombio, struc
+       }
+ }
++static struct page *zero_copy_data(struct bio *bio, sector_t sector)
++{
++      struct bio_vec *bvl;
++      int i;
++
++      for (;bio && bio->bi_sector < sector+STRIPE_SECTORS;
++            bio = r5_next_bio(bio, sector) ) {
++              int page_offset;
++              if (bio->bi_sector >= sector)
++                      page_offset = (signed)(bio->bi_sector - sector) * 512;
++              else 
++                      page_offset = (signed)(sector - bio->bi_sector) * -512;
++              bio_for_each_segment(bvl, bio, i) {
++                      int len = bio_iovec_idx(bio,i)->bv_len;
++                      int clen;
++                      int b_offset = 0;                       
++
++                      if (page_offset < 0) {
++                              b_offset = -page_offset;
++                              page_offset += b_offset;
++                              len -= b_offset;
++                      }
++
++                      if (len > 0 && page_offset + len > STRIPE_SIZE)
++                              clen = STRIPE_SIZE - page_offset;       
++                      else clen = len;
++                      
++                      if (clen > 0) {
++                              BUG_ON(clen < STRIPE_SIZE);
++                              /*printk("  sector %lu: page %p from index %u\n",
++                                      (unsigned long) sector,
++                                      bio_iovec_idx(bio, i)->bv_page, i);*/
++                              return bio_iovec_idx(bio, i)->bv_page;
++                      }       
++                      if (clen < len) /* hit end of page */
++                              break;
++                      page_offset +=  len;
++              }
++      }
++      BUG();
++      return NULL;
++}
++
+ #define check_xor()   do {                                            \
+                          if (count == MAX_XOR_BLOCKS) {               \
+                               xor_block(count, STRIPE_SIZE, ptr);     \
+@@ -717,6 +766,8 @@ static void compute_parity(struct stripe
+       int i, pd_idx = sh->pd_idx, disks = conf->raid_disks, count;
+       void *ptr[MAX_XOR_BLOCKS];
+       struct bio *chosen;
++      struct page *page;
++      int zerocopy = 0;
+       PRINTK("compute_parity, stripe %llu, method %d\n",
+               (unsigned long long)sh->sector, method);
+@@ -743,13 +794,17 @@ static void compute_parity(struct stripe
+               break;
+       case RECONSTRUCT_WRITE:
+               memset(ptr[0], 0, STRIPE_SIZE);
+-              for (i= disks; i-- ;)
++              zerocopy = 1;
++              for (i= disks; i-- ;) {
++                      if (i != pd_idx && !sh->dev[i].towrite)
++                              zerocopy = 0;
+                       if (i!=pd_idx && sh->dev[i].towrite) {
+                               chosen = sh->dev[i].towrite;
+                               sh->dev[i].towrite = NULL;
+                               if (sh->dev[i].written) BUG();
+                               sh->dev[i].written = chosen;
+                       }
++              }
+               break;
+       case CHECK_PARITY:
+               break;
+@@ -759,34 +814,61 @@ static void compute_parity(struct stripe
+               count = 1;
+       }
+       
+-      for (i = disks; i--;)
+-              if (sh->dev[i].written) {
+-                      sector_t sector = sh->dev[i].sector;
+-                      struct bio *wbi = sh->dev[i].written;
+-                      while (wbi && wbi->bi_sector < sector + STRIPE_SECTORS) {
+-                              copy_data(1, wbi, sh->dev[i].page, sector);
+-                              wbi = r5_next_bio(wbi, sector);
+-                      }
++      for (i = disks; i--;) {
++              struct bio *wbi = sh->dev[i].written;
++              sector_t sector;
++
++              if (!wbi)
++                      continue;
++
++              sector = sh->dev[i].sector;
++              set_bit(R5_LOCKED, &sh->dev[i].flags);
++              BUG_ON(test_bit(R5_Direct, &sh->dev[i].flags));
++
++              /* check if it's covered by a single page
++                 and whole stripe is written at once.
++               * in this case we can avoid memcpy() */
++              if (zerocopy && wbi && wbi->bi_next == NULL && 
++                              test_bit(R5_OVERWRITE, &sh->dev[i].flags)) {
++                      page = zero_copy_data(wbi, sector);
++                      BUG_ON(PageHighMem(page));
++                      sh->dev[i].req.bi_io_vec[0].bv_page = page;
++                      set_bit(R5_Direct, &sh->dev[i].flags);
++                      continue;
++              }
+-                      set_bit(R5_LOCKED, &sh->dev[i].flags);
+-                      set_bit(R5_UPTODATE, &sh->dev[i].flags);
++              set_bit(R5_UPTODATE, &sh->dev[i].flags);
++              while (wbi && wbi->bi_sector < sector + STRIPE_SECTORS) {
++                      copy_data(1, wbi, sh->dev[i].page, sector);
++                      wbi = r5_next_bio(wbi, sector);
+               }
++      }
+       switch(method) {
+       case RECONSTRUCT_WRITE:
+       case CHECK_PARITY:
+-              for (i=disks; i--;)
+-                      if (i != pd_idx) {
+-                              ptr[count++] = page_address(sh->dev[i].page);
+-                              check_xor();
+-                      }
++              for (i=disks; i--;) {
++                      if (i == pd_idx)
++                              continue;
++                      if (test_bit(R5_Direct, &sh->dev[i].flags))
++                              page = sh->dev[i].req.bi_io_vec[0].bv_page;
++                      else
++                              page = sh->dev[i].page;
++                      ptr[count++] = page_address(page);
++                      check_xor();
++              }
+               break;
+       case READ_MODIFY_WRITE:
+-              for (i = disks; i--;)
+-                      if (sh->dev[i].written) {
+-                              ptr[count++] = page_address(sh->dev[i].page);
+-                              check_xor();
+-                      }
++              for (i = disks; i--;) {
++                      if (!sh->dev[i].written)
++                              continue;
++                      if (test_bit(R5_Direct, &sh->dev[i].flags))
++                              page = sh->dev[i].req.bi_io_vec[0].bv_page;
++                      else
++                              page = sh->dev[i].page;
++                      ptr[count++] = page_address(page);
++                      check_xor();
++              }
+       }
+       if (count != 1)
+               xor_block(count, STRIPE_SIZE, ptr);
+@@ -1012,7 +1094,7 @@ static void handle_stripe(struct stripe_
+       dev = &sh->dev[sh->pd_idx];
+       if ( written &&
+            ( (test_bit(R5_Insync, &dev->flags) && !test_bit(R5_LOCKED, &dev->flags) &&
+-              test_bit(R5_UPTODATE, &dev->flags))
++              (test_bit(R5_UPTODATE, &dev->flags) || test_bit(R5_Direct, &dev->flags)))
+              || (failed == 1 && failed_num == sh->pd_idx))
+           ) {
+           /* any written block on an uptodate or failed drive can be returned.
+@@ -1023,13 +1105,16 @@ static void handle_stripe(struct stripe_
+               if (sh->dev[i].written) {
+                   dev = &sh->dev[i];
+                   if (!test_bit(R5_LOCKED, &dev->flags) &&
+-                       test_bit(R5_UPTODATE, &dev->flags) ) {
++                       (test_bit(R5_UPTODATE, &dev->flags) ||
++                              test_bit(R5_Direct, &dev->flags)) ) {
+                       /* We can return any write requests */
+                           struct bio *wbi, *wbi2;
+                           PRINTK("Return write for disc %d\n", i);
+                           spin_lock_irq(&conf->device_lock);
+                           wbi = dev->written;
+                           dev->written = NULL;
++                          if (test_bit(R5_Direct, &dev->flags))
++                                  clear_bit(R5_Direct, &dev->flags);
+                           while (wbi && wbi->bi_sector < dev->sector + STRIPE_SECTORS) {
+                                   wbi2 = r5_next_bio(wbi, dev->sector);
+                                   if (--wbi->bi_phys_segments == 0) {
diff --git a/lustre/kernel_patches/patches/raid5-serialize-ovelapping-reqs.patch b/lustre/kernel_patches/patches/raid5-serialize-ovelapping-reqs.patch
new file mode 100644 (file)
index 0000000..d3c989c
--- /dev/null
@@ -0,0 +1,140 @@
+RAID5 wasn't designed to support overlapping requests because
+in Linux all I/Os are serialized by page/buffer lock.  As Lustre
+doesn't use pagecache on server, we need to serialize I/Os in RAID5.
+
+Index: linux-2.6.9/include/linux/raid/raid5.h
+===================================================================
+--- linux-2.6.9.orig/include/linux/raid/raid5.h        2006-05-22 00:11:21.000000000 +0400
++++ linux-2.6.9/include/linux/raid/raid5.h     2006-05-22 00:11:21.000000000 +0400
+@@ -134,6 +134,7 @@ struct stripe_head {
+       unsigned long           state;                  /* state flags */
+       atomic_t                count;                  /* nr of active thread/requests */
+       spinlock_t              lock;
++      wait_queue_head_t       wait;                   /* waitchan for overlapped bio's */
+       struct r5dev {
+               struct bio      req;
+               struct bio_vec  vec;
+Index: linux-2.6.9/drivers/md/raid5.c
+===================================================================
+--- linux-2.6.9.orig/drivers/md/raid5.c        2006-05-22 00:11:21.000000000 +0400
++++ linux-2.6.9/drivers/md/raid5.c     2006-05-22 00:19:27.000000000 +0400
+@@ -308,6 +308,7 @@ static int grow_stripes(raid5_conf_t *co
+               memset(sh, 0, sizeof(*sh) + (devs-1)*sizeof(struct r5dev));
+               sh->raid_conf = conf;
+               sh->lock = SPIN_LOCK_UNLOCKED;
++              init_waitqueue_head(&sh->wait);
+               if (grow_buffers(sh, conf->raid_disks)) {
+                       shrink_buffers(sh, conf->raid_disks);
+@@ -878,6 +879,9 @@ static void compute_parity(struct stripe
+               set_bit(R5_LOCKED,   &sh->dev[pd_idx].flags);
+       } else
+               clear_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
++
++      /* probably someone waits for our completion? */
++      wake_up(&sh->wait);
+ }
+ /*
+@@ -885,7 +889,7 @@ static void compute_parity(struct stripe
+  * toread/towrite point to the first in a chain. 
+  * The bi_next chain must be in order.
+  */
+-static void add_stripe_bio (struct stripe_head *sh, struct bio *bi, int dd_idx, int forwrite)
++static int add_stripe_bio (struct stripe_head *sh, struct bio *bi, int dd_idx, int forwrite)
+ {
+       struct bio **bip;
+       raid5_conf_t *conf = sh->raid_conf;
+@@ -894,13 +898,21 @@ static void add_stripe_bio (struct strip
+               (unsigned long long)bi->bi_sector,
+               (unsigned long long)sh->sector);
+-
+       spin_lock(&sh->lock);
+       spin_lock_irq(&conf->device_lock);
+       if (forwrite)
+               bip = &sh->dev[dd_idx].towrite;
+       else
+               bip = &sh->dev[dd_idx].toread;
++
++#if 1
++      if (*bip) {
++              /* overlapping bio, let's wait till first one is completed */
++              spin_unlock_irq(&conf->device_lock);
++              spin_unlock(&sh->lock);
++              return 1;
++      }
++#else
+       while (*bip && (*bip)->bi_sector < bi->bi_sector) {
+               BUG_ON((*bip)->bi_sector + ((*bip)->bi_size >> 9) > bi->bi_sector);
+               bip = & (*bip)->bi_next;
+@@ -910,6 +922,7 @@ static void add_stripe_bio (struct strip
+               BUG();
+       if (*bip)
+               bi->bi_next = *bip;
++#endif
+       *bip = bi;
+       bi->bi_phys_segments ++;
+       spin_unlock_irq(&conf->device_lock);
+@@ -932,6 +945,7 @@ static void add_stripe_bio (struct strip
+               if (sector >= sh->dev[dd_idx].sector + STRIPE_SECTORS)
+                       set_bit(R5_OVERWRITE, &sh->dev[dd_idx].flags);
+       }
++      return 0;
+ }
+ /*
+@@ -1014,6 +1028,7 @@ static void handle_stripe(struct stripe_
+                       rbi = dev->toread;
+                       dev->toread = NULL;
+                       spin_unlock_irq(&conf->device_lock);
++                      wake_up(&sh->wait);
+                       while (rbi && rbi->bi_sector < dev->sector + STRIPE_SECTORS) {
+                               copy_data(0, rbi, dev->page, dev->sector);
+                               rbi2 = r5_next_bio(rbi, dev->sector);
+@@ -1059,6 +1074,7 @@ static void handle_stripe(struct stripe_
+                       bi = sh->dev[i].towrite;
+                       sh->dev[i].towrite = NULL;
+                       if (bi) to_write--;
++                      wake_up(&sh->wait);
+                       while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){
+                               struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
+@@ -1511,6 +1527,16 @@ static inline void raid5_plug_device(rai
+       spin_unlock_irq(&conf->device_lock);
+ }
++static inline void raid5_wait_stripe(struct stripe_head *sh, int dd_idx, int forwrite)
++{
++      struct bio **bip;
++      if (forwrite)
++              bip = &sh->dev[dd_idx].towrite;
++      else
++              bip = &sh->dev[dd_idx].toread;
++      wait_event(sh->wait, *bip == NULL);
++}
++
+ static int make_request (request_queue_t *q, struct bio * bi)
+ {
+       mddev_t *mddev = q->queuedata;
+@@ -1580,6 +1606,7 @@ repeat:
+                                * if we can't, then it's time to submit
+                                * all collected bio's in order to free
+                                * some space in the cache -bzzz */
++try_stripe:
+                               sh = get_active_stripe(conf, new_sector, pd_idx, 1);
+                               if (!sh && !(bi->bi_rw&RWA_MASK)) {
+                                       raid5_flush_bios(conf, bios, raid_disks);
+@@ -1587,7 +1614,11 @@ repeat:
+                               }
+                       }
+                       if (sh) {
+-                              add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK));
++                              if (add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK))) {
++                                      release_stripe(sh);
++                                      raid5_wait_stripe(sh, dd_idx, bi->bi_rw&RW_MASK);
++                                      goto try_stripe;
++                              }
+                       } else {
+                               /* cannot get stripe for read-ahead, just give-up */
+                               clear_bit(BIO_UPTODATE, &bi->bi_flags);
diff --git a/lustre/kernel_patches/patches/raid5-stats.patch b/lustre/kernel_patches/patches/raid5-stats.patch
new file mode 100644 (file)
index 0000000..1308009
--- /dev/null
@@ -0,0 +1,200 @@
+Add RAID statistics counters to /proc/mdstat
+
+Index: linux-2.6.9/include/linux/raid/raid5.h
+===================================================================
+--- linux-2.6.9.orig/include/linux/raid/raid5.h        2004-10-19 01:54:55.000000000 +0400
++++ linux-2.6.9/include/linux/raid/raid5.h     2006-05-17 14:10:53.000000000 +0400
+@@ -222,6 +222,22 @@ struct raid5_private_data {
+       int                     inactive_blocked;       /* release of inactive stripes blocked,
+                                                        * waiting for 25% to be free
+                                                        */        
++      /*
++       * Stats
++       */
++      atomic_t                reads_in;
++      atomic_t                writes_in;
++      atomic_t                reads_out;
++      atomic_t                writes_out;
++      atomic_t                handled_in_raid5d;
++      atomic_t                out_of_stripes;
++      atomic_t                reads_for_rmw;
++      atomic_t                reads_for_rcw;
++      atomic_t                handle_called;
++      atomic_t                delayed;
++      atomic_t                in_reqs_in_queue;
++      atomic_t                out_reqs_in_queue;
++
+       spinlock_t              device_lock;
+       struct disk_info        disks[0];
+ };
+Index: linux-2.6.9/drivers/md/raid5.c
+===================================================================
+--- linux-2.6.9.orig/drivers/md/raid5.c        2006-03-10 18:20:48.000000000 +0300
++++ linux-2.6.9/drivers/md/raid5.c     2006-05-17 14:10:53.000000000 +0400
+@@ -77,9 +77,10 @@ static inline void __release_stripe(raid
+               if (atomic_read(&conf->active_stripes)==0)
+                       BUG();
+               if (test_bit(STRIPE_HANDLE, &sh->state)) {
+-                      if (test_bit(STRIPE_DELAYED, &sh->state))
++                      if (test_bit(STRIPE_DELAYED, &sh->state)) {
+                               list_add_tail(&sh->lru, &conf->delayed_list);
+-                      else
++                              atomic_inc(&conf->delayed);
++                      } else
+                               list_add_tail(&sh->lru, &conf->handle_list);
+                       md_wakeup_thread(conf->mddev->thread);
+               } else {
+@@ -250,6 +251,7 @@ static struct stripe_head *get_active_st
+                       if (noblock && sh == NULL)
+                               break;
+                       if (!sh) {
++                              atomic_inc(&conf->out_of_stripes);
+                               conf->inactive_blocked = 1;
+                               wait_event_lock_irq(conf->wait_for_stripe,
+                                                   !list_empty(&conf->inactive_list) &&
+@@ -271,6 +273,8 @@ static struct stripe_head *get_active_st
+                               if (list_empty(&sh->lru))
+                                       BUG();
+                               list_del_init(&sh->lru);
++                              if (test_bit(STRIPE_DELAYED, &sh->state))
++                                      atomic_dec(&conf->delayed);
+                       }
+               }
+       } while (sh == NULL);
+@@ -349,6 +353,8 @@ static int raid5_end_read_request (struc
+       if (bi->bi_size)
+               return 1;
++      atomic_dec(&conf->out_reqs_in_queue);
++
+       for (i=0 ; i<disks; i++)
+               if (bi == &sh->dev[i].req)
+                       break;
+@@ -422,6 +428,8 @@ static int raid5_end_write_request (stru
+       if (bi->bi_size)
+               return 1;
++      atomic_dec(&conf->out_reqs_in_queue);
++
+       for (i=0 ; i<disks; i++)
+               if (bi == &sh->dev[i].req)
+                       break;
+@@ -882,6 +890,7 @@ static void handle_stripe(struct stripe_
+       spin_lock(&sh->lock);
+       clear_bit(STRIPE_HANDLE, &sh->state);
+       clear_bit(STRIPE_DELAYED, &sh->state);
++      atomic_inc(&conf->handle_called);
+       syncing = test_bit(STRIPE_SYNCING, &sh->state);
+       /* Now to look around and see what can be done */
+@@ -1127,6 +1136,7 @@ static void handle_stripe(struct stripe_
+                                               set_bit(R5_LOCKED, &dev->flags);
+                                               set_bit(R5_Wantread, &dev->flags);
+                                               locked++;
++                                              atomic_inc(&conf->reads_for_rmw);
+                                       } else {
+                                               set_bit(STRIPE_DELAYED, &sh->state);
+                                               set_bit(STRIPE_HANDLE, &sh->state);
+@@ -1146,6 +1156,7 @@ static void handle_stripe(struct stripe_
+                                               set_bit(R5_LOCKED, &dev->flags);
+                                               set_bit(R5_Wantread, &dev->flags);
+                                               locked++;
++                                              atomic_inc(&conf->reads_for_rcw);
+                                       } else {
+                                               set_bit(STRIPE_DELAYED, &sh->state);
+                                               set_bit(STRIPE_HANDLE, &sh->state);
+@@ -1228,6 +1239,7 @@ static void handle_stripe(struct stripe_
+               bi->bi_next = NULL;
+               bi->bi_size = 0;
+               bi->bi_end_io(bi, bytes, 0);
++              atomic_dec(&conf->in_reqs_in_queue);
+       }
+       for (i=disks; i-- ;) {
+               int rw;
+@@ -1243,10 +1255,13 @@ static void handle_stripe(struct stripe_
+               bi = &sh->dev[i].req;
+  
+               bi->bi_rw = rw;
+-              if (rw)
++              if (rw) {
++                      atomic_inc(&conf->writes_out);
+                       bi->bi_end_io = raid5_end_write_request;
+-              else
++              } else {
++                      atomic_inc(&conf->reads_out);
+                       bi->bi_end_io = raid5_end_read_request;
++              }
+  
+               spin_lock_irq(&conf->device_lock);
+               rdev = conf->disks[i].rdev;
+@@ -1274,6 +1289,7 @@ static void handle_stripe(struct stripe_
+                       bi->bi_io_vec[0].bv_offset = 0;
+                       bi->bi_size = STRIPE_SIZE;
+                       bi->bi_next = NULL;
++                      atomic_inc(&conf->out_reqs_in_queue);
+                       generic_make_request(bi);
+               } else {
+                       PRINTK("skip op %ld on disc %d for sector %llu\n",
+@@ -1296,6 +1312,7 @@ static inline void raid5_activate_delaye
+                       if (!test_and_set_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
+                               atomic_inc(&conf->preread_active_stripes);
+                       list_add_tail(&sh->lru, &conf->handle_list);
++                      atomic_dec(&conf->delayed);
+               }
+       }
+ }
+@@ -1395,12 +1412,16 @@ static int make_request (request_queue_t
+       sector_t logical_sector, last_sector;
+       struct stripe_head *sh;
++      atomic_inc(&conf->in_reqs_in_queue);
++
+       if (bio_data_dir(bi)==WRITE) {
+               disk_stat_inc(mddev->gendisk, writes);
+               disk_stat_add(mddev->gendisk, write_sectors, bio_sectors(bi));
++              atomic_inc(&conf->writes_in);
+       } else {
+               disk_stat_inc(mddev->gendisk, reads);
+               disk_stat_add(mddev->gendisk, read_sectors, bio_sectors(bi));
++              atomic_inc(&conf->reads_in);
+       }
+       logical_sector = bi->bi_sector & ~((sector_t)STRIPE_SECTORS-1);
+@@ -1439,6 +1460,7 @@ static int make_request (request_queue_t
+               if ( bio_data_dir(bi) == WRITE )
+                       md_write_end(mddev);
++              atomic_dec(&conf->in_reqs_in_queue);
+               bi->bi_size = 0;
+               bi->bi_end_io(bi, bytes, 0);
+       }
+@@ -1535,6 +1557,7 @@ static void raid5d (mddev_t *mddev)
+               spin_unlock_irq(&conf->device_lock);
+               
+               handled++;
++              atomic_inc(&conf->handled_in_raid5d);
+               handle_stripe(sh);
+               release_stripe(sh);
+@@ -1767,6 +1790,21 @@ static void status (struct seq_file *seq
+                              conf->disks[i].rdev &&
+                              conf->disks[i].rdev->in_sync ? "U" : "_");
+       seq_printf (seq, "]");
++      seq_printf (seq, "\n\t\tin: %u reads, %u writes; out: %u reads, %u writes",
++                      atomic_read(&conf->reads_in), atomic_read(&conf->writes_in),
++                      atomic_read(&conf->reads_out), atomic_read(&conf->writes_out));
++      seq_printf (seq, "\n\t\t%u in raid5d, %u out of stripes, %u handle called",
++                      atomic_read(&conf->handled_in_raid5d),
++                      atomic_read(&conf->out_of_stripes),
++                      atomic_read(&conf->handle_called));
++      seq_printf (seq, "\n\t\treads: %u for rmw, %u for rcw",
++                      atomic_read(&conf->reads_for_rmw),
++                      atomic_read(&conf->reads_for_rcw));
++      seq_printf (seq, "\n\t\t%u delayed, %u active, queues: %u in, %u out\n",
++                      atomic_read(&conf->delayed),
++                      atomic_read(&conf->active_stripes),
++                      atomic_read(&conf->in_reqs_in_queue),
++                      atomic_read(&conf->out_reqs_in_queue));
+ #if RAID5_DEBUG
+ #define D(x) \
+       seq_printf (seq, "<"#x":%d>", atomic_read(&conf->x))
diff --git a/lustre/kernel_patches/patches/raid5-stripe-by-stripe-handling.patch b/lustre/kernel_patches/patches/raid5-stripe-by-stripe-handling.patch
new file mode 100644 (file)
index 0000000..d86a42a
--- /dev/null
@@ -0,0 +1,104 @@
+Helps to avoid unnesessary reads if request covers full stripe.
+
+Note that reads needed to update parity hurt performance badly
+
+Index: linux-2.6.9/drivers/md/raid5.c
+===================================================================
+--- linux-2.6.9.orig/drivers/md/raid5.c        2006-05-22 00:09:56.000000000 +0400
++++ linux-2.6.9/drivers/md/raid5.c     2006-05-22 00:10:01.000000000 +0400
+@@ -1412,6 +1412,11 @@ static int make_request (request_queue_t
+       sector_t new_sector;
+       sector_t logical_sector, last_sector;
+       struct stripe_head *sh;
++      sector_t stripe, sectors, block, r_sector, b_sector;
++      int sectors_per_chunk = conf->chunk_size >> 9;
++      int stripes_per_chunk, sectors_per_block;
++      int sectors_per_stripe;
++      int i, j;
+       atomic_inc(&conf->in_reqs_in_queue);
+@@ -1431,30 +1436,66 @@ static int make_request (request_queue_t
+       bi->bi_phys_segments = 1;       /* over-loaded to count active stripes */
+       if ( bio_data_dir(bi) == WRITE )
+               md_write_start(mddev);
+-      for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) {
+-              
+-              new_sector = raid5_compute_sector(logical_sector,
+-                                                raid_disks, data_disks, &dd_idx, &pd_idx, conf);
+-
+-              PRINTK("raid5: make_request, sector %Lu logical %Lu\n",
+-                      (unsigned long long)new_sector, 
+-                      (unsigned long long)logical_sector);
+-              sh = get_active_stripe(conf, new_sector, pd_idx, (bi->bi_rw&RWA_MASK));
++      stripes_per_chunk = conf->chunk_size / STRIPE_SIZE;
++      sectors_per_stripe = STRIPE_SECTORS * data_disks;
++      sectors_per_block = stripes_per_chunk * sectors_per_stripe;
++
++      block = logical_sector & ~((sector_t)sectors_per_block - 1);
++      sector_div(block, sectors_per_block);
++      sectors = bi->bi_size >> 9;
++
++repeat:
++      stripe = block * (sectors_per_block / data_disks);
++      b_sector = stripe * data_disks;
++      /* iterate through all stripes in this block,
++       * where block is a set of internal stripes
++       * which covers chunk */
++      for (i = 0; i < stripes_per_chunk && sectors > 0; i++) {
++              r_sector = b_sector + (i * STRIPE_SECTORS);
++              sh = NULL;
++              /* iterrate through all pages in the stripe */
++              for (j = 0; j < data_disks && sectors > 0; j++) {
++                      if (r_sector + STRIPE_SECTORS <= bi->bi_sector ||
++                                      r_sector >= last_sector) {
++                              r_sector += sectors_per_chunk;
++                              continue;
++                      }
++                      new_sector = raid5_compute_sector(r_sector, raid_disks,
++                                                      data_disks, &dd_idx, 
++                                                      &pd_idx, conf);
++                      if (sh == NULL)
++                              sh = get_active_stripe(conf, new_sector, pd_idx,
++                                                      (bi->bi_rw&RWA_MASK));
++                      if (sh) {
++                              add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK));
++                      } else {
++                              /* cannot get stripe for read-ahead, just give-up */
++                              clear_bit(BIO_UPTODATE, &bi->bi_flags);
++                              sectors = 0;
++                              break;
++                      }
++
++                      BUG_ON (new_sector != stripe);
++                      sectors -= STRIPE_SECTORS;
++                      if (bi->bi_sector > r_sector)
++                              sectors += bi->bi_sector - r_sector;
++                      if (r_sector + STRIPE_SECTORS > last_sector)
++                              sectors += r_sector + STRIPE_SECTORS - last_sector;
++                      r_sector += sectors_per_chunk;
++              }
+               if (sh) {
+-
+-                      add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK));
+-
+                       raid5_plug_device(conf);
+                       handle_stripe(sh);
+                       release_stripe(sh);
+-              } else {
+-                      /* cannot get stripe for read-ahead, just give-up */
+-                      clear_bit(BIO_UPTODATE, &bi->bi_flags);
+-                      break;
++                      sh = NULL;
+               }
+-                      
++              stripe += STRIPE_SECTORS;
+       }
++      block++; 
++      if (sectors > 0)
++              goto repeat;
++
+       spin_lock_irq(&conf->device_lock);
+       if (--bi->bi_phys_segments == 0) {
+               int bytes = bi->bi_size;
index 41d9d8a..625f85f 100644 (file)
@@ -1,8 +1,7 @@
-Index: linux-2.4.21/crypto/cipher.c
-===================================================================
---- linux-2.4.21.orig/crypto/cipher.c  2005-06-01 22:51:50.000000000 -0400
-+++ linux-2.4.21/crypto/cipher.c       2005-06-01 23:07:51.067582960 -0400
-@@ -88,12 +88,21 @@
+diff -X dontdiff -urp kern_oldest/crypto/cipher.c kern_fix/crypto/cipher.c
+--- kern_oldest/crypto/cipher.c        2006-05-01 11:55:53.000000000 -0700
++++ kern_fix/crypto/cipher.c   2006-05-01 14:14:13.000000000 -0700
+@@ -88,12 +88,21 @@ static void scatterwalk_start(struct sca
  
        walk->sg = sg;
  
@@ -24,11 +23,10 @@ Index: linux-2.4.21/crypto/cipher.c
  }
  
  static void scatterwalk_map(struct scatter_walk *walk, int out)
-Index: linux-2.4.21/crypto/digest.c
-===================================================================
---- linux-2.4.21.orig/crypto/digest.c  2005-06-01 22:51:50.000000000 -0400
-+++ linux-2.4.21/crypto/digest.c       2005-06-01 23:07:51.068582808 -0400
-@@ -29,7 +29,11 @@
+diff -X dontdiff -urp kern_oldest/crypto/digest.c kern_fix/crypto/digest.c
+--- kern_oldest/crypto/digest.c        2006-05-01 11:55:53.000000000 -0700
++++ kern_fix/crypto/digest.c   2006-05-01 14:14:13.000000000 -0700
+@@ -29,7 +29,11 @@ static void update(struct crypto_tfm *tf
        unsigned int i;
        
        for (i = 0; i < nsg; i++) {
@@ -40,7 +38,7 @@ Index: linux-2.4.21/crypto/digest.c
                tfm->__crt_alg->cra_digest.dia_update(crypto_tfm_ctx(tfm),
                                                      p, sg[i].length);
                crypto_kunmap(p, 0);
-@@ -50,7 +54,11 @@
+@@ -50,7 +54,11 @@ static void digest(struct crypto_tfm *tf
        tfm->crt_digest.dit_init(tfm);
                
        for (i = 0; i < nsg; i++) {
@@ -52,11 +50,10 @@ Index: linux-2.4.21/crypto/digest.c
                tfm->__crt_alg->cra_digest.dia_update(crypto_tfm_ctx(tfm),
                                                      p, sg[i].length);
                crypto_kunmap(p, 0);
-Index: linux-2.4.21/crypto/hmac.c
-===================================================================
---- linux-2.4.21.orig/crypto/hmac.c    2005-06-01 22:51:50.000000000 -0400
-+++ linux-2.4.21/crypto/hmac.c 2005-06-01 23:07:51.068582808 -0400
-@@ -25,8 +25,14 @@
+diff -X dontdiff -urp kern_oldest/crypto/hmac.c kern_fix/crypto/hmac.c
+--- kern_oldest/crypto/hmac.c  2006-05-01 11:55:53.000000000 -0700
++++ kern_fix/crypto/hmac.c     2006-05-01 14:14:13.000000000 -0700
+@@ -25,8 +25,14 @@ static void hash_key(struct crypto_tfm *
  {
        struct scatterlist tmp;
        
@@ -71,7 +68,7 @@ Index: linux-2.4.21/crypto/hmac.c
        tmp.length = keylen;
        crypto_digest_digest(tfm, &tmp, 1, key);
                
-@@ -70,8 +76,14 @@
+@@ -70,8 +76,14 @@ void crypto_hmac_init(struct crypto_tfm 
        for (i = 0; i < crypto_tfm_alg_blocksize(tfm); i++)
                ipad[i] ^= 0x36;
  
@@ -86,7 +83,7 @@ Index: linux-2.4.21/crypto/hmac.c
        tmp.length = crypto_tfm_alg_blocksize(tfm);
        
        crypto_digest_init(tfm);
-@@ -104,15 +116,27 @@
+@@ -104,15 +116,27 @@ void crypto_hmac_final(struct crypto_tfm
        for (i = 0; i < crypto_tfm_alg_blocksize(tfm); i++)
                opad[i] ^= 0x5c;
  
@@ -114,10 +111,9 @@ Index: linux-2.4.21/crypto/hmac.c
        tmp.length = crypto_tfm_alg_digestsize(tfm);
        
        crypto_digest_update(tfm, &tmp, 1);
-Index: linux-2.4.21/crypto/tcrypt.c
-===================================================================
---- linux-2.4.21.orig/crypto/tcrypt.c  2005-06-01 22:51:50.000000000 -0400
-+++ linux-2.4.21/crypto/tcrypt.c       2005-06-01 23:07:51.071582352 -0400
+diff -X dontdiff -urp kern_oldest/crypto/tcrypt.c kern_fix/crypto/tcrypt.c
+--- kern_oldest/crypto/tcrypt.c        2006-05-01 11:55:53.000000000 -0700
++++ kern_fix/crypto/tcrypt.c   2006-05-01 14:14:13.000000000 -0700
 @@ -24,6 +24,15 @@
  #include <linux/highmem.h>
  #include "tcrypt.h"
@@ -134,7 +130,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
  /*
   * Need to kmalloc() memory for testing kmap().
   */
-@@ -95,8 +104,8 @@
+@@ -95,8 +104,8 @@ test_md5(void)
                memset(result, 0, sizeof (result));
  
                p = md5_tv[i].plaintext;
@@ -145,7 +141,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                sg[0].length = strlen(md5_tv[i].plaintext);
  
                crypto_digest_init(tfm);
-@@ -118,13 +127,13 @@
+@@ -118,13 +127,13 @@ test_md5(void)
        memcpy(&xbuf[IDX2], "nopqrstuvwxyz", 13);
  
        p = &xbuf[IDX1];
@@ -163,7 +159,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
        sg[1].length = 13;
  
        memset(result, 0, sizeof (result));
-@@ -172,8 +181,8 @@
+@@ -172,8 +181,8 @@ test_hmac_md5(void)
                memset(result, 0, sizeof (result));
  
                p = hmac_md5_tv[i].plaintext;
@@ -174,7 +170,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                sg[0].length = strlen(hmac_md5_tv[i].plaintext);
  
                klen = strlen(hmac_md5_tv[i].key);
-@@ -194,13 +203,13 @@
+@@ -194,13 +203,13 @@ test_hmac_md5(void)
        memcpy(&xbuf[IDX2], "for nothing?", 12);
  
        p = &xbuf[IDX1];
@@ -192,7 +188,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
        sg[1].length = 12;
  
        memset(result, 0, sizeof (result));
-@@ -249,8 +258,8 @@
+@@ -249,8 +258,8 @@ test_hmac_sha1(void)
                memset(result, 0, sizeof (result));
  
                p = hmac_sha1_tv[i].plaintext;
@@ -203,7 +199,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                sg[0].length = strlen(hmac_sha1_tv[i].plaintext);
  
                klen = strlen(hmac_sha1_tv[i].key);
-@@ -273,13 +282,13 @@
+@@ -273,13 +282,13 @@ test_hmac_sha1(void)
        memcpy(&xbuf[IDX2], "for nothing?", 12);
  
        p = &xbuf[IDX1];
@@ -221,7 +217,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
        sg[1].length = 12;
  
        memset(result, 0, sizeof (result));
-@@ -328,8 +337,8 @@
+@@ -328,8 +337,8 @@ test_hmac_sha256(void)
                memset(result, 0, sizeof (result));
  
                p = hmac_sha256_tv[i].plaintext;
@@ -232,7 +228,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                sg[0].length = strlen(hmac_sha256_tv[i].plaintext);
  
                klen = strlen(hmac_sha256_tv[i].key);
-@@ -382,8 +391,8 @@
+@@ -382,8 +391,8 @@ test_md4(void)
                memset(result, 0, sizeof (result));
  
                p = md4_tv[i].plaintext;
@@ -243,7 +239,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                sg[0].length = strlen(md4_tv[i].plaintext);
  
                crypto_digest_digest(tfm, sg, 1, result);
-@@ -432,8 +441,8 @@
+@@ -432,8 +441,8 @@ test_sha1(void)
                memset(result, 0, sizeof (result));
  
                p = sha1_tv[i].plaintext;
@@ -254,7 +250,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                sg[0].length = strlen(sha1_tv[i].plaintext);
  
                crypto_digest_init(tfm);
-@@ -455,13 +464,13 @@
+@@ -455,13 +464,13 @@ test_sha1(void)
        memcpy(&xbuf[IDX2], "hijkijkljklmklmnlmnomnopnopq", 28);
  
        p = &xbuf[IDX1];
@@ -272,7 +268,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
        sg[1].length = 28;
  
        memset(result, 0, sizeof (result));
-@@ -507,8 +516,8 @@
+@@ -507,8 +516,8 @@ test_sha256(void)
                memset(result, 0, sizeof (result));
  
                p = sha256_tv[i].plaintext;
@@ -283,7 +279,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                sg[0].length = strlen(sha256_tv[i].plaintext);
  
                crypto_digest_init(tfm);
-@@ -530,13 +539,13 @@
+@@ -530,13 +539,13 @@ test_sha256(void)
        memcpy(&xbuf[IDX2], "hijkijkljklmklmnlmnomnopnopq", 28);
  
        p = &xbuf[IDX1];
@@ -301,7 +297,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
        sg[1].length = 28;
  
        memset(result, 0, sizeof (result));
-@@ -583,8 +592,8 @@
+@@ -583,8 +592,8 @@ test_sha384(void)
                memset(result, 0, sizeof (result));
  
                p = sha384_tv[i].plaintext;
@@ -312,7 +308,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                sg[0].length = strlen(sha384_tv[i].plaintext);
  
                crypto_digest_init(tfm);
-@@ -635,8 +644,8 @@
+@@ -635,8 +644,8 @@ test_sha512(void)
                memset(result, 0, sizeof (result));
  
                p = sha512_tv[i].plaintext;
@@ -323,7 +319,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                sg[0].length = strlen(sha512_tv[i].plaintext);
  
                crypto_digest_init(tfm);
-@@ -700,8 +709,8 @@
+@@ -700,8 +709,8 @@ test_des(void)
                len = des_tv[i].len;
  
                p = des_tv[i].plaintext;
@@ -334,7 +330,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                sg[0].length = len;
                ret = crypto_cipher_encrypt(tfm, sg, sg, len);
                if (ret) {
-@@ -709,7 +718,7 @@
+@@ -709,7 +718,7 @@ test_des(void)
                        goto out;
                }
  
@@ -343,7 +339,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                hexdump(q, len);
  
                printk("%s\n",
-@@ -737,13 +746,13 @@
+@@ -737,13 +746,13 @@ test_des(void)
        memcpy(&xbuf[IDX2], des_tv[i].plaintext + 8, 8);
  
        p = &xbuf[IDX1];
@@ -361,7 +357,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
        sg[1].length = 8;
  
        ret = crypto_cipher_encrypt(tfm, sg, sg, 16);
-@@ -753,12 +762,12 @@
+@@ -753,12 +762,12 @@ test_des(void)
        }
  
        printk("page 1\n");
@@ -376,7 +372,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
        hexdump(q, 8);
        printk("%s\n", memcmp(q, des_tv[i].result + 8, 8) ? "fail" : "pass");
  
-@@ -800,18 +809,18 @@
+@@ -800,18 +809,18 @@ test_des(void)
        memcpy(&xbuf[IDX5], des_tv[i].plaintext + 24, 8);
  
        p = &xbuf[IDX3];
@@ -401,7 +397,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
        sg[2].length = 8;
  
        ret = crypto_cipher_encrypt(tfm, sg, sg, 32);
-@@ -822,17 +831,17 @@
+@@ -822,17 +831,17 @@ test_des(void)
        }
  
        printk("page 1\n");
@@ -422,7 +418,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
        hexdump(q, 8);
        printk("%s\n", memcmp(q, des_tv[i].result + 24, 8) ? "fail" : "pass");
  
-@@ -871,23 +880,23 @@
+@@ -871,23 +880,23 @@ test_des(void)
        memcpy(&xbuf[IDX6], des_tv[i].plaintext + 6, 18);
  
        p = &xbuf[IDX3];
@@ -454,7 +450,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
        sg[3].length = 18;
  
        ret = crypto_cipher_encrypt(tfm, sg, sg, 24);
-@@ -898,22 +907,22 @@
+@@ -898,22 +907,22 @@ test_des(void)
        }
  
        printk("page 1\n");
@@ -481,7 +477,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
        hexdump(q, 18);
        printk("%s\n", memcmp(q, des_tv[i].result + 6, 18) ? "fail" : "pass");
  
-@@ -955,28 +964,28 @@
+@@ -955,28 +964,28 @@ test_des(void)
        memcpy(&xbuf[IDX7], des_tv[i].plaintext + 8, 8);
  
        p = &xbuf[IDX3];
@@ -520,7 +516,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
        sg[4].length = 8;
  
        ret = crypto_cipher_encrypt(tfm, sg, sg, 16);
-@@ -987,27 +996,27 @@
+@@ -987,27 +996,27 @@ test_des(void)
        }
  
        printk("page 1\n");
@@ -553,7 +549,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
        hexdump(q, 8);
        printk("%s\n", memcmp(q, des_tv[i].result + 8, 8) ? "fail" : "pass");
  
-@@ -1039,43 +1048,43 @@
+@@ -1039,43 +1048,43 @@ test_des(void)
        xbuf[IDX8] = des_tv[i].plaintext[7];
  
        p = &xbuf[IDX1];
@@ -613,7 +609,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
        sg[7].length = 1;
  
        ret = crypto_cipher_encrypt(tfm, sg, sg, 8);
-@@ -1085,7 +1094,7 @@
+@@ -1085,7 +1094,7 @@ test_des(void)
        }
  
        for (i = 0; i < 8; i++)
@@ -622,7 +618,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
  
        hexdump(res, 8);
        printk("%s\n", memcmp(res, des_tv[7].result, 8) ? "fail" : "pass");
-@@ -1116,8 +1125,8 @@
+@@ -1116,8 +1125,8 @@ test_des(void)
                len = des_tv[i].len;
  
                p = des_tv[i].plaintext;
@@ -633,7 +629,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                sg[0].length = len;
  
                ret = crypto_cipher_decrypt(tfm, sg, sg, sg[0].length);
-@@ -1127,7 +1136,7 @@
+@@ -1127,7 +1136,7 @@ test_des(void)
                        goto out;
                }
  
@@ -642,7 +638,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                hexdump(q, len);
  
                printk("%s\n",
-@@ -1154,13 +1163,13 @@
+@@ -1154,13 +1163,13 @@ test_des(void)
        memcpy(&xbuf[IDX2], des_tv[i].plaintext + 8, 8);
  
        p = &xbuf[IDX1];
@@ -660,7 +656,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
        sg[1].length = 8;
  
        ret = crypto_cipher_decrypt(tfm, sg, sg, 16);
-@@ -1170,12 +1179,12 @@
+@@ -1170,12 +1179,12 @@ test_des(void)
        }
  
        printk("page 1\n");
@@ -675,7 +671,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
        hexdump(q, 8);
        printk("%s\n", memcmp(q, des_tv[i].result + 8, 8) ? "fail" : "pass");
  
-@@ -1206,18 +1215,18 @@
+@@ -1206,18 +1215,18 @@ test_des(void)
        memcpy(&xbuf[IDX3], des_tv[i].plaintext + 15, 1);
  
        p = &xbuf[IDX1];
@@ -700,7 +696,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
        sg[2].length = 1;
  
        ret = crypto_cipher_decrypt(tfm, sg, sg, 16);
-@@ -1228,17 +1237,17 @@
+@@ -1228,17 +1237,17 @@ test_des(void)
        }
  
        printk("page 1\n");
@@ -721,7 +717,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
        hexdump(q, 1);
        printk("%s\n", memcmp(q, des_tv[i].result + 15, 1) ? "fail" : "pass");
  
-@@ -1283,8 +1292,8 @@
+@@ -1283,8 +1292,8 @@ test_des(void)
                len = des_tv[i].len;
                p = des_tv[i].plaintext;
  
@@ -732,7 +728,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                sg[0].length = len;
  
                crypto_cipher_set_iv(tfm, des_tv[i].iv,
-@@ -1297,7 +1306,7 @@
+@@ -1297,7 +1306,7 @@ test_des(void)
                        goto out;
                }
  
@@ -741,7 +737,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                hexdump(q, len);
  
                printk("%s\n",
-@@ -1338,13 +1347,13 @@
+@@ -1338,13 +1347,13 @@ test_des(void)
        memcpy(&xbuf[IDX2], des_tv[i].plaintext + 13, 11);
  
        p = &xbuf[IDX1];
@@ -759,7 +755,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
        sg[1].length = 11;
  
        crypto_cipher_set_iv(tfm, des_tv[i].iv, crypto_tfm_alg_ivsize(tfm));
-@@ -1356,12 +1365,12 @@
+@@ -1356,12 +1365,12 @@ test_des(void)
        }
  
        printk("page 1\n");
@@ -774,7 +770,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
        hexdump(q, 11);
        printk("%s\n", memcmp(q, des_tv[i].result + 13, 11) ? "fail" : "pass");
  
-@@ -1391,8 +1400,8 @@
+@@ -1391,8 +1400,8 @@ test_des(void)
                len = des_tv[i].len;
                p = des_tv[i].plaintext;
  
@@ -785,7 +781,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                sg[0].length = len;
  
                crypto_cipher_set_iv(tfm, des_tv[i].iv,
-@@ -1407,7 +1416,7 @@
+@@ -1407,7 +1416,7 @@ test_des(void)
  
                hexdump(tfm->crt_cipher.cit_iv, 8);
  
@@ -794,7 +790,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                hexdump(q, len);
  
                printk("%s\n",
-@@ -1439,13 +1448,13 @@
+@@ -1439,13 +1448,13 @@ test_des(void)
        memcpy(&xbuf[IDX2], des_tv[i].plaintext + 4, 4);
  
        p = &xbuf[IDX1];
@@ -812,7 +808,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
        sg[1].length = 4;
  
        crypto_cipher_set_iv(tfm, des_tv[i].iv, crypto_tfm_alg_ivsize(tfm));
-@@ -1457,12 +1466,12 @@
+@@ -1457,12 +1466,12 @@ test_des(void)
        }
  
        printk("page 1\n");
@@ -827,7 +823,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
        hexdump(q, 4);
        printk("%s\n", memcmp(q, des_tv[i].result + 4, 4) ? "fail" : "pass");
  
-@@ -1515,8 +1524,8 @@
+@@ -1515,8 +1524,8 @@ test_des3_ede(void)
                len = des_tv[i].len;
  
                p = des_tv[i].plaintext;
@@ -838,7 +834,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                sg[0].length = len;
                ret = crypto_cipher_encrypt(tfm, sg, sg, len);
                if (ret) {
-@@ -1524,7 +1533,7 @@
+@@ -1524,7 +1533,7 @@ test_des3_ede(void)
                        goto out;
                }
  
@@ -847,7 +843,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                hexdump(q, len);
  
                printk("%s\n",
-@@ -1558,8 +1567,8 @@
+@@ -1558,8 +1567,8 @@ test_des3_ede(void)
                len = des_tv[i].len;
  
                p = des_tv[i].plaintext;
@@ -858,7 +854,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                sg[0].length = len;
                ret = crypto_cipher_decrypt(tfm, sg, sg, len);
                if (ret) {
-@@ -1567,7 +1576,7 @@
+@@ -1567,7 +1576,7 @@ test_des3_ede(void)
                        goto out;
                }
  
@@ -867,7 +863,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                hexdump(q, len);
  
                printk("%s\n",
-@@ -1621,8 +1630,8 @@
+@@ -1621,8 +1630,8 @@ test_blowfish(void)
                }
  
                p = bf_tv[i].plaintext;
@@ -878,7 +874,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                sg[0].length = bf_tv[i].plen;
                ret = crypto_cipher_encrypt(tfm, sg, sg, sg[0].length);
                if (ret) {
-@@ -1630,7 +1639,7 @@
+@@ -1630,7 +1639,7 @@ test_blowfish(void)
                        goto out;
                }
  
@@ -887,7 +883,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                hexdump(q, bf_tv[i].rlen);
  
                printk("%s\n", memcmp(q, bf_tv[i].result, bf_tv[i].rlen) ?
-@@ -1663,8 +1672,8 @@
+@@ -1663,8 +1672,8 @@ test_blowfish(void)
                }
  
                p = bf_tv[i].plaintext;
@@ -898,7 +894,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                sg[0].length = bf_tv[i].plen;
                ret = crypto_cipher_decrypt(tfm, sg, sg, sg[0].length);
                if (ret) {
-@@ -1672,7 +1681,7 @@
+@@ -1672,7 +1681,7 @@ test_blowfish(void)
                        goto out;
                }
  
@@ -907,7 +903,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                hexdump(q, bf_tv[i].rlen);
  
                printk("%s\n", memcmp(q, bf_tv[i].result, bf_tv[i].rlen) ?
-@@ -1712,8 +1721,8 @@
+@@ -1712,8 +1721,8 @@ test_blowfish(void)
  
                p = bf_tv[i].plaintext;
  
@@ -918,7 +914,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                sg[0].length =  bf_tv[i].plen;
  
                crypto_cipher_set_iv(tfm, bf_tv[i].iv,
-@@ -1726,7 +1735,7 @@
+@@ -1726,7 +1735,7 @@ test_blowfish(void)
                        goto out;
                }
  
@@ -927,7 +923,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                hexdump(q, bf_tv[i].rlen);
  
                printk("%s\n", memcmp(q, bf_tv[i].result, bf_tv[i].rlen)
-@@ -1757,8 +1766,8 @@
+@@ -1757,8 +1766,8 @@ test_blowfish(void)
  
                p = bf_tv[i].plaintext;
  
@@ -938,7 +934,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                sg[0].length =  bf_tv[i].plen;
  
                crypto_cipher_set_iv(tfm, bf_tv[i].iv,
-@@ -1771,7 +1780,7 @@
+@@ -1771,7 +1780,7 @@ test_blowfish(void)
                        goto out;
                }
  
@@ -947,7 +943,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                hexdump(q, bf_tv[i].rlen);
  
                printk("%s\n", memcmp(q, bf_tv[i].result, bf_tv[i].rlen)
-@@ -1826,8 +1835,8 @@
+@@ -1826,8 +1835,8 @@ test_twofish(void)
                }
  
                p = tf_tv[i].plaintext;
@@ -958,7 +954,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                sg[0].length = tf_tv[i].plen;
                ret = crypto_cipher_encrypt(tfm, sg, sg, sg[0].length);
                if (ret) {
-@@ -1835,7 +1844,7 @@
+@@ -1835,7 +1844,7 @@ test_twofish(void)
                        goto out;
                }
  
@@ -967,7 +963,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                hexdump(q, tf_tv[i].rlen);
  
                printk("%s\n", memcmp(q, tf_tv[i].result, tf_tv[i].rlen) ?
-@@ -1868,8 +1877,8 @@
+@@ -1868,8 +1877,8 @@ test_twofish(void)
                }
  
                p = tf_tv[i].plaintext;
@@ -978,7 +974,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                sg[0].length = tf_tv[i].plen;
                ret = crypto_cipher_decrypt(tfm, sg, sg, sg[0].length);
                if (ret) {
-@@ -1877,7 +1886,7 @@
+@@ -1877,7 +1886,7 @@ test_twofish(void)
                        goto out;
                }
  
@@ -987,7 +983,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                hexdump(q, tf_tv[i].rlen);
  
                printk("%s\n", memcmp(q, tf_tv[i].result, tf_tv[i].rlen) ?
-@@ -1917,8 +1926,8 @@
+@@ -1917,8 +1926,8 @@ test_twofish(void)
  
                p = tf_tv[i].plaintext;
  
@@ -998,7 +994,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                sg[0].length =  tf_tv[i].plen;
  
                crypto_cipher_set_iv(tfm, tf_tv[i].iv,
-@@ -1931,7 +1940,7 @@
+@@ -1931,7 +1940,7 @@ test_twofish(void)
                        goto out;
                }
  
@@ -1007,7 +1003,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                hexdump(q, tf_tv[i].rlen);
  
                printk("%s\n", memcmp(q, tf_tv[i].result, tf_tv[i].rlen)
-@@ -1963,8 +1972,8 @@
+@@ -1963,8 +1972,8 @@ test_twofish(void)
  
                p = tf_tv[i].plaintext;
  
@@ -1018,7 +1014,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                sg[0].length =  tf_tv[i].plen;
  
                crypto_cipher_set_iv(tfm, tf_tv[i].iv,
-@@ -1977,7 +1986,7 @@
+@@ -1977,7 +1986,7 @@ test_twofish(void)
                        goto out;
                }
  
@@ -1027,7 +1023,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                hexdump(q, tf_tv[i].rlen);
  
                printk("%s\n", memcmp(q, tf_tv[i].result, tf_tv[i].rlen)
-@@ -2027,8 +2036,8 @@
+@@ -2027,8 +2036,8 @@ test_serpent(void)
                }
  
                p = serp_tv[i].plaintext;
@@ -1038,7 +1034,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                sg[0].length = sizeof(serp_tv[i].plaintext);
                ret = crypto_cipher_encrypt(tfm, sg, sg, sg[0].length);
                if (ret) {
-@@ -2036,7 +2045,7 @@
+@@ -2036,7 +2045,7 @@ test_serpent(void)
                        goto out;
                }
  
@@ -1047,7 +1043,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                hexdump(q, sizeof(serp_tv[i].result));
  
                printk("%s\n", memcmp(q, serp_tv[i].result,
-@@ -2067,8 +2076,8 @@
+@@ -2067,8 +2076,8 @@ test_serpent(void)
                }
  
                p = serp_tv[i].plaintext;
@@ -1058,7 +1054,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                sg[0].length = sizeof(serp_tv[i].plaintext);
                ret = crypto_cipher_decrypt(tfm, sg, sg, sg[0].length);
                if (ret) {
-@@ -2076,7 +2085,7 @@
+@@ -2076,7 +2085,7 @@ test_serpent(void)
                        goto out;
                }
  
@@ -1067,7 +1063,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                hexdump(q, sizeof(serp_tv[i].result));
  
                printk("%s\n", memcmp(q, serp_tv[i].result,
-@@ -2126,8 +2135,8 @@
+@@ -2126,8 +2135,8 @@ test_cast6(void)
                }
  
                p = cast_tv[i].plaintext;
@@ -1078,7 +1074,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                sg[0].length = sizeof(cast_tv[i].plaintext);
                ret = crypto_cipher_encrypt(tfm, sg, sg, sg[0].length);
                if (ret) {
-@@ -2135,7 +2144,7 @@
+@@ -2135,7 +2144,7 @@ test_cast6(void)
                        goto out;
                }
  
@@ -1087,7 +1083,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                hexdump(q, sizeof(cast_tv[i].result));
  
                printk("%s\n", memcmp(q, cast_tv[i].result,
-@@ -2166,8 +2175,8 @@
+@@ -2166,8 +2175,8 @@ test_cast6(void)
                }
  
                p = cast_tv[i].plaintext;
@@ -1098,7 +1094,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                sg[0].length = sizeof(cast_tv[i].plaintext);
                ret = crypto_cipher_decrypt(tfm, sg, sg, sg[0].length);
                if (ret) {
-@@ -2175,7 +2184,7 @@
+@@ -2175,7 +2184,7 @@ test_cast6(void)
                        goto out;
                }
  
@@ -1107,7 +1103,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                hexdump(q, sizeof(cast_tv[i].result));
  
                printk("%s\n", memcmp(q, cast_tv[i].result,
-@@ -2229,8 +2238,8 @@
+@@ -2229,8 +2238,8 @@ test_aes(void)
                }
  
                p = aes_tv[i].plaintext;
@@ -1118,7 +1114,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                sg[0].length = aes_tv[i].plen;
                ret = crypto_cipher_encrypt(tfm, sg, sg, sg[0].length);
                if (ret) {
-@@ -2238,7 +2247,7 @@
+@@ -2238,7 +2247,7 @@ test_aes(void)
                        goto out;
                }
  
@@ -1127,7 +1123,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                hexdump(q, aes_tv[i].rlen);
  
                printk("%s\n", memcmp(q, aes_tv[i].result, aes_tv[i].rlen) ?
-@@ -2271,8 +2280,8 @@
+@@ -2271,8 +2280,8 @@ test_aes(void)
                }
  
                p = aes_tv[i].plaintext;
@@ -1138,7 +1134,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                sg[0].length = aes_tv[i].plen;
                ret = crypto_cipher_decrypt(tfm, sg, sg, sg[0].length);
                if (ret) {
-@@ -2280,7 +2289,7 @@
+@@ -2280,7 +2289,7 @@ test_aes(void)
                        goto out;
                }
  
@@ -1147,7 +1143,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                hexdump(q, aes_tv[i].rlen);
  
                printk("%s\n", memcmp(q, aes_tv[i].result, aes_tv[i].rlen) ?
-@@ -2330,8 +2339,8 @@
+@@ -2330,8 +2339,8 @@ test_cast5(void)
                }
  
                p = c5_tv[i].plaintext;
@@ -1158,7 +1154,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                sg[0].length = sizeof(c5_tv[i].plaintext);
                ret = crypto_cipher_encrypt(tfm, sg, sg, sg[0].length);
                if (ret) {
-@@ -2339,7 +2348,7 @@
+@@ -2339,7 +2348,7 @@ test_cast5(void)
                        goto out;
                }
  
@@ -1167,7 +1163,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                hexdump(q, sizeof(c5_tv[i].ciphertext));
  
                printk("%s\n", memcmp(q, c5_tv[i].ciphertext,
-@@ -2368,8 +2377,8 @@
+@@ -2368,8 +2377,8 @@ test_cast5(void)
                }
  
                p = c5_tv[i].plaintext;
@@ -1178,7 +1174,7 @@ Index: linux-2.4.21/crypto/tcrypt.c
                sg[0].length = sizeof(c5_tv[i].plaintext);
                ret = crypto_cipher_decrypt(tfm, sg, sg, sg[0].length);
                if (ret) {
-@@ -2377,7 +2386,7 @@
+@@ -2377,7 +2386,7 @@ test_cast5(void)
                        goto out;
                }
  
@@ -1187,11 +1183,244 @@ Index: linux-2.4.21/crypto/tcrypt.c
                hexdump(q, sizeof(c5_tv[i].ciphertext));
  
                printk("%s\n", memcmp(q, c5_tv[i].ciphertext,
-Index: linux-2.4.21/drivers/ide/ide-dma.c
-===================================================================
---- linux-2.4.21.orig/drivers/ide/ide-dma.c    2005-06-01 22:52:05.000000000 -0400
-+++ linux-2.4.21/drivers/ide/ide-dma.c 2005-06-01 23:07:51.072582200 -0400
-@@ -280,14 +280,25 @@
+diff -X dontdiff -urp kern_oldest/drivers/addon/iscsi_sfnet/iscsi.c kern_fix/drivers/addon/iscsi_sfnet/iscsi.c
+--- kern_oldest/drivers/addon/iscsi_sfnet/iscsi.c      2006-05-01 11:55:44.000000000 -0700
++++ kern_fix/drivers/addon/iscsi_sfnet/iscsi.c 2006-05-01 14:14:13.000000000 -0700
+@@ -118,6 +118,16 @@
+ #include "iscsi-probe.h"
+ #include "iscsi-crc.h"
++#if SMALL_SCATTERLIST
++#define ISCSI_SG_ADDRESS(sg) (sg->u.address)
++#define ISCSI_SG_PAGE(sg)    (sg->u.page.page)
++#define ISCSI_SG_OFFSET(sg)  (sg->u.page.offset)
++#else
++#define ISCSI_SG_ADDRESS(sg) (sg->address)
++#define ISCSI_SG_PAGE(sg)    (sg->page)
++#define ISCSI_SG_OFFSET(sg)  (sg->offset)
++#endif
++
+ /*
+  *  IMPORTANT NOTE: to prevent deadlock, when holding multiple locks,
+  *  the following locking order must be followed at all times:
+@@ -2932,15 +2942,17 @@ print_cmnd(Scsi_Cmnd * sc)
+ #if (HAS_SCATTERLIST_PAGE && HAS_SCATTERLIST_ADDRESS)
+           printk("iSCSI:   sglist %p index %02d = addr %p, page %p, "
+                  "offset %u, len %u\n",
+-                 sglist, i, sglist->address, sglist->page, sglist->offset,
+-                 sglist->length);
++                 sglist, i, ISCSI_SG_ADDRESS(sglist), 
++                 ISCSI_SG_PAGE(sglist),
++                 ISCSI_SG_OFFSET(sglist), sglist->length);
+ #elif HAS_SCATTERLIST_PAGE
+           printk("iSCSI:   sglist %p index %02d = page %p, offset %u, "
+                  "len %u\n",
+-                 sglist, i, sglist->page, sglist->offset, sglist->length);
++                 sglist, i, ISCSI_SG_PAGE(sglist), ISCSI_SG_OFFSET(sglist),
++                 sglist->length);
+ #else
+           printk("iSCSI:   sglist %p index %02d = addr %p, len %u\n",
+-                 sglist, i, sglist->address, sglist->length);
++                 sglist, i, ISCSI_SG_ADDRESS(sglist), sglist->length);
+ #endif
+           sglist++;
+       }
+@@ -5305,7 +5317,7 @@ iscsi_xmit_task(iscsi_task_t * task)
+                   bytes_from_segment = sg->length - segment_offset;
+                   if (bytes_from_segment > bytes_to_fill) {
+                       /* only need part of this segment */
+-                      iov[iovn].iov_base = sg->address + segment_offset;
++                      iov[iovn].iov_base = ISCSI_SG_ADDRESS(sg) + segment_offset;
+                       iov[iovn].iov_len = bytes_to_fill;
+                       xfrlen += bytes_to_fill;
+                       DEBUG_FLOW("iSCSI: session %p xmit_data xfrlen %d, "
+@@ -5862,21 +5874,21 @@ sg_virtual_address(struct scatterlist *s
+ {
+ #if (HAS_SCATTERLIST_PAGE && HAS_SCATTERLIST_ADDRESS)
+     /* page may or may not be mapped */
+-    if (sg->address) {
+-      return sg->address;
+-    } else if (sg->page) {
+-      return page_address(sg->page) + sg->offset;
++    if (ISCSI_SG_ADDRESS(sg)) {
++      return ISCSI_SG_ADDRESS(sg);
++    } else if (ISCSI_SG_PAGE(sg)) {
++      return page_address(ISCSI_SG_PAGE(sg)) + ISCSI_SG_OFFSET(sg);
+     }
+     return NULL;
+ #elif HAS_SCATTERLIST_PAGE
+     /* should have already mapped the page */
+-    if (sg->page) {
+-      return page_address(sg->page) + sg->offset;
++    if (ISCSI_SG_PAGE(sg)) {
++      return page_address(ISCSI_SG_PAGE(sg)) + ISCSI_SG_OFFSET(sg);
+     }
+     return NULL;
+ #else
+-    return sg->address;
++    return ISCSI_SG_ADDRESS(sg);
+ #endif
+ }
+@@ -5899,12 +5911,12 @@ kmap_sg(struct scatterlist *sg)
+ {
+ #if (HAS_SCATTERLIST_PAGE && HAS_SCATTERLIST_ADDRESS)
+     /* page may or may not be mapped if HIGHMEM is in use */
+-    if (sg->address) {
+-      DEBUG_FLOW("iSCSI: kmap sg %p to address %p\n", sg, sg->address);
+-      return sg->address;
+-    } else if (sg->page) {
+-      void *addr = kmap(sg->page);
+-      DEBUG_FLOW("iSCSI: kmap sg %p page %p to addr %p\n", sg, sg->page,
++    if (ISCSI_SG_ADDRESS(sg)) {
++      DEBUG_FLOW("iSCSI: kmap sg %p to address %p\n", sg, ISCSI_SG_ADDRESS(sg));
++      return ISCSI_SG_ADDRESS(sg);
++    } else if (ISCSI_SG_PAGE(sg)) {
++      void *addr = kmap(ISCSI_SG_PAGE(sg));
++      DEBUG_FLOW("iSCSI: kmap sg %p page %p to addr %p\n", sg, ISCSI_SG_PAGE(sg),
+                  addr);
+       return addr;
+     }
+@@ -5912,15 +5924,15 @@ kmap_sg(struct scatterlist *sg)
+ #elif HAS_SCATTERLIST_PAGE
+     /* there is no address, must kmap the page */
+-    if (sg->page) {
+-      return kmap(sg->page);
++    if (ISCSI_SG_PAGE(sg)) {
++      return kmap(ISCSI_SG_PAGE(sg));
+     }
+     return NULL;
+ #else
+     /* just use the address */
+-    DEBUG_FLOW("iSCSI: kmap sg %p to address %p\n", sg, sg->address);
+-    return sg->address;
++    DEBUG_FLOW("iSCSI: kmap sg %p to address %p\n", sg, ISCSI_SG_ADDRESS(sg));
++    return ISCSI_SG_ADDRESS(sg);
+ #endif
+ }
+@@ -5932,11 +5944,11 @@ static inline void
+ kunmap_sg(struct scatterlist *sg)
+ {
+ #if (HAS_SCATTERLIST_PAGE && HAS_SCATTERLIST_ADDRESS)
+-    if (!sg->address && sg->page)
+-      kunmap(sg->page);
++    if (!ISCSI_SG_ADDRESS(sg) && ISCSI_SG_PAGE(sg))
++      kunmap(ISCSI_SG_PAGE(sg));
+ #elif HAS_SCATTERLIST_PAGE
+-    if (sg->page)
+-      kunmap(sg->page);
++    if (ISCSI_SG_PAGE(sg))
++      kunmap(ISCSI_SG_PAGE(sg));
+ #endif
+     return;
+ }
+diff -X dontdiff -urp kern_oldest/drivers/block/cciss.c kern_fix/drivers/block/cciss.c
+--- kern_oldest/drivers/block/cciss.c  2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/block/cciss.c     2006-05-01 14:14:13.000000000 -0700
+@@ -2636,9 +2636,14 @@ next:
+               } else {
+                       if (seg == MAXSGENTRIES)
+                               BUG();
++#if SMALL_SCATTERLIST
++                      tmp_sg[seg].u.page.page = bh->b_page;
++                      tmp_sg[seg].u.page.offset = bh_offset(bh);
++#else
+                       tmp_sg[seg].page = bh->b_page;
+-                      tmp_sg[seg].length = bh->b_size;
+                       tmp_sg[seg].offset = bh_offset(bh);
++#endif
++                      tmp_sg[seg].length = bh->b_size;
+                       lastdataend = bh_phys(bh) + bh->b_size;
+                       seg++;
+               }
+@@ -2652,8 +2657,16 @@ next:
+               ddir = PCI_DMA_TODEVICE;
+       for (i=0; i<seg; i++) {
+               c->SG[i].Len = tmp_sg[i].length;
+-              temp64.val = pci_map_page(h->pdev, tmp_sg[i].page,
+-                          tmp_sg[i].offset, tmp_sg[i].length, ddir);
++#if SMALL_SCATTERLIST
++              temp64.val = pci_map_page(h->pdev,
++                                        tmp_sg[i].u.page.page, 
++                                        tmp_sg[i].u.page.offset,
++                                        tmp_sg[i].length, ddir);
++#else
++              temp64.val = pci_map_page(h->pdev,
++                                        tmp_sg[i].page, tmp_sg[i].offset,
++                                        tmp_sg[i].length, ddir);
++#endif
+               c->SG[i].Addr.lower = temp64.val32.lower;
+                 c->SG[i].Addr.upper = temp64.val32.upper;
+                 c->SG[i].Ext = 0;  /* we are not chaining */
+diff -X dontdiff -urp kern_oldest/drivers/block/cpqarray.c kern_fix/drivers/block/cpqarray.c
+--- kern_oldest/drivers/block/cpqarray.c       2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/block/cpqarray.c  2006-05-01 14:14:13.000000000 -0700
+@@ -1003,9 +1003,14 @@ DBGPX(
+               } else {
+                       if (seg == SG_MAX)
+                               BUG();
++#if SMALL_SCATTERLIST
++                      tmp_sg[seg].u.page.page = bh->b_page;
++                      tmp_sg[seg].u.page.offset = bh_offset(bh);
++#else
+                       tmp_sg[seg].page = bh->b_page;
+-                      tmp_sg[seg].length = bh->b_size;
+                       tmp_sg[seg].offset = bh_offset(bh);
++#endif
++                      tmp_sg[seg].length = bh->b_size;
+                       lastdataend = bh_phys(bh) + bh->b_size;
+                       seg++;
+               }
+@@ -1014,11 +1019,21 @@ DBGPX(
+       /* Now do all the DMA Mappings */
+       for( i=0; i < seg; i++) {
+               c->req.sg[i].size = tmp_sg[i].length;
++#if SMALL_SCATTERLIST
++              c->req.sg[i].addr = (__u32) pci_map_page(
++                              h->pci_dev, 
++                              tmp_sg[i].u.page.page, tmp_sg[i].u.page.offset,
++                              tmp_sg[i].length,
++                                (creq->cmd == READ) ? 
++                                      PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
++#else
+               c->req.sg[i].addr = (__u32) pci_map_page(
+-                              h->pci_dev, tmp_sg[i].page, tmp_sg[i].offset,
++                              h->pci_dev, 
++                              tmp_sg[i].page, tmp_sg[i].offset,
+                               tmp_sg[i].length,
+                                 (creq->cmd == READ) ? 
+                                       PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
++#endif
+       }
+ DBGPX(        printk("Submitting %d sectors in %d segments\n", sect, seg); );
+       c->req.hdr.sg_cnt = seg;
+diff -X dontdiff -urp kern_oldest/drivers/block/sx8.c kern_fix/drivers/block/sx8.c
+--- kern_oldest/drivers/block/sx8.c    2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/block/sx8.c       2006-05-01 14:14:13.000000000 -0700
+@@ -1103,9 +1103,15 @@ static int blk_rq_map_sg(request_queue_t
+               } else {
+                       if (unlikely(n_elem == CARM_MAX_REQ_SG))
+                               BUG();
++#if SMALL_SCATTERLIST
++                      sg[n_elem].u.page.page = bh->b_page;
++                      sg[n_elem].length = bh->b_size;
++                      sg[n_elem].u.page.offset = bh_offset(bh);
++#else
+                       sg[n_elem].page = bh->b_page;
+                       sg[n_elem].length = bh->b_size;
+                       sg[n_elem].offset = bh_offset(bh);
++#endif /* !SMALL_SCATTERLIST */
+                       last_phys = bh_phys(bh) + bh->b_size;
+                       n_elem++;
+               }
+diff -X dontdiff -urp kern_oldest/drivers/ide/ide-dma.c kern_fix/drivers/ide/ide-dma.c
+--- kern_oldest/drivers/ide/ide-dma.c  2006-05-01 11:55:42.000000000 -0700
++++ kern_fix/drivers/ide/ide-dma.c     2006-05-01 14:14:13.000000000 -0700
+@@ -280,14 +280,25 @@ static int ide_build_sglist (ide_hwif_t 
                memset(&sg[nents], 0, sizeof(*sg));
  
                if (bh->b_page) {
@@ -1217,7 +1446,7 @@ Index: linux-2.4.21/drivers/ide/ide-dma.c
                        lastdataend = (unsigned long) bh->b_data + bh->b_size;
                }
  
-@@ -328,14 +339,24 @@
+@@ -328,14 +339,24 @@ static int ide_raw_build_sglist (ide_hwi
  #if 1
        if (sector_count > 128) {
                memset(&sg[nents], 0, sizeof(*sg));
@@ -1242,562 +1471,1021 @@ Index: linux-2.4.21/drivers/ide/ide-dma.c
        sg[nents].length =  sector_count  * SECTOR_SIZE;
        nents++;
  #else
-Index: linux-2.4.21/drivers/scsi/dpt_i2o.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/dpt_i2o.c   2005-06-01 22:51:54.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/dpt_i2o.c        2005-06-01 23:07:51.074581896 -0400
-@@ -2152,7 +2152,13 @@
-               for(i = 0 ; i < cmd->use_sg; i++) {
-                       *mptr++ = direction|0x10000000|sg->length;
-                       len+=sg->length;
+diff -X dontdiff -urp kern_oldest/drivers/ieee1394/dma.c kern_fix/drivers/ieee1394/dma.c
+--- kern_oldest/drivers/ieee1394/dma.c 2006-05-01 11:55:43.000000000 -0700
++++ kern_fix/drivers/ieee1394/dma.c    2006-05-01 14:14:13.000000000 -0700
+@@ -97,8 +97,12 @@ int dma_region_alloc(struct dma_region *
+       /* fill scatter/gather list with pages */
+       for(i = 0; i < dma->n_pages; i++) {
+               unsigned long va = (unsigned long) dma->kvirt + i * PAGE_SIZE;
+-                      
++
 +#if SMALL_SCATTERLIST
-+                      if (sg->ispaged)
-+                         BUG();
-+                      *mptr++ = virt_to_bus(sg->u.address);
-+#else
-                       *mptr++ = virt_to_bus(sg->address);
-+#endif
-                       sg++;
-               }
-               /* Make this an end of list */
-Index: linux-2.4.21/drivers/scsi/scsi_debug.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/scsi_debug.c        2002-11-28 18:53:14.000000000 -0500
-+++ linux-2.4.21/drivers/scsi/scsi_debug.c     2005-06-01 23:07:51.075581744 -0400
-@@ -186,7 +186,13 @@
-               struct scatterlist *sgpnt = (struct scatterlist *)
-                                               SCpnt->request_buffer;
-+#if SMALL_SCATTERLIST         
-+              if (sgpnt[0].ispaged)
-+                 BUG();
-+              buff = sgpnt[0].u.address;
++              dma->sglist[i].u.page.page = vmalloc_to_page((void *)va);
 +#else
-               buff = sgpnt[0].address;
+               dma->sglist[i].page = vmalloc_to_page((void *)va);
 +#endif
-               bufflen = sgpnt[0].length;
-               /* READ and WRITE process scatterlist themselves */
+               dma->sglist[i].length = PAGE_SIZE;
        }
-@@ -672,7 +678,13 @@
-       if (SCpnt->use_sg) {
-               sgcount = 0;
-               sgpnt = (struct scatterlist *) buff;
+diff -X dontdiff -urp kern_oldest/drivers/ieee1394/sbp2.c kern_fix/drivers/ieee1394/sbp2.c
+--- kern_oldest/drivers/ieee1394/sbp2.c        2006-05-01 11:55:43.000000000 -0700
++++ kern_fix/drivers/ieee1394/sbp2.c   2006-05-01 14:14:13.000000000 -0700
+@@ -2036,11 +2036,19 @@ static int sbp2_create_command_orb(struc
+                       command->dma_dir = dma_dir;
+                       command->dma_size = sgpnt[0].length;
+                       command->dma_type = CMD_DMA_PAGE;
 +#if SMALL_SCATTERLIST
-+              if (sgpnt[sgcount].ispaged)
-+                 BUG();
-+              buff = sgpnt[sgcount].u.address;
++                      command->cmd_dma = pci_map_page(hi->host->pdev,
++                                                      sgpnt[0].u.page.page,
++                                                      sgpnt[0].u.page.offset,
++                                                      command->dma_size,
++                                                      command->dma_dir);
 +#else
-               buff = sgpnt[sgcount].address;
+                       command->cmd_dma = pci_map_page(hi->host->pdev,
+                                                       sgpnt[0].page,
+                                                       sgpnt[0].offset,
+                                                       command->dma_size,
+                                                       command->dma_dir);
 +#endif
-               bufflen = sgpnt[sgcount].length;
-       }
-       do {
-@@ -682,7 +694,13 @@
-                       block += bufflen >> POW2_SECT_SIZE;
-                       sgcount++;
-                       if (nbytes) {
+                       SBP2_DMA_ALLOC("single page scatter element");
+                       command_orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
+diff -X dontdiff -urp kern_oldest/drivers/message/i2o/i2o_scsi.c kern_fix/drivers/message/i2o/i2o_scsi.c
+--- kern_oldest/drivers/message/i2o/i2o_scsi.c 2006-05-01 11:55:43.000000000 -0700
++++ kern_fix/drivers/message/i2o/i2o_scsi.c    2006-05-01 14:14:13.000000000 -0700
+@@ -693,7 +693,11 @@ static int i2o_scsi_queuecommand(Scsi_Cm
+                       {
+                               *mptr++=direction|0x10000000|sg->length;
+                               len+=sg->length;
 +#if SMALL_SCATTERLIST
-+                              if (sgpnt[sgcount].ispaged)
-+                                      BUG();
-+                              buff = sgpnt[sgcount].u.address;
++                              *mptr++=virt_to_bus(sg->u.address);
 +#else
-                               buff = sgpnt[sgcount].address;
+                               *mptr++=virt_to_bus(sg->address);
 +#endif
-                               bufflen = sgpnt[sgcount].length;
+                               sg++;
                        }
-               } else if (nbytes > 0)
-@@ -713,7 +731,13 @@
-       if (SCpnt->use_sg) {
-               sgcount = 0;
-               sgpnt = (struct scatterlist *) buff;
+                       mptr[-2]=direction|0xD0000000|(sg-1)->length;
+@@ -704,7 +708,11 @@ static int i2o_scsi_queuecommand(Scsi_Cm
+                       {
+                               i2o_raw_writel(direction|0x10000000|sg->length, mptr++);
+                               len+=sg->length;
 +#if SMALL_SCATTERLIST
-+              if (sgpnt[sgcount].ispaged)
-+                      BUG();
-+              buff = sgpnt[sgcount].u.address;
++                              i2o_raw_writel(virt_to_bus(sg->u.address), mptr++);
 +#else
-               buff = sgpnt[sgcount].address;
+                               i2o_raw_writel(virt_to_bus(sg->address), mptr++);
 +#endif
-               bufflen = sgpnt[sgcount].length;
-       }
-       do {
-@@ -724,7 +748,13 @@
-                       block += bufflen >> POW2_SECT_SIZE;
-                       sgcount++;
-                       if (nbytes) {
+                               sg++;
+                       }
+diff -X dontdiff -urp kern_oldest/drivers/net/fc/iph5526.c kern_fix/drivers/net/fc/iph5526.c
+--- kern_oldest/drivers/net/fc/iph5526.c       2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/net/fc/iph5526.c  2006-05-01 14:14:13.000000000 -0700
+@@ -4249,7 +4249,11 @@ int no_of_sg = 0;
+                       if (Cmnd->use_sg) {
+                       int count = 0, j;
+                               for(i = 0; i < no_of_sg; i++) {
 +#if SMALL_SCATTERLIST
-+                              if (sgpnt[sgcount].ispaged)
-+                                      BUG();
-+                              buff = sgpnt[sgcount].u.address;
++                              char *addr_ptr = sl2->u.address;
 +#else
-                               buff = sgpnt[sgcount].address;
+                               char *addr_ptr = sl2->address;
 +#endif
-                               bufflen = sgpnt[sgcount].length;
-                       }
-               } else if (nbytes > 0)
-Index: linux-2.4.21/drivers/scsi/scsi_lib.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/scsi_lib.c  2005-06-01 22:52:05.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/scsi_lib.c       2005-06-01 23:07:51.076581592 -0400
-@@ -554,7 +554,13 @@
-               if (bbpnt) {
-                       for (i = 0; i < SCpnt->use_sg; i++) {
-                               if (bbpnt[i])
+                                       count = sl2->length / SEST_BUFFER_SIZE;
+                                       if (sl2->length % SEST_BUFFER_SIZE)
+                                               count++;
+@@ -4349,7 +4353,11 @@ int no_of_sg = 0;
+                               int count = 0, j;
+                                       count = sl1->length / SEST_BUFFER_SIZE;
+                                       for (j = 0; j < count; j++) {
 +#if SMALL_SCATTERLIST
-+                                      if (sgpnt[i].ispaged)
-+                                              BUG();
-+                                      scsi_free(sgpnt[i].u.address, sgpnt[i].length);
++                                              build_EDB(fi, (char *)sl1->u.address, 0, SEST_BUFFER_SIZE);
 +#else
-                                       scsi_free(sgpnt[i].address, sgpnt[i].length);
+                                               build_EDB(fi, (char *)sl1->address, 0, SEST_BUFFER_SIZE);
 +#endif
-                       }
-               }
-               scsi_free(SCpnt->request_buffer, SCpnt->sglist_len);
-@@ -630,12 +636,23 @@
-               if (bbpnt) {
-                       for (i = 0; i < SCpnt->use_sg; i++) {
-                               if (bbpnt[i]) {
+                                               memcpy(fi->q.ptr_edb[fi->q.edb_buffer_indx], &(fi->g.edb), sizeof(EDB));
+                                               /* Mark this EDB as being in use */
+                                               fi->q.free_edb_list[fi->q.edb_buffer_indx] = EDB_BUSY;
+@@ -4358,13 +4366,21 @@ int no_of_sg = 0;
+                                                * safe.
+                                                */
+                                               update_EDB_indx(fi);
 +#if SMALL_SCATTERLIST
-+                                      if (sgpnt[i].ispaged)
-+                                              BUG();
-+                                      if (req->cmd == READ) {
-+                                              memcpy(bbpnt[i],
-+                                                     sgpnt[i].u.address,
-+                                                     sgpnt[i].length);
-+                                      }
-+                                      scsi_free(sgpnt[i].u.address, sgpnt[i].length);
++                                              sl1->u.address += SEST_BUFFER_SIZE;
 +#else
-                                       if (req->cmd == READ) {
-                                               memcpy(bbpnt[i],
-                                                      sgpnt[i].address,
-                                                      sgpnt[i].length);
+                                               sl1->address += SEST_BUFFER_SIZE;
++#endif
                                        }
-                                       scsi_free(sgpnt[i].address, sgpnt[i].length);
+                                       /* Just in case itz not a multiple of 
+                                        * SEST_BUFFER_SIZE bytes.
+                                        */
+                                       if (sl1->length % SEST_BUFFER_SIZE) {
++#if SMALL_SCATTERLIST
++                                              build_EDB(fi, (char *)sl1->u.address, 0, sl1->length % SEST_BUFFER_SIZE);
++#else
+                                               build_EDB(fi, (char *)sl1->address, 0, sl1->length % SEST_BUFFER_SIZE);
 +#endif
-                               }
-                       }
-               }
-Index: linux-2.4.21/drivers/scsi/scsi_merge.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/scsi_merge.c        2005-06-01 22:51:45.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/scsi_merge.c     2005-06-01 23:07:51.077581440 -0400
-@@ -144,11 +144,21 @@
-        */
-       for(jj=0; jj < SCpnt->use_sg; jj++)
-       {
+                                               memcpy(fi->q.ptr_edb[fi->q.edb_buffer_indx], &(fi->g.edb), sizeof(EDB));
+                                               fi->q.free_edb_list[fi->q.edb_buffer_indx] = EDB_BUSY;
+                                               update_EDB_indx(fi);
+diff -X dontdiff -urp kern_oldest/drivers/net/wireless/airo.c kern_fix/drivers/net/wireless/airo.c
+--- kern_oldest/drivers/net/wireless/airo.c    2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/net/wireless/airo.c       2006-05-01 14:14:13.000000000 -0700
+@@ -1584,11 +1584,20 @@ void emmh32_setseed(emmh32_context *cont
+               aes_counter[12] = (u8)(counter >> 24);
+               counter++;
+               memcpy (plain, aes_counter, 16);
 +#if SMALL_SCATTERLIST
-+              if (sgpnt[jj].ispaged)
-+                      BUG();
-+              printk("[%d]\tlen:%d\taddr:%p\tbounce:%p\n",
-+                     jj,
-+                     sgpnt[jj].length,
-+                     sgpnt[jj].u.address,
-+                     (bbpnt ? bbpnt[jj] : NULL));
++              sg[0].u.page.page = virt_to_page(plain);
++              sg[0].u.page.offset = ((long) plain & ~PAGE_MASK);
 +#else
-               printk("[%d]\tlen:%d\taddr:%p\tbounce:%p\n",
-                      jj,
-                      sgpnt[jj].length,
-                      sgpnt[jj].address,
-                      (bbpnt ? bbpnt[jj] : NULL));
+               sg[0].page = virt_to_page(plain);
+               sg[0].offset = ((long) plain & ~PAGE_MASK);
 +#endif
-               if (bbpnt && bbpnt[jj])
-                       consumed += sgpnt[jj].length;
-       }
-@@ -612,6 +622,9 @@
-               max_segments = scsi_max_sg;
- #ifdef DMA_CHUNK_SIZE
-+# if SMALL_SCATTERLIST
-+#  error "This defeats the purpose of SMALL_SCATTERLIST"
-+# endif
-       if (max_segments > 64)
-               max_segments = 64;
-@@ -929,15 +942,26 @@
-               }
-               if (SCpnt->host->highmem_io) {
+               sg[0].length = 16;
+               crypto_cipher_encrypt(tfm, sg, sg, 16);
 +#if SMALL_SCATTERLIST
-+                      sgpnt[count].ispaged = 1;
-+                      sgpnt[count].u.page.page = bh->b_page;
-+                      sgpnt[count].u.page.offset = bh_offset(bh);
++              cipher = kmap(sg[0].u.page.page) + sg[0].u.page.offset;
 +#else
-                       sgpnt[count].page = bh->b_page;
-                       sgpnt[count].offset = bh_offset(bh);
-                       sgpnt[count].address = NULL;
+               cipher = kmap(sg[0].page) + sg[0].offset;
 +#endif
-               } else {
-                       if (PageHighMem(bh->b_page))
-                               BUG();
+               for (j=0; (j<16) && (i< (sizeof(context->coeff)/sizeof(context->coeff[0]))); ) {
+                       context->coeff[i++] = ntohl(*(u32 *)&cipher[j]);
+                       j += 4;
+diff -X dontdiff -urp kern_oldest/drivers/scsi/53c7,8xx.c kern_fix/drivers/scsi/53c7,8xx.c
+--- kern_oldest/drivers/scsi/53c7,8xx.c        2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/53c7,8xx.c   2006-05-01 14:14:13.000000000 -0700
+@@ -3787,7 +3787,11 @@ create_cmd (Scsi_Cmnd *cmd) {
+     for (i = 0; cmd->use_sg ? (i < cmd->use_sg) : !i; cmd_datain += 4, 
+       cmd_dataout += 4, ++i) {
+       u32 buf = cmd->use_sg ? 
++#if SMALL_SCATTERLIST
++          virt_to_bus(((struct scatterlist *)cmd->buffer)[i].u.address) :
++#else
+           virt_to_bus(((struct scatterlist *)cmd->buffer)[i].address) :
++#endif
+           virt_to_bus(cmd->request_buffer);
+       u32 count = cmd->use_sg ?
+           ((struct scatterlist *)cmd->buffer)[i].length :
+@@ -5752,8 +5756,13 @@ insn_to_offset (Scsi_Cmnd *cmd, u32 *ins
+           if ((buffers = cmd->use_sg)) {
+               for (offset = 0, 
+                       segment = (struct scatterlist *) cmd->buffer;
++#if SMALL_SCATTERLIST
++                   buffers && !((found = ((ptr >= segment->u.address) && 
++                          (ptr < (segment->u.address + segment->length)))));
++#else
+                    buffers && !((found = ((ptr >= segment->address) && 
+                           (ptr < (segment->address + segment->length)))));
++#endif
+                    --buffers, offset += segment->length, ++segment)
+ #if 0
+                   printk("scsi%d: comparing 0x%p to 0x%p\n", 
+@@ -5761,7 +5770,11 @@ insn_to_offset (Scsi_Cmnd *cmd, u32 *ins
+ #else
+                   ;
+ #endif
++#if SMALL_SCATTERLIST
++                  offset += ptr - segment->u.address;
++#else
+                   offset += ptr - segment->address;
++#endif
+           } else {
+               found = 1;
+               offset = ptr - (char *) (cmd->request_buffer);
+diff -X dontdiff -urp kern_oldest/drivers/scsi/advansys.c kern_fix/drivers/scsi/advansys.c
+--- kern_oldest/drivers/scsi/advansys.c        2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/advansys.c   2006-05-01 14:14:13.000000000 -0700
+@@ -6803,7 +6803,11 @@ asc_build_req(asc_board_t *boardp, Scsi_
+         slp = (struct scatterlist *) scp->request_buffer;
+         for (sgcnt = 0; sgcnt < scp->use_sg; sgcnt++, slp++) {
+             asc_sg_head.sg_list[sgcnt].addr =
++#if SMALL_SCATTERLIST
++                cpu_to_le32(virt_to_bus(slp->u.address));
++#else
+                 cpu_to_le32(virt_to_bus(slp->address));
++#endif
+             asc_sg_head.sg_list[sgcnt].bytes = cpu_to_le32(slp->length);
+             ASC_STATS_ADD(scp->host, sg_xfer, ASC_CEILING(slp->length, 512));
+         }
+@@ -7061,7 +7065,11 @@ adv_get_sglist(asc_board_t *boardp, adv_
+         for (i = 0; i < NO_OF_SG_PER_BLOCK; i++)
+         {
+             sg_block->sg_list[i].sg_addr =
++#if SMALL_SCATTERLIST
++                cpu_to_le32(virt_to_bus(slp->u.address));
++#else
+                 cpu_to_le32(virt_to_bus(slp->address));
++#endif
+             sg_block->sg_list[i].sg_count = cpu_to_le32(slp->length);
+             ASC_STATS_ADD(scp->host, sg_xfer, ASC_CEILING(slp->length, 512));
+diff -X dontdiff -urp kern_oldest/drivers/scsi/aha152x.c kern_fix/drivers/scsi/aha152x.c
+--- kern_oldest/drivers/scsi/aha152x.c 2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/aha152x.c    2006-05-01 14:14:13.000000000 -0700
+@@ -603,7 +603,11 @@ struct aha152x_scdata {
+ #define SCSEM(SCpnt)          SCDATA(SCpnt)->sem
  
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 +#if SMALL_SCATTERLIST
-+                      sgpnt[count].ispaged = 0;
-+                      sgpnt[count].u.address = bh->b_data;
++#define SG_ADDRESS(buffer)    ((buffer)->u.address)
 +#else
-                       sgpnt[count].page = NULL;
-                       sgpnt[count].address = bh->b_data;
+ #define SG_ADDRESS(buffer)    ((buffer)->address)
 +#endif
-               }
-               
-               sgpnt[count].length = bh->b_size;
-@@ -972,6 +996,50 @@
-                * only done for dma_host, in which case .page is not
-                * set since it's guarenteed to be a low memory page
-                */
+ #else
+ #define SG_ADDRESS(buffer)    ((char *) (page_address((buffer)->page)+(buffer)->offset))
+ #endif
+diff -X dontdiff -urp kern_oldest/drivers/scsi/aha1542.c kern_fix/drivers/scsi/aha1542.c
+--- kern_oldest/drivers/scsi/aha1542.c 2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/aha1542.c    2006-05-01 14:14:13.000000000 -0700
+@@ -69,8 +69,13 @@ static void BAD_SG_DMA(Scsi_Cmnd * SCpnt
+ {
+       printk(KERN_CRIT "sgpnt[%d:%d] addr %p/0x%lx length %d\n",
+              badseg, nseg,
 +#if SMALL_SCATTERLIST
-+              if (sgpnt[i].ispaged)
-+                      BUG();
-+              if (virt_to_phys(sgpnt[i].u.address) + sgpnt[i].length - 1 >
-+                  ISA_DMA_THRESHOLD) {
-+                      if( scsi_dma_free_sectors - sectors <= 10  ) {
-+                              /*
-+                               * If this would nearly drain the DMA
-+                               * pool empty, then let's stop here.
-+                               * Don't make this request any larger.
-+                               * This is kind of a safety valve that
-+                               * we use - we could get screwed later
-+                               * on if we run out completely.  
-+                               */
-+                              SCpnt->request_bufflen -= sgpnt[i].length;
-+                              SCpnt->use_sg = i;
-+                              if (i == 0) {
-+                                      goto big_trouble;
-+                              }
-+                              break;
-+                      }
++             sgpnt[badseg].u.address,
++             SCSI_PA(sgpnt[badseg].u.address),
++#else
+              sgpnt[badseg].address,
+              SCSI_PA(sgpnt[badseg].address),
++#endif
+              sgpnt[badseg].length);
+       /*
+@@ -710,11 +715,21 @@ static int aha1542_queuecommand(Scsi_Cmn
+                       panic("aha1542.c: unable to allocate DMA memory\n");
+               for (i = 0; i < SCpnt->use_sg; i++) {
+                       if (sgpnt[i].length == 0 || SCpnt->use_sg > 16 ||
+-                          (((int) sgpnt[i].address) & 1) || (sgpnt[i].length & 1)) {
++#if SMALL_SCATTERLIST
++                          (((int) sgpnt[i].u.address) & 1) 
++#else
++                          (((int) sgpnt[i].address) & 1)
++#endif
++                          || (sgpnt[i].length & 1)) {
+                               unsigned char *ptr;
+                               printk(KERN_CRIT "Bad segment list supplied to aha1542.c (%d, %d)\n", SCpnt->use_sg, i);
+                               for (i = 0; i < SCpnt->use_sg; i++) {
+-                                      printk(KERN_CRIT "%d: %p %d\n", i, sgpnt[i].address,
++                                      printk(KERN_CRIT "%d: %p %d\n", i, 
++#if SMALL_SCATTERLIST
++                                             sgpnt[i].u.address,
++#else
++                                             sgpnt[i].address,
++#endif
+                                              sgpnt[i].length);
+                               };
+                               printk(KERN_CRIT "cptr %x: ", (unsigned int) cptr);
+@@ -723,8 +738,13 @@ static int aha1542_queuecommand(Scsi_Cmn
+                                       printk("%02x ", ptr[i]);
+                               panic("Foooooooood fight!");
+                       };
++#if SMALL_SCATTERLIST
++                      any2scsi(cptr[i].dataptr, SCSI_PA(sgpnt[i].u.address));
++                      if (SCSI_PA(sgpnt[i].u.address + sgpnt[i].length - 1) > ISA_DMA_THRESHOLD)
++#else
+                       any2scsi(cptr[i].dataptr, SCSI_PA(sgpnt[i].address));
+                       if (SCSI_PA(sgpnt[i].address + sgpnt[i].length - 1) > ISA_DMA_THRESHOLD)
++#endif
+                               BAD_SG_DMA(SCpnt, sgpnt, SCpnt->use_sg, i);
+                       any2scsi(cptr[i].datalen, sgpnt[i].length);
+               };
+diff -X dontdiff -urp kern_oldest/drivers/scsi/aha1740.c kern_fix/drivers/scsi/aha1740.c
+--- kern_oldest/drivers/scsi/aha1740.c 2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/aha1740.c    2006-05-01 14:14:13.000000000 -0700
+@@ -397,7 +397,11 @@ int aha1740_queuecommand(Scsi_Cmnd * SCp
+       for(i=0; i<SCpnt->use_sg; i++)
+       {
+           cptr[i].datalen = sgpnt[i].length;
++#if SMALL_SCATTERLIST
++          cptr[i].dataptr = virt_to_bus(sgpnt[i].u.address);
++#else
+           cptr[i].dataptr = virt_to_bus(sgpnt[i].address);
++#endif
+       }
+       host->ecb[ecbno].datalen = SCpnt->use_sg * sizeof(struct aha1740_chain);
+       host->ecb[ecbno].dataptr = virt_to_bus(cptr);
+diff -X dontdiff -urp kern_oldest/drivers/scsi/aic7xxx_old.c kern_fix/drivers/scsi/aic7xxx_old.c
+--- kern_oldest/drivers/scsi/aic7xxx_old.c     2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/aic7xxx_old.c        2006-05-01 14:14:13.000000000 -0700
+@@ -2845,7 +2845,11 @@ aic7xxx_done(struct aic7xxx_host *p, str
+           struct scatterlist *sg;
+           sg = (struct scatterlist *)cmd->request_buffer;
++#if SMALL_SCATTERLIST
++          buffer = (char *)sg[0].u.address;
++#else
+           buffer = (char *)sg[0].address;
++#endif
+         }
+         else
+         {
+diff -X dontdiff -urp kern_oldest/drivers/scsi/AM53C974.c kern_fix/drivers/scsi/AM53C974.c
+--- kern_oldest/drivers/scsi/AM53C974.c        2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/AM53C974.c   2006-05-01 14:14:13.000000000 -0700
+@@ -842,7 +842,11 @@ static __inline__ void initialize_SCp(Sc
+       if (cmd->use_sg) {
+               cmd->SCp.buffer = (struct scatterlist *) cmd->buffer;
+               cmd->SCp.buffers_residual = cmd->use_sg - 1;
++#if SMALL_SCATTERLIST
++              cmd->SCp.ptr = (char *) cmd->SCp.buffer->u.address;
++#else
+               cmd->SCp.ptr = (char *) cmd->SCp.buffer->address;
++#endif
+               cmd->SCp.this_residual = cmd->SCp.buffer->length;
+       } else {
+               cmd->SCp.buffer = NULL;
+@@ -1555,7 +1559,11 @@ static void AM53C974_information_transfe
+               if ((!cmd->SCp.this_residual) && cmd->SCp.buffers_residual) {
+                       cmd->SCp.buffer++;
+                       cmd->SCp.buffers_residual--;
++#if SMALL_SCATTERLIST
++                      cmd->SCp.ptr = (unsigned char *) cmd->SCp.buffer->u.address;
++#else
+                       cmd->SCp.ptr = (unsigned char *) cmd->SCp.buffer->address;
++#endif
+                       cmd->SCp.this_residual = cmd->SCp.buffer->length;
+               }
+               if (cmd->SCp.this_residual) {
+diff -X dontdiff -urp kern_oldest/drivers/scsi/atp870u.c kern_fix/drivers/scsi/atp870u.c
+--- kern_oldest/drivers/scsi/atp870u.c 2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/atp870u.c    2006-05-01 14:14:13.000000000 -0700
+@@ -804,7 +804,11 @@ oktosend:
+               sgpnt = (struct scatterlist *) workrequ->request_buffer;
+               i = 0;
+               for (j = 0; j < workrequ->use_sg; j++) {
++#if SMALL_SCATTERLIST
++                      bttl = virt_to_bus(sgpnt[j].u.address);
++#else
+                       bttl = virt_to_bus(sgpnt[j].address);
++#endif
+                       l = sgpnt[j].length;
+                       while (l > 0x10000) {
+                               (unsigned short int) (((unsigned short int *) (prd))[i + 3]) = 0x0000;
+diff -X dontdiff -urp kern_oldest/drivers/scsi/BusLogic.c kern_fix/drivers/scsi/BusLogic.c
+--- kern_oldest/drivers/scsi/BusLogic.c        2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/BusLogic.c   2006-05-01 14:14:13.000000000 -0700
+@@ -3402,7 +3402,12 @@ int BusLogic_QueueCommand(SCSI_Command_T
+         CCB->ScatterGatherList[Segment].SegmentByteCount =
+           ScatterList[Segment].length;
+         CCB->ScatterGatherList[Segment].SegmentDataPointer =
++#if SMALL_SCATTERLIST
++          Virtual_to_Bus(ScatterList[Segment].u.address);
++#else
+           Virtual_to_Bus(ScatterList[Segment].address);
++#endif
 +
-+                      bbpnt[i] = sgpnt[i].u.address;
-+                      sgpnt[i].u.address =
-+                          (char *) scsi_malloc(sgpnt[i].length);
-+                      /*
-+                       * If we cannot allocate memory for this DMA bounce
-+                       * buffer, then queue just what we have done so far.
-+                       */
-+                      if (sgpnt[i].u.address == NULL) {
-+                              printk("Warning - running low on DMA memory\n");
-+                              SCpnt->request_bufflen -= sgpnt[i].length;
-+                              SCpnt->use_sg = i;
-+                              if (i == 0) {
-+                                      goto big_trouble;
-+                              }
-+                              break;
-+                      }
-+                      if (req->cmd == WRITE) {
-+                              memcpy(sgpnt[i].u.address, bbpnt[i],
-+                                     sgpnt[i].length);
-+                      }
-+              }
+       }
+     }
+   switch (CDB[0])
+diff -X dontdiff -urp kern_oldest/drivers/scsi/dpt_i2o.c kern_fix/drivers/scsi/dpt_i2o.c
+--- kern_oldest/drivers/scsi/dpt_i2o.c 2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/dpt_i2o.c    2006-05-01 14:14:13.000000000 -0700
+@@ -2166,7 +2166,13 @@ static s32 adpt_scsi_to_i2o(adpt_hba* pH
+               for(i = 0 ; i < cmd->use_sg; i++) {
+                       *mptr++ = direction|0x10000000|sg->length;
+                       len+=sg->length;
++#if SMALL_SCATTERLIST
++                      if (sg->ispaged)
++                         BUG();
++                      *mptr++ = virt_to_bus(sg->u.address);
++#else
+                       *mptr++ = virt_to_bus(sg->address);
++#endif
+                       sg++;
+               }
+               /* Make this an end of list */
+diff -X dontdiff -urp kern_oldest/drivers/scsi/eata_dma.c kern_fix/drivers/scsi/eata_dma.c
+--- kern_oldest/drivers/scsi/eata_dma.c        2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/eata_dma.c   2006-05-01 14:14:13.000000000 -0700
+@@ -571,7 +571,11 @@ int eata_queue(Scsi_Cmnd * cmd, void (* 
+       ccb->cp_datalen = htonl(cmd->use_sg * sizeof(struct eata_sg_list));
+       sl=(struct scatterlist *)cmd->request_buffer;
+       for(i = 0; i < cmd->use_sg; i++, sl++){
++#if SMALL_SCATTERLIST
++          ccb->sg_list[i].data = htonl(virt_to_bus(sl->u.address));
++#else
+           ccb->sg_list[i].data = htonl(virt_to_bus(sl->address));
++#endif
+           ccb->sg_list[i].len = htonl((u32) sl->length);
+       }
+     } else {
+diff -X dontdiff -urp kern_oldest/drivers/scsi/eata_pio.c kern_fix/drivers/scsi/eata_pio.c
+--- kern_oldest/drivers/scsi/eata_pio.c        2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/eata_pio.c   2006-05-01 14:14:13.000000000 -0700
+@@ -99,7 +99,11 @@ void IncStat(Scsi_Pointer *SCp, uint Inc
+       else
+       {
+           SCp->buffer++;
++#if SMALL_SCATTERLIST
++          SCp->ptr=SCp->buffer->u.address;
++#else
+           SCp->ptr=SCp->buffer->address;
++#endif
+           SCp->this_residual=SCp->buffer->length;
+       }
+     }
+@@ -371,7 +375,11 @@ int eata_pio_queue(Scsi_Cmnd * cmd, void
+     } else {
+       cmd->SCp.buffer = cmd->request_buffer;
+       cmd->SCp.buffers_residual = cmd->use_sg;
++#if SMALL_SCATTERLIST
++      cmd->SCp.ptr = cmd->SCp.buffer->u.address;
++#else
+       cmd->SCp.ptr = cmd->SCp.buffer->address;
++#endif
+       cmd->SCp.this_residual = cmd->SCp.buffer->length;
+     }
+     cmd->SCp.Status = (cmd->SCp.this_residual != 0);  /* TRUE as long as bytes 
+diff -X dontdiff -urp kern_oldest/drivers/scsi/fdomain.c kern_fix/drivers/scsi/fdomain.c
+--- kern_oldest/drivers/scsi/fdomain.c 2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/fdomain.c    2006-05-01 14:14:13.000000000 -0700
+@@ -1564,7 +1564,11 @@ void do_fdomain_16x0_intr( int irq, void
+           if (current_SC->SCp.buffers_residual) {
+              --current_SC->SCp.buffers_residual;
+              ++current_SC->SCp.buffer;
++#if SMALL_SCATTERLIST
++             current_SC->SCp.ptr = current_SC->SCp.buffer->u.address;
++#else
+              current_SC->SCp.ptr = current_SC->SCp.buffer->address;
++#endif
+              current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
+           } else
+                 break;
+@@ -1597,7 +1601,11 @@ void do_fdomain_16x0_intr( int irq, void
+            && current_SC->SCp.buffers_residual) {
+           --current_SC->SCp.buffers_residual;
+           ++current_SC->SCp.buffer;
++#if SMALL_SCATTERLIST
++          current_SC->SCp.ptr = current_SC->SCp.buffer->u.address;
++#else
+           current_SC->SCp.ptr = current_SC->SCp.buffer->address;
++#endif
+           current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
+        }
+       }
+@@ -1683,7 +1691,11 @@ int fdomain_16x0_queue( Scsi_Cmnd * SCpn
+    if (current_SC->use_sg) {
+       current_SC->SCp.buffer =
+           (struct scatterlist *)current_SC->request_buffer;
++#if SMALL_SCATTERLIST
++      current_SC->SCp.ptr              = current_SC->SCp.buffer->u.address;
++#else
+       current_SC->SCp.ptr              = current_SC->SCp.buffer->address;
++#endif
+       current_SC->SCp.this_residual    = current_SC->SCp.buffer->length;
+       current_SC->SCp.buffers_residual = current_SC->use_sg - 1;
+    } else {
+diff -X dontdiff -urp kern_oldest/drivers/scsi/gdth.c kern_fix/drivers/scsi/gdth.c
+--- kern_oldest/drivers/scsi/gdth.c    2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/gdth.c       2006-05-01 14:14:13.000000000 -0700
+@@ -2662,7 +2662,11 @@ static void gdth_copy_internal_data(Scsi
+             if (cpsum+cpnow > cpcount) 
+                 cpnow = cpcount - cpsum;
+             cpsum += cpnow;
++#if SMALL_SCATTERLIST
++            memcpy((char*)sl->u.address,buffer,cpnow);
++#else
+             memcpy((char*)sl->address,buffer,cpnow);
++#endif
+             if (cpsum == cpcount)
+                 break;
+             buffer += cpnow;
+@@ -2837,7 +2841,11 @@ static int gdth_fill_cache_cmd(int hanum
+             cmdp->u.cache.DestAddr= 0xffffffff;
+             sl = (struct scatterlist *)scp->request_buffer;
+             for (i=0; i<scp->use_sg; ++i,++sl) {
++#if SMALL_SCATTERLIST
++                cmdp->u.cache.sg_lst[i].sg_ptr = virt_to_bus(sl->u.address);
++#else
+                 cmdp->u.cache.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
++#endif
+                 cmdp->u.cache.sg_lst[i].sg_len = (ulong32)sl->length;
+             }
+             cmdp->u.cache.sg_canz = (ulong32)i;
+@@ -2954,7 +2962,11 @@ static int gdth_fill_raw_cmd(int hanum,S
+             cmdp->u.raw.sdata  = 0xffffffff;
+             sl = (struct scatterlist *)scp->request_buffer;
+             for (i=0; i<scp->use_sg; ++i,++sl) {
++#if SMALL_SCATTERLIST
++                cmdp->u.raw.sg_lst[i].sg_ptr = virt_to_bus(sl->u.address);
++#else
+                 cmdp->u.raw.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
++#endif
+                 cmdp->u.raw.sg_lst[i].sg_len = (ulong32)sl->length;
+             }
+             cmdp->u.raw.sg_ranz = (ulong32)i;
+diff -X dontdiff -urp kern_oldest/drivers/scsi/ide-scsi.c kern_fix/drivers/scsi/ide-scsi.c
+--- kern_oldest/drivers/scsi/ide-scsi.c        2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/ide-scsi.c   2006-05-01 14:14:13.000000000 -0700
+@@ -154,7 +154,11 @@ static void idescsi_input_buffers (ide_d
+                       return;
+               }
+               count = IDE_MIN(pc->sg->length - pc->b_count, bcount);
++#if SMALL_SCATTERLIST
++              HWIF(drive)->atapi_input_bytes(drive, pc->sg->u.address + pc->b_count, count);
++#else
+               HWIF(drive)->atapi_input_bytes(drive, pc->sg->address + pc->b_count, count);
++#endif
+               bcount -= count;
+               pc->b_count += count;
+               if (pc->b_count == pc->sg->length) {
+@@ -176,7 +180,11 @@ static void idescsi_output_buffers (ide_
+                       return;
+               }
+               count = IDE_MIN(pc->sg->length - pc->b_count, bcount);
++#if SMALL_SCATTERLIST
++              HWIF(drive)->atapi_output_bytes(drive, pc->sg->u.address + pc->b_count, count);
++#else
+               HWIF(drive)->atapi_output_bytes(drive, pc->sg->address + pc->b_count, count);
++#endif
+               bcount -= count;
+               pc->b_count += count;
+               if (pc->b_count == pc->sg->length) {
+@@ -1026,6 +1034,19 @@ static inline struct buffer_head *idescs
+                       pc->request_transfer >> 10);
+ #endif /* IDESCSI_DEBUG_LOG */
+               while (segments--) {
++#if SMALL_SCATTERLIST
++#if 1
++                      bh->b_data = sg->u.address;
 +#else
-               if (virt_to_phys(sgpnt[i].address) + sgpnt[i].length - 1 >
-                   ISA_DMA_THRESHOLD) {
-                       if( scsi_dma_free_sectors - sectors <= 10  ) {
-@@ -1012,6 +1080,7 @@
-                                      sgpnt[i].length);
++                      if (sg->u.address) {
++                              bh->b_page = virt_to_page(sg->u.address);
++                              bh->b_data = (char *) ((unsigned long) sg->u.address & ~PAGE_MASK);
++                      } else if (sg->u.page.page) {
++                              bh->b_page = sg->u.page.page;
++                              bh->b_data = (char *) sg->u.page.offset;
++                      }
++#endif
++#else /* !SMALL_SCATTERLIST */
+ #if 1
+                       bh->b_data = sg->address;
+ #else
+@@ -1037,6 +1058,7 @@ static inline struct buffer_head *idescs
+                               bh->b_data = (char *) sg->offset;
                        }
-               }
+ #endif
++#endif /* !SMALL_SCATTERLIST */
+                       bh->b_size = sg->length;
+                       bh = bh->b_reqnext;
+                       sg++;
+diff -X dontdiff -urp kern_oldest/drivers/scsi/imm.c kern_fix/drivers/scsi/imm.c
+--- kern_oldest/drivers/scsi/imm.c     2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/imm.c        2006-05-01 14:14:13.000000000 -0700
+@@ -834,7 +834,11 @@ static int imm_completion(Scsi_Cmnd * cm
+           if (cmd->SCp.buffers_residual--) {
+               cmd->SCp.buffer++;
+               cmd->SCp.this_residual = cmd->SCp.buffer->length;
++#if SMALL_SCATTERLIST
++              cmd->SCp.ptr = cmd->SCp.buffer->u.address;
++#else
+               cmd->SCp.ptr = cmd->SCp.buffer->address;
 +#endif
-       }
-       return 1;
  
-Index: linux-2.4.21/drivers/scsi/sg.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/sg.c        2005-06-01 22:52:05.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/sg.c     2005-06-01 23:07:51.080580984 -0400
-@@ -1077,7 +1077,11 @@
-         for (k = 0; k < rsv_schp->k_use_sg; ++k, ++sclp) {
-           for (m = PAGE_SIZE; m < sclp->length; m += PAGE_SIZE) {
+               /*
+                * Make sure that we transfer even number of bytes
+@@ -1008,7 +1012,11 @@ static int imm_engine(imm_struct * tmp, 
+           /* if many buffers are available, start filling the first */
+           cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer;
+           cmd->SCp.this_residual = cmd->SCp.buffer->length;
 +#if SMALL_SCATTERLIST
-+              page_ptr = (unsigned char *)sclp->u.address + m;
++          cmd->SCp.ptr = cmd->SCp.buffer->u.address;
 +#else
-               page_ptr = (unsigned char *)sclp->address + m;
+           cmd->SCp.ptr = cmd->SCp.buffer->address;
 +#endif
-               page = virt_to_page(page_ptr);
-               if (startFinish)
-                   get_page(page);     /* increment page count */
-@@ -1130,7 +1134,11 @@
-             len = vma->vm_end - sa;
-             len = (len < sclp->length) ? len : sclp->length;
-           if (offset < len) {
+       } else {
+           /* else fill the only available buffer */
+           cmd->SCp.buffer = NULL;
+diff -X dontdiff -urp kern_oldest/drivers/scsi/in2000.c kern_fix/drivers/scsi/in2000.c
+--- kern_oldest/drivers/scsi/in2000.c  2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/in2000.c     2006-05-01 14:14:13.000000000 -0700
+@@ -355,7 +355,11 @@ DB(DB_QUEUE_COMMAND,printk("Q-%d-%02x-%l
+    if (cmd->use_sg) {
+       cmd->SCp.buffer = (struct scatterlist *)cmd->buffer;
+       cmd->SCp.buffers_residual = cmd->use_sg - 1;
 +#if SMALL_SCATTERLIST
-+              page_ptr = (unsigned char *)sclp->u.address + offset;
++      cmd->SCp.ptr = (char *)cmd->SCp.buffer->u.address;
 +#else
-               page_ptr = (unsigned char *)sclp->address + offset;
+       cmd->SCp.ptr = (char *)cmd->SCp.buffer->address;
 +#endif
-               page = virt_to_page(page_ptr);
-               get_page(page); /* increment page count */
-               break;
-@@ -1175,8 +1183,13 @@
-       for (k = 0; (k < rsv_schp->k_use_sg) && (sa < vma->vm_end); 
-            ++k, ++sclp) {
+       cmd->SCp.this_residual = cmd->SCp.buffer->length;
+       }
+    else {
+@@ -762,7 +766,11 @@ int i;
+       ++cmd->SCp.buffer;
+       --cmd->SCp.buffers_residual;
+       cmd->SCp.this_residual = cmd->SCp.buffer->length;
 +#if SMALL_SCATTERLIST
-+          if ((unsigned long)sclp->u.address & (PAGE_SIZE - 1))
-+              return -EFAULT;     /* non page aligned memory ?? */
++      cmd->SCp.ptr = cmd->SCp.buffer->u.address;
 +#else
-           if ((unsigned long)sclp->address & (PAGE_SIZE - 1))
-               return -EFAULT;     /* non page aligned memory ?? */
+       cmd->SCp.ptr = cmd->SCp.buffer->address;
 +#endif
-           len = vma->vm_end - sa;
-           len = (len < sclp->length) ? len : sclp->length;
-           sa += len;
-@@ -1725,16 +1738,27 @@
-       offset = (0 == k) ? kp->offset : 0;
-       num = (rem_sz > (PAGE_SIZE - offset)) ? (PAGE_SIZE - offset) :
-                                               rem_sz;
+       }
+ /* Set up hardware registers */
+diff -X dontdiff -urp kern_oldest/drivers/scsi/ini9100u.c kern_fix/drivers/scsi/ini9100u.c
+--- kern_oldest/drivers/scsi/ini9100u.c        2006-05-01 11:55:41.000000000 -0700
++++ kern_fix/drivers/scsi/ini9100u.c   2006-05-01 14:14:13.000000000 -0700
+@@ -489,7 +489,11 @@ static void i91uBuildSCB(HCS * pHCB, SCB
+       if (SCpnt->use_sg) {
+               pSrbSG = (struct scatterlist *) SCpnt->request_buffer;
+               if (SCpnt->use_sg == 1) {       /* If only one entry in the list *//*      treat it as regular I/O */
 +#if SMALL_SCATTERLIST
-+      sclp->u.address = page_address(kp->maplist[k]) + offset;
-+      sclp->ispaged = 0;
++                      pSCB->SCB_BufPtr = (U32) VIRT_TO_BUS(pSrbSG->u.address);
 +#else
-       sclp->address = page_address(kp->maplist[k]) + offset;
- #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
-       sclp->page = NULL;
- #endif
+                       pSCB->SCB_BufPtr = (U32) VIRT_TO_BUS(pSrbSG->address);
 +#endif
-       sclp->length = num;
-       mem_src_arr[k] = SG_USER_MEM;
-       rem_sz -= num;
+                       TotalLen = pSrbSG->length;
+                       pSCB->SCB_SGLen = 0;
+               } else {        /* Assign SG physical address   */
+@@ -498,7 +502,11 @@ static void i91uBuildSCB(HCS * pHCB, SCB
+                       for (i = 0, TotalLen = 0, pSG = &pSCB->SCB_SGList[0];   /* 1.01g */
+                            i < SCpnt->use_sg;
+                            i++, pSG++, pSrbSG++) {
 +#if SMALL_SCATTERLIST
-+      SCSI_LOG_TIMEOUT(5,
-+          printk("sg_build_dir: k=%d, a=0x%p, len=%d, ms=%d\n",
-+          k, sclp->u.address, num, mem_src_arr[k]));
++                              pSG->SG_Ptr = (U32) VIRT_TO_BUS(pSrbSG->u.address);
 +#else
-       SCSI_LOG_TIMEOUT(5,
-           printk("sg_build_dir: k=%d, a=0x%p, len=%d, ms=%d\n",
-           k, sclp->address, num, mem_src_arr[k]));
+                               pSG->SG_Ptr = (U32) VIRT_TO_BUS(pSrbSG->address);
 +#endif
-     }
-     schp->k_use_sg = k;
-     SCSI_LOG_TIMEOUT(5,
-@@ -1814,16 +1838,27 @@
-                 if (! p)
-                     break;
-             }
+                               TotalLen += pSG->SG_Len = pSrbSG->length;
+                       }
+                       pSCB->SCB_SGLen = i;
+diff -X dontdiff -urp kern_oldest/drivers/scsi/inia100.c kern_fix/drivers/scsi/inia100.c
+--- kern_oldest/drivers/scsi/inia100.c 2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/inia100.c    2006-05-01 14:14:13.000000000 -0700
+@@ -494,7 +494,11 @@ static void inia100BuildSCB(ORC_HCS * pH
+                       pSCB->SCB_SGLen = (U32) (SCpnt->use_sg * 8);
+                       pSrbSG = (struct scatterlist *) SCpnt->request_buffer;
+                       for (i = 0; i < SCpnt->use_sg; i++, pSG++, pSrbSG++) {
 +#if SMALL_SCATTERLIST
-+            sclp->u.address = p;
-+          sclp->ispaged = 0;
++                              pSG->SG_Ptr = (U32) (VIRT_TO_BUS(pSrbSG->u.address));
 +#else
-             sclp->address = p;
- #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
-           sclp->page = NULL;
- #endif
+                               pSG->SG_Ptr = (U32) (VIRT_TO_BUS(pSrbSG->address));
 +#endif
-             sclp->length = ret_sz;
-           mem_src_arr[k] = mem_src;
+                               pSG->SG_Len = (U32) pSrbSG->length;
+                               TotalLen += (U32) pSrbSG->length;
+                       }
+diff -X dontdiff -urp kern_oldest/drivers/scsi/ips.c kern_fix/drivers/scsi/ips.c
+--- kern_oldest/drivers/scsi/ips.c     2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/ips.c        2006-05-01 14:14:13.000000000 -0700
+@@ -217,7 +217,11 @@ MODULE_PARM(ips, "s");
+ #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
+ #include <linux/blk.h>
+ #include "sd.h"
++#ifdef SMALL_SCATTERLIST
++#define IPS_SG_ADDRESS(sg)       ((sg)->u.address)
++#else
+ #define IPS_SG_ADDRESS(sg)       ((sg)->address)
++#endif /* !SMALL_SCATTERLIST */
+ #define IPS_LOCK_SAVE(lock,flags) spin_lock_irqsave(&io_request_lock,flags)
+ #define IPS_UNLOCK_RESTORE(lock,flags) spin_unlock_irqrestore(&io_request_lock,flags)
+ #ifndef __devexit_p
+diff -X dontdiff -urp kern_oldest/drivers/scsi/libata-core.c kern_fix/drivers/scsi/libata-core.c
+--- kern_oldest/drivers/scsi/libata-core.c     2006-05-01 11:55:41.000000000 -0700
++++ kern_fix/drivers/scsi/libata-core.c        2006-05-01 14:14:13.000000000 -0700
+@@ -3010,8 +3010,13 @@ static void ata_pio_sector(struct ata_qu
+       if (qc->cursect == (qc->nsect - 1))
+               ap->hsm_task_state = HSM_ST_LAST;
  
 +#if SMALL_SCATTERLIST
-+          SCSI_LOG_TIMEOUT(5,
-+              printk("sg_build_build: k=%d, a=0x%p, len=%d, ms=%d\n",
-+                k, sclp->u.address, ret_sz, mem_src));
++      page = sg[qc->cursg].u.page.page;
++      offset = sg[qc->cursg].u.page.offset + qc->cursg_ofs * ATA_SECT_SIZE;
 +#else
-           SCSI_LOG_TIMEOUT(5,
-               printk("sg_build_build: k=%d, a=0x%p, len=%d, ms=%d\n",
-                 k, sclp->address, ret_sz, mem_src));
-+#endif
-         } /* end of for loop */
-       schp->k_use_sg = k;
-       SCSI_LOG_TIMEOUT(5,
-@@ -1888,13 +1923,21 @@
-       struct scatterlist * sclp = (struct scatterlist *)schp->buffer;
-       char * mem_src_arr = sg_get_sgat_msa(schp);
-       ksglen = (int)sclp->length;
+       page = sg[qc->cursg].page;
+       offset = sg[qc->cursg].offset + qc->cursg_ofs * ATA_SECT_SIZE;
++#endif /* SMALL_SCATTERLIST */
+       /* get the current page and offset */
+       page = nth_page(page, (offset >> PAGE_SHIFT));
+@@ -3086,8 +3091,13 @@ next_sg:
+       sg = &qc->__sg[qc->cursg];
 +#if SMALL_SCATTERLIST
-+      p = sclp->u.address;
++      page = sg->u.page.page;
++      offset = sg->u.page.offset + qc->cursg_ofs;
 +#else
-       p = sclp->address;
+       page = sg->page;
+       offset = sg->offset + qc->cursg_ofs;
 +#endif
  
-       for (j = 0, k = 0; j < onum; ++j) {
-           res = sg_u_iovec(hp, iovec_count, j, 1, &usglen, &up);
-           if (res) return res;
+       /* get the current page and offset */
+       page = nth_page(page, (offset >> PAGE_SHIFT));
+diff -X dontdiff -urp kern_oldest/drivers/scsi/libata-scsi.c kern_fix/drivers/scsi/libata-scsi.c
+--- kern_oldest/drivers/scsi/libata-scsi.c     2006-05-01 11:55:41.000000000 -0700
++++ kern_fix/drivers/scsi/libata-scsi.c        2006-05-01 14:14:13.000000000 -0700
+@@ -1314,7 +1314,11 @@ static unsigned int ata_scsi_rbuf_get(st
+               struct scatterlist *sg;
+               sg = (struct scatterlist *) cmd->request_buffer;
++#if SMALL_SCATTERLIST
++              buf = kmap_atomic(sg->u.page.page, KM_USER0) + sg->u.page.offset;
++#else
+               buf = kmap_atomic(sg->page, KM_USER0) + sg->offset;
++#endif /* !SMALL_SCATTERLIST */
+               buflen = sg->length;
+       } else {
+               buf = cmd->request_buffer;
+@@ -1342,7 +1346,11 @@ static inline void ata_scsi_rbuf_put(str
+               struct scatterlist *sg;
  
+               sg = (struct scatterlist *) cmd->request_buffer;
 +#if SMALL_SCATTERLIST
-+          for ( ; p; ++sclp, ksglen = (int)sclp->length, p = sclp->u.address) {
++              kunmap_atomic(buf - sg->u.page.offset, KM_USER0);
 +#else
-           for ( ; p; ++sclp, ksglen = (int)sclp->length, p = sclp->address) {
-+#endif
-               ok = (SG_USER_MEM != mem_src_arr[k]);
-               if (usglen <= 0)
-                   break;
-@@ -1971,6 +2014,18 @@
-         struct scatterlist * sclp = (struct scatterlist *)schp->buffer;
-       char * mem_src_arr = sg_get_sgat_msa(schp);
+               kunmap_atomic(buf - sg->offset, KM_USER0);
++#endif /* !SMALL_SCATTERLIST */
+       }
+ }
  
+diff -X dontdiff -urp kern_oldest/drivers/scsi/megaraid2.c kern_fix/drivers/scsi/megaraid2.c
+--- kern_oldest/drivers/scsi/megaraid2.c       2006-05-01 11:55:41.000000000 -0700
++++ kern_fix/drivers/scsi/megaraid2.c  2006-05-01 14:14:13.000000000 -0700
+@@ -2068,7 +2068,11 @@ mega_cmd_done(adapter_t *adapter, u8 com
+                       if( cmd->use_sg ) {
+                               sgl = (struct scatterlist *)
+                                       cmd->request_buffer;
 +#if SMALL_SCATTERLIST
-+      for (k = 0; (k < schp->k_use_sg) && sclp->u.address; ++k, ++sclp) {
-+          mem_src = mem_src_arr[k];
-+          SCSI_LOG_TIMEOUT(5,
-+              printk("sg_remove_scat: k=%d, a=0x%p, len=%d, ms=%d\n",
-+                       k, sclp->u.address, sclp->length, mem_src));
-+            sg_free(sclp->u.address, sclp->length, mem_src);
-+            sclp->u.address = NULL;
-+          sclp->ispaged = 0;
-+            sclp->length = 0;
-+        }
++                              c = *(u8 *)sgl[0].u.address;
 +#else
-       for (k = 0; (k < schp->k_use_sg) && sclp->address; ++k, ++sclp) {
-           mem_src = mem_src_arr[k];
-           SCSI_LOG_TIMEOUT(5,
-@@ -1983,6 +2038,7 @@
- #endif
-             sclp->length = 0;
-         }
+                               c = *(u8 *)sgl[0].address;
 +#endif
-       sg_free(schp->buffer, schp->sglist_len, schp->buffer_mem_src);
-     }
-     else if (schp->buffer)
-@@ -2043,13 +2099,21 @@
-       struct scatterlist * sclp = (struct scatterlist *)schp->buffer;
-       char * mem_src_arr = sg_get_sgat_msa(schp);
-       ksglen = (int)sclp->length;
+                       }
+                       else {
+                               c = *(u8 *)cmd->request_buffer;
+diff -X dontdiff -urp kern_oldest/drivers/scsi/megaraid.c kern_fix/drivers/scsi/megaraid.c
+--- kern_oldest/drivers/scsi/megaraid.c        2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/megaraid.c   2006-05-01 14:14:13.000000000 -0700
+@@ -1201,8 +1201,13 @@ static void mega_cmd_done (mega_host_con
+       case READ_CAPACITY:
+               if ( SCpnt->use_sg ) {
+                       sgList = (struct scatterlist *)SCpnt->request_buffer;
++#if SMALL_SCATTERLIST
++                      memcpy(sgList[0].u.address, pScb->bounce_buffer,
++                             SCpnt->request_bufflen);
++#else
+                       memcpy(sgList[0].address, pScb->bounce_buffer,
+-                                                      SCpnt->request_bufflen);
++                             SCpnt->request_bufflen);
++#endif
+               } else {
+                               memcpy (SCpnt->request_buffer, pScb->bounce_buffer,
+                                                               SCpnt->request_bufflen);
+@@ -1226,7 +1231,11 @@ static void mega_cmd_done (mega_host_con
+       if (SCpnt->cmnd[0] == INQUIRY && !islogical) {
+               if ( SCpnt->use_sg ) {
+                       sgList = (struct scatterlist *)SCpnt->request_buffer;
 +#if SMALL_SCATTERLIST
-+      p = sclp->u.address;
++                      memcpy(&c, sgList[0].u.address, 0x1);
 +#else
-       p = sclp->address;
+                       memcpy(&c, sgList[0].address, 0x1);
 +#endif
-       for (j = 0, k = 0; j < onum; ++j) {
-           res = sg_u_iovec(hp, iovec_count, j, 0, &usglen, &up);
-           if (res) return res;
+               } else {
+                       memcpy(&c, SCpnt->request_buffer, 0x1);
+               }
+diff -X dontdiff -urp kern_oldest/drivers/scsi/NCR5380.c kern_fix/drivers/scsi/NCR5380.c
+--- kern_oldest/drivers/scsi/NCR5380.c 2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/NCR5380.c    2006-05-01 14:14:13.000000000 -0700
+@@ -337,7 +337,11 @@ static __inline__ void initialize_SCp(Sc
+       if (cmd->use_sg) {
+               cmd->SCp.buffer = (struct scatterlist *) cmd->buffer;
+               cmd->SCp.buffers_residual = cmd->use_sg - 1;
 +#if SMALL_SCATTERLIST
-+          for ( ; p; ++sclp, ksglen = (int)sclp->length, p = sclp->u.address) {
++              cmd->SCp.ptr = (char *) cmd->SCp.buffer->u.address;
 +#else
-           for ( ; p; ++sclp, ksglen = (int)sclp->length, p = sclp->address) {
+               cmd->SCp.ptr = (char *) cmd->SCp.buffer->address;
 +#endif
-               ok = (SG_USER_MEM != mem_src_arr[k]);
-               if (usglen <= 0)
-                   break;
-@@ -2093,14 +2157,26 @@
-         int k, num;
-         struct scatterlist * sclp = (struct scatterlist *)schp->buffer;
+               cmd->SCp.this_residual = cmd->SCp.buffer->length;
+       } else {
+               cmd->SCp.buffer = NULL;
+@@ -2308,7 +2312,11 @@ static void NCR5380_information_transfer
+                                       ++cmd->SCp.buffer;
+                                       --cmd->SCp.buffers_residual;
+                                       cmd->SCp.this_residual = cmd->SCp.buffer->length;
 +#if SMALL_SCATTERLIST
-+      for (k = 0; (k < schp->k_use_sg) && sclp->u.address; ++k, ++sclp) {
++                                      cmd->SCp.ptr = cmd->SCp.buffer->u.address;
 +#else
-       for (k = 0; (k < schp->k_use_sg) && sclp->address; ++k, ++sclp) {
+                                       cmd->SCp.ptr = cmd->SCp.buffer->address;
 +#endif
-             num = (int)sclp->length;
-             if (num > num_read_xfer) {
+                                       dprintk(NDEBUG_INFORMATION, ("scsi%d : %d bytes and %d buffers left\n", instance->host_no, cmd->SCp.this_residual, cmd->SCp.buffers_residual));
+                               }
+                               /*
+diff -X dontdiff -urp kern_oldest/drivers/scsi/NCR53c406a.c kern_fix/drivers/scsi/NCR53c406a.c
+--- kern_oldest/drivers/scsi/NCR53c406a.c      2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/NCR53c406a.c 2006-05-01 14:14:13.000000000 -0700
+@@ -895,7 +895,11 @@ NCR53c406a_intr(int unused, void *dev_id
+                 sgcount = current_SC->use_sg;
+                 sglist = current_SC->request_buffer;
+                 while( sgcount-- ) {
 +#if SMALL_SCATTERLIST
-+                __copy_to_user(outp, sclp->u.address, num_read_xfer);
++                    NCR53c406a_pio_write(sglist->u.address, sglist->length);
 +#else
-                 __copy_to_user(outp, sclp->address, num_read_xfer);
+                     NCR53c406a_pio_write(sglist->address, sglist->length);
 +#endif
-                 break;
+                     sglist++;
+                 }
              }
-             else {
+@@ -924,7 +928,11 @@ NCR53c406a_intr(int unused, void *dev_id
+                 sgcount = current_SC->use_sg;
+                 sglist = current_SC->request_buffer;
+                 while( sgcount-- ) {
 +#if SMALL_SCATTERLIST
-+                __copy_to_user(outp, sclp->u.address, num);
++                    NCR53c406a_pio_read(sglist->u.address, sglist->length);
 +#else
-                 __copy_to_user(outp, sclp->address, num);
+                     NCR53c406a_pio_read(sglist->address, sglist->length);
 +#endif
-                 num_read_xfer -= num;
-                 if (num_read_xfer <= 0)
-                     break;
-@@ -2146,7 +2222,11 @@
-             if (rem <= num) {
-               if (0 == k) {
-                   req_schp->k_use_sg = 0;
+                     sglist++;
+                 }
+             }
+diff -X dontdiff -urp kern_oldest/drivers/scsi/osst.c kern_fix/drivers/scsi/osst.c
+--- kern_oldest/drivers/scsi/osst.c    2006-05-01 11:55:41.000000000 -0700
++++ kern_fix/drivers/scsi/osst.c       2006-05-01 14:14:13.000000000 -0700
+@@ -477,7 +477,11 @@ static int osst_verify_frame(OS_Scsi_Tap
+       if (STp->raw) {
+               if (STp->buffer->syscall_result) {
+                       for (i=0; i < STp->buffer->sg_segs; i++)
 +#if SMALL_SCATTERLIST
-+                  req_schp->buffer = sclp->u.address;
++                              memset(STp->buffer->sg[i].u.address, 0, STp->buffer->sg[i].length);
 +#else
-                   req_schp->buffer = sclp->address;
+                               memset(STp->buffer->sg[i].address, 0, STp->buffer->sg[i].length);
 +#endif
-               }
-               else {
-                   sfp->save_scat_len = num;
-Index: linux-2.4.21/drivers/scsi/sr.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/sr.c        2005-06-01 22:51:55.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/sr.c     2005-06-01 23:07:51.080580984 -0400
-@@ -343,7 +343,12 @@
-       i = 0;
-       if (fsize) {
+                       strcpy(STp->buffer->b_data, "READ ERROR ON FRAME");
+                 } else
+                       STp->buffer->buffer_bytes = OS_FRAME_SIZE;
+@@ -4460,10 +4464,19 @@ static int os_scsi_tape_open(struct inod
+               for (i = 0, b_size = 0; 
+                    i < STp->buffer->sg_segs && (b_size + STp->buffer->sg[i].length) <= OS_DATA_SIZE; 
+                    b_size += STp->buffer->sg[i++].length);
 +#if SMALL_SCATTERLIST
-+              sg[0].ispaged = 0;
-+              sg[0].u.address = bbpnt[0] = front;
++              STp->buffer->aux = (os_aux_t *) (STp->buffer->sg[i].u.address + OS_DATA_SIZE - b_size);
 +#else
-               sg[0].address = bbpnt[0] = front;
+               STp->buffer->aux = (os_aux_t *) (STp->buffer->sg[i].address + OS_DATA_SIZE - b_size);
 +#endif
-               sg[0].length = fsize;
-               i++;
-       }
-@@ -354,7 +359,12 @@
-               scsi_free(old_sg, (((SCpnt->use_sg * sizeof(struct scatterlist)) +
-                                   (SCpnt->use_sg * sizeof(void *))) + 511) & ~511);
-       } else {
+ #if DEBUG
+               printk(OSST_DEB_MSG "osst%d:D: b_data points to %p in segment 0 at %p\n", dev,
+-                      STp->buffer->b_data, STp->buffer->sg[0].address);
++                      STp->buffer->b_data, 
 +#if SMALL_SCATTERLIST
-+              sg[i].ispaged = 0;
-+              sg[i].u.address = SCpnt->request_buffer;
++                     STp->buffer->sg[0].u.address);
 +#else
-               sg[i].address = SCpnt->request_buffer;
++                     STp->buffer->sg[0].address);
 +#endif
-               sg[i].length = SCpnt->request_bufflen;
-       }
-@@ -364,7 +374,12 @@
-       SCpnt->use_sg += i;
+               printk(OSST_DEB_MSG "osst%d:D: AUX points to %p in segment %d at %p\n", dev,
+                        STp->buffer->aux, i, STp->buffer->sg[i].address);
+ #endif
+@@ -5007,6 +5020,12 @@ out:
\f
+ /* Memory handling routines */
  
-       if (bsize) {
 +#if SMALL_SCATTERLIST
-+              sg[SCpnt->use_sg].ispaged = 0;
-+              sg[SCpnt->use_sg].u.address = back;
++#define SG_ADDRESS(sg) ((sg).u.address)
 +#else
-               sg[SCpnt->use_sg].address = back;
++#define SG_ADDRESS(sg) ((sg).address)
 +#endif
-               bbpnt[SCpnt->use_sg] = back;
-               sg[SCpnt->use_sg].length = bsize;
-               SCpnt->use_sg++;
-Index: linux-2.4.21/drivers/scsi/sim710.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/sim710.c    2002-08-02 20:39:44.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/sim710.c 2005-06-01 23:07:51.082580680 -0400
-@@ -1164,7 +1164,11 @@
++
+ /* Try to allocate a new tape buffer */
+ static OSST_buffer * new_tape_buffer( int from_initialization, int need_dma )
+ {
+@@ -5035,15 +5054,19 @@ static OSST_buffer * new_tape_buffer( in
+                    b_size *= 2,                 order++ );
  
-     for (i = 0; cmd->use_sg ? (i < cmd->use_sg) : !i; i++) {
-       u32 vbuf = cmd->use_sg ?
+               for ( ; b_size >= PAGE_SIZE; order--, b_size /= 2) {
+-                      tb->sg[0].address =
++                      SG_ADDRESS(tb->sg[0]) =
+                           (unsigned char *)__get_free_pages(priority, order);
+-                      if (tb->sg[0].address != NULL) {
++                      if (SG_ADDRESS(tb->sg[0]) != NULL) {
 +#if SMALL_SCATTERLIST
-+              (u32)(((struct scatterlist *)cmd->buffer)[i].u.address) :
++                          tb->sg[0].ispaged = 0;
 +#else
-               (u32)(((struct scatterlist *)cmd->buffer)[i].address) :
+                           tb->sg[0].page = NULL;
 +#endif
-               (u32)(cmd->request_buffer);
-       u32 bbuf = virt_to_bus((void *)vbuf);
-       u32 cnt = cmd->use_sg ?
-Index: linux-2.4.21/drivers/scsi/advansys.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/advansys.c  2005-06-01 22:52:05.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/advansys.c       2005-06-01 23:07:51.097578400 -0400
-@@ -6803,7 +6803,11 @@
-         slp = (struct scatterlist *) scp->request_buffer;
-         for (sgcnt = 0; sgcnt < scp->use_sg; sgcnt++, slp++) {
-             asc_sg_head.sg_list[sgcnt].addr =
+                           tb->sg[0].length = b_size;
+                           break;
+                       }
+               }
+-              if (tb->sg[segs].address == NULL) {
++              if (SG_ADDRESS(tb->sg[segs]) == NULL) {
+                       kfree(tb);
+                       tb = NULL;
+               }
+@@ -5055,9 +5078,9 @@ static OSST_buffer * new_tape_buffer( in
+                       for (segs=1, got=tb->sg[0].length;
+                            got < osst_buffer_size && segs < OSST_FIRST_SG; ) {
+-                          tb->sg[segs].address =
++                          SG_ADDRESS(tb->sg[segs]) =
+                               (unsigned char *)__get_free_pages(priority, order);
+-                          if (tb->sg[segs].address == NULL) {
++                          if (SG_ADDRESS(tb->sg[segs]) == NULL) {
+                               if (osst_buffer_size - got <=
+                                   (OSST_FIRST_SG - segs) * b_size / 2) {
+                                   b_size /= 2; /* Large enough for the rest of the buffers */
+@@ -5074,7 +5097,11 @@ static OSST_buffer * new_tape_buffer( in
+                               tb = NULL;
+                               break;
+                           }
 +#if SMALL_SCATTERLIST
-+                cpu_to_le32(virt_to_bus(slp->u.address));
++                          tb->sg[segs].ispaged = 0;
 +#else
-                 cpu_to_le32(virt_to_bus(slp->address));
+                             tb->sg[segs].page = NULL;
 +#endif
-             asc_sg_head.sg_list[sgcnt].bytes = cpu_to_le32(slp->length);
-             ASC_STATS_ADD(scp->host, sg_xfer, ASC_CEILING(slp->length, 512));
-         }
-@@ -7061,7 +7065,11 @@
-         for (i = 0; i < NO_OF_SG_PER_BLOCK; i++)
-         {
-             sg_block->sg_list[i].sg_addr =
+                           tb->sg[segs].length = b_size;
+                           got += b_size;
+                           segs++;
+@@ -5087,7 +5114,7 @@ static OSST_buffer * new_tape_buffer( in
+               return NULL;
+       }
+       tb->sg_segs = tb->orig_sg_segs = segs;
+-      tb->b_data = tb->sg[0].address;
++      tb->b_data = SG_ADDRESS(tb->sg[0]);
+ #if DEBUG
+       if (debugging) {
+@@ -5132,9 +5159,9 @@ static int enlarge_buffer(OSST_buffer *S
+       for (segs=STbuffer->sg_segs, got=STbuffer->buffer_size;
+            segs < max_segs && got < new_size; ) {
+-              STbuffer->sg[segs].address =
++              SG_ADDRESS(STbuffer->sg[segs]) =
+                         (unsigned char *)__get_free_pages(priority, order);
+-              if (STbuffer->sg[segs].address == NULL) {
++              if (SG_ADDRESS(STbuffer->sg[segs]) == NULL) {
+                       if (new_size - got <= (max_segs - segs) * b_size / 2) {
+                               b_size /= 2;  /* Large enough for the rest of the buffers */
+                               order--;
+@@ -5148,7 +5175,11 @@ static int enlarge_buffer(OSST_buffer *S
+                       normalize_buffer(STbuffer);
+                       return FALSE;
+               }
 +#if SMALL_SCATTERLIST
-+                cpu_to_le32(virt_to_bus(slp->u.address));
++              STbuffer->sg[segs].ispaged = 0;
 +#else
-                 cpu_to_le32(virt_to_bus(slp->address));
+               STbuffer->sg[segs].page = NULL;
 +#endif
-             sg_block->sg_list[i].sg_count = cpu_to_le32(slp->length);
-             ASC_STATS_ADD(scp->host, sg_xfer, ASC_CEILING(slp->length, 512));
-Index: linux-2.4.21/drivers/scsi/pci2000.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/pci2000.c   2001-11-09 17:05:06.000000000 -0500
-+++ linux-2.4.21/drivers/scsi/pci2000.c        2005-06-01 23:07:51.098578248 -0400
-@@ -513,7 +513,11 @@
+               STbuffer->sg[segs].length = b_size;
+               STbuffer->sg_segs += 1;
+               got += b_size;
+@@ -5181,8 +5212,8 @@ static void normalize_buffer(OSST_buffer
+               for (b_size = PAGE_SIZE, order = 0;
+                    b_size < STbuffer->sg[i].length;
+                    b_size *= 2, order++);
+-
+-              free_pages((unsigned long)STbuffer->sg[i].address, order);
++ 
++              free_pages((unsigned long)SG_ADDRESS(STbuffer->sg[i]), order);
+               STbuffer->buffer_size -= STbuffer->sg[i].length;
+       }
+ #if DEBUG
+@@ -5210,7 +5241,7 @@ static int append_to_buffer(const char *
+       for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
+               cnt = st_bp->sg[i].length - offset < do_count ?
+                     st_bp->sg[i].length - offset : do_count;
+-              res = copy_from_user(st_bp->sg[i].address + offset, ubp, cnt);
++              res = copy_from_user(SG_ADDRESS(st_bp->sg[i]) + offset, ubp, cnt);
+               if (res)
+                       return (-EFAULT);
+               do_count -= cnt;
+@@ -5243,7 +5274,7 @@ static int from_buffer(OSST_buffer *st_b
+       for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
+               cnt = st_bp->sg[i].length - offset < do_count ?
+                     st_bp->sg[i].length - offset : do_count;
+-              res = copy_to_user(ubp, st_bp->sg[i].address + offset, cnt);
++              res = copy_to_user(ubp, SG_ADDRESS(st_bp->sg[i]) + offset, cnt);
+               if (res)
+                       return (-EFAULT);
+               do_count -= cnt;
+@@ -5276,7 +5307,7 @@ static int osst_zero_buffer_tail(OSST_bu
+            i < st_bp->sg_segs && do_count > 0; i++) {
+               cnt = st_bp->sg[i].length - offset < do_count ?
+                     st_bp->sg[i].length - offset : do_count ;
+-              memset(st_bp->sg[i].address + offset, 0, cnt);
++              memset(SG_ADDRESS(st_bp->sg[i]) + offset, 0, cnt);
+               do_count -= cnt;
+               offset = 0;
+       }
+@@ -5296,7 +5327,7 @@ static int osst_copy_to_buffer(OSST_buff
+       for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
+               cnt = st_bp->sg[i].length < do_count ?
+                     st_bp->sg[i].length : do_count ;
+-              memcpy(st_bp->sg[i].address, ptr, cnt);
++              memcpy(SG_ADDRESS(st_bp->sg[i]), ptr, cnt);
+               do_count -= cnt;
+               ptr      += cnt;
+       }
+@@ -5317,7 +5348,7 @@ static int osst_copy_from_buffer(OSST_bu
+       for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
+               cnt = st_bp->sg[i].length < do_count ?
+                     st_bp->sg[i].length : do_count ;
+-              memcpy(ptr, st_bp->sg[i].address, cnt);
++              memcpy(ptr, SG_ADDRESS(st_bp->sg[i]), cnt);
+               do_count -= cnt;
+               ptr      += cnt;
+       }
+diff -X dontdiff -urp kern_oldest/drivers/scsi/pci2000.c kern_fix/drivers/scsi/pci2000.c
+--- kern_oldest/drivers/scsi/pci2000.c 2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/pci2000.c    2006-05-01 14:14:13.000000000 -0700
+@@ -513,7 +513,11 @@ int Pci2000_QueueCommand (Scsi_Cmnd *SCp
                        
                        if ( SCpnt->use_sg )
                                {
@@ -1809,7 +2497,7 @@ Index: linux-2.4.21/drivers/scsi/pci2000.c
                                                                                  SCpnt->request_bufflen, scsi_to_pci_dma_dir (SCpnt->sc_data_direction));
                                }
                        else
-@@ -536,7 +540,11 @@
+@@ -536,7 +540,11 @@ int Pci2000_QueueCommand (Scsi_Cmnd *SCp
                case SCSIOP_READ_CAPACITY:                              // read capacity CDB
                        if ( SCpnt->use_sg )
                                {
@@ -1821,11 +2509,10 @@ Index: linux-2.4.21/drivers/scsi/pci2000.c
                                                                                  8, PCI_DMA_FROMDEVICE);
                                }
                        else
-Index: linux-2.4.21/drivers/scsi/pci2220i.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/pci2220i.c  2001-11-09 17:05:06.000000000 -0500
-+++ linux-2.4.21/drivers/scsi/pci2220i.c       2005-06-01 23:07:51.100577944 -0400
-@@ -463,7 +463,11 @@
+diff -X dontdiff -urp kern_oldest/drivers/scsi/pci2220i.c kern_fix/drivers/scsi/pci2220i.c
+--- kern_oldest/drivers/scsi/pci2220i.c        2006-05-01 11:55:41.000000000 -0700
++++ kern_fix/drivers/scsi/pci2220i.c   2006-05-01 14:14:13.000000000 -0700
+@@ -463,7 +463,11 @@ static void WalkScatGath (PADAPTER2220I 
                        {
                        if ( padapter->nextSg < padapter->SCpnt->use_sg )
                                {
@@ -1837,7 +2524,7 @@ Index: linux-2.4.21/drivers/scsi/pci2220i.c
                                padapter->currentSgCount = ((struct scatterlist *)padapter->SCpnt->request_buffer)[padapter->nextSg].length;
                                padapter->nextSg++;
                                }
-@@ -2057,7 +2061,11 @@
+@@ -2057,7 +2061,11 @@ int Pci2220i_QueueCommand (Scsi_Cmnd *SC
  
        if ( SCpnt->use_sg )
                {
@@ -1849,316 +2536,76 @@ Index: linux-2.4.21/drivers/scsi/pci2220i.c
                padapter->currentSgCount = ((struct scatterlist *)SCpnt->request_buffer)[0].length;
                }
        else
-Index: linux-2.4.21/drivers/scsi/BusLogic.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/BusLogic.c  2001-12-21 12:41:55.000000000 -0500
-+++ linux-2.4.21/drivers/scsi/BusLogic.c       2005-06-01 23:07:51.104577336 -0400
-@@ -3402,7 +3402,12 @@
-         CCB->ScatterGatherList[Segment].SegmentByteCount =
-           ScatterList[Segment].length;
-         CCB->ScatterGatherList[Segment].SegmentDataPointer =
-+#if SMALL_SCATTERLIST
-+          Virtual_to_Bus(ScatterList[Segment].u.address);
-+#else
-           Virtual_to_Bus(ScatterList[Segment].address);
-+#endif
-+
-       }
-     }
-   switch (CDB[0])
-Index: linux-2.4.21/drivers/scsi/ultrastor.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/ultrastor.c 2002-08-02 20:39:44.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/ultrastor.c      2005-06-01 23:07:51.105577184 -0400
-@@ -666,7 +666,11 @@
-       sl = (struct scatterlist *) SCpnt->request_buffer;
-       max = SCpnt->use_sg;
-       for (i = 0; i < max; i++) {
-+#if SMALL_SCATTERLIST
-+              mscp->sglist[i].address = virt_to_bus(sl[i].u.address);
-+#else
-               mscp->sglist[i].address = virt_to_bus(sl[i].address);
-+#endif
-               mscp->sglist[i].num_bytes = sl[i].length;
-               transfer_length += sl[i].length;
-       }
-Index: linux-2.4.21/drivers/scsi/aha152x.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/aha152x.c   2003-06-13 10:51:36.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/aha152x.c        2005-06-01 23:07:51.108576728 -0400
-@@ -603,7 +603,11 @@
- #define SCSEM(SCpnt)          SCDATA(SCpnt)->sem
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-+#if SMALL_SCATTERLIST
-+#define SG_ADDRESS(buffer)    ((buffer)->u.address)
-+#else
- #define SG_ADDRESS(buffer)    ((buffer)->address)
-+#endif
- #else
- #define SG_ADDRESS(buffer)    ((char *) (page_address((buffer)->page)+(buffer)->offset))
- #endif
-Index: linux-2.4.21/drivers/scsi/aha1542.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/aha1542.c   2001-10-12 18:35:53.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/aha1542.c        2005-06-01 23:07:51.109576576 -0400
-@@ -69,8 +69,13 @@
- {
-       printk(KERN_CRIT "sgpnt[%d:%d] addr %p/0x%lx length %d\n",
-              badseg, nseg,
-+#if SMALL_SCATTERLIST
-+             sgpnt[badseg].u.address,
-+             SCSI_PA(sgpnt[badseg].u.address),
-+#else
-              sgpnt[badseg].address,
-              SCSI_PA(sgpnt[badseg].address),
-+#endif
-              sgpnt[badseg].length);
-       /*
-@@ -710,11 +715,21 @@
-                       panic("aha1542.c: unable to allocate DMA memory\n");
-               for (i = 0; i < SCpnt->use_sg; i++) {
-                       if (sgpnt[i].length == 0 || SCpnt->use_sg > 16 ||
--                          (((int) sgpnt[i].address) & 1) || (sgpnt[i].length & 1)) {
-+#if SMALL_SCATTERLIST
-+                          (((int) sgpnt[i].u.address) & 1) 
-+#else
-+                          (((int) sgpnt[i].address) & 1)
-+#endif
-+                          || (sgpnt[i].length & 1)) {
-                               unsigned char *ptr;
-                               printk(KERN_CRIT "Bad segment list supplied to aha1542.c (%d, %d)\n", SCpnt->use_sg, i);
-                               for (i = 0; i < SCpnt->use_sg; i++) {
--                                      printk(KERN_CRIT "%d: %p %d\n", i, sgpnt[i].address,
-+                                      printk(KERN_CRIT "%d: %p %d\n", i, 
-+#if SMALL_SCATTERLIST
-+                                             sgpnt[i].u.address,
-+#else
-+                                             sgpnt[i].address,
-+#endif
-                                              sgpnt[i].length);
-                               };
-                               printk(KERN_CRIT "cptr %x: ", (unsigned int) cptr);
-@@ -723,8 +738,13 @@
-                                       printk("%02x ", ptr[i]);
-                               panic("Foooooooood fight!");
-                       };
+diff -X dontdiff -urp kern_oldest/drivers/scsi/pcmcia/nsp_cs.c kern_fix/drivers/scsi/pcmcia/nsp_cs.c
+--- kern_oldest/drivers/scsi/pcmcia/nsp_cs.c   2006-05-01 11:55:41.000000000 -0700
++++ kern_fix/drivers/scsi/pcmcia/nsp_cs.c      2006-05-01 14:14:13.000000000 -0700
+@@ -201,7 +201,11 @@ static int nsp_queuecommand(Scsi_Cmnd *S
+          SCp.phase            : current state of the command */
+       if (SCpnt->use_sg) {
+               SCpnt->SCp.buffer           = (struct scatterlist *) SCpnt->request_buffer;
 +#if SMALL_SCATTERLIST
-+                      any2scsi(cptr[i].dataptr, SCSI_PA(sgpnt[i].u.address));
-+                      if (SCSI_PA(sgpnt[i].u.address + sgpnt[i].length - 1) > ISA_DMA_THRESHOLD)
++              SCpnt->SCp.ptr              = SCpnt->SCp.buffer->u.address;
 +#else
-                       any2scsi(cptr[i].dataptr, SCSI_PA(sgpnt[i].address));
-                       if (SCSI_PA(sgpnt[i].address + sgpnt[i].length - 1) > ISA_DMA_THRESHOLD)
+               SCpnt->SCp.ptr              = SCpnt->SCp.buffer->address;
 +#endif
-                               BAD_SG_DMA(SCpnt, sgpnt, SCpnt->use_sg, i);
-                       any2scsi(cptr[i].datalen, sgpnt[i].length);
-               };
-Index: linux-2.4.21/drivers/scsi/aha1740.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/aha1740.c   2001-09-30 15:26:07.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/aha1740.c        2005-06-01 23:07:51.110576424 -0400
-@@ -397,7 +397,11 @@
-       for(i=0; i<SCpnt->use_sg; i++)
-       {
-           cptr[i].datalen = sgpnt[i].length;
+               SCpnt->SCp.this_residual    = SCpnt->SCp.buffer->length;
+               SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1;
+       } else {
+@@ -713,7 +717,11 @@ static void nsp_pio_read(Scsi_Cmnd *SCpn
+                       //DEBUG(0, " scatterlist next timeout=%d\n", time_out);
+                       SCpnt->SCp.buffers_residual--;
+                       SCpnt->SCp.buffer++;
 +#if SMALL_SCATTERLIST
-+          cptr[i].dataptr = virt_to_bus(sgpnt[i].u.address);
++                      SCpnt->SCp.ptr           = SCpnt->SCp.buffer->u.address;
 +#else
-           cptr[i].dataptr = virt_to_bus(sgpnt[i].address);
+                       SCpnt->SCp.ptr           = SCpnt->SCp.buffer->address;
 +#endif
-       }
-       host->ecb[ecbno].datalen = SCpnt->use_sg * sizeof(struct aha1740_chain);
-       host->ecb[ecbno].dataptr = virt_to_bus(cptr);
-Index: linux-2.4.21/drivers/scsi/aic7xxx_old.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/aic7xxx_old.c       2005-06-01 22:51:54.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/aic7xxx_old.c    2005-06-01 23:07:51.118575208 -0400
-@@ -2845,7 +2845,11 @@
-           struct scatterlist *sg;
+                       SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;
+               }
  
-           sg = (struct scatterlist *)cmd->request_buffer;
-+#if SMALL_SCATTERLIST
-+          buffer = (char *)sg[0].u.address;
-+#else
-           buffer = (char *)sg[0].address;
-+#endif
-         }
-         else
-         {
-Index: linux-2.4.21/drivers/scsi/fdomain.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/fdomain.c   2002-11-28 18:53:14.000000000 -0500
-+++ linux-2.4.21/drivers/scsi/fdomain.c        2005-06-01 23:07:51.120574904 -0400
-@@ -1564,7 +1564,11 @@
-           if (current_SC->SCp.buffers_residual) {
-              --current_SC->SCp.buffers_residual;
-              ++current_SC->SCp.buffer;
-+#if SMALL_SCATTERLIST
-+             current_SC->SCp.ptr = current_SC->SCp.buffer->u.address;
-+#else
-              current_SC->SCp.ptr = current_SC->SCp.buffer->address;
-+#endif
-              current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
-           } else
-                 break;
-@@ -1597,7 +1601,11 @@
-            && current_SC->SCp.buffers_residual) {
-           --current_SC->SCp.buffers_residual;
-           ++current_SC->SCp.buffer;
-+#if SMALL_SCATTERLIST
-+          current_SC->SCp.ptr = current_SC->SCp.buffer->u.address;
-+#else
-           current_SC->SCp.ptr = current_SC->SCp.buffer->address;
-+#endif
-           current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
-        }
-       }
-@@ -1683,7 +1691,11 @@
-    if (current_SC->use_sg) {
-       current_SC->SCp.buffer =
-           (struct scatterlist *)current_SC->request_buffer;
-+#if SMALL_SCATTERLIST
-+      current_SC->SCp.ptr              = current_SC->SCp.buffer->u.address;
-+#else
-       current_SC->SCp.ptr              = current_SC->SCp.buffer->address;
-+#endif
-       current_SC->SCp.this_residual    = current_SC->SCp.buffer->length;
-       current_SC->SCp.buffers_residual = current_SC->use_sg - 1;
-    } else {
-Index: linux-2.4.21/drivers/scsi/in2000.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/in2000.c    2003-06-13 10:51:36.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/in2000.c 2005-06-01 23:07:51.122574600 -0400
-@@ -355,7 +355,11 @@
-    if (cmd->use_sg) {
-       cmd->SCp.buffer = (struct scatterlist *)cmd->buffer;
-       cmd->SCp.buffers_residual = cmd->use_sg - 1;
-+#if SMALL_SCATTERLIST
-+      cmd->SCp.ptr = (char *)cmd->SCp.buffer->u.address;
-+#else
-       cmd->SCp.ptr = (char *)cmd->SCp.buffer->address;
-+#endif
-       cmd->SCp.this_residual = cmd->SCp.buffer->length;
-       }
-    else {
-@@ -762,7 +766,11 @@
-       ++cmd->SCp.buffer;
-       --cmd->SCp.buffers_residual;
-       cmd->SCp.this_residual = cmd->SCp.buffer->length;
+@@ -786,7 +794,11 @@ static void nsp_pio_write(Scsi_Cmnd *SCp
+                       //DEBUG(0, " scatterlist next\n");
+                       SCpnt->SCp.buffers_residual--;
+                       SCpnt->SCp.buffer++;
 +#if SMALL_SCATTERLIST
-+      cmd->SCp.ptr = cmd->SCp.buffer->u.address;
++                      SCpnt->SCp.ptr           = SCpnt->SCp.buffer->u.address;
 +#else
-       cmd->SCp.ptr = cmd->SCp.buffer->address;
+                       SCpnt->SCp.ptr           = SCpnt->SCp.buffer->address;
 +#endif
-       }
+                       SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;
+               }
  
- /* Set up hardware registers */
-Index: linux-2.4.21/drivers/scsi/NCR5380.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/NCR5380.c   2003-06-13 10:51:36.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/NCR5380.c        2005-06-01 23:07:51.124574296 -0400
-@@ -337,7 +337,11 @@
-       if (cmd->use_sg) {
-               cmd->SCp.buffer = (struct scatterlist *) cmd->buffer;
-               cmd->SCp.buffers_residual = cmd->use_sg - 1;
-+#if SMALL_SCATTERLIST
-+              cmd->SCp.ptr = (char *) cmd->SCp.buffer->u.address;
-+#else
-               cmd->SCp.ptr = (char *) cmd->SCp.buffer->address;
-+#endif
+diff -X dontdiff -urp kern_oldest/drivers/scsi/ppa.c kern_fix/drivers/scsi/ppa.c
+--- kern_oldest/drivers/scsi/ppa.c     2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/ppa.c        2006-05-01 14:14:13.000000000 -0700
+@@ -740,7 +740,11 @@ static int ppa_completion(Scsi_Cmnd * cm
+           if (cmd->SCp.buffers_residual--) {
+               cmd->SCp.buffer++;
                cmd->SCp.this_residual = cmd->SCp.buffer->length;
-       } else {
-               cmd->SCp.buffer = NULL;
-@@ -2308,7 +2312,11 @@
-                                       ++cmd->SCp.buffer;
-                                       --cmd->SCp.buffers_residual;
-                                       cmd->SCp.this_residual = cmd->SCp.buffer->length;
-+#if SMALL_SCATTERLIST
-+                                      cmd->SCp.ptr = cmd->SCp.buffer->u.address;
-+#else
-                                       cmd->SCp.ptr = cmd->SCp.buffer->address;
-+#endif
-                                       dprintk(NDEBUG_INFORMATION, ("scsi%d : %d bytes and %d buffers left\n", instance->host_no, cmd->SCp.this_residual, cmd->SCp.buffers_residual));
-                               }
-                               /*
-Index: linux-2.4.21/drivers/scsi/NCR53c406a.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/NCR53c406a.c        2001-09-30 15:26:07.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/NCR53c406a.c     2005-06-01 23:07:51.125574144 -0400
-@@ -895,7 +895,11 @@
-                 sgcount = current_SC->use_sg;
-                 sglist = current_SC->request_buffer;
-                 while( sgcount-- ) {
-+#if SMALL_SCATTERLIST
-+                    NCR53c406a_pio_write(sglist->u.address, sglist->length);
-+#else
-                     NCR53c406a_pio_write(sglist->address, sglist->length);
-+#endif
-                     sglist++;
-                 }
-             }
-@@ -924,7 +928,11 @@
-                 sgcount = current_SC->use_sg;
-                 sglist = current_SC->request_buffer;
-                 while( sgcount-- ) {
 +#if SMALL_SCATTERLIST
-+                    NCR53c406a_pio_read(sglist->u.address, sglist->length);
-+#else
-                     NCR53c406a_pio_read(sglist->address, sglist->length);
-+#endif
-                     sglist++;
-                 }
-             }
-Index: linux-2.4.21/drivers/scsi/sym53c416.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/sym53c416.c 2001-09-30 15:26:07.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/sym53c416.c      2005-06-01 23:07:51.126573992 -0400
-@@ -448,7 +448,11 @@
-                                       sglist = current_command->request_buffer;
-                                       while(sgcount--)
-                                       {
-+#if SMALL_SCATTERLIST
-+                                              tot_trans += sym53c416_write(base, sglist->u.address, sglist->length);
-+#else
-                                               tot_trans += sym53c416_write(base, sglist->address, sglist->length);
-+#endif
-                                               sglist++;
-                                       }
-                               }
-@@ -474,7 +478,11 @@
-                                       sglist = current_command->request_buffer;
-                                       while(sgcount--)
-                                       {
-+#if SMALL_SCATTERLIST
-+                                              tot_trans += sym53c416_read(base, sglist->u.address, sglist->length);
++              cmd->SCp.ptr = cmd->SCp.buffer->u.address;
 +#else
-                                               tot_trans += sym53c416_read(base, sglist->address, sglist->length);
-+#endif
-                                               sglist++;
-                                       }
-                               }
-Index: linux-2.4.21/drivers/scsi/qlogicfas.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/qlogicfas.c 2003-06-13 10:51:36.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/qlogicfas.c      2005-06-01 23:07:51.126573992 -0400
-@@ -393,7 +393,11 @@
-                                       REG0;
-                                       return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16);
-                               }
+               cmd->SCp.ptr = cmd->SCp.buffer->address;
++#endif
+           }
+       }
+       /* Now check to see if the drive is ready to comunicate */
+@@ -925,7 +929,11 @@ static int ppa_engine(ppa_struct * tmp, 
+           /* if many buffers are available, start filling the first */
+           cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer;
+           cmd->SCp.this_residual = cmd->SCp.buffer->length;
 +#if SMALL_SCATTERLIST
-+                              if (ql_pdma(phase, sglist->u.address, sglist->length))
++          cmd->SCp.ptr = cmd->SCp.buffer->u.address;
 +#else
-                               if (ql_pdma(phase, sglist->address, sglist->length))
+           cmd->SCp.ptr = cmd->SCp.buffer->address;
 +#endif
-                                       break;
-                               sglist++;
-                       }
-Index: linux-2.4.21/drivers/scsi/qla1280.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/qla1280.c   2001-09-30 15:26:07.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/qla1280.c        2005-06-01 23:07:51.131573232 -0400
-@@ -3985,8 +3985,13 @@
+       } else {
+           /* else fill the only available buffer */
+           cmd->SCp.buffer = NULL;
+diff -X dontdiff -urp kern_oldest/drivers/scsi/qla1280.c kern_fix/drivers/scsi/qla1280.c
+--- kern_oldest/drivers/scsi/qla1280.c 2006-05-01 11:55:41.000000000 -0700
++++ kern_fix/drivers/scsi/qla1280.c    2006-05-01 14:14:13.000000000 -0700
+@@ -3985,8 +3985,13 @@ qla1280_64bit_start_scsi(scsi_qla_host_t
                      {
                          DEBUG(sprintf(debug_buff,"SG Segment ap=0x%p, len=0x%x\n\r",sg->address,sg->length));
                          DEBUG(qla1280_print(debug_buff));
@@ -2172,7 +2619,7 @@ Index: linux-2.4.21/drivers/scsi/qla1280.c
                          *dword_ptr++ = sg->length;
                          sg++;
                      }
-@@ -4038,8 +4043,13 @@
+@@ -4038,8 +4043,13 @@ qla1280_64bit_start_scsi(scsi_qla_host_t
                          /* Load continuation entry data segments. */
                          for (cnt = 0; cnt < 5 && seg_cnt; cnt++, seg_cnt--)
                          {
@@ -2186,7 +2633,7 @@ Index: linux-2.4.21/drivers/scsi/qla1280.c
                              *dword_ptr++ = sg->length;
                              sg++;
                          }
-@@ -4325,7 +4335,11 @@
+@@ -4325,7 +4335,11 @@ qla1280_32bit_start_scsi(scsi_qla_host_t
                      /* Load command entry data segments. */
                      for (cnt = 0; cnt < 4 && seg_cnt; cnt++, seg_cnt--)
                      {
@@ -2198,7 +2645,7 @@ Index: linux-2.4.21/drivers/scsi/qla1280.c
                          *dword_ptr++ = sg->length;
                          DEBUG(sprintf(debug_buff,"SG Segment ap=0x%p, len=0x%x\n\r",sg->address,sg->length));
                          DEBUG(qla1280_print(debug_buff));
-@@ -4368,7 +4382,11 @@
+@@ -4368,7 +4382,11 @@ qla1280_32bit_start_scsi(scsi_qla_host_t
                          /* Load continuation entry data segments. */
                          for (cnt = 0; cnt < 7 && seg_cnt; cnt++, seg_cnt--)
                          {
@@ -2210,154 +2657,98 @@ Index: linux-2.4.21/drivers/scsi/qla1280.c
                              *dword_ptr++ = sg->length;
                              sg++;
                          }
-Index: linux-2.4.21/drivers/scsi/seagate.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/seagate.c   2005-06-01 22:51:40.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/seagate.c        2005-06-01 23:07:51.133572928 -0400
-@@ -1070,7 +1070,11 @@
-                       buffer = (struct scatterlist *) SCint->buffer;
-                       len = buffer->length;
-+#if SMALL_SCATTERLIST
-+                      data = (unsigned char *) buffer->u.address;
-+#else
-                       data = (unsigned char *) buffer->address;
-+#endif
-               } else {
-                       DPRINTK (DEBUG_SG,
-                                "scsi%d : scatter gather not requested.\n",
-@@ -1337,7 +1341,11 @@
-                                       ++buffer;
-                                       len = buffer->length;
-                                       data =
--                                          (unsigned char *) buffer->address;
-+#if SMALL_SCATTERLIST
-+                                          (unsigned char *)buffer->u.address;
-+#else
-+                                          (unsigned char *)buffer->address;
-+#endif
-                                       DPRINTK (DEBUG_SG,
-                                                "scsi%d : next scatter-gather buffer len = %d address = %08x\n",
-                                                hostno, len, data);
-@@ -1521,7 +1529,11 @@
-                                       ++buffer;
-                                       len = buffer->length;
-                                       data =
-+#if SMALL_SCATTERLIST
-+                                          (unsigned char *)buffer->u.address;
-+#else
-                                           (unsigned char *) buffer->address;
-+#endif
-                                       DPRINTK (DEBUG_SG,
-                                                "scsi%d : next scatter-gather buffer len = %d address = %08x\n",
-                                                hostno, len, data);
-Index: linux-2.4.21/drivers/scsi/53c7,8xx.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/53c7,8xx.c  2002-02-25 14:38:04.000000000 -0500
-+++ linux-2.4.21/drivers/scsi/53c7,8xx.c       2005-06-01 23:07:51.137572320 -0400
-@@ -3787,7 +3787,11 @@
-     for (i = 0; cmd->use_sg ? (i < cmd->use_sg) : !i; cmd_datain += 4, 
-       cmd_dataout += 4, ++i) {
-       u32 buf = cmd->use_sg ? 
-+#if SMALL_SCATTERLIST
-+          virt_to_bus(((struct scatterlist *)cmd->buffer)[i].u.address) :
-+#else
-           virt_to_bus(((struct scatterlist *)cmd->buffer)[i].address) :
-+#endif
-           virt_to_bus(cmd->request_buffer);
-       u32 count = cmd->use_sg ?
-           ((struct scatterlist *)cmd->buffer)[i].length :
-@@ -5752,8 +5756,13 @@
-           if ((buffers = cmd->use_sg)) {
-               for (offset = 0, 
-                       segment = (struct scatterlist *) cmd->buffer;
+diff -X dontdiff -urp kern_oldest/drivers/scsi/qlogicfas.c kern_fix/drivers/scsi/qlogicfas.c
+--- kern_oldest/drivers/scsi/qlogicfas.c       2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/qlogicfas.c  2006-05-01 14:14:13.000000000 -0700
+@@ -393,7 +393,11 @@ rtrc(2)
+                                       REG0;
+                                       return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16);
+                               }
 +#if SMALL_SCATTERLIST
-+                   buffers && !((found = ((ptr >= segment->u.address) && 
-+                          (ptr < (segment->u.address + segment->length)))));
++                              if (ql_pdma(phase, sglist->u.address, sglist->length))
 +#else
-                    buffers && !((found = ((ptr >= segment->address) && 
-                           (ptr < (segment->address + segment->length)))));
+                               if (ql_pdma(phase, sglist->address, sglist->length))
 +#endif
-                    --buffers, offset += segment->length, ++segment)
- #if 0
-                   printk("scsi%d: comparing 0x%p to 0x%p\n", 
-@@ -5761,7 +5770,11 @@
- #else
-                   ;
- #endif
-+#if SMALL_SCATTERLIST
-+                  offset += ptr - segment->u.address;
+                                       break;
+                               sglist++;
+                       }
+diff -X dontdiff -urp kern_oldest/drivers/scsi/scsi_debug.c kern_fix/drivers/scsi/scsi_debug.c
+--- kern_oldest/drivers/scsi/scsi_debug.c      2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/scsi_debug.c 2006-05-01 14:14:13.000000000 -0700
+@@ -186,7 +186,13 @@ int scsi_debug_queuecommand(Scsi_Cmnd * 
+               struct scatterlist *sgpnt = (struct scatterlist *)
+                                               SCpnt->request_buffer;
++#if SMALL_SCATTERLIST         
++              if (sgpnt[0].ispaged)
++                 BUG();
++              buff = sgpnt[0].u.address;
 +#else
-                   offset += ptr - segment->address;
+               buff = sgpnt[0].address;
 +#endif
-           } else {
-               found = 1;
-               offset = ptr - (char *) (cmd->request_buffer);
-Index: linux-2.4.21/drivers/scsi/eata_dma.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/eata_dma.c  2005-06-01 22:52:05.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/eata_dma.c       2005-06-01 23:07:51.138572168 -0400
-@@ -571,7 +571,11 @@
-       ccb->cp_datalen = htonl(cmd->use_sg * sizeof(struct eata_sg_list));
-       sl=(struct scatterlist *)cmd->request_buffer;
-       for(i = 0; i < cmd->use_sg; i++, sl++){
+               bufflen = sgpnt[0].length;
+               /* READ and WRITE process scatterlist themselves */
+       }
+@@ -672,7 +678,13 @@ static int resp_read(Scsi_Cmnd * SCpnt, 
+       if (SCpnt->use_sg) {
+               sgcount = 0;
+               sgpnt = (struct scatterlist *) buff;
 +#if SMALL_SCATTERLIST
-+          ccb->sg_list[i].data = htonl(virt_to_bus(sl->u.address));
++              if (sgpnt[sgcount].ispaged)
++                 BUG();
++              buff = sgpnt[sgcount].u.address;
 +#else
-           ccb->sg_list[i].data = htonl(virt_to_bus(sl->address));
+               buff = sgpnt[sgcount].address;
 +#endif
-           ccb->sg_list[i].len = htonl((u32) sl->length);
+               bufflen = sgpnt[sgcount].length;
        }
-     } else {
-Index: linux-2.4.21/drivers/scsi/eata_pio.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/eata_pio.c  2001-09-30 15:26:07.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/eata_pio.c       2005-06-01 23:07:51.139572016 -0400
-@@ -99,7 +99,11 @@
-       else
-       {
-           SCp->buffer++;
+       do {
+@@ -682,7 +694,13 @@ static int resp_read(Scsi_Cmnd * SCpnt, 
+                       block += bufflen >> POW2_SECT_SIZE;
+                       sgcount++;
+                       if (nbytes) {
 +#if SMALL_SCATTERLIST
-+          SCp->ptr=SCp->buffer->u.address;
++                              if (sgpnt[sgcount].ispaged)
++                                      BUG();
++                              buff = sgpnt[sgcount].u.address;
 +#else
-           SCp->ptr=SCp->buffer->address;
+                               buff = sgpnt[sgcount].address;
 +#endif
-           SCp->this_residual=SCp->buffer->length;
-       }
-     }
-@@ -371,7 +375,11 @@
-     } else {
-       cmd->SCp.buffer = cmd->request_buffer;
-       cmd->SCp.buffers_residual = cmd->use_sg;
+                               bufflen = sgpnt[sgcount].length;
+                       }
+               } else if (nbytes > 0)
+@@ -713,7 +731,13 @@ static int resp_write(Scsi_Cmnd * SCpnt,
+       if (SCpnt->use_sg) {
+               sgcount = 0;
+               sgpnt = (struct scatterlist *) buff;
 +#if SMALL_SCATTERLIST
-+      cmd->SCp.ptr = cmd->SCp.buffer->u.address;
++              if (sgpnt[sgcount].ispaged)
++                      BUG();
++              buff = sgpnt[sgcount].u.address;
 +#else
-       cmd->SCp.ptr = cmd->SCp.buffer->address;
+               buff = sgpnt[sgcount].address;
 +#endif
-       cmd->SCp.this_residual = cmd->SCp.buffer->length;
-     }
-     cmd->SCp.Status = (cmd->SCp.this_residual != 0);  /* TRUE as long as bytes 
-Index: linux-2.4.21/drivers/scsi/wd7000.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/wd7000.c    2001-09-30 15:26:08.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/wd7000.c 2005-06-01 23:07:51.140571864 -0400
-@@ -1189,7 +1189,11 @@
-       any2scsi (scb->maxlen, SCpnt->use_sg * sizeof (Sgb));
-       for (i = 0; i < SCpnt->use_sg; i++) {
+               bufflen = sgpnt[sgcount].length;
+       }
+       do {
+@@ -724,7 +748,13 @@ static int resp_write(Scsi_Cmnd * SCpnt,
+                       block += bufflen >> POW2_SECT_SIZE;
+                       sgcount++;
+                       if (nbytes) {
 +#if SMALL_SCATTERLIST
-+          any2scsi (sgb[i].ptr, (int) sg[i].u.address);
++                              if (sgpnt[sgcount].ispaged)
++                                      BUG();
++                              buff = sgpnt[sgcount].u.address;
 +#else
-           any2scsi (sgb[i].ptr, (int) sg[i].address);
+                               buff = sgpnt[sgcount].address;
 +#endif
-           any2scsi (sgb[i].len, sg[i].length);
-       }
-     }
-Index: linux-2.4.21/drivers/scsi/scsiiom.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/scsiiom.c   2000-12-31 14:06:00.000000000 -0500
-+++ linux-2.4.21/drivers/scsi/scsiiom.c        2005-06-01 23:07:51.142571560 -0400
-@@ -379,7 +379,11 @@
+                               bufflen = sgpnt[sgcount].length;
+                       }
+               } else if (nbytes > 0)
+diff -X dontdiff -urp kern_oldest/drivers/scsi/scsiiom.c kern_fix/drivers/scsi/scsiiom.c
+--- kern_oldest/drivers/scsi/scsiiom.c 2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/scsiiom.c    2006-05-01 14:14:13.000000000 -0700
+@@ -379,7 +379,11 @@ dc390_DataOut_0( PACB pACB, PSRB pSRB, P
                pSRB->pSegmentList++;
                psgl = pSRB->pSegmentList;
  
@@ -2369,7 +2760,7 @@ Index: linux-2.4.21/drivers/scsi/scsiiom.c
                pSRB->SGToBeXferLen = (ULONG) psgl->length;
            }
            else
-@@ -443,7 +447,11 @@
+@@ -443,7 +447,11 @@ dc390_DataIn_0( PACB pACB, PSRB pSRB, PU
                pSRB->pSegmentList++;
                psgl = pSRB->pSegmentList;
  
@@ -2381,7 +2772,7 @@ Index: linux-2.4.21/drivers/scsi/scsiiom.c
                pSRB->SGToBeXferLen = (ULONG) psgl->length;
            }
            else
-@@ -742,7 +750,11 @@
+@@ -742,7 +750,11 @@ dc390_restore_ptr (PACB pACB, PSRB pSRB)
              pSRB->pSegmentList++;
              psgl = pSRB->pSegmentList;
              
@@ -2393,7 +2784,7 @@ Index: linux-2.4.21/drivers/scsi/scsiiom.c
              pSRB->SGToBeXferLen = (ULONG) psgl->length;
            }
          else
-@@ -756,10 +768,17 @@
+@@ -756,10 +768,17 @@ dc390_restore_ptr (PACB pACB, PSRB pSRB)
      {
        pSRB->SGcount = 1;
        pSRB->pSegmentList = (PSGL) &pSRB->Segmentx;
@@ -2408,377 +2799,539 @@ Index: linux-2.4.21/drivers/scsi/scsiiom.c
        printk (KERN_INFO "DC390: Pointer restored. Total %li, Bus %p\n",
                pSRB->Saved_Ptr, pSRB->Segmentx.address);
 +#endif
-     }
-      else
-        {
-@@ -893,7 +912,11 @@
-       if( !pSRB->SGToBeXferLen )
+     }
+      else
+        {
+@@ -893,7 +912,11 @@ dc390_DataIO_Comm( PACB pACB, PSRB pSRB,
+       if( !pSRB->SGToBeXferLen )
+       {
+           psgl = pSRB->pSegmentList;
++#if SMALL_SCATTERLIST
++          pSRB->SGBusAddr = virt_to_bus( psgl->u.address );
++#else
+           pSRB->SGBusAddr = virt_to_bus( psgl->address );
++#endif
+           pSRB->SGToBeXferLen = (ULONG) psgl->length;
+           DEBUG1(printk (KERN_DEBUG " DC390: Next SG segment.");)
+       }
+@@ -1368,7 +1391,11 @@ dc390_SRBdone( PACB pACB, PDCB pDCB, PSR
+     status = pSRB->TargetStatus;
+     ptr = (PSCSI_INQDATA) (pcmd->request_buffer);
+     if( pcmd->use_sg )
++#if SMALL_SCATTERLIST
++      ptr = (PSCSI_INQDATA) (((PSGL) ptr)->u.address);
++#else
+       ptr = (PSCSI_INQDATA) (((PSGL) ptr)->address);
++#endif
+       
+     DEBUG0(printk (" SRBdone (%02x,%08x), SRB %p, pid %li\n", status, pcmd->result,\
+               pSRB, pcmd->pid);)
+@@ -1443,7 +1470,11 @@ dc390_SRBdone( PACB pACB, PDCB pDCB, PSR
+           else if( pcmd->request_buffer )
+           {
+               pSRB->pSegmentList = (PSGL) &pSRB->Segmentx;
++#if SMALL_SCATTERLIST
++              pSRB->Segmentx.u.address = (PUCHAR) pcmd->request_buffer;
++#else
+               pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer;
++#endif
+               pSRB->Segmentx.length = pcmd->request_bufflen;
+           }
+           if( dc390_StartSCSI( pACB, pDCB, pSRB ) ) {
+@@ -1518,7 +1549,11 @@ dc390_SRBdone( PACB pACB, PDCB pDCB, PSR
+               else if( pcmd->request_buffer )
+               {
+                   pSRB->pSegmentList = (PSGL) &pSRB->Segmentx;
++#if SMALL_SCATTERLIST
++                  pSRB->Segmentx.u.address = (PUCHAR) pcmd->request_buffer;
++#else
+                   pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer;
++#endif
+                   pSRB->Segmentx.length = pcmd->request_bufflen;
+               }
+               if( dc390_StartSCSI( pACB, pDCB, pSRB ) ) {
+@@ -1759,7 +1794,11 @@ dc390_RequestSense( PACB pACB, PDCB pDCB
+     pcmd = pSRB->pcmd;
++#if SMALL_SCATTERLIST
++    pSRB->Segmentx.u.address = (PUCHAR) &(pcmd->sense_buffer);
++#else
+     pSRB->Segmentx.address = (PUCHAR) &(pcmd->sense_buffer);
++#endif
+     pSRB->Segmentx.length = sizeof(pcmd->sense_buffer);
+     pSRB->pSegmentList = &pSRB->Segmentx;
+     pSRB->SGcount = 1;
+diff -X dontdiff -urp kern_oldest/drivers/scsi/scsi_lib.c kern_fix/drivers/scsi/scsi_lib.c
+--- kern_oldest/drivers/scsi/scsi_lib.c        2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/scsi_lib.c   2006-05-01 14:14:13.000000000 -0700
+@@ -553,7 +553,13 @@ static void scsi_release_buffers(Scsi_Cm
+               if (bbpnt) {
+                       for (i = 0; i < SCpnt->use_sg; i++) {
+                               if (bbpnt[i])
++#if SMALL_SCATTERLIST
++                                      if (sgpnt[i].ispaged)
++                                              BUG();
++                                      scsi_free(sgpnt[i].u.address, sgpnt[i].length);
++#else
+                                       scsi_free(sgpnt[i].address, sgpnt[i].length);
++#endif
+                       }
+               }
+               scsi_free(SCpnt->request_buffer, SCpnt->sglist_len);
+@@ -629,12 +635,23 @@ void scsi_io_completion(Scsi_Cmnd * SCpn
+               if (bbpnt) {
+                       for (i = 0; i < SCpnt->use_sg; i++) {
+                               if (bbpnt[i]) {
++#if SMALL_SCATTERLIST
++                                      if (sgpnt[i].ispaged)
++                                              BUG();
++                                      if (req->cmd == READ) {
++                                              memcpy(bbpnt[i],
++                                                     sgpnt[i].u.address,
++                                                     sgpnt[i].length);
++                                      }
++                                      scsi_free(sgpnt[i].u.address, sgpnt[i].length);
++#else
+                                       if (req->cmd == READ) {
+                                               memcpy(bbpnt[i],
+                                                      sgpnt[i].address,
+                                                      sgpnt[i].length);
+                                       }
+                                       scsi_free(sgpnt[i].address, sgpnt[i].length);
++#endif
+                               }
+                       }
+               }
+diff -X dontdiff -urp kern_oldest/drivers/scsi/scsi_merge.c kern_fix/drivers/scsi/scsi_merge.c
+--- kern_oldest/drivers/scsi/scsi_merge.c      2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/scsi_merge.c 2006-05-01 14:14:13.000000000 -0700
+@@ -144,11 +144,21 @@ static void dma_exhausted(Scsi_Cmnd * SC
+        */
+       for(jj=0; jj < SCpnt->use_sg; jj++)
        {
-           psgl = pSRB->pSegmentList;
 +#if SMALL_SCATTERLIST
-+          pSRB->SGBusAddr = virt_to_bus( psgl->u.address );
++              if (sgpnt[jj].ispaged)
++                      BUG();
++              printk("[%d]\tlen:%d\taddr:%p\tbounce:%p\n",
++                     jj,
++                     sgpnt[jj].length,
++                     sgpnt[jj].u.address,
++                     (bbpnt ? bbpnt[jj] : NULL));
 +#else
-           pSRB->SGBusAddr = virt_to_bus( psgl->address );
+               printk("[%d]\tlen:%d\taddr:%p\tbounce:%p\n",
+                      jj,
+                      sgpnt[jj].length,
+                      sgpnt[jj].address,
+                      (bbpnt ? bbpnt[jj] : NULL));
 +#endif
-           pSRB->SGToBeXferLen = (ULONG) psgl->length;
-           DEBUG1(printk (KERN_DEBUG " DC390: Next SG segment.");)
+               if (bbpnt && bbpnt[jj])
+                       consumed += sgpnt[jj].length;
        }
-@@ -1368,7 +1391,11 @@
-     status = pSRB->TargetStatus;
-     ptr = (PSCSI_INQDATA) (pcmd->request_buffer);
-     if( pcmd->use_sg )
+@@ -612,6 +622,9 @@ __inline static int __scsi_merge_request
+               max_segments = scsi_max_sg;
+ #ifdef DMA_CHUNK_SIZE
++# if SMALL_SCATTERLIST
++#  error "This defeats the purpose of SMALL_SCATTERLIST"
++# endif
+       if (max_segments > 64)
+               max_segments = 64;
+@@ -929,15 +942,26 @@ __inline static int __init_io(Scsi_Cmnd 
+               }
+               if (SCpnt->host->highmem_io) {
 +#if SMALL_SCATTERLIST
-+      ptr = (PSCSI_INQDATA) (((PSGL) ptr)->u.address);
++                      sgpnt[count].ispaged = 1;
++                      sgpnt[count].u.page.page = bh->b_page;
++                      sgpnt[count].u.page.offset = bh_offset(bh);
 +#else
-       ptr = (PSCSI_INQDATA) (((PSGL) ptr)->address);
+                       sgpnt[count].page = bh->b_page;
+                       sgpnt[count].offset = bh_offset(bh);
+                       sgpnt[count].address = NULL;
 +#endif
-       
-     DEBUG0(printk (" SRBdone (%02x,%08x), SRB %p, pid %li\n", status, pcmd->result,\
-               pSRB, pcmd->pid);)
-@@ -1443,7 +1470,11 @@
-           else if( pcmd->request_buffer )
-           {
-               pSRB->pSegmentList = (PSGL) &pSRB->Segmentx;
+               } else {
+                       if (PageHighMem(bh->b_page))
+                               BUG();
 +#if SMALL_SCATTERLIST
-+              pSRB->Segmentx.u.address = (PUCHAR) pcmd->request_buffer;
++                      sgpnt[count].ispaged = 0;
++                      sgpnt[count].u.address = bh->b_data;
 +#else
-               pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer;
+                       sgpnt[count].page = NULL;
+                       sgpnt[count].address = bh->b_data;
 +#endif
-               pSRB->Segmentx.length = pcmd->request_bufflen;
-           }
-           if( dc390_StartSCSI( pACB, pDCB, pSRB ) ) {
-@@ -1518,7 +1549,11 @@
-               else if( pcmd->request_buffer )
-               {
-                   pSRB->pSegmentList = (PSGL) &pSRB->Segmentx;
+               }
+               
+               sgpnt[count].length = bh->b_size;
+@@ -972,6 +996,50 @@ __inline static int __init_io(Scsi_Cmnd 
+                * only done for dma_host, in which case .page is not
+                * set since it's guarenteed to be a low memory page
+                */
 +#if SMALL_SCATTERLIST
-+                  pSRB->Segmentx.u.address = (PUCHAR) pcmd->request_buffer;
++              if (sgpnt[i].ispaged)
++                      BUG();
++              if (virt_to_phys(sgpnt[i].u.address) + sgpnt[i].length - 1 >
++                  ISA_DMA_THRESHOLD) {
++                      if( scsi_dma_free_sectors - sectors <= 10  ) {
++                              /*
++                               * If this would nearly drain the DMA
++                               * pool empty, then let's stop here.
++                               * Don't make this request any larger.
++                               * This is kind of a safety valve that
++                               * we use - we could get screwed later
++                               * on if we run out completely.  
++                               */
++                              SCpnt->request_bufflen -= sgpnt[i].length;
++                              SCpnt->use_sg = i;
++                              if (i == 0) {
++                                      goto big_trouble;
++                              }
++                              break;
++                      }
++
++                      bbpnt[i] = sgpnt[i].u.address;
++                      sgpnt[i].u.address =
++                          (char *) scsi_malloc(sgpnt[i].length);
++                      /*
++                       * If we cannot allocate memory for this DMA bounce
++                       * buffer, then queue just what we have done so far.
++                       */
++                      if (sgpnt[i].u.address == NULL) {
++                              printk("Warning - running low on DMA memory\n");
++                              SCpnt->request_bufflen -= sgpnt[i].length;
++                              SCpnt->use_sg = i;
++                              if (i == 0) {
++                                      goto big_trouble;
++                              }
++                              break;
++                      }
++                      if (req->cmd == WRITE) {
++                              memcpy(sgpnt[i].u.address, bbpnt[i],
++                                     sgpnt[i].length);
++                      }
++              }
 +#else
-                   pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer;
-+#endif
-                   pSRB->Segmentx.length = pcmd->request_bufflen;
+               if (virt_to_phys(sgpnt[i].address) + sgpnt[i].length - 1 >
+                   ISA_DMA_THRESHOLD) {
+                       if( scsi_dma_free_sectors - sectors <= 10  ) {
+@@ -1012,6 +1080,7 @@ __inline static int __init_io(Scsi_Cmnd 
+                                      sgpnt[i].length);
+                       }
                }
-               if( dc390_StartSCSI( pACB, pDCB, pSRB ) ) {
-@@ -1759,7 +1794,11 @@
++#endif
+       }
+       return 1;
  
-     pcmd = pSRB->pcmd;
+diff -X dontdiff -urp kern_oldest/drivers/scsi/seagate.c kern_fix/drivers/scsi/seagate.c
+--- kern_oldest/drivers/scsi/seagate.c 2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/seagate.c    2006-05-01 14:14:13.000000000 -0700
+@@ -1070,7 +1070,11 @@ static int internal_command (unsigned ch
  
+                       buffer = (struct scatterlist *) SCint->buffer;
+                       len = buffer->length;
 +#if SMALL_SCATTERLIST
-+    pSRB->Segmentx.u.address = (PUCHAR) &(pcmd->sense_buffer);
++                      data = (unsigned char *) buffer->u.address;
 +#else
-     pSRB->Segmentx.address = (PUCHAR) &(pcmd->sense_buffer);
+                       data = (unsigned char *) buffer->address;
 +#endif
-     pSRB->Segmentx.length = sizeof(pcmd->sense_buffer);
-     pSRB->pSegmentList = &pSRB->Segmentx;
-     pSRB->SGcount = 1;
-Index: linux-2.4.21/drivers/scsi/tmscsim.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/tmscsim.c   2001-12-21 12:41:55.000000000 -0500
-+++ linux-2.4.21/drivers/scsi/tmscsim.c        2005-06-01 23:07:51.144571256 -0400
-@@ -1146,7 +1146,11 @@
-     {
-       pSRB->SGcount = 1;
-       pSRB->pSegmentList = (PSGL) &pSRB->Segmentx;
+               } else {
+                       DPRINTK (DEBUG_SG,
+                                "scsi%d : scatter gather not requested.\n",
+@@ -1337,7 +1341,11 @@ static int internal_command (unsigned ch
+                                       ++buffer;
+                                       len = buffer->length;
+                                       data =
+-                                          (unsigned char *) buffer->address;
 +#if SMALL_SCATTERLIST
-+      pSRB->Segmentx.u.address = (PUCHAR) pcmd->request_buffer;
++                                          (unsigned char *)buffer->u.address;
 +#else
-       pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer;
++                                          (unsigned char *)buffer->address;
 +#endif
-       pSRB->Segmentx.length = pcmd->request_bufflen;
-     }
-     else
-Index: linux-2.4.21/drivers/scsi/AM53C974.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/AM53C974.c  2001-09-30 15:26:07.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/AM53C974.c       2005-06-01 23:07:51.146570952 -0400
-@@ -842,7 +842,11 @@
-       if (cmd->use_sg) {
-               cmd->SCp.buffer = (struct scatterlist *) cmd->buffer;
-               cmd->SCp.buffers_residual = cmd->use_sg - 1;
+                                       DPRINTK (DEBUG_SG,
+                                                "scsi%d : next scatter-gather buffer len = %d address = %08x\n",
+                                                hostno, len, data);
+@@ -1521,7 +1529,11 @@ static int internal_command (unsigned ch
+                                       ++buffer;
+                                       len = buffer->length;
+                                       data =
 +#if SMALL_SCATTERLIST
-+              cmd->SCp.ptr = (char *) cmd->SCp.buffer->u.address;
++                                          (unsigned char *)buffer->u.address;
 +#else
-               cmd->SCp.ptr = (char *) cmd->SCp.buffer->address;
+                                           (unsigned char *) buffer->address;
 +#endif
-               cmd->SCp.this_residual = cmd->SCp.buffer->length;
-       } else {
-               cmd->SCp.buffer = NULL;
-@@ -1555,7 +1559,11 @@
-               if ((!cmd->SCp.this_residual) && cmd->SCp.buffers_residual) {
-                       cmd->SCp.buffer++;
-                       cmd->SCp.buffers_residual--;
+                                       DPRINTK (DEBUG_SG,
+                                                "scsi%d : next scatter-gather buffer len = %d address = %08x\n",
+                                                hostno, len, data);
+diff -X dontdiff -urp kern_oldest/drivers/scsi/sg.c kern_fix/drivers/scsi/sg.c
+--- kern_oldest/drivers/scsi/sg.c      2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/sg.c 2006-05-01 14:14:13.000000000 -0700
+@@ -1077,7 +1077,11 @@ static void sg_rb_correct4mmap(Sg_scatte
+         for (k = 0; k < rsv_schp->k_use_sg; ++k, ++sclp) {
+           for (m = PAGE_SIZE; m < sclp->length; m += PAGE_SIZE) {
 +#if SMALL_SCATTERLIST
-+                      cmd->SCp.ptr = (unsigned char *) cmd->SCp.buffer->u.address;
++              page_ptr = (unsigned char *)sclp->u.address + m;
 +#else
-                       cmd->SCp.ptr = (unsigned char *) cmd->SCp.buffer->address;
+               page_ptr = (unsigned char *)sclp->address + m;
 +#endif
-                       cmd->SCp.this_residual = cmd->SCp.buffer->length;
-               }
-               if (cmd->SCp.this_residual) {
-Index: linux-2.4.21/drivers/scsi/megaraid2.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/megaraid2.c 2005-06-01 22:51:54.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/megaraid2.c      2005-06-01 23:07:51.149570496 -0400
-@@ -2180,7 +2180,11 @@
-                       if( cmd->use_sg ) {
-                               sgl = (struct scatterlist *)
-                                       cmd->request_buffer;
+               page = virt_to_page(page_ptr);
+               if (startFinish)
+                   get_page(page);     /* increment page count */
+@@ -1130,7 +1134,11 @@ static struct page * sg_vma_nopage(struc
+             len = vma->vm_end - sa;
+             len = (len < sclp->length) ? len : sclp->length;
+           if (offset < len) {
 +#if SMALL_SCATTERLIST
-+                              c = *(u8 *)sgl[0].u.address;
++              page_ptr = (unsigned char *)sclp->u.address + offset;
 +#else
-                               c = *(u8 *)sgl[0].address;
+               page_ptr = (unsigned char *)sclp->address + offset;
 +#endif
-                       }
-                       else {
-                               c = *(u8 *)cmd->request_buffer;
-Index: linux-2.4.21/drivers/scsi/megaraid.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/megaraid.c  2005-06-01 22:51:54.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/megaraid.c       2005-06-01 23:07:51.152570040 -0400
-@@ -1201,8 +1201,13 @@
-       case READ_CAPACITY:
-               if ( SCpnt->use_sg ) {
-                       sgList = (struct scatterlist *)SCpnt->request_buffer;
+               page = virt_to_page(page_ptr);
+               get_page(page); /* increment page count */
+               break;
+@@ -1175,8 +1183,13 @@ static int sg_mmap(struct file * filp, s
+       for (k = 0; (k < rsv_schp->k_use_sg) && (sa < vma->vm_end); 
+            ++k, ++sclp) {
 +#if SMALL_SCATTERLIST
-+                      memcpy(sgList[0].u.address, pScb->bounce_buffer,
-+                             SCpnt->request_bufflen);
++          if ((unsigned long)sclp->u.address & (PAGE_SIZE - 1))
++              return -EFAULT;     /* non page aligned memory ?? */
 +#else
-                       memcpy(sgList[0].address, pScb->bounce_buffer,
--                                                      SCpnt->request_bufflen);
-+                             SCpnt->request_bufflen);
+           if ((unsigned long)sclp->address & (PAGE_SIZE - 1))
+               return -EFAULT;     /* non page aligned memory ?? */
++#endif
+           len = vma->vm_end - sa;
+           len = (len < sclp->length) ? len : sclp->length;
+           sa += len;
+@@ -1725,16 +1738,27 @@ static int sg_build_dir(Sg_request * srp
+       offset = (0 == k) ? kp->offset : 0;
+       num = (rem_sz > (PAGE_SIZE - offset)) ? (PAGE_SIZE - offset) :
+                                               rem_sz;
++#if SMALL_SCATTERLIST
++      sclp->u.address = page_address(kp->maplist[k]) + offset;
++      sclp->ispaged = 0;
++#else
+       sclp->address = page_address(kp->maplist[k]) + offset;
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
+       sclp->page = NULL;
+ #endif
++#endif
+       sclp->length = num;
+       mem_src_arr[k] = SG_USER_MEM;
+       rem_sz -= num;
++#if SMALL_SCATTERLIST
++      SCSI_LOG_TIMEOUT(5,
++          printk("sg_build_dir: k=%d, a=0x%p, len=%d, ms=%d\n",
++          k, sclp->u.address, num, mem_src_arr[k]));
++#else
+       SCSI_LOG_TIMEOUT(5,
+           printk("sg_build_dir: k=%d, a=0x%p, len=%d, ms=%d\n",
+           k, sclp->address, num, mem_src_arr[k]));
 +#endif
-               } else {
-                               memcpy (SCpnt->request_buffer, pScb->bounce_buffer,
-                                                               SCpnt->request_bufflen);
-@@ -1226,7 +1231,11 @@
-       if (SCpnt->cmnd[0] == INQUIRY && !islogical) {
-               if ( SCpnt->use_sg ) {
-                       sgList = (struct scatterlist *)SCpnt->request_buffer;
+     }
+     schp->k_use_sg = k;
+     SCSI_LOG_TIMEOUT(5,
+@@ -1814,16 +1838,27 @@ static int sg_build_indi(Sg_scatter_hold
+                 if (! p)
+                     break;
+             }
 +#if SMALL_SCATTERLIST
-+                      memcpy(&c, sgList[0].u.address, 0x1);
++            sclp->u.address = p;
++          sclp->ispaged = 0;
 +#else
-                       memcpy(&c, sgList[0].address, 0x1);
+             sclp->address = p;
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
+           sclp->page = NULL;
+ #endif
 +#endif
-               } else {
-                       memcpy(&c, SCpnt->request_buffer, 0x1);
-               }
-Index: linux-2.4.21/drivers/scsi/atp870u.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/atp870u.c   2002-08-02 20:39:44.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/atp870u.c        2005-06-01 23:07:51.154569736 -0400
-@@ -804,7 +804,11 @@
-               sgpnt = (struct scatterlist *) workrequ->request_buffer;
-               i = 0;
-               for (j = 0; j < workrequ->use_sg; j++) {
+             sclp->length = ret_sz;
+           mem_src_arr[k] = mem_src;
 +#if SMALL_SCATTERLIST
-+                      bttl = virt_to_bus(sgpnt[j].u.address);
++          SCSI_LOG_TIMEOUT(5,
++              printk("sg_build_build: k=%d, a=0x%p, len=%d, ms=%d\n",
++                k, sclp->u.address, ret_sz, mem_src));
 +#else
-                       bttl = virt_to_bus(sgpnt[j].address);
+           SCSI_LOG_TIMEOUT(5,
+               printk("sg_build_build: k=%d, a=0x%p, len=%d, ms=%d\n",
+                 k, sclp->address, ret_sz, mem_src));
 +#endif
-                       l = sgpnt[j].length;
-                       while (l > 0x10000) {
-                               (unsigned short int) (((unsigned short int *) (prd))[i + 3]) = 0x0000;
-Index: linux-2.4.21/drivers/scsi/gdth.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/gdth.c      2003-06-13 10:51:36.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/gdth.c   2005-06-01 23:07:51.158569128 -0400
-@@ -2662,7 +2662,11 @@
-             if (cpsum+cpnow > cpcount) 
-                 cpnow = cpcount - cpsum;
-             cpsum += cpnow;
+         } /* end of for loop */
+       schp->k_use_sg = k;
+       SCSI_LOG_TIMEOUT(5,
+@@ -1888,13 +1923,21 @@ static int sg_write_xfer(Sg_request * sr
+       struct scatterlist * sclp = (struct scatterlist *)schp->buffer;
+       char * mem_src_arr = sg_get_sgat_msa(schp);
+       ksglen = (int)sclp->length;
 +#if SMALL_SCATTERLIST
-+            memcpy((char*)sl->u.address,buffer,cpnow);
++      p = sclp->u.address;
 +#else
-             memcpy((char*)sl->address,buffer,cpnow);
+       p = sclp->address;
 +#endif
-             if (cpsum == cpcount)
-                 break;
-             buffer += cpnow;
-@@ -2837,7 +2841,11 @@
-             cmdp->u.cache.DestAddr= 0xffffffff;
-             sl = (struct scatterlist *)scp->request_buffer;
-             for (i=0; i<scp->use_sg; ++i,++sl) {
+       for (j = 0, k = 0; j < onum; ++j) {
+           res = sg_u_iovec(hp, iovec_count, j, 1, &usglen, &up);
+           if (res) return res;
 +#if SMALL_SCATTERLIST
-+                cmdp->u.cache.sg_lst[i].sg_ptr = virt_to_bus(sl->u.address);
++          for ( ; p; ++sclp, ksglen = (int)sclp->length, p = sclp->u.address) {
 +#else
-                 cmdp->u.cache.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
+           for ( ; p; ++sclp, ksglen = (int)sclp->length, p = sclp->address) {
 +#endif
-                 cmdp->u.cache.sg_lst[i].sg_len = (ulong32)sl->length;
-             }
-             cmdp->u.cache.sg_canz = (ulong32)i;
-@@ -2954,7 +2962,11 @@
-             cmdp->u.raw.sdata  = 0xffffffff;
-             sl = (struct scatterlist *)scp->request_buffer;
-             for (i=0; i<scp->use_sg; ++i,++sl) {
+               ok = (SG_USER_MEM != mem_src_arr[k]);
+               if (usglen <= 0)
+                   break;
+@@ -1971,6 +2014,18 @@ static void sg_remove_scat(Sg_scatter_ho
+         struct scatterlist * sclp = (struct scatterlist *)schp->buffer;
+       char * mem_src_arr = sg_get_sgat_msa(schp);
 +#if SMALL_SCATTERLIST
-+                cmdp->u.raw.sg_lst[i].sg_ptr = virt_to_bus(sl->u.address);
++      for (k = 0; (k < schp->k_use_sg) && sclp->u.address; ++k, ++sclp) {
++          mem_src = mem_src_arr[k];
++          SCSI_LOG_TIMEOUT(5,
++              printk("sg_remove_scat: k=%d, a=0x%p, len=%d, ms=%d\n",
++                       k, sclp->u.address, sclp->length, mem_src));
++            sg_free(sclp->u.address, sclp->length, mem_src);
++            sclp->u.address = NULL;
++          sclp->ispaged = 0;
++            sclp->length = 0;
++        }
 +#else
-                 cmdp->u.raw.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
+       for (k = 0; (k < schp->k_use_sg) && sclp->address; ++k, ++sclp) {
+           mem_src = mem_src_arr[k];
+           SCSI_LOG_TIMEOUT(5,
+@@ -1983,6 +2038,7 @@ static void sg_remove_scat(Sg_scatter_ho
+ #endif
+             sclp->length = 0;
+         }
 +#endif
-                 cmdp->u.raw.sg_lst[i].sg_len = (ulong32)sl->length;
-             }
-             cmdp->u.raw.sg_ranz = (ulong32)i;
-Index: linux-2.4.21/drivers/scsi/ini9100u.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/ini9100u.c  2001-09-30 15:26:07.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/ini9100u.c       2005-06-01 23:07:51.159568976 -0400
-@@ -489,7 +489,11 @@
-       if (SCpnt->use_sg) {
-               pSrbSG = (struct scatterlist *) SCpnt->request_buffer;
-               if (SCpnt->use_sg == 1) {       /* If only one entry in the list *//*      treat it as regular I/O */
+       sg_free(schp->buffer, schp->sglist_len, schp->buffer_mem_src);
+     }
+     else if (schp->buffer)
+@@ -2043,13 +2099,21 @@ static int sg_read_xfer(Sg_request * srp
+       struct scatterlist * sclp = (struct scatterlist *)schp->buffer;
+       char * mem_src_arr = sg_get_sgat_msa(schp);
+       ksglen = (int)sclp->length;
 +#if SMALL_SCATTERLIST
-+                      pSCB->SCB_BufPtr = (U32) VIRT_TO_BUS(pSrbSG->u.address);
++      p = sclp->u.address;
 +#else
-                       pSCB->SCB_BufPtr = (U32) VIRT_TO_BUS(pSrbSG->address);
+       p = sclp->address;
 +#endif
-                       TotalLen = pSrbSG->length;
-                       pSCB->SCB_SGLen = 0;
-               } else {        /* Assign SG physical address   */
-@@ -498,7 +502,11 @@
-                       for (i = 0, TotalLen = 0, pSG = &pSCB->SCB_SGList[0];   /* 1.01g */
-                            i < SCpnt->use_sg;
-                            i++, pSG++, pSrbSG++) {
+       for (j = 0, k = 0; j < onum; ++j) {
+           res = sg_u_iovec(hp, iovec_count, j, 0, &usglen, &up);
+           if (res) return res;
 +#if SMALL_SCATTERLIST
-+                              pSG->SG_Ptr = (U32) VIRT_TO_BUS(pSrbSG->u.address);
++          for ( ; p; ++sclp, ksglen = (int)sclp->length, p = sclp->u.address) {
 +#else
-                               pSG->SG_Ptr = (U32) VIRT_TO_BUS(pSrbSG->address);
+           for ( ; p; ++sclp, ksglen = (int)sclp->length, p = sclp->address) {
 +#endif
-                               TotalLen += pSG->SG_Len = pSrbSG->length;
-                       }
-                       pSCB->SCB_SGLen = i;
-Index: linux-2.4.21/drivers/scsi/inia100.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/inia100.c   2001-09-30 15:26:07.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/inia100.c        2005-06-01 23:07:51.159568976 -0400
-@@ -494,7 +494,11 @@
-                       pSCB->SCB_SGLen = (U32) (SCpnt->use_sg * 8);
-                       pSrbSG = (struct scatterlist *) SCpnt->request_buffer;
-                       for (i = 0; i < SCpnt->use_sg; i++, pSG++, pSrbSG++) {
+               ok = (SG_USER_MEM != mem_src_arr[k]);
+               if (usglen <= 0)
+                   break;
+@@ -2093,14 +2157,26 @@ static void sg_read_oxfer(Sg_request * s
+         int k, num;
+         struct scatterlist * sclp = (struct scatterlist *)schp->buffer;
 +#if SMALL_SCATTERLIST
-+                              pSG->SG_Ptr = (U32) (VIRT_TO_BUS(pSrbSG->u.address));
++      for (k = 0; (k < schp->k_use_sg) && sclp->u.address; ++k, ++sclp) {
 +#else
-                               pSG->SG_Ptr = (U32) (VIRT_TO_BUS(pSrbSG->address));
+       for (k = 0; (k < schp->k_use_sg) && sclp->address; ++k, ++sclp) {
 +#endif
-                               pSG->SG_Len = (U32) pSrbSG->length;
-                               TotalLen += (U32) pSrbSG->length;
-                       }
-Index: linux-2.4.21/drivers/scsi/ide-scsi.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/ide-scsi.c  2005-06-01 22:52:05.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/ide-scsi.c       2005-06-01 23:07:51.160568824 -0400
-@@ -154,7 +154,11 @@
-                       return;
-               }
-               count = IDE_MIN(pc->sg->length - pc->b_count, bcount);
+             num = (int)sclp->length;
+             if (num > num_read_xfer) {
 +#if SMALL_SCATTERLIST
-+              HWIF(drive)->atapi_input_bytes(drive, pc->sg->u.address + pc->b_count, count);
++                __copy_to_user(outp, sclp->u.address, num_read_xfer);
 +#else
-               HWIF(drive)->atapi_input_bytes(drive, pc->sg->address + pc->b_count, count);
+                 __copy_to_user(outp, sclp->address, num_read_xfer);
 +#endif
-               bcount -= count;
-               pc->b_count += count;
-               if (pc->b_count == pc->sg->length) {
-@@ -176,7 +180,11 @@
-                       return;
-               }
-               count = IDE_MIN(pc->sg->length - pc->b_count, bcount);
+                 break;
+             }
+             else {
 +#if SMALL_SCATTERLIST
-+              HWIF(drive)->atapi_output_bytes(drive, pc->sg->u.address + pc->b_count, count);
++                __copy_to_user(outp, sclp->u.address, num);
 +#else
-               HWIF(drive)->atapi_output_bytes(drive, pc->sg->address + pc->b_count, count);
+                 __copy_to_user(outp, sclp->address, num);
 +#endif
-               bcount -= count;
-               pc->b_count += count;
-               if (pc->b_count == pc->sg->length) {
-@@ -1026,6 +1034,19 @@
-                       pc->request_transfer >> 10);
- #endif /* IDESCSI_DEBUG_LOG */
-               while (segments--) {
+                 num_read_xfer -= num;
+                 if (num_read_xfer <= 0)
+                     break;
+@@ -2146,7 +2222,11 @@ static void sg_link_reserve(Sg_fd * sfp,
+             if (rem <= num) {
+               if (0 == k) {
+                   req_schp->k_use_sg = 0;
 +#if SMALL_SCATTERLIST
-+#if 1
-+                      bh->b_data = sg->u.address;
++                  req_schp->buffer = sclp->u.address;
 +#else
-+                      if (sg->u.address) {
-+                              bh->b_page = virt_to_page(sg->u.address);
-+                              bh->b_data = (char *) ((unsigned long) sg->u.address & ~PAGE_MASK);
-+                      } else if (sg->u.page.page) {
-+                              bh->b_page = sg->u.page.page;
-+                              bh->b_data = (char *) sg->u.page.offset;
-+                      }
+                   req_schp->buffer = sclp->address;
 +#endif
-+#else /* !SMALL_SCATTERLIST */
- #if 1
-                       bh->b_data = sg->address;
- #else
-@@ -1037,6 +1058,7 @@
-                               bh->b_data = (char *) sg->offset;
-                       }
- #endif
-+#endif /* !SMALL_SCATTERLIST */
-                       bh->b_size = sg->length;
-                       bh = bh->b_reqnext;
-                       sg++;
-Index: linux-2.4.21/drivers/scsi/ppa.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/ppa.c       2005-06-01 22:52:05.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/ppa.c    2005-06-01 23:07:51.161568672 -0400
-@@ -740,7 +740,11 @@
-           if (cmd->SCp.buffers_residual--) {
-               cmd->SCp.buffer++;
-               cmd->SCp.this_residual = cmd->SCp.buffer->length;
+               }
+               else {
+                   sfp->save_scat_len = num;
+diff -X dontdiff -urp kern_oldest/drivers/scsi/sim710.c kern_fix/drivers/scsi/sim710.c
+--- kern_oldest/drivers/scsi/sim710.c  2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/sim710.c     2006-05-01 14:14:13.000000000 -0700
+@@ -1164,7 +1164,11 @@ run_command (struct sim710_hostdata *hos
+     for (i = 0; cmd->use_sg ? (i < cmd->use_sg) : !i; i++) {
+       u32 vbuf = cmd->use_sg ?
 +#if SMALL_SCATTERLIST
-+              cmd->SCp.ptr = cmd->SCp.buffer->u.address;
++              (u32)(((struct scatterlist *)cmd->buffer)[i].u.address) :
 +#else
-               cmd->SCp.ptr = cmd->SCp.buffer->address;
+               (u32)(((struct scatterlist *)cmd->buffer)[i].address) :
 +#endif
-           }
-       }
-       /* Now check to see if the drive is ready to comunicate */
-@@ -925,7 +929,11 @@
-           /* if many buffers are available, start filling the first */
-           cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer;
-           cmd->SCp.this_residual = cmd->SCp.buffer->length;
+               (u32)(cmd->request_buffer);
+       u32 bbuf = virt_to_bus((void *)vbuf);
+       u32 cnt = cmd->use_sg ?
+diff -X dontdiff -urp kern_oldest/drivers/scsi/sr.c kern_fix/drivers/scsi/sr.c
+--- kern_oldest/drivers/scsi/sr.c      2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/sr.c 2006-05-01 14:14:13.000000000 -0700
+@@ -343,7 +343,12 @@ static int sr_scatter_pad(Scsi_Cmnd *SCp
+       i = 0;
+       if (fsize) {
 +#if SMALL_SCATTERLIST
-+          cmd->SCp.ptr = cmd->SCp.buffer->u.address;
++              sg[0].ispaged = 0;
++              sg[0].u.address = bbpnt[0] = front;
 +#else
-           cmd->SCp.ptr = cmd->SCp.buffer->address;
+               sg[0].address = bbpnt[0] = front;
 +#endif
+               sg[0].length = fsize;
+               i++;
+       }
+@@ -354,7 +359,12 @@ static int sr_scatter_pad(Scsi_Cmnd *SCp
+               scsi_free(old_sg, (((SCpnt->use_sg * sizeof(struct scatterlist)) +
+                                   (SCpnt->use_sg * sizeof(void *))) + 511) & ~511);
        } else {
-           /* else fill the only available buffer */
-           cmd->SCp.buffer = NULL;
-Index: linux-2.4.21/drivers/scsi/imm.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/imm.c       2005-06-01 22:52:05.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/imm.c    2005-06-01 23:07:51.162568520 -0400
-@@ -834,7 +834,11 @@
-           if (cmd->SCp.buffers_residual--) {
-               cmd->SCp.buffer++;
-               cmd->SCp.this_residual = cmd->SCp.buffer->length;
 +#if SMALL_SCATTERLIST
-+              cmd->SCp.ptr = cmd->SCp.buffer->u.address;
++              sg[i].ispaged = 0;
++              sg[i].u.address = SCpnt->request_buffer;
 +#else
-               cmd->SCp.ptr = cmd->SCp.buffer->address;
+               sg[i].address = SCpnt->request_buffer;
 +#endif
+               sg[i].length = SCpnt->request_bufflen;
+       }
+@@ -364,7 +374,12 @@ static int sr_scatter_pad(Scsi_Cmnd *SCp
+       SCpnt->use_sg += i;
  
-               /*
-                * Make sure that we transfer even number of bytes
-@@ -1008,7 +1012,11 @@
-           /* if many buffers are available, start filling the first */
-           cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer;
-           cmd->SCp.this_residual = cmd->SCp.buffer->length;
+       if (bsize) {
 +#if SMALL_SCATTERLIST
-+          cmd->SCp.ptr = cmd->SCp.buffer->u.address;
++              sg[SCpnt->use_sg].ispaged = 0;
++              sg[SCpnt->use_sg].u.address = back;
 +#else
-           cmd->SCp.ptr = cmd->SCp.buffer->address;
+               sg[SCpnt->use_sg].address = back;
 +#endif
-       } else {
-           /* else fill the only available buffer */
-           cmd->SCp.buffer = NULL;
-Index: linux-2.4.21/drivers/scsi/st.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/st.c        2005-06-01 22:52:04.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/st.c     2005-06-01 23:07:51.164568216 -0400
-@@ -3409,6 +3409,12 @@
+               bbpnt[SCpnt->use_sg] = back;
+               sg[SCpnt->use_sg].length = bsize;
+               SCpnt->use_sg++;
+diff -X dontdiff -urp kern_oldest/drivers/scsi/st.c kern_fix/drivers/scsi/st.c
+--- kern_oldest/drivers/scsi/st.c      2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/st.c 2006-05-01 14:14:13.000000000 -0700
+@@ -3410,6 +3410,12 @@ static int st_ioctl(struct inode *inode,
  }
  \f
  
@@ -2791,7 +3344,7 @@ Index: linux-2.4.21/drivers/scsi/st.c
  /* Try to allocate a new tape buffer. Calling function must not hold
     dev_arr_lock. */
  static ST_buffer *
-@@ -3446,18 +3452,23 @@
+@@ -3447,18 +3453,23 @@ static ST_buffer *
                     order++, b_size *= 2)
                        ;
                for ( ; b_size >= PAGE_SIZE; order--, b_size /= 2) {
@@ -2819,7 +3372,7 @@ Index: linux-2.4.21/drivers/scsi/st.c
  
                        for (b_size = PAGE_SIZE, order=0;
                             st_buffer_size >
-@@ -3466,10 +3477,10 @@
+@@ -3467,10 +3478,10 @@ static ST_buffer *
                                ;
                        for (segs = 1, got = tb->sg_lengths[0];
                             got < st_buffer_size && segs < ST_FIRST_SG;) {
@@ -2832,7 +3385,7 @@ Index: linux-2.4.21/drivers/scsi/st.c
                                        if (st_buffer_size - got <=
                                            (ST_FIRST_SG - segs) * b_size / 2) {
                                                b_size /= 2; /* Large enough for the
-@@ -3485,7 +3496,11 @@
+@@ -3486,7 +3497,11 @@ static ST_buffer *
                                        tb = NULL;
                                        break;
                                }
@@ -2844,7 +3397,7 @@ Index: linux-2.4.21/drivers/scsi/st.c
                                tb->sg_lengths[segs] = b_size;
                                got += b_size;
                                segs++;
-@@ -3499,7 +3514,7 @@
+@@ -3500,7 +3515,7 @@ static ST_buffer *
                return NULL;
        }
        tb->sg_segs = tb->orig_sg_segs = segs;
@@ -2853,7 +3406,7 @@ Index: linux-2.4.21/drivers/scsi/st.c
  
          DEBC(printk(ST_DEB_MSG
                      "st: Allocated tape buffer %d (%d bytes, %d segments, dma: %d, a: %p).\n",
-@@ -3545,9 +3560,9 @@
+@@ -3546,9 +3561,9 @@ static int enlarge_buffer(ST_buffer * ST
  
        for (segs = STbuffer->sg_segs, got = STbuffer->buffer_size;
             segs < max_segs && got < new_size;) {
@@ -2865,7 +3418,7 @@ Index: linux-2.4.21/drivers/scsi/st.c
                        if (new_size - got <= (max_segs - segs) * b_size / 2) {
                                b_size /= 2; /* Large enough for the rest of the buffers */
                                order--;
-@@ -3559,7 +3574,11 @@
+@@ -3560,7 +3575,11 @@ static int enlarge_buffer(ST_buffer * ST
                        normalize_buffer(STbuffer);
                        return FALSE;
                }
@@ -2877,7 +3430,7 @@ Index: linux-2.4.21/drivers/scsi/st.c
                STbuffer->sg_lengths[segs] = b_size;
                STbuffer->sg_segs += 1;
                got += b_size;
-@@ -3583,13 +3602,13 @@
+@@ -3584,13 +3603,13 @@ static void normalize_buffer(ST_buffer *
                for (b_size=PAGE_SIZE, order=0; b_size < STbuffer->sg_lengths[i];
                     order++, b_size *= 2)
                        ; /* empty */
@@ -2893,7 +3446,7 @@ Index: linux-2.4.21/drivers/scsi/st.c
                       STbuffer->sg_segs);
          ) /* end DEB */
        STbuffer->sg_segs = STbuffer->orig_sg_segs;
-@@ -3612,7 +3631,7 @@
+@@ -3613,7 +3632,7 @@ static int append_to_buffer(const char *
        for (; i < st_bp->sg_segs && do_count > 0; i++) {
                cnt = st_bp->sg_lengths[i] - offset < do_count ?
                    st_bp->sg_lengths[i] - offset : do_count;
@@ -2902,7 +3455,7 @@ Index: linux-2.4.21/drivers/scsi/st.c
                if (res)
                        return (-EFAULT);
                do_count -= cnt;
-@@ -3645,7 +3664,7 @@
+@@ -3646,7 +3665,7 @@ static int from_buffer(ST_buffer * st_bp
        for (; i < st_bp->sg_segs && do_count > 0; i++) {
                cnt = st_bp->sg_lengths[i] - offset < do_count ?
                    st_bp->sg_lengths[i] - offset : do_count;
@@ -2911,7 +3464,7 @@ Index: linux-2.4.21/drivers/scsi/st.c
                if (res)
                        return (-EFAULT);
                do_count -= cnt;
-@@ -3688,8 +3707,8 @@
+@@ -3689,8 +3708,8 @@ static void move_buffer_data(ST_buffer *
        for (dst_seg=dst_offset=0; total > 0; ) {
                count = min(st_bp->sg_lengths[dst_seg] - dst_offset,
                            st_bp->sg_lengths[src_seg] - src_offset);
@@ -2922,632 +3475,338 @@ Index: linux-2.4.21/drivers/scsi/st.c
                printk("st: move (%d,%d) -> (%d,%d) count %d\n",
                       src_seg, src_offset, dst_seg, dst_offset, count);
                src_offset += count;
-Index: linux-2.4.21/drivers/scsi/osst.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/osst.c      2005-06-01 22:52:04.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/osst.c   2005-06-01 23:07:51.169567456 -0400
-@@ -477,7 +477,11 @@
-       if (STp->raw) {
-               if (STp->buffer->syscall_result) {
-                       for (i=0; i < STp->buffer->sg_segs; i++)
-+#if SMALL_SCATTERLIST
-+                              memset(STp->buffer->sg[i].u.address, 0, STp->buffer->sg[i].length);
-+#else
-                               memset(STp->buffer->sg[i].address, 0, STp->buffer->sg[i].length);
-+#endif
-                       strcpy(STp->buffer->b_data, "READ ERROR ON FRAME");
-                 } else
-                       STp->buffer->buffer_bytes = OS_FRAME_SIZE;
-@@ -4460,10 +4464,19 @@
-               for (i = 0, b_size = 0; 
-                    i < STp->buffer->sg_segs && (b_size + STp->buffer->sg[i].length) <= OS_DATA_SIZE; 
-                    b_size += STp->buffer->sg[i++].length);
-+#if SMALL_SCATTERLIST
-+              STp->buffer->aux = (os_aux_t *) (STp->buffer->sg[i].u.address + OS_DATA_SIZE - b_size);
-+#else
-               STp->buffer->aux = (os_aux_t *) (STp->buffer->sg[i].address + OS_DATA_SIZE - b_size);
-+#endif
- #if DEBUG
-               printk(OSST_DEB_MSG "osst%d:D: b_data points to %p in segment 0 at %p\n", dev,
--                      STp->buffer->b_data, STp->buffer->sg[0].address);
-+                      STp->buffer->b_data, 
-+#if SMALL_SCATTERLIST
-+                     STp->buffer->sg[0].u.address);
-+#else
-+                     STp->buffer->sg[0].address);
-+#endif
-               printk(OSST_DEB_MSG "osst%d:D: AUX points to %p in segment %d at %p\n", dev,
-                        STp->buffer->aux, i, STp->buffer->sg[i].address);
- #endif
-@@ -5007,6 +5020,12 @@
\f
- /* Memory handling routines */
-+#if SMALL_SCATTERLIST
-+#define SG_ADDRESS(sg) ((sg).u.address)
-+#else
-+#define SG_ADDRESS(sg) ((sg).address)
-+#endif
-+
- /* Try to allocate a new tape buffer */
- static OSST_buffer * new_tape_buffer( int from_initialization, int need_dma )
- {
-@@ -5035,15 +5054,19 @@
-                    b_size *= 2,                 order++ );
-               for ( ; b_size >= PAGE_SIZE; order--, b_size /= 2) {
--                      tb->sg[0].address =
-+                      SG_ADDRESS(tb->sg[0]) =
-                           (unsigned char *)__get_free_pages(priority, order);
--                      if (tb->sg[0].address != NULL) {
-+                      if (SG_ADDRESS(tb->sg[0]) != NULL) {
-+#if SMALL_SCATTERLIST
-+                          tb->sg[0].ispaged = 0;
-+#else
-                           tb->sg[0].page = NULL;
-+#endif
-                           tb->sg[0].length = b_size;
-                           break;
-                       }
-               }
--              if (tb->sg[segs].address == NULL) {
-+              if (SG_ADDRESS(tb->sg[segs]) == NULL) {
-                       kfree(tb);
-                       tb = NULL;
-               }
-@@ -5055,9 +5078,9 @@
-                       for (segs=1, got=tb->sg[0].length;
-                            got < osst_buffer_size && segs < OSST_FIRST_SG; ) {
--                          tb->sg[segs].address =
-+                          SG_ADDRESS(tb->sg[segs]) =
-                               (unsigned char *)__get_free_pages(priority, order);
--                          if (tb->sg[segs].address == NULL) {
-+                          if (SG_ADDRESS(tb->sg[segs]) == NULL) {
-                               if (osst_buffer_size - got <=
-                                   (OSST_FIRST_SG - segs) * b_size / 2) {
-                                   b_size /= 2; /* Large enough for the rest of the buffers */
-@@ -5074,7 +5097,11 @@
-                               tb = NULL;
-                               break;
-                           }
-+#if SMALL_SCATTERLIST
-+                          tb->sg[segs].ispaged = 0;
-+#else
-                             tb->sg[segs].page = NULL;
-+#endif
-                           tb->sg[segs].length = b_size;
-                           got += b_size;
-                           segs++;
-@@ -5087,7 +5114,7 @@
-               return NULL;
-       }
-       tb->sg_segs = tb->orig_sg_segs = segs;
--      tb->b_data = tb->sg[0].address;
-+      tb->b_data = SG_ADDRESS(tb->sg[0]);
- #if DEBUG
-       if (debugging) {
-@@ -5132,9 +5159,9 @@
-       for (segs=STbuffer->sg_segs, got=STbuffer->buffer_size;
-            segs < max_segs && got < new_size; ) {
--              STbuffer->sg[segs].address =
-+              SG_ADDRESS(STbuffer->sg[segs]) =
-                         (unsigned char *)__get_free_pages(priority, order);
--              if (STbuffer->sg[segs].address == NULL) {
-+              if (SG_ADDRESS(STbuffer->sg[segs]) == NULL) {
-                       if (new_size - got <= (max_segs - segs) * b_size / 2) {
-                               b_size /= 2;  /* Large enough for the rest of the buffers */
-                               order--;
-@@ -5148,7 +5175,11 @@
-                       normalize_buffer(STbuffer);
-                       return FALSE;
-               }
-+#if SMALL_SCATTERLIST
-+              STbuffer->sg[segs].ispaged = 0;
-+#else
-               STbuffer->sg[segs].page = NULL;
-+#endif
-               STbuffer->sg[segs].length = b_size;
-               STbuffer->sg_segs += 1;
-               got += b_size;
-@@ -5181,8 +5212,8 @@
-               for (b_size = PAGE_SIZE, order = 0;
-                    b_size < STbuffer->sg[i].length;
-                    b_size *= 2, order++);
--
--              free_pages((unsigned long)STbuffer->sg[i].address, order);
-+ 
-+              free_pages((unsigned long)SG_ADDRESS(STbuffer->sg[i]), order);
-               STbuffer->buffer_size -= STbuffer->sg[i].length;
-       }
- #if DEBUG
-@@ -5210,7 +5241,7 @@
-       for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
-               cnt = st_bp->sg[i].length - offset < do_count ?
-                     st_bp->sg[i].length - offset : do_count;
--              res = copy_from_user(st_bp->sg[i].address + offset, ubp, cnt);
-+              res = copy_from_user(SG_ADDRESS(st_bp->sg[i]) + offset, ubp, cnt);
-               if (res)
-                       return (-EFAULT);
-               do_count -= cnt;
-@@ -5243,7 +5274,7 @@
-       for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
-               cnt = st_bp->sg[i].length - offset < do_count ?
-                     st_bp->sg[i].length - offset : do_count;
--              res = copy_to_user(ubp, st_bp->sg[i].address + offset, cnt);
-+              res = copy_to_user(ubp, SG_ADDRESS(st_bp->sg[i]) + offset, cnt);
-               if (res)
-                       return (-EFAULT);
-               do_count -= cnt;
-@@ -5276,7 +5307,7 @@
-            i < st_bp->sg_segs && do_count > 0; i++) {
-               cnt = st_bp->sg[i].length - offset < do_count ?
-                     st_bp->sg[i].length - offset : do_count ;
--              memset(st_bp->sg[i].address + offset, 0, cnt);
-+              memset(SG_ADDRESS(st_bp->sg[i]) + offset, 0, cnt);
-               do_count -= cnt;
-               offset = 0;
-       }
-@@ -5296,7 +5327,7 @@
-       for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
-               cnt = st_bp->sg[i].length < do_count ?
-                     st_bp->sg[i].length : do_count ;
--              memcpy(st_bp->sg[i].address, ptr, cnt);
-+              memcpy(SG_ADDRESS(st_bp->sg[i]), ptr, cnt);
-               do_count -= cnt;
-               ptr      += cnt;
-       }
-@@ -5317,7 +5348,7 @@
-       for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
-               cnt = st_bp->sg[i].length < do_count ?
-                     st_bp->sg[i].length : do_count ;
--              memcpy(ptr, st_bp->sg[i].address, cnt);
-+              memcpy(ptr, SG_ADDRESS(st_bp->sg[i]), cnt);
-               do_count -= cnt;
-               ptr      += cnt;
-       }
-Index: linux-2.4.21/drivers/scsi/pcmcia/nsp_cs.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/pcmcia/nsp_cs.c     2003-06-13 10:51:36.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/pcmcia/nsp_cs.c  2005-06-01 23:07:51.170567304 -0400
-@@ -201,7 +201,11 @@
-          SCp.phase            : current state of the command */
-       if (SCpnt->use_sg) {
-               SCpnt->SCp.buffer           = (struct scatterlist *) SCpnt->request_buffer;
-+#if SMALL_SCATTERLIST
-+              SCpnt->SCp.ptr              = SCpnt->SCp.buffer->u.address;
-+#else
-               SCpnt->SCp.ptr              = SCpnt->SCp.buffer->address;
-+#endif
-               SCpnt->SCp.this_residual    = SCpnt->SCp.buffer->length;
-               SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1;
-       } else {
-@@ -713,7 +717,11 @@
-                       //DEBUG(0, " scatterlist next timeout=%d\n", time_out);
-                       SCpnt->SCp.buffers_residual--;
-                       SCpnt->SCp.buffer++;
-+#if SMALL_SCATTERLIST
-+                      SCpnt->SCp.ptr           = SCpnt->SCp.buffer->u.address;
-+#else
-                       SCpnt->SCp.ptr           = SCpnt->SCp.buffer->address;
-+#endif
-                       SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;
-               }
-@@ -786,7 +794,11 @@
-                       //DEBUG(0, " scatterlist next\n");
-                       SCpnt->SCp.buffers_residual--;
-                       SCpnt->SCp.buffer++;
+diff -X dontdiff -urp kern_oldest/drivers/scsi/sym53c416.c kern_fix/drivers/scsi/sym53c416.c
+--- kern_oldest/drivers/scsi/sym53c416.c       2006-05-01 11:55:41.000000000 -0700
++++ kern_fix/drivers/scsi/sym53c416.c  2006-05-01 14:14:13.000000000 -0700
+@@ -448,7 +448,11 @@ static void sym53c416_intr_handle(int ir
+                                       sglist = current_command->request_buffer;
+                                       while(sgcount--)
+                                       {
 +#if SMALL_SCATTERLIST
-+                      SCpnt->SCp.ptr           = SCpnt->SCp.buffer->u.address;
++                                              tot_trans += sym53c416_write(base, sglist->u.address, sglist->length);
 +#else
-                       SCpnt->SCp.ptr           = SCpnt->SCp.buffer->address;
+                                               tot_trans += sym53c416_write(base, sglist->address, sglist->length);
 +#endif
-                       SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;
-               }
-Index: linux-2.4.21/drivers/scsi/ips.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/ips.c       2005-06-01 22:51:54.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/ips.c    2005-06-01 23:07:51.175566544 -0400
-@@ -217,7 +217,11 @@
- #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
- #include <linux/blk.h>
- #include "sd.h"
-+#if SMALL_SCATTERLIST
-+#define IPS_SG_ADDRESS(sg)       ((sg)->u.address)
-+#else
- #define IPS_SG_ADDRESS(sg)       ((sg)->address)
-+#endif /* !SMALL_SCATTERLIST */
- #define IPS_LOCK_SAVE(lock,flags) spin_lock_irqsave(&io_request_lock,flags)
- #define IPS_UNLOCK_RESTORE(lock,flags) spin_unlock_irqrestore(&io_request_lock,flags)
- #ifndef __devexit_p
-Index: linux-2.4.21/drivers/scsi/libata-core.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/libata-core.c       2005-06-01 22:51:58.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/libata-core.c    2005-06-01 23:36:21.244596536 -0400
-@@ -2068,8 +2068,13 @@
-       qc->buf_virt = buf;
-       sg = qc->sg;
-+#if SMALL_SCATTERLIST
-+      sg->u.page.page = virt_to_page(buf);
-+      sg->u.page.offset = (unsigned long) buf & ~PAGE_MASK;
-+#else
-       sg->page = virt_to_page(buf);
-       sg->offset = (unsigned long) buf & ~PAGE_MASK;
-+#endif /* !SMALL_SCATTERLIST */
-       sg->length = buflen;
- }
-@@ -2297,8 +2302,13 @@
-       if (qc->cursect == (qc->nsect - 1))
-               ap->pio_task_state = PIO_ST_LAST;
-+#if SMALL_SCATTERLIST
-+      page = sg[qc->cursg].u.page.page;
-+      offset = sg[qc->cursg].u.page.offset + qc->cursg_ofs * ATA_SECT_SIZE;
-+#else
-       page = sg[qc->cursg].page;
-       offset = sg[qc->cursg].offset + qc->cursg_ofs * ATA_SECT_SIZE;
-+#endif /* SMALL_SCATTERLIST */
-       /* get the current page and offset */
-       page = nth_page(page, (offset >> PAGE_SHIFT));
-@@ -2339,8 +2349,13 @@
- next_sg:
-       sg = &qc->sg[qc->cursg];
+                                               sglist++;
+                                       }
+                               }
+@@ -474,7 +478,11 @@ static void sym53c416_intr_handle(int ir
+                                       sglist = current_command->request_buffer;
+                                       while(sgcount--)
+                                       {
 +#if SMALL_SCATTERLIST
-+      page = sg->u.page.page;
-+      offset = sg->u.page.offset + qc->cursg_ofs;
++                                              tot_trans += sym53c416_read(base, sglist->u.address, sglist->length);
 +#else
-       page = sg->page;
-       offset = sg->offset + qc->cursg_ofs;
+                                               tot_trans += sym53c416_read(base, sglist->address, sglist->length);
 +#endif
-       /* get the current page and offset */
-       page = nth_page(page, (offset >> PAGE_SHIFT));
-Index: linux-2.4.21/drivers/scsi/libata-scsi.c
-===================================================================
---- linux-2.4.21.orig/drivers/scsi/libata-scsi.c       2005-06-01 22:51:58.000000000 -0400
-+++ linux-2.4.21/drivers/scsi/libata-scsi.c    2005-06-01 23:12:15.112442040 -0400
-@@ -689,7 +689,11 @@
-               struct scatterlist *sg;
-               sg = (struct scatterlist *) cmd->request_buffer;
+                                               sglist++;
+                                       }
+                               }
+diff -X dontdiff -urp kern_oldest/drivers/scsi/tmscsim.c kern_fix/drivers/scsi/tmscsim.c
+--- kern_oldest/drivers/scsi/tmscsim.c 2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/tmscsim.c    2006-05-01 14:14:13.000000000 -0700
+@@ -1146,7 +1146,11 @@ static void dc390_BuildSRB (Scsi_Cmnd* p
+     {
+       pSRB->SGcount = 1;
+       pSRB->pSegmentList = (PSGL) &pSRB->Segmentx;
 +#if SMALL_SCATTERLIST
-+              buf = kmap_atomic(sg->u.page.page, KM_USER0) + sg->u.page.offset;
++      pSRB->Segmentx.u.address = (PUCHAR) pcmd->request_buffer;
 +#else
-               buf = kmap_atomic(sg->page, KM_USER0) + sg->offset;
-+#endif /* !SMALL_SCATTERLIST */
-               buflen = sg->length;
-       } else {
-               buf = cmd->request_buffer;
-@@ -717,7 +721,11 @@
-               struct scatterlist *sg;
-               sg = (struct scatterlist *) cmd->request_buffer;
+       pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer;
++#endif
+       pSRB->Segmentx.length = pcmd->request_bufflen;
+     }
+     else
+diff -X dontdiff -urp kern_oldest/drivers/scsi/ultrastor.c kern_fix/drivers/scsi/ultrastor.c
+--- kern_oldest/drivers/scsi/ultrastor.c       2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/ultrastor.c  2006-05-01 14:14:13.000000000 -0700
+@@ -666,7 +666,11 @@ static inline void build_sg_list(registe
+       sl = (struct scatterlist *) SCpnt->request_buffer;
+       max = SCpnt->use_sg;
+       for (i = 0; i < max; i++) {
 +#if SMALL_SCATTERLIST
-+              kunmap_atomic(buf - sg->u.page.offset, KM_USER0);
++              mscp->sglist[i].address = virt_to_bus(sl[i].u.address);
 +#else
-               kunmap_atomic(buf - sg->offset, KM_USER0);
-+#endif /* !SMALL_SCATTERLIST */
+               mscp->sglist[i].address = virt_to_bus(sl[i].address);
++#endif
+               mscp->sglist[i].num_bytes = sl[i].length;
+               transfer_length += sl[i].length;
        }
- }
+diff -X dontdiff -urp kern_oldest/drivers/scsi/wd7000.c kern_fix/drivers/scsi/wd7000.c
+--- kern_oldest/drivers/scsi/wd7000.c  2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/drivers/scsi/wd7000.c     2006-05-01 14:14:13.000000000 -0700
+@@ -1189,7 +1189,11 @@ int wd7000_queuecommand (Scsi_Cmnd *SCpn
+       any2scsi (scb->maxlen, SCpnt->use_sg * sizeof (Sgb));
  
-Index: linux-2.4.21/drivers/block/cpqarray.c
-===================================================================
---- linux-2.4.21.orig/drivers/block/cpqarray.c 2005-06-01 22:51:54.000000000 -0400
-+++ linux-2.4.21/drivers/block/cpqarray.c      2005-06-01 23:07:51.183565328 -0400
-@@ -1003,9 +1003,14 @@
-               } else {
-                       if (seg == SG_MAX)
-                               BUG();
+       for (i = 0; i < SCpnt->use_sg; i++) {
 +#if SMALL_SCATTERLIST
-+                      tmp_sg[seg].u.page.page = bh->b_page;
-+                      tmp_sg[seg].u.page.offset = bh_offset(bh);
++          any2scsi (sgb[i].ptr, (int) sg[i].u.address);
 +#else
-                       tmp_sg[seg].page = bh->b_page;
--                      tmp_sg[seg].length = bh->b_size;
-                       tmp_sg[seg].offset = bh_offset(bh);
+           any2scsi (sgb[i].ptr, (int) sg[i].address);
 +#endif
-+                      tmp_sg[seg].length = bh->b_size;
-                       lastdataend = bh_phys(bh) + bh->b_size;
-                       seg++;
-               }
-@@ -1014,11 +1019,21 @@
-       /* Now do all the DMA Mappings */
-       for( i=0; i < seg; i++) {
-               c->req.sg[i].size = tmp_sg[i].length;
+           any2scsi (sgb[i].len, sg[i].length);
+       }
+     }
+diff -X dontdiff -urp kern_oldest/drivers/usb/hpusbscsi.c kern_fix/drivers/usb/hpusbscsi.c
+--- kern_oldest/drivers/usb/hpusbscsi.c        2006-05-01 11:55:42.000000000 -0700
++++ kern_fix/drivers/usb/hpusbscsi.c   2006-05-01 14:14:13.000000000 -0700
+@@ -576,6 +576,17 @@ static void scatter_gather_callback(stru
+               hpusbscsi->state = HP_STATE_WORKING;
+       PDEBUG(2, "state= %s", states[hpusbscsi->state]);
 +#if SMALL_SCATTERLIST
-+              c->req.sg[i].addr = (__u32) pci_map_page(
-+                              h->pci_dev, 
-+                              tmp_sg[i].u.page.page, tmp_sg[i].u.page.offset,
-+                              tmp_sg[i].length,
-+                                (creq->cmd == READ) ? 
-+                                      PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
++        FILL_BULK_URB(
++                u,
++                hpusbscsi->dev,
++                hpusbscsi->current_data_pipe,
++                sg[hpusbscsi->fragment].u.address,
++                sg[hpusbscsi->fragment++].length,
++                callback,
++                hpusbscsi
++        );
 +#else
-               c->req.sg[i].addr = (__u32) pci_map_page(
--                              h->pci_dev, tmp_sg[i].page, tmp_sg[i].offset,
-+                              h->pci_dev, 
-+                              tmp_sg[i].page, tmp_sg[i].offset,
-                               tmp_sg[i].length,
-                                 (creq->cmd == READ) ? 
-                                       PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
+         FILL_BULK_URB(
+                 u,
+                 hpusbscsi->dev,
+@@ -585,6 +596,7 @@ static void scatter_gather_callback(stru
+                 callback,
+                 hpusbscsi
+         );
 +#endif
-       }
- DBGPX(        printk("Submitting %d sectors in %d segments\n", sect, seg); );
-       c->req.hdr.sg_cnt = seg;
-Index: linux-2.4.21/drivers/block/cciss.c
-===================================================================
---- linux-2.4.21.orig/drivers/block/cciss.c    2005-06-01 22:51:54.000000000 -0400
-+++ linux-2.4.21/drivers/block/cciss.c 2005-06-01 23:07:51.185565024 -0400
-@@ -2491,9 +2491,14 @@
-               } else {
-                       if (seg == MAXSGENTRIES)
-                               BUG();
+         res = usb_submit_urb(u);
+         if (res)
+diff -X dontdiff -urp kern_oldest/drivers/usb/microtek.c kern_fix/drivers/usb/microtek.c
+--- kern_oldest/drivers/usb/microtek.c 2006-05-01 11:55:42.000000000 -0700
++++ kern_fix/drivers/usb/microtek.c    2006-05-01 14:14:13.000000000 -0700
+@@ -623,7 +623,11 @@ static void mts_do_sg (struct urb* trans
+       context->fragment++;
+       mts_int_submit_urb(transfer,
+                       context->data_pipe,
 +#if SMALL_SCATTERLIST
-+                      tmp_sg[seg].u.page.page = bh->b_page;
-+                      tmp_sg[seg].u.page.offset = bh_offset(bh);
++                      sg[context->fragment].u.address,
 +#else
-                       tmp_sg[seg].page = bh->b_page;
--                      tmp_sg[seg].length = bh->b_size;
-                       tmp_sg[seg].offset = bh_offset(bh);
+                       sg[context->fragment].address,
 +#endif
-+                      tmp_sg[seg].length = bh->b_size;
-                       lastdataend = bh_phys(bh) + bh->b_size;
-                       seg++;
-               }
-@@ -2507,8 +2512,16 @@
-               ddir = PCI_DMA_TODEVICE;
-       for (i=0; i<seg; i++) {
-               c->SG[i].Len = tmp_sg[i].length;
--              temp64.val = pci_map_page(h->pdev, tmp_sg[i].page,
--                          tmp_sg[i].offset, tmp_sg[i].length, ddir);
+                       sg[context->fragment].length,
+                       context->fragment + 1 == context->srb->use_sg ? mts_data_done : mts_do_sg);
+       return;
+@@ -667,7 +671,11 @@ mts_build_transfer_context( Scsi_Cmnd *s
+       } else {
+               MTS_DEBUG("Using scatter/gather\n");
+               sg = srb->buffer;
 +#if SMALL_SCATTERLIST
-+              temp64.val = pci_map_page(h->pdev,
-+                                        tmp_sg[i].u.page.page, 
-+                                        tmp_sg[i].u.page.offset,
-+                                        tmp_sg[i].length, ddir);
++              desc->context.data = sg[0].u.address;
 +#else
-+              temp64.val = pci_map_page(h->pdev,
-+                                        tmp_sg[i].page, tmp_sg[i].offset,
-+                                        tmp_sg[i].length, ddir);
+               desc->context.data = sg[0].address;
 +#endif
-               c->SG[i].Addr.lower = temp64.val32.lower;
-                 c->SG[i].Addr.upper = temp64.val32.upper;
-                 c->SG[i].Ext = 0;  /* we are not chaining */
-Index: linux-2.4.21/drivers/block/sx8.c
-===================================================================
---- linux-2.4.21.orig/drivers/block/sx8.c      2005-06-01 22:51:58.000000000 -0400
-+++ linux-2.4.21/drivers/block/sx8.c   2005-06-01 23:07:51.186564872 -0400
-@@ -1103,9 +1103,15 @@
-               } else {
-                       if (unlikely(n_elem == CARM_MAX_REQ_SG))
-                               BUG();
+               desc->context.data_length = sg[0].length;
+       }
+diff -X dontdiff -urp kern_oldest/drivers/usb/storage/datafab.c kern_fix/drivers/usb/storage/datafab.c
+--- kern_oldest/drivers/usb/storage/datafab.c  2006-05-01 11:55:42.000000000 -0700
++++ kern_fix/drivers/usb/storage/datafab.c     2006-05-01 14:14:13.000000000 -0700
+@@ -265,18 +265,30 @@ static int datafab_read_data(struct us_d
+                       while (sg_idx < use_sg && transferred < len) {
+                               if (len - transferred >= sg[sg_idx].length - current_sg_offset) {
+                                       US_DEBUGP("datafab_read_data:  adding %d bytes to %d byte sg buffer\n", sg[sg_idx].length - current_sg_offset, sg[sg_idx].length);
 +#if SMALL_SCATTERLIST
-+                      sg[n_elem].u.page.page = bh->b_page;
-+                      sg[n_elem].length = bh->b_size;
-+                      sg[n_elem].u.page.offset = bh_offset(bh);
++                                      memcpy(sg[sg_idx].u.address + current_sg_offset,
++                                             buffer + transferred,
++                                             sg[sg_idx].length - current_sg_offset);
 +#else
-                       sg[n_elem].page = bh->b_page;
-                       sg[n_elem].length = bh->b_size;
-                       sg[n_elem].offset = bh_offset(bh);
-+#endif /* !SMALL_SCATTERLIST */
-                       last_phys = bh_phys(bh) + bh->b_size;
-                       n_elem++;
-               }
-Index: linux-2.4.21/drivers/ieee1394/dma.c
-===================================================================
---- linux-2.4.21.orig/drivers/ieee1394/dma.c   2005-06-01 22:52:05.000000000 -0400
-+++ linux-2.4.21/drivers/ieee1394/dma.c        2005-06-01 23:07:51.187564720 -0400
-@@ -97,8 +97,12 @@
-       /* fill scatter/gather list with pages */
-       for(i = 0; i < dma->n_pages; i++) {
-               unsigned long va = (unsigned long) dma->kvirt + i * PAGE_SIZE;
--                      
-+
+                                       memcpy(sg[sg_idx].address + current_sg_offset,
+                                              buffer + transferred,
+                                              sg[sg_idx].length - current_sg_offset);
++#endif
+                                       transferred += sg[sg_idx].length - current_sg_offset;
+                                       current_sg_offset = 0;
+                                       // on to the next sg buffer
+                                       ++sg_idx;
+                               } else {
+                                       US_DEBUGP("datafab_read_data:  adding %d bytes to %d byte sg buffer\n", len - transferred, sg[sg_idx].length);
 +#if SMALL_SCATTERLIST
-+              dma->sglist[i].u.page.page = vmalloc_to_page((void *)va);
++                                      memcpy(sg[sg_idx].u.address + current_sg_offset,
++                                             buffer + transferred,
++                                             len - transferred);
 +#else
-               dma->sglist[i].page = vmalloc_to_page((void *)va);
+                                       memcpy(sg[sg_idx].address + current_sg_offset,
+                                              buffer + transferred,
+                                              len - transferred);
 +#endif
-               dma->sglist[i].length = PAGE_SIZE;
-       }
-Index: linux-2.4.21/drivers/ieee1394/sbp2.c
-===================================================================
---- linux-2.4.21.orig/drivers/ieee1394/sbp2.c  2003-06-13 10:51:34.000000000 -0400
-+++ linux-2.4.21/drivers/ieee1394/sbp2.c       2005-06-01 23:07:51.189564416 -0400
-@@ -2036,11 +2036,19 @@
-                       command->dma_dir = dma_dir;
-                       command->dma_size = sgpnt[0].length;
-                       command->dma_type = CMD_DMA_PAGE;
+                                       current_sg_offset += len - transferred;
+                                       // this sg buffer is only partially full and we're out of data to copy in
+                                       break;
+@@ -355,18 +367,30 @@ static int datafab_write_data(struct us_
+                       while (transferred < len) {
+                               if (len - transferred >= sg[sg_idx].length - current_sg_offset) {
+                                       US_DEBUGP("datafab_write_data:  getting %d bytes from %d byte sg buffer\n", sg[sg_idx].length - current_sg_offset, sg[sg_idx].length);
 +#if SMALL_SCATTERLIST
-+                      command->cmd_dma = pci_map_page(hi->host->pdev,
-+                                                      sgpnt[0].u.page.page,
-+                                                      sgpnt[0].u.page.offset,
-+                                                      command->dma_size,
-+                                                      command->dma_dir);
++                                      memcpy(ptr + transferred,
++                                             sg[sg_idx].u.address + current_sg_offset,
++                                             sg[sg_idx].length - current_sg_offset);
 +#else
-                       command->cmd_dma = pci_map_page(hi->host->pdev,
-                                                       sgpnt[0].page,
-                                                       sgpnt[0].offset,
-                                                       command->dma_size,
-                                                       command->dma_dir);
+                                       memcpy(ptr + transferred,
+                                              sg[sg_idx].address + current_sg_offset,
+                                              sg[sg_idx].length - current_sg_offset);
 +#endif
-                       SBP2_DMA_ALLOC("single page scatter element");
-                       command_orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
-Index: linux-2.4.21/drivers/message/i2o/i2o_scsi.c
-===================================================================
---- linux-2.4.21.orig/drivers/message/i2o/i2o_scsi.c   2002-08-02 20:39:44.000000000 -0400
-+++ linux-2.4.21/drivers/message/i2o/i2o_scsi.c        2005-06-01 23:07:51.190564264 -0400
-@@ -693,7 +693,11 @@
-                       {
-                               *mptr++=direction|0x10000000|sg->length;
-                               len+=sg->length;
+                                       transferred += sg[sg_idx].length - current_sg_offset;
+                                       current_sg_offset = 0;
+                                       // on to the next sg buffer
+                                       ++sg_idx;
+                               } else {
+                                       US_DEBUGP("datafab_write_data:  getting %d bytes from %d byte sg buffer\n", len - transferred, sg[sg_idx].length);
 +#if SMALL_SCATTERLIST
-+                              *mptr++=virt_to_bus(sg->u.address);
++                                      memcpy(ptr + transferred,
++                                             sg[sg_idx].u.address + current_sg_offset,
++                                             len - transferred);
 +#else
-                               *mptr++=virt_to_bus(sg->address);
+                                       memcpy(ptr + transferred,
+                                              sg[sg_idx].address + current_sg_offset,
+                                              len - transferred);
 +#endif
-                               sg++;
-                       }
-                       mptr[-2]=direction|0xD0000000|(sg-1)->length;
-@@ -704,7 +708,11 @@
-                       {
-                               i2o_raw_writel(direction|0x10000000|sg->length, mptr++);
-                               len+=sg->length;
+                                       current_sg_offset += len - transferred;
+                                       // we only copied part of this sg buffer
+                                       break;
+diff -X dontdiff -urp kern_oldest/drivers/usb/storage/freecom.c kern_fix/drivers/usb/storage/freecom.c
+--- kern_oldest/drivers/usb/storage/freecom.c  2006-05-01 11:55:42.000000000 -0700
++++ kern_fix/drivers/usb/storage/freecom.c     2006-05-01 14:14:13.000000000 -0700
+@@ -144,11 +144,20 @@ static void us_transfer_freecom(Scsi_Cmn
+                       if (transfer_amount - total_transferred >= 
+                                       sg[i].length) {
+                               result = usb_stor_transfer_partial(us,
+-                                              sg[i].address, sg[i].length);
 +#if SMALL_SCATTERLIST
-+                              i2o_raw_writel(virt_to_bus(sg->u.address), mptr++);
++                                              sg[i].u.address,
 +#else
-                               i2o_raw_writel(virt_to_bus(sg->address), mptr++);
++                                              sg[i].address,
 +#endif
-                               sg++;
-                       }
-Index: linux-2.4.21/drivers/net/fc/iph5526.c
-===================================================================
---- linux-2.4.21.orig/drivers/net/fc/iph5526.c 2003-06-13 10:51:34.000000000 -0400
-+++ linux-2.4.21/drivers/net/fc/iph5526.c      2005-06-01 23:07:51.193563808 -0400
-@@ -4249,7 +4249,11 @@
-                       if (Cmnd->use_sg) {
-                       int count = 0, j;
-                               for(i = 0; i < no_of_sg; i++) {
++                                              sg[i].length);
+                               total_transferred += sg[i].length;
+                       } else {
+                               result = usb_stor_transfer_partial(us,
 +#if SMALL_SCATTERLIST
-+                              char *addr_ptr = sl2->u.address;
++                                              sg[i].u.address,
 +#else
-                               char *addr_ptr = sl2->address;
+                                               sg[i].address,
 +#endif
-                                       count = sl2->length / SEST_BUFFER_SIZE;
-                                       if (sl2->length % SEST_BUFFER_SIZE)
-                                               count++;
-@@ -4349,7 +4353,11 @@
-                               int count = 0, j;
-                                       count = sl1->length / SEST_BUFFER_SIZE;
-                                       for (j = 0; j < count; j++) {
+                                               transfer_amount - total_transferred);
+                               total_transferred += transfer_amount - total_transferred;
+                       }
+diff -X dontdiff -urp kern_oldest/drivers/usb/storage/isd200.c kern_fix/drivers/usb/storage/isd200.c
+--- kern_oldest/drivers/usb/storage/isd200.c   2006-05-01 11:55:42.000000000 -0700
++++ kern_fix/drivers/usb/storage/isd200.c      2006-05-01 14:14:13.000000000 -0700
+@@ -494,13 +494,21 @@ static void isd200_transfer( struct us_d
+                             sg[i].length) {
+                                 result = isd200_transfer_partial(us, 
+                                                                  srb->sc_data_direction,
 +#if SMALL_SCATTERLIST
-+                                              build_EDB(fi, (char *)sl1->u.address, 0, SEST_BUFFER_SIZE);
++                                                                 sg[i].u.address, 
 +#else
-                                               build_EDB(fi, (char *)sl1->address, 0, SEST_BUFFER_SIZE);
+                                                                  sg[i].address, 
 +#endif
-                                               memcpy(fi->q.ptr_edb[fi->q.edb_buffer_indx], &(fi->g.edb), sizeof(EDB));
-                                               /* Mark this EDB as being in use */
-                                               fi->q.free_edb_list[fi->q.edb_buffer_indx] = EDB_BUSY;
-@@ -4358,13 +4366,21 @@
-                                                * safe.
-                                                */
-                                               update_EDB_indx(fi);
+                                                                  sg[i].length);
+                                 total_transferred += sg[i].length;
+                         } else
+                                 result = isd200_transfer_partial(us, 
+                                                                  srb->sc_data_direction,                            
 +#if SMALL_SCATTERLIST
-+                                              sl1->u.address += SEST_BUFFER_SIZE;
++                                                                 sg[i].u.address,
 +#else
-                                               sl1->address += SEST_BUFFER_SIZE;
+                                                                  sg[i].address,
 +#endif
-                                       }
-                                       /* Just in case itz not a multiple of 
-                                        * SEST_BUFFER_SIZE bytes.
-                                        */
-                                       if (sl1->length % SEST_BUFFER_SIZE) {
+                                                                  transfer_amount - total_transferred);
+                         /* if we get an error, end the loop here */
+@@ -1396,10 +1404,18 @@ void isd200_data_copy(Scsi_Cmnd *srb, ch
+                               /* transfer the lesser of the next buffer or the
+                                * remaining data */
+                               if (len - total >= sg[i].length) {
 +#if SMALL_SCATTERLIST
-+                                              build_EDB(fi, (char *)sl1->u.address, 0, sl1->length % SEST_BUFFER_SIZE);
++                                      memcpy(sg[i].u.address, src + total, sg[i].length);
 +#else
-                                               build_EDB(fi, (char *)sl1->address, 0, sl1->length % SEST_BUFFER_SIZE);
+                                       memcpy(sg[i].address, src + total, sg[i].length);
 +#endif
-                                               memcpy(fi->q.ptr_edb[fi->q.edb_buffer_indx], &(fi->g.edb), sizeof(EDB));
-                                               fi->q.free_edb_list[fi->q.edb_buffer_indx] = EDB_BUSY;
-                                               update_EDB_indx(fi);
-Index: linux-2.4.21/drivers/net/wireless/airo.c
-===================================================================
---- linux-2.4.21.orig/drivers/net/wireless/airo.c      2005-06-01 22:51:55.000000000 -0400
-+++ linux-2.4.21/drivers/net/wireless/airo.c   2005-06-01 23:07:51.198563048 -0400
-@@ -1584,11 +1584,20 @@
-               aes_counter[12] = (u8)(counter >> 24);
-               counter++;
-               memcpy (plain, aes_counter, 16);
+                                       total += sg[i].length;
+                               } else {
 +#if SMALL_SCATTERLIST
-+              sg[0].u.page.page = virt_to_page(plain);
-+              sg[0].u.page.offset = ((long) plain & ~PAGE_MASK);
++                                      memcpy(sg[i].u.address, src + total, len - total);
 +#else
-               sg[0].page = virt_to_page(plain);
-               sg[0].offset = ((long) plain & ~PAGE_MASK);
+                                       memcpy(sg[i].address, src + total, len - total);
 +#endif
-               sg[0].length = 16;
-               crypto_cipher_encrypt(tfm, sg, sg, 16);
+                                       total = len;
+                               }
+                       } 
+diff -X dontdiff -urp kern_oldest/drivers/usb/storage/jumpshot.c kern_fix/drivers/usb/storage/jumpshot.c
+--- kern_oldest/drivers/usb/storage/jumpshot.c 2006-05-01 11:55:42.000000000 -0700
++++ kern_fix/drivers/usb/storage/jumpshot.c    2006-05-01 14:14:13.000000000 -0700
+@@ -341,18 +341,30 @@ static int jumpshot_read_data(struct us_
+                         while (sg_idx < use_sg && transferred < len) {
+                                 if (len - transferred >= sg[sg_idx].length - current_sg_offset) {
+                                         US_DEBUGP("jumpshot_read_data:  adding %d bytes to %d byte sg buffer\n", sg[sg_idx].length - current_sg_offset, sg[sg_idx].length);
 +#if SMALL_SCATTERLIST
-+              cipher = kmap(sg[0].u.page.page) + sg[0].u.page.offset;
++                                        memcpy(sg[sg_idx].u.address + current_sg_offset,
++                                               buffer + transferred,
++                                               sg[sg_idx].length - current_sg_offset);
 +#else
-               cipher = kmap(sg[0].page) + sg[0].offset;
+                                         memcpy(sg[sg_idx].address + current_sg_offset,
+                                                buffer + transferred,
+                                                sg[sg_idx].length - current_sg_offset);
 +#endif
-               for (j=0; (j<16) && (i< (sizeof(context->coeff)/sizeof(context->coeff[0]))); ) {
-                       context->coeff[i++] = ntohl(*(u32 *)&cipher[j]);
-                       j += 4;
-Index: linux-2.4.21/drivers/usb/microtek.c
-===================================================================
---- linux-2.4.21.orig/drivers/usb/microtek.c   2002-11-28 18:53:14.000000000 -0500
-+++ linux-2.4.21/drivers/usb/microtek.c        2005-06-01 23:07:51.199562896 -0400
-@@ -623,7 +623,11 @@
-       context->fragment++;
-       mts_int_submit_urb(transfer,
-                       context->data_pipe,
+                                         transferred += sg[sg_idx].length - current_sg_offset;
+                                         current_sg_offset = 0;
+                                         // on to the next sg buffer
+                                         ++sg_idx;
+                                 } else {
+                                         US_DEBUGP("jumpshot_read_data:  adding %d bytes to %d byte sg buffer\n", len - transferred, sg[sg_idx].length);
 +#if SMALL_SCATTERLIST
-+                      sg[context->fragment].u.address,
++                                        memcpy(sg[sg_idx].u.address + current_sg_offset,
++                                               buffer + transferred,
++                                               len - transferred);
 +#else
-                       sg[context->fragment].address,
+                                         memcpy(sg[sg_idx].address + current_sg_offset,
+                                                buffer + transferred,
+                                                len - transferred);
 +#endif
-                       sg[context->fragment].length,
-                       context->fragment + 1 == context->srb->use_sg ? mts_data_done : mts_do_sg);
-       return;
-@@ -667,7 +671,11 @@
-       } else {
-               MTS_DEBUG("Using scatter/gather\n");
-               sg = srb->buffer;
+                                         current_sg_offset += len - transferred;
+                                         // this sg buffer is only partially full and we're out of data to copy in
+                                         break;
+@@ -422,18 +434,31 @@ static int jumpshot_write_data(struct us
+                         while (transferred < len) {
+                                 if (len - transferred >= sg[sg_idx].length - current_sg_offset) {
+                                         US_DEBUGP("jumpshot_write_data:  getting %d bytes from %d byte sg buffer\n", sg[sg_idx].length - current_sg_offset, sg[sg_idx].length);
 +#if SMALL_SCATTERLIST
-+              desc->context.data = sg[0].u.address;
++                                        memcpy(ptr + transferred,
++                                               sg[sg_idx].u.address + current_sg_offset,
++                                               sg[sg_idx].length - current_sg_offset);
 +#else
-               desc->context.data = sg[0].address;
+                                         memcpy(ptr + transferred,
+                                                sg[sg_idx].address + current_sg_offset,
+                                                sg[sg_idx].length - current_sg_offset);
++
 +#endif
-               desc->context.data_length = sg[0].length;
-       }
-Index: linux-2.4.21/drivers/usb/hpusbscsi.c
-===================================================================
---- linux-2.4.21.orig/drivers/usb/hpusbscsi.c  2003-06-13 10:51:36.000000000 -0400
-+++ linux-2.4.21/drivers/usb/hpusbscsi.c       2005-06-01 23:07:51.199562896 -0400
-@@ -576,6 +576,17 @@
-               hpusbscsi->state = HP_STATE_WORKING;
-       PDEBUG(2, "state= %s", states[hpusbscsi->state]);
+                                         transferred += sg[sg_idx].length - current_sg_offset;
+                                         current_sg_offset = 0;
+                                         // on to the next sg buffer
+                                         ++sg_idx;
+                                 } else {
+                                         US_DEBUGP("jumpshot_write_data:  getting %d bytes from %d byte sg buffer\n", len - transferred, sg[sg_idx].length);
 +#if SMALL_SCATTERLIST
-+        FILL_BULK_URB(
-+                u,
-+                hpusbscsi->dev,
-+                hpusbscsi->current_data_pipe,
-+                sg[hpusbscsi->fragment].u.address,
-+                sg[hpusbscsi->fragment++].length,
-+                callback,
-+                hpusbscsi
-+        );
++                                        memcpy(ptr + transferred,
++                                               sg[sg_idx].u.address + current_sg_offset,
++                                               len - transferred);
 +#else
-         FILL_BULK_URB(
-                 u,
-                 hpusbscsi->dev,
-@@ -585,6 +596,7 @@
-                 callback,
-                 hpusbscsi
-         );
+                                         memcpy(ptr + transferred,
+                                                sg[sg_idx].address + current_sg_offset,
+                                                len - transferred);
 +#endif
-         res = usb_submit_urb(u);
-         if (res)
-Index: linux-2.4.21/drivers/usb/storage/protocol.c
-===================================================================
---- linux-2.4.21.orig/drivers/usb/storage/protocol.c   2002-08-02 20:39:45.000000000 -0400
-+++ linux-2.4.21/drivers/usb/storage/protocol.c        2005-06-01 23:07:51.200562744 -0400
-@@ -72,7 +72,11 @@
+                                         current_sg_offset += len - transferred;
+                                         // we only copied part of this sg buffer
+                                         break;
+diff -X dontdiff -urp kern_oldest/drivers/usb/storage/protocol.c kern_fix/drivers/usb/storage/protocol.c
+--- kern_oldest/drivers/usb/storage/protocol.c 2006-05-01 11:55:42.000000000 -0700
++++ kern_fix/drivers/usb/storage/protocol.c    2006-05-01 14:14:13.000000000 -0700
+@@ -72,7 +72,11 @@ void fix_inquiry_data(Scsi_Cmnd *srb)
                struct scatterlist *sg;
  
                sg = (struct scatterlist *) srb->request_buffer;
@@ -3559,109 +3818,85 @@ Index: linux-2.4.21/drivers/usb/storage/protocol.c
        } else
                data_ptr = (unsigned char *)srb->request_buffer;
  
-Index: linux-2.4.21/drivers/usb/storage/transport.c
-===================================================================
---- linux-2.4.21.orig/drivers/usb/storage/transport.c  2005-06-01 22:51:52.000000000 -0400
-+++ linux-2.4.21/drivers/usb/storage/transport.c       2005-06-01 23:07:51.201562592 -0400
-@@ -592,11 +592,20 @@
-                       if (transfer_amount - total_transferred >= 
-                                       sg[i].length) {
-                               result = usb_stor_transfer_partial(us,
--                                              sg[i].address, sg[i].length);
-+#if SMALL_SCATTERLIST
-+                                              sg[i].u.address,
-+#else
-+                                              sg[i].address,
-+#endif
-+                                              sg[i].length);
-                               total_transferred += sg[i].length;
-                       } else
-                               result = usb_stor_transfer_partial(us,
-+#if SMALL_SCATTERLIST
-+                                              sg[i].u.address,
-+#else
-                                               sg[i].address,
-+#endif
-                                               transfer_amount - total_transferred);
+diff -X dontdiff -urp kern_oldest/drivers/usb/storage/scsiglue.c kern_fix/drivers/usb/storage/scsiglue.c
+--- kern_oldest/drivers/usb/storage/scsiglue.c 2006-05-01 11:55:42.000000000 -0700
++++ kern_fix/drivers/usb/storage/scsiglue.c    2006-05-01 14:14:13.000000000 -0700
+@@ -606,7 +606,11 @@ int usb_stor_scsiSense10to6( Scsi_Cmnd* 
+           }
  
-                       /* if we get an error, end the loop here */
-Index: linux-2.4.21/drivers/usb/storage/usb.c
-===================================================================
---- linux-2.4.21.orig/drivers/usb/storage/usb.c        2005-06-01 22:51:52.000000000 -0400
-+++ linux-2.4.21/drivers/usb/storage/usb.c     2005-06-01 23:07:51.202562440 -0400
-@@ -291,13 +291,21 @@
-       if (us->srb->use_sg) {
-               sg = (struct scatterlist *)us->srb->request_buffer;
-               for (i=0; i<us->srb->use_sg; i++)
+         /* copy one byte */
 +#if SMALL_SCATTERLIST
-+                      memset(sg[i].u.address, 0, sg[i].length);
++        sg[db].u.address[di] = sg[sb].u.address[si];
 +#else
-                       memset(sg[i].address, 0, sg[i].length);
+         sg[db].address[di] = sg[sb].address[si];
 +#endif
-               for (i=0, transferred=0; 
-                               i<us->srb->use_sg && transferred < len;
-                               i++) {
-                       amt = sg[i].length > len-transferred ? 
-                                       len-transferred : sg[i].length;
+         /* get next destination */
+         if ( sg[db].length-1 == di )
+@@ -644,7 +648,11 @@ int usb_stor_scsiSense10to6( Scsi_Cmnd* 
+             break;
+           }
 +#if SMALL_SCATTERLIST
-+                      memcpy(sg[i].u.address, data+transferred, amt);
++        sg[db].u.address[di] = 0;
 +#else
-                       memcpy(sg[i].address, data+transferred, amt);
+         sg[db].address[di] = 0;
 +#endif
-                       transferred -= amt;
-               }
-       } else {
-Index: linux-2.4.21/drivers/usb/storage/shuttle_usbat.c
-===================================================================
---- linux-2.4.21.orig/drivers/usb/storage/shuttle_usbat.c      2003-06-13 10:51:37.000000000 -0400
-+++ linux-2.4.21/drivers/usb/storage/shuttle_usbat.c   2005-06-01 23:07:51.202562440 -0400
-@@ -217,7 +217,11 @@
-               sg = (struct scatterlist *)data;
-               for (i=0; i<use_sg && transferred<len; i++) {
-                       result = usbat_raw_bulk(us, direction,
+         /* get next destination */
+         if ( sg[db].length-1 == di )
+@@ -794,7 +802,11 @@ int usb_stor_scsiSense6to10( Scsi_Cmnd* 
+           }
+         /* copy one byte */
 +#if SMALL_SCATTERLIST
-+                              sg[i].u.address, 
++        sg[db].u.address[di] = sg[sb].u.address[si];
 +#else
-                               sg[i].address, 
+         sg[db].address[di] = sg[sb].address[si];
 +#endif
-                               len-transferred > sg[i].length ?
-                                       sg[i].length : len-transferred);
-                       if (result!=US_BULK_TRANSFER_GOOD)
-@@ -742,17 +746,29 @@
-                       while (amount<len) {
-                               if (len - amount >= 
-                                         sg[sg_segment].length-sg_offset) {
+         /* get next destination */
+         if ( di == 0 )
+@@ -831,7 +843,11 @@ int usb_stor_scsiSense6to10( Scsi_Cmnd* 
+             break;
+           }
 +#if SMALL_SCATTERLIST
-+                                memcpy(sg[sg_segment].u.address + sg_offset,
-+                                      buffer + amount,
-+                                      sg[sg_segment].length - sg_offset);
++        sg[db].u.address[di] = tempBuffer[element-USB_STOR_SCSI_SENSE_HDRSZ];
 +#else
-                                 memcpy(sg[sg_segment].address + sg_offset,
-                                       buffer + amount,
-                                       sg[sg_segment].length - sg_offset);
-+#endif
-                                 amount += 
-                                         sg[sg_segment].length-sg_offset;
-                                 sg_segment++;
-                                 sg_offset=0;
-                               } else {
+         sg[db].address[di] = tempBuffer[element-USB_STOR_SCSI_SENSE_HDRSZ];
++#endif
+         /* get next destination */
+         if ( di == 0 )
+@@ -881,6 +897,15 @@ void usb_stor_scsiSenseParseBuffer( Scsi
+                 if ( element < USB_STOR_SCSI_SENSE_HDRSZ )
+                   {
+                     /* fill in the pointers for both header types */
 +#if SMALL_SCATTERLIST
-+                                memcpy(sg[sg_segment].u.address + sg_offset,
-+                                      buffer + amount,
-+                                      len - amount);
++                    the6->array[element] = &(sg[i].u.address[j]);
++                    the10->array[element] = &(sg[i].u.address[j]);
++                  }
++                else if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ )
++                  {
++                    /* only the longer headers still cares now */
++                    the10->array[element] = &(sg[i].u.address[j]);
 +#else
-                                 memcpy(sg[sg_segment].address + sg_offset,
-                                       buffer + amount,
-                                       len - amount);
+                     the6->array[element] = &(sg[i].address[j]);
+                     the10->array[element] = &(sg[i].address[j]);
+                   }
+@@ -888,6 +913,7 @@ void usb_stor_scsiSenseParseBuffer( Scsi
+                   {
+                     /* only the longer headers still cares now */
+                     the10->array[element] = &(sg[i].address[j]);
 +#endif
-                                 sg_offset += (len - amount);
-                                 amount = len;
-                               }
-Index: linux-2.4.21/drivers/usb/storage/sddr09.c
-===================================================================
---- linux-2.4.21.orig/drivers/usb/storage/sddr09.c     2003-06-13 10:51:37.000000000 -0400
-+++ linux-2.4.21/drivers/usb/storage/sddr09.c  2005-06-01 23:07:51.204562136 -0400
-@@ -387,7 +387,11 @@
+                   }
+                 /* increase element counter */
+                 element++;
+diff -X dontdiff -urp kern_oldest/drivers/usb/storage/sddr09.c kern_fix/drivers/usb/storage/sddr09.c
+--- kern_oldest/drivers/usb/storage/sddr09.c   2006-05-01 11:55:42.000000000 -0700
++++ kern_fix/drivers/usb/storage/sddr09.c      2006-05-01 14:14:13.000000000 -0700
+@@ -387,7 +387,11 @@ sddr09_bulk_transport(struct us_data *us
                        unsigned char *buf;
                        unsigned int length;
  
@@ -3673,7 +3908,7 @@ Index: linux-2.4.21/drivers/usb/storage/sddr09.c
                        length = len-transferred;
                        if (length > sg[i].length)
                                length = sg[i].length;
-@@ -903,7 +907,11 @@
+@@ -903,7 +907,11 @@ sddr09_read_data(struct us_data *us,
                int transferred = 0;
  
                for (i=0; i<use_sg && transferred<len; i++) {
@@ -3685,7 +3920,7 @@ Index: linux-2.4.21/drivers/usb/storage/sddr09.c
                        unsigned int length;
  
                        length = len-transferred;
-@@ -1085,10 +1093,17 @@
+@@ -1085,10 +1093,17 @@ sddr09_write_data(struct us_data *us,
                        return USB_STOR_TRANSPORT_ERROR;
  
                for (i=0; i<use_sg && transferred<len; i++) {
@@ -3703,7 +3938,7 @@ Index: linux-2.4.21/drivers/usb/storage/sddr09.c
                        transferred += sg[i].length;
                }
                ptr = buffer;
-@@ -1307,17 +1322,35 @@
+@@ -1307,17 +1322,35 @@ sddr09_read_map(struct us_data *us) {
  
        for (i=0; i<alloc_blocks; i++) {
                if (i<alloc_blocks-1) {
@@ -3739,7 +3974,7 @@ Index: linux-2.4.21/drivers/usb/storage/sddr09.c
                if (sg[i].address == NULL) {
                        for (i=0; i<alloc_blocks; i++)
                                if (sg[i].address != NULL)
-@@ -1325,14 +1358,18 @@
+@@ -1325,14 +1358,18 @@ sddr09_read_map(struct us_data *us) {
                        kfree(sg);
                        return 0;
                }
@@ -3759,7 +3994,7 @@ Index: linux-2.4.21/drivers/usb/storage/sddr09.c
                kfree(sg);
                return -1;
        }
-@@ -1348,7 +1385,12 @@
+@@ -1348,7 +1385,12 @@ sddr09_read_map(struct us_data *us) {
                info->lba_to_pba = NULL;
                info->pba_to_lba = NULL;
                for (i=0; i<alloc_blocks; i++)
@@ -3772,7 +4007,7 @@ Index: linux-2.4.21/drivers/usb/storage/sddr09.c
                kfree(sg);
                return 0;
        }
-@@ -1356,7 +1398,11 @@
+@@ -1356,7 +1398,11 @@ sddr09_read_map(struct us_data *us) {
        for (i = 0; i < numblocks; i++)
                info->lba_to_pba[i] = info->pba_to_lba[i] = UNDEF;
  
@@ -3784,7 +4019,7 @@ Index: linux-2.4.21/drivers/usb/storage/sddr09.c
  
        /*
         * Define lba-pba translation table
-@@ -1374,7 +1420,11 @@
+@@ -1374,7 +1420,11 @@ sddr09_read_map(struct us_data *us) {
        printk("sddr09: no translation today\n");
  #else
        for (i=0; i<numblocks; i++) {
@@ -3796,7 +4031,7 @@ Index: linux-2.4.21/drivers/usb/storage/sddr09.c
  
                if (i == 0 || i == 1) {
                        info->pba_to_lba[i] = UNUSABLE;
-@@ -1477,7 +1527,11 @@
+@@ -1477,7 +1527,11 @@ sddr09_read_map(struct us_data *us) {
        US_DEBUGP("Found %d LBA's\n", lbact);
  
        for (i=0; i<alloc_blocks; i++)
@@ -3808,11 +4043,10 @@ Index: linux-2.4.21/drivers/usb/storage/sddr09.c
        kfree(sg);
        return 0;
  }
-Index: linux-2.4.21/drivers/usb/storage/sddr55.c
-===================================================================
---- linux-2.4.21.orig/drivers/usb/storage/sddr55.c     2003-06-13 10:51:37.000000000 -0400
-+++ linux-2.4.21/drivers/usb/storage/sddr55.c  2005-06-01 23:07:51.204562136 -0400
-@@ -402,9 +402,15 @@
+diff -X dontdiff -urp kern_oldest/drivers/usb/storage/sddr55.c kern_fix/drivers/usb/storage/sddr55.c
+--- kern_oldest/drivers/usb/storage/sddr55.c   2006-05-01 11:55:42.000000000 -0700
++++ kern_fix/drivers/usb/storage/sddr55.c      2006-05-01 14:14:13.000000000 -0700
+@@ -402,9 +402,15 @@ static int sddr55_read_data(struct us_da
        if (use_sg) {
                transferred = 0;
                for (i=0; i<use_sg && transferred<len; i++) {
@@ -3828,7 +4062,7 @@ Index: linux-2.4.21/drivers/usb/storage/sddr55.c
                        transferred += sg[i].length;
                }
                kfree(buffer);
-@@ -462,9 +468,15 @@
+@@ -462,9 +468,15 @@ static int sddr55_write_data(struct us_d
  
                transferred = 0;
                for (i=0; i<use_sg && transferred<len; i++) {
@@ -3844,527 +4078,129 @@ Index: linux-2.4.21/drivers/usb/storage/sddr55.c
                        transferred += sg[i].length;
                }
  
-Index: linux-2.4.21/drivers/usb/storage/freecom.c
-===================================================================
---- linux-2.4.21.orig/drivers/usb/storage/freecom.c    2003-06-13 10:51:37.000000000 -0400
-+++ linux-2.4.21/drivers/usb/storage/freecom.c 2005-06-01 23:07:51.205561984 -0400
-@@ -144,11 +144,20 @@
-                       if (transfer_amount - total_transferred >= 
-                                       sg[i].length) {
-                               result = usb_stor_transfer_partial(us,
--                                              sg[i].address, sg[i].length);
-+#if SMALL_SCATTERLIST
-+                                              sg[i].u.address,
-+#else
-+                                              sg[i].address,
-+#endif
-+                                              sg[i].length);
-                               total_transferred += sg[i].length;
-                       } else {
-                               result = usb_stor_transfer_partial(us,
-+#if SMALL_SCATTERLIST
-+                                              sg[i].u.address,
-+#else
-                                               sg[i].address,
-+#endif
-                                               transfer_amount - total_transferred);
-                               total_transferred += transfer_amount - total_transferred;
-                       }
-Index: linux-2.4.21/drivers/usb/storage/isd200.c
-===================================================================
---- linux-2.4.21.orig/drivers/usb/storage/isd200.c     2003-06-13 10:51:37.000000000 -0400
-+++ linux-2.4.21/drivers/usb/storage/isd200.c  2005-06-01 23:07:51.206561832 -0400
-@@ -494,13 +494,21 @@
-                             sg[i].length) {
-                                 result = isd200_transfer_partial(us, 
-                                                                  srb->sc_data_direction,
-+#if SMALL_SCATTERLIST
-+                                                                 sg[i].u.address, 
-+#else
-                                                                  sg[i].address, 
-+#endif
-                                                                  sg[i].length);
-                                 total_transferred += sg[i].length;
-                         } else
-                                 result = isd200_transfer_partial(us, 
-                                                                  srb->sc_data_direction,                            
-+#if SMALL_SCATTERLIST
-+                                                                 sg[i].u.address,
-+#else
-                                                                  sg[i].address,
-+#endif
-                                                                  transfer_amount - total_transferred);
-                         /* if we get an error, end the loop here */
-@@ -1396,10 +1404,18 @@
-                               /* transfer the lesser of the next buffer or the
-                                * remaining data */
-                               if (len - total >= sg[i].length) {
-+#if SMALL_SCATTERLIST
-+                                      memcpy(sg[i].u.address, src + total, sg[i].length);
-+#else
-                                       memcpy(sg[i].address, src + total, sg[i].length);
-+#endif
-                                       total += sg[i].length;
-                               } else {
-+#if SMALL_SCATTERLIST
-+                                      memcpy(sg[i].u.address, src + total, len - total);
-+#else
-                                       memcpy(sg[i].address, src + total, len - total);
-+#endif
-                                       total = len;
-                               }
-                       } 
-Index: linux-2.4.21/drivers/usb/storage/datafab.c
-===================================================================
---- linux-2.4.21.orig/drivers/usb/storage/datafab.c    2003-06-13 10:51:37.000000000 -0400
-+++ linux-2.4.21/drivers/usb/storage/datafab.c 2005-06-01 23:07:51.207561680 -0400
-@@ -265,18 +265,30 @@
-                       while (sg_idx < use_sg && transferred < len) {
-                               if (len - transferred >= sg[sg_idx].length - current_sg_offset) {
-                                       US_DEBUGP("datafab_read_data:  adding %d bytes to %d byte sg buffer\n", sg[sg_idx].length - current_sg_offset, sg[sg_idx].length);
-+#if SMALL_SCATTERLIST
-+                                      memcpy(sg[sg_idx].u.address + current_sg_offset,
-+                                             buffer + transferred,
-+                                             sg[sg_idx].length - current_sg_offset);
-+#else
-                                       memcpy(sg[sg_idx].address + current_sg_offset,
-                                              buffer + transferred,
-                                              sg[sg_idx].length - current_sg_offset);
-+#endif
-                                       transferred += sg[sg_idx].length - current_sg_offset;
-                                       current_sg_offset = 0;
-                                       // on to the next sg buffer
-                                       ++sg_idx;
-                               } else {
-                                       US_DEBUGP("datafab_read_data:  adding %d bytes to %d byte sg buffer\n", len - transferred, sg[sg_idx].length);
+diff -X dontdiff -urp kern_oldest/drivers/usb/storage/shuttle_usbat.c kern_fix/drivers/usb/storage/shuttle_usbat.c
+--- kern_oldest/drivers/usb/storage/shuttle_usbat.c    2006-05-01 11:55:42.000000000 -0700
++++ kern_fix/drivers/usb/storage/shuttle_usbat.c       2006-05-01 14:14:13.000000000 -0700
+@@ -217,7 +217,11 @@ static int usbat_bulk_transport(struct u
+               sg = (struct scatterlist *)data;
+               for (i=0; i<use_sg && transferred<len; i++) {
+                       result = usbat_raw_bulk(us, direction,
 +#if SMALL_SCATTERLIST
-+                                      memcpy(sg[sg_idx].u.address + current_sg_offset,
-+                                             buffer + transferred,
-+                                             len - transferred);
++                              sg[i].u.address, 
 +#else
-                                       memcpy(sg[sg_idx].address + current_sg_offset,
-                                              buffer + transferred,
-                                              len - transferred);
+                               sg[i].address, 
 +#endif
-                                       current_sg_offset += len - transferred;
-                                       // this sg buffer is only partially full and we're out of data to copy in
-                                       break;
-@@ -355,18 +367,30 @@
-                       while (transferred < len) {
-                               if (len - transferred >= sg[sg_idx].length - current_sg_offset) {
-                                       US_DEBUGP("datafab_write_data:  getting %d bytes from %d byte sg buffer\n", sg[sg_idx].length - current_sg_offset, sg[sg_idx].length);
+                               len-transferred > sg[i].length ?
+                                       sg[i].length : len-transferred);
+                       if (result!=US_BULK_TRANSFER_GOOD)
+@@ -742,17 +746,29 @@ int usbat_handle_read10(struct us_data *
+                       while (amount<len) {
+                               if (len - amount >= 
+                                         sg[sg_segment].length-sg_offset) {
 +#if SMALL_SCATTERLIST
-+                                      memcpy(ptr + transferred,
-+                                             sg[sg_idx].u.address + current_sg_offset,
-+                                             sg[sg_idx].length - current_sg_offset);
++                                memcpy(sg[sg_segment].u.address + sg_offset,
++                                      buffer + amount,
++                                      sg[sg_segment].length - sg_offset);
 +#else
-                                       memcpy(ptr + transferred,
-                                              sg[sg_idx].address + current_sg_offset,
-                                              sg[sg_idx].length - current_sg_offset);
+                                 memcpy(sg[sg_segment].address + sg_offset,
+                                       buffer + amount,
+                                       sg[sg_segment].length - sg_offset);
 +#endif
-                                       transferred += sg[sg_idx].length - current_sg_offset;
-                                       current_sg_offset = 0;
-                                       // on to the next sg buffer
-                                       ++sg_idx;
+                                 amount += 
+                                         sg[sg_segment].length-sg_offset;
+                                 sg_segment++;
+                                 sg_offset=0;
                                } else {
-                                       US_DEBUGP("datafab_write_data:  getting %d bytes from %d byte sg buffer\n", len - transferred, sg[sg_idx].length);
-+#if SMALL_SCATTERLIST
-+                                      memcpy(ptr + transferred,
-+                                             sg[sg_idx].u.address + current_sg_offset,
-+                                             len - transferred);
-+#else
-                                       memcpy(ptr + transferred,
-                                              sg[sg_idx].address + current_sg_offset,
-                                              len - transferred);
-+#endif
-                                       current_sg_offset += len - transferred;
-                                       // we only copied part of this sg buffer
-                                       break;
-Index: linux-2.4.21/drivers/usb/storage/jumpshot.c
-===================================================================
---- linux-2.4.21.orig/drivers/usb/storage/jumpshot.c   2003-06-13 10:51:37.000000000 -0400
-+++ linux-2.4.21/drivers/usb/storage/jumpshot.c        2005-06-01 23:07:51.208561528 -0400
-@@ -341,18 +341,30 @@
-                         while (sg_idx < use_sg && transferred < len) {
-                                 if (len - transferred >= sg[sg_idx].length - current_sg_offset) {
-                                         US_DEBUGP("jumpshot_read_data:  adding %d bytes to %d byte sg buffer\n", sg[sg_idx].length - current_sg_offset, sg[sg_idx].length);
-+#if SMALL_SCATTERLIST
-+                                        memcpy(sg[sg_idx].u.address + current_sg_offset,
-+                                               buffer + transferred,
-+                                               sg[sg_idx].length - current_sg_offset);
-+#else
-                                         memcpy(sg[sg_idx].address + current_sg_offset,
-                                                buffer + transferred,
-                                                sg[sg_idx].length - current_sg_offset);
-+#endif
-                                         transferred += sg[sg_idx].length - current_sg_offset;
-                                         current_sg_offset = 0;
-                                         // on to the next sg buffer
-                                         ++sg_idx;
-                                 } else {
-                                         US_DEBUGP("jumpshot_read_data:  adding %d bytes to %d byte sg buffer\n", len - transferred, sg[sg_idx].length);
-+#if SMALL_SCATTERLIST
-+                                        memcpy(sg[sg_idx].u.address + current_sg_offset,
-+                                               buffer + transferred,
-+                                               len - transferred);
-+#else
-                                         memcpy(sg[sg_idx].address + current_sg_offset,
-                                                buffer + transferred,
-                                                len - transferred);
-+#endif
-                                         current_sg_offset += len - transferred;
-                                         // this sg buffer is only partially full and we're out of data to copy in
-                                         break;
-@@ -422,18 +434,31 @@
-                         while (transferred < len) {
-                                 if (len - transferred >= sg[sg_idx].length - current_sg_offset) {
-                                         US_DEBUGP("jumpshot_write_data:  getting %d bytes from %d byte sg buffer\n", sg[sg_idx].length - current_sg_offset, sg[sg_idx].length);
-+#if SMALL_SCATTERLIST
-+                                        memcpy(ptr + transferred,
-+                                               sg[sg_idx].u.address + current_sg_offset,
-+                                               sg[sg_idx].length - current_sg_offset);
-+#else
-                                         memcpy(ptr + transferred,
-                                                sg[sg_idx].address + current_sg_offset,
-                                                sg[sg_idx].length - current_sg_offset);
-+
-+#endif
-                                         transferred += sg[sg_idx].length - current_sg_offset;
-                                         current_sg_offset = 0;
-                                         // on to the next sg buffer
-                                         ++sg_idx;
-                                 } else {
-                                         US_DEBUGP("jumpshot_write_data:  getting %d bytes from %d byte sg buffer\n", len - transferred, sg[sg_idx].length);
-+#if SMALL_SCATTERLIST
-+                                        memcpy(ptr + transferred,
-+                                               sg[sg_idx].u.address + current_sg_offset,
-+                                               len - transferred);
-+#else
-                                         memcpy(ptr + transferred,
-                                                sg[sg_idx].address + current_sg_offset,
-                                                len - transferred);
-+#endif
-                                         current_sg_offset += len - transferred;
-                                         // we only copied part of this sg buffer
-                                         break;
-Index: linux-2.4.21/drivers/usb/storage/scsiglue.c
-===================================================================
---- linux-2.4.21.orig/drivers/usb/storage/scsiglue.c   2005-06-01 22:51:52.000000000 -0400
-+++ linux-2.4.21/drivers/usb/storage/scsiglue.c        2005-06-01 23:07:51.209561376 -0400
-@@ -606,7 +606,11 @@
-           }
-         /* copy one byte */
-+#if SMALL_SCATTERLIST
-+        sg[db].u.address[di] = sg[sb].u.address[si];
-+#else
-         sg[db].address[di] = sg[sb].address[si];
-+#endif
-         /* get next destination */
-         if ( sg[db].length-1 == di )
-@@ -644,7 +648,11 @@
-             break;
-           }
 +#if SMALL_SCATTERLIST
-+        sg[db].u.address[di] = 0;
++                                memcpy(sg[sg_segment].u.address + sg_offset,
++                                      buffer + amount,
++                                      len - amount);
 +#else
-         sg[db].address[di] = 0;
+                                 memcpy(sg[sg_segment].address + sg_offset,
+                                       buffer + amount,
+                                       len - amount);
 +#endif
-         /* get next destination */
-         if ( sg[db].length-1 == di )
-@@ -794,7 +802,11 @@
-           }
-         /* copy one byte */
+                                 sg_offset += (len - amount);
+                                 amount = len;
+                               }
+diff -X dontdiff -urp kern_oldest/drivers/usb/storage/transport.c kern_fix/drivers/usb/storage/transport.c
+--- kern_oldest/drivers/usb/storage/transport.c        2006-05-01 11:55:42.000000000 -0700
++++ kern_fix/drivers/usb/storage/transport.c   2006-05-01 14:14:13.000000000 -0700
+@@ -592,11 +592,20 @@ void usb_stor_transfer(Scsi_Cmnd *srb, s
+                       if (transfer_amount - total_transferred >= 
+                                       sg[i].length) {
+                               result = usb_stor_transfer_partial(us,
+-                                              sg[i].address, sg[i].length);
 +#if SMALL_SCATTERLIST
-+        sg[db].u.address[di] = sg[sb].u.address[si];
++                                              sg[i].u.address,
 +#else
-         sg[db].address[di] = sg[sb].address[si];
++                                              sg[i].address,
 +#endif
-         /* get next destination */
-         if ( di == 0 )
-@@ -831,7 +843,11 @@
-             break;
-           }
++                                              sg[i].length);
+                               total_transferred += sg[i].length;
+                       } else
+                               result = usb_stor_transfer_partial(us,
 +#if SMALL_SCATTERLIST
-+        sg[db].u.address[di] = tempBuffer[element-USB_STOR_SCSI_SENSE_HDRSZ];
++                                              sg[i].u.address,
 +#else
-         sg[db].address[di] = tempBuffer[element-USB_STOR_SCSI_SENSE_HDRSZ];
+                                               sg[i].address,
 +#endif
+                                               transfer_amount - total_transferred);
  
-         /* get next destination */
-         if ( di == 0 )
-@@ -881,6 +897,15 @@
-                 if ( element < USB_STOR_SCSI_SENSE_HDRSZ )
-                   {
-                     /* fill in the pointers for both header types */
+                       /* if we get an error, end the loop here */
+diff -X dontdiff -urp kern_oldest/drivers/usb/storage/usb.c kern_fix/drivers/usb/storage/usb.c
+--- kern_oldest/drivers/usb/storage/usb.c      2006-05-01 11:55:42.000000000 -0700
++++ kern_fix/drivers/usb/storage/usb.c 2006-05-01 14:14:13.000000000 -0700
+@@ -291,13 +291,21 @@ void fill_inquiry_response(struct us_dat
+       if (us->srb->use_sg) {
+               sg = (struct scatterlist *)us->srb->request_buffer;
+               for (i=0; i<us->srb->use_sg; i++)
 +#if SMALL_SCATTERLIST
-+                    the6->array[element] = &(sg[i].u.address[j]);
-+                    the10->array[element] = &(sg[i].u.address[j]);
-+                  }
-+                else if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ )
-+                  {
-+                    /* only the longer headers still cares now */
-+                    the10->array[element] = &(sg[i].u.address[j]);
-+#else
-                     the6->array[element] = &(sg[i].address[j]);
-                     the10->array[element] = &(sg[i].address[j]);
-                   }
-@@ -888,6 +913,7 @@
-                   {
-                     /* only the longer headers still cares now */
-                     the10->array[element] = &(sg[i].address[j]);
-+#endif
-                   }
-                 /* increase element counter */
-                 element++;
-Index: linux-2.4.21/drivers/addon/ips_70015/ips.c
-===================================================================
---- linux-2.4.21.orig/drivers/addon/ips_70015/ips.c    2005-06-01 22:51:54.000000000 -0400
-+++ linux-2.4.21/drivers/addon/ips_70015/ips.c 2005-06-01 23:07:51.214560616 -0400
-@@ -207,7 +207,11 @@
- #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
- #include <linux/blk.h>
- #include "sd.h"
-+#ifdef SMALL_SCATTERLIST
-+#define IPS_SG_ADDRESS(sg)       ((sg)->u.address)
++                      memset(sg[i].u.address, 0, sg[i].length);
 +#else
- #define IPS_SG_ADDRESS(sg)       ((sg)->address)
+                       memset(sg[i].address, 0, sg[i].length);
 +#endif
- #define IPS_LOCK_SAVE(lock,flags) spin_lock_irqsave(&io_request_lock,flags)
- #define IPS_UNLOCK_RESTORE(lock,flags) spin_unlock_irqrestore(&io_request_lock,flags)
- #ifndef __devexit_p
-Index: linux-2.4.21/drivers/addon/megaraid_2106/megaraid2.c
-===================================================================
---- linux-2.4.21.orig/drivers/addon/megaraid_2106/megaraid2.c  2005-06-01 22:51:54.000000000 -0400
-+++ linux-2.4.21/drivers/addon/megaraid_2106/megaraid2.c       2005-06-01 23:07:51.217560160 -0400
-@@ -2198,7 +2198,11 @@
-                       if( cmd->use_sg ) {
-                               sgl = (struct scatterlist *)
-                                       cmd->request_buffer;
+               for (i=0, transferred=0; 
+                               i<us->srb->use_sg && transferred < len;
+                               i++) {
+                       amt = sg[i].length > len-transferred ? 
+                                       len-transferred : sg[i].length;
 +#if SMALL_SCATTERLIST
-+                              c = *(u8 *)sgl[0].u.address;
++                      memcpy(sg[i].u.address, data+transferred, amt);
 +#else
-                               c = *(u8 *)sgl[0].address;
+                       memcpy(sg[i].address, data+transferred, amt);
 +#endif
-                       }
-                       else {
-                               c = *(u8 *)cmd->request_buffer;
-Index: linux-2.4.21/drivers/addon/iscsi_sfnet/iscsi.c
-===================================================================
---- linux-2.4.21.orig/drivers/addon/iscsi_sfnet/iscsi.c        2005-06-01 22:51:59.000000000 -0400
-+++ linux-2.4.21/drivers/addon/iscsi_sfnet/iscsi.c     2005-06-01 23:07:51.229558336 -0400
-@@ -118,6 +118,16 @@
- #include "iscsi-probe.h"
- #include "iscsi-crc.h"
+                       transferred -= amt;
+               }
+       } else {
+diff -X dontdiff -urp kern_oldest/net/ipv6/addrconf.c kern_fix/net/ipv6/addrconf.c
+--- kern_oldest/net/ipv6/addrconf.c    2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/net/ipv6/addrconf.c       2006-05-01 14:14:24.000000000 -0700
+@@ -1047,11 +1047,18 @@ static int __ipv6_regen_rndid(struct ine
+       u8 digest[16];
+       struct scatterlist sg[2];
  
+-      sg[0].page = virt_to_page(idev->entropy);
 +#if SMALL_SCATTERLIST
-+#define ISCSI_SG_ADDRESS(sg) (sg->u.address)
-+#define ISCSI_SG_PAGE(sg)    (sg->u.page.page)
-+#define ISCSI_SG_OFFSET(sg)  (sg->u.page.offset)
++      sg[0].u.page.page = virt_to_page(idev->entropy);
++      sg[0].u.page.offset = ((long) idev->entropy & ~PAGE_MASK);
++      sg[1].u.page.page = virt_to_page(eui64);
++      sg[1].u.page.offset = ((long) eui64 & ~PAGE_MASK);
 +#else
-+#define ISCSI_SG_ADDRESS(sg) (sg->address)
-+#define ISCSI_SG_PAGE(sg)    (sg->page)
-+#define ISCSI_SG_OFFSET(sg)  (sg->offset)
++      sg[0].page = virt_to_page(idev->entropy);
+       sg[0].offset = ((long) idev->entropy & ~PAGE_MASK);
+-      sg[0].length = 8;
+       sg[1].page = virt_to_page(eui64);
+       sg[1].offset = ((long) eui64 & ~PAGE_MASK);
 +#endif
-+
- /*
-  *  IMPORTANT NOTE: to prevent deadlock, when holding multiple locks,
-  *  the following locking order must be followed at all times:
-@@ -2932,15 +2942,17 @@
- #if (HAS_SCATTERLIST_PAGE && HAS_SCATTERLIST_ADDRESS)
-           printk("iSCSI:   sglist %p index %02d = addr %p, page %p, "
-                  "offset %u, len %u\n",
--                 sglist, i, sglist->address, sglist->page, sglist->offset,
--                 sglist->length);
-+                 sglist, i, ISCSI_SG_ADDRESS(sglist), 
-+                 ISCSI_SG_PAGE(sglist),
-+                 ISCSI_SG_OFFSET(sglist), sglist->length);
- #elif HAS_SCATTERLIST_PAGE
-           printk("iSCSI:   sglist %p index %02d = page %p, offset %u, "
-                  "len %u\n",
--                 sglist, i, sglist->page, sglist->offset, sglist->length);
-+                 sglist, i, ISCSI_SG_PAGE(sglist), ISCSI_SG_OFFSET(sglist),
-+                 sglist->length);
- #else
-           printk("iSCSI:   sglist %p index %02d = addr %p, len %u\n",
--                 sglist, i, sglist->address, sglist->length);
-+                 sglist, i, ISCSI_SG_ADDRESS(sglist), sglist->length);
- #endif
-           sglist++;
-       }
-@@ -5306,7 +5318,7 @@
-                   bytes_from_segment = sg->length - segment_offset;
-                   if (bytes_from_segment > bytes_to_fill) {
-                       /* only need part of this segment */
--                      iov[iovn].iov_base = sg->address + segment_offset;
-+                      iov[iovn].iov_base = ISCSI_SG_ADDRESS(sg) + segment_offset;
-                       iov[iovn].iov_len = bytes_to_fill;
-                       xfrlen += bytes_to_fill;
-                       DEBUG_FLOW("iSCSI: session %p xmit_data xfrlen %d, "
-@@ -5863,21 +5875,21 @@
- {
- #if (HAS_SCATTERLIST_PAGE && HAS_SCATTERLIST_ADDRESS)
-     /* page may or may not be mapped */
--    if (sg->address) {
--      return sg->address;
--    } else if (sg->page) {
--      return page_address(sg->page) + sg->offset;
-+    if (ISCSI_SG_ADDRESS(sg)) {
-+      return ISCSI_SG_ADDRESS(sg);
-+    } else if (ISCSI_SG_PAGE(sg)) {
-+      return page_address(ISCSI_SG_PAGE(sg)) + ISCSI_SG_OFFSET(sg);
-     }
-     return NULL;
- #elif HAS_SCATTERLIST_PAGE
-     /* should have already mapped the page */
--    if (sg->page) {
--      return page_address(sg->page) + sg->offset;
-+    if (ISCSI_SG_PAGE(sg)) {
-+      return page_address(ISCSI_SG_PAGE(sg)) + ISCSI_SG_OFFSET(sg);
-     }
-     return NULL;
- #else
--    return sg->address;
-+    return ISCSI_SG_ADDRESS(sg);
- #endif
- }
-@@ -5900,12 +5912,12 @@
- {
- #if (HAS_SCATTERLIST_PAGE && HAS_SCATTERLIST_ADDRESS)
-     /* page may or may not be mapped if HIGHMEM is in use */
--    if (sg->address) {
--      DEBUG_FLOW("iSCSI: kmap sg %p to address %p\n", sg, sg->address);
--      return sg->address;
--    } else if (sg->page) {
--      void *addr = kmap(sg->page);
--      DEBUG_FLOW("iSCSI: kmap sg %p page %p to addr %p\n", sg, sg->page,
-+    if (ISCSI_SG_ADDRESS(sg)) {
-+      DEBUG_FLOW("iSCSI: kmap sg %p to address %p\n", sg, ISCSI_SG_ADDRESS(sg));
-+      return ISCSI_SG_ADDRESS(sg);
-+    } else if (ISCSI_SG_PAGE(sg)) {
-+      void *addr = kmap(ISCSI_SG_PAGE(sg));
-+      DEBUG_FLOW("iSCSI: kmap sg %p page %p to addr %p\n", sg, ISCSI_SG_PAGE(sg),
-                  addr);
-       return addr;
-     }
-@@ -5913,15 +5925,15 @@
- #elif HAS_SCATTERLIST_PAGE
-     /* there is no address, must kmap the page */
--    if (sg->page) {
--      return kmap(sg->page);
-+    if (ISCSI_SG_PAGE(sg)) {
-+      return kmap(ISCSI_SG_PAGE(sg));
-     }
-     return NULL;
- #else
-     /* just use the address */
--    DEBUG_FLOW("iSCSI: kmap sg %p to address %p\n", sg, sg->address);
--    return sg->address;
-+    DEBUG_FLOW("iSCSI: kmap sg %p to address %p\n", sg, ISCSI_SG_ADDRESS(sg));
-+    return ISCSI_SG_ADDRESS(sg);
- #endif
- }
++      sg[0].length = 8;
+       sg[1].length = 8;
  
-@@ -5933,11 +5945,11 @@
- kunmap_sg(struct scatterlist *sg)
- {
- #if (HAS_SCATTERLIST_PAGE && HAS_SCATTERLIST_ADDRESS)
--    if (!sg->address && sg->page)
--      kunmap(sg->page);
-+    if (!ISCSI_SG_ADDRESS(sg) && ISCSI_SG_PAGE(sg))
-+      kunmap(ISCSI_SG_PAGE(sg));
- #elif HAS_SCATTERLIST_PAGE
--    if (sg->page)
--      kunmap(sg->page);
-+    if (ISCSI_SG_PAGE(sg))
-+      kunmap(ISCSI_SG_PAGE(sg));
- #endif
-     return;
- }
-Index: linux-2.4.21/include/asm-i386/pci.h
-===================================================================
---- linux-2.4.21.orig/include/asm-i386/pci.h   2005-06-01 22:51:45.000000000 -0400
-+++ linux-2.4.21/include/asm-i386/pci.h        2005-06-01 23:21:02.208311288 -0400
-@@ -157,6 +157,17 @@
-        * temporary 2.4 hack
-        */
-       for (i = 0; i < nents; i++ ) {
-+#if SMALL_SCATTERLIST
-+              if (sg[i].ispaged) {
-+                      if (!sg[i].u.page.page)
-+                              out_of_line_bug();
-+                      sg[i].dma_address = page_to_bus(sg[i].u.page.page) + sg[i].u.page.offset;
-+              } else {
-+                      if (!sg[i].u.address)
-+                              out_of_line_bug();
-+                      sg[i].dma_address = virt_to_bus(sg[i].u.address);
-+              }
-+#else
-               if (sg[i].address && sg[i].page)
-                       out_of_line_bug();
-               else if (!sg[i].address && !sg[i].page)
-@@ -166,6 +177,7 @@
-                       sg[i].dma_address = virt_to_bus(sg[i].address);
-               else
-                       sg[i].dma_address = page_to_bus(sg[i].page) + sg[i].offset;
-+#endif
-       }
-  
-       flush_write_buffers();
-Index: linux-2.4.21/include/asm-i386/scatterlist.h
-===================================================================
---- linux-2.4.21.orig/include/asm-i386/scatterlist.h   2002-11-28 18:53:15.000000000 -0500
-+++ linux-2.4.21/include/asm-i386/scatterlist.h        2005-06-01 23:07:51.230558184 -0400
-@@ -19,7 +19,25 @@
-  *
-  * and that's it. There's no excuse for not highmem enabling YOUR driver. /jens
-  */
-+
-+/* Define SMALL_SCATTERLIST non-zero if you want to compress scatter/gather
-+   descriptors to fit in 1 page.  NB this file is arch-specific, so we only
-+   define this where we actually need/want it */
-+#define SMALL_SCATTERLIST 1
-+
- struct scatterlist {
-+#if SMALL_SCATTERLIST
-+    union {
-+       char         *address;                 /* mapped address... */
-+       struct {
-+        struct page  *page;                   /* ...or page + offset... */
-+        unsigned int  offset;
-+       } page;
-+    } u;
-+    dma_addr_t dma_address;
-+    unsigned int length:31;                   /* ...steal 1 bit from the length */
-+    unsigned int ispaged:1;                   /* to discriminate */
-+#else
-     char *  address;    /* Location data is to be transferred to, NULL for
-                        * highmem page */
-     struct page * page; /* Location for highmem page, if any */
-@@ -27,6 +45,7 @@
-     dma_addr_t dma_address;
-     unsigned int length;
-+#endif
- };
- #define ISA_DMA_THRESHOLD (0x00ffffff)
-Index: linux-2.4.21/net/xfrm/xfrm_algo.c
-===================================================================
---- linux-2.4.21.orig/net/xfrm/xfrm_algo.c     2005-06-01 22:51:50.000000000 -0400
-+++ linux-2.4.21/net/xfrm/xfrm_algo.c  2005-06-01 23:07:51.231558032 -0400
-@@ -487,9 +487,14 @@
+       dev = idev->dev;
+diff -X dontdiff -urp kern_oldest/net/xfrm/xfrm_algo.c kern_fix/net/xfrm/xfrm_algo.c
+--- kern_oldest/net/xfrm/xfrm_algo.c   2006-05-01 11:55:40.000000000 -0700
++++ kern_fix/net/xfrm/xfrm_algo.c      2006-05-01 14:14:24.000000000 -0700
+@@ -487,9 +487,14 @@ void skb_icv_walk(const struct sk_buff *
        if (copy > 0) {
                if (copy > len)
                        copy = len;
@@ -4380,7 +4216,7 @@ Index: linux-2.4.21/net/xfrm/xfrm_algo.c
                sg.length = copy;
                
                icv_update(tfm, &sg, 1);
-@@ -511,8 +516,14 @@
+@@ -511,8 +516,14 @@ void skb_icv_walk(const struct sk_buff *
                        if (copy > len)
                                copy = len;
                        
@@ -4395,7 +4231,7 @@ Index: linux-2.4.21/net/xfrm/xfrm_algo.c
                        sg.length = copy;
                        
                        icv_update(tfm, &sg, 1);
-@@ -562,8 +573,15 @@
+@@ -562,8 +573,15 @@ skb_to_sgvec(struct sk_buff *skb, struct
        if (copy > 0) {
                if (copy > len)
                        copy = len;
@@ -4411,7 +4247,7 @@ Index: linux-2.4.21/net/xfrm/xfrm_algo.c
                sg[elt].length = copy;
                elt++;
                if ((len -= copy) == 0)
-@@ -582,8 +600,13 @@
+@@ -582,8 +600,13 @@ skb_to_sgvec(struct sk_buff *skb, struct
  
                        if (copy > len)
                                copy = len;
@@ -4425,28 +4261,74 @@ Index: linux-2.4.21/net/xfrm/xfrm_algo.c
                        sg[elt].length = copy;
                        elt++;
                        if (!(len -= copy))
-Index: linux-2.4.21/net/ipv6/addrconf.c
-===================================================================
---- linux-2.4.21.orig/net/ipv6/addrconf.c      2005-06-01 22:51:50.000000000 -0400
-+++ linux-2.4.21/net/ipv6/addrconf.c   2005-06-01 23:07:51.232557880 -0400
-@@ -1047,11 +1047,18 @@
-       u8 digest[16];
-       struct scatterlist sg[2];
+diff -urp a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
+--- a/drivers/scsi/libata-core.c       2006-05-15 00:42:16.000000000 -0700
++++ b/drivers/scsi/libata-core.c       2006-05-15 00:40:14.000000000 -0700
+@@ -54,6 +54,7 @@
+ #include <asm/io.h>
+ #include <asm/semaphore.h>
+ #include <asm/byteorder.h>
++#include <asm/scatterlist.h>
+ #include "libata.h"
+@@ -2424,9 +2425,15 @@ static void ata_sg_clean(struct ata_queu
+               sg[qc->orig_n_elem - 1].length += qc->pad_len;
+               if (pad_buf) {
+                       struct scatterlist *psg = &qc->pad_sgent;
++#if SMALL_SCATTERLIST
++                      void *addr = kmap_atomic(psg->u.page.page, KM_IRQ0);
++                      memcpy(addr + psg->u.page.offset, pad_buf, qc->pad_len);
++                      kunmap_atomic(psg->u.page.page, KM_IRQ0);
++#else
+                       void *addr = kmap_atomic(psg->page, KM_IRQ0);
+                       memcpy(addr + psg->offset, pad_buf, qc->pad_len);
+                       kunmap_atomic(psg->page, KM_IRQ0);
++#endif
+               }
+       } else {
+               if (sg_dma_len(&sg[0]) > 0)
+@@ -2693,14 +2700,26 @@ static int ata_sg_setup(struct ata_queue
+                * psg->page/offset are used to copy to-be-written
+                * data in this function or read data in ata_sg_clean.
+                */
++#if SMALL_SCATTERLIST
++              offset = lsg->u.page.offset + lsg->length - qc->pad_len;
++              psg->u.page.page = nth_page(lsg->u.page.page, offset >> PAGE_SHIFT);
++              psg->u.page.offset = offset_in_page(offset);
++#else
+               offset = lsg->offset + lsg->length - qc->pad_len;
+               psg->page = nth_page(lsg->page, offset >> PAGE_SHIFT);
+               psg->offset = offset_in_page(offset);
++#endif
  
--      sg[0].page = virt_to_page(idev->entropy);
+               if (qc->tf.flags & ATA_TFLAG_WRITE) {
 +#if SMALL_SCATTERLIST
-+      sg[0].u.page.page = virt_to_page(idev->entropy);
-+      sg[0].u.page.offset = ((long) idev->entropy & ~PAGE_MASK);
-+      sg[1].u.page.page = virt_to_page(eui64);
-+      sg[1].u.page.offset = ((long) eui64 & ~PAGE_MASK);
++                      void *addr = kmap_atomic(psg->u.page.page, KM_IRQ0);
++                      memcpy(pad_buf, addr + psg->u.page.offset, qc->pad_len);
++                      kunmap_atomic(psg->u.page.page, KM_IRQ0);
 +#else
-+      sg[0].page = virt_to_page(idev->entropy);
-       sg[0].offset = ((long) idev->entropy & ~PAGE_MASK);
--      sg[0].length = 8;
-       sg[1].page = virt_to_page(eui64);
-       sg[1].offset = ((long) eui64 & ~PAGE_MASK);
+                       void *addr = kmap_atomic(psg->page, KM_IRQ0);
+                       memcpy(pad_buf, addr + psg->offset, qc->pad_len);
+                       kunmap_atomic(psg->page, KM_IRQ0);
 +#endif
-+      sg[0].length = 8;
-       sg[1].length = 8;
+               }
+               sg_dma_address(psg) = ap->pad_dma + (qc->tag * ATA_DMA_PAD_SZ);
+diff -urp a/include/linux/libata-compat.h b/include/linux/libata-compat.h
+--- a/include/linux/libata-compat.h    2006-05-15 00:41:42.000000000 -0700
++++ b/include/linux/libata-compat.h    2006-05-15 00:39:53.000000000 -0700
+@@ -198,8 +198,13 @@ pci_iomap(struct pci_dev *dev, int bar, 
+ static inline void sg_set_buf(struct scatterlist *sg, void *buf,
+                             unsigned int buflen)
+ {
++#if SMALL_SCATTERLIST
++      sg->u.page.page = virt_to_page(buf);
++      sg->u.page.offset = offset_in_page(buf);
++#else
+       sg->page = virt_to_page(buf);
+       sg->offset = offset_in_page(buf);
++#endif
+       sg->length = buflen;
+ }
  
-       dev = idev->dev;
diff --git a/lustre/kernel_patches/patches/tcp-zero-copy-2.6-fc5.patch b/lustre/kernel_patches/patches/tcp-zero-copy-2.6-fc5.patch
new file mode 100644 (file)
index 0000000..2183518
--- /dev/null
@@ -0,0 +1,475 @@
+Index: linux-2.6.16.i686/net/core/dev.c
+===================================================================
+--- linux-2.6.16.i686.orig/net/core/dev.c      2006-05-30 15:47:10.000000000 +0800
++++ linux-2.6.16.i686/net/core/dev.c   2006-05-30 21:24:07.000000000 +0800
+@@ -1181,6 +1181,9 @@
+       ninfo->tso_segs = skb_shinfo(skb)->tso_segs;
+       ninfo->nr_frags = 0;
+       ninfo->frag_list = NULL;
++      ninfo->zccd = NULL;             /* copied data => no user zero copy descriptor */
++      ninfo->zccd2 = NULL;
++
+       /* Offset between the two in bytes */
+       offset = data - skb->head;
+Index: linux-2.6.16.i686/net/core/skbuff.c
+===================================================================
+--- linux-2.6.16.i686.orig/net/core/skbuff.c   2006-05-30 15:47:12.000000000 +0800
++++ linux-2.6.16.i686/net/core/skbuff.c        2006-05-30 21:26:35.000000000 +0800
+@@ -170,7 +170,8 @@
+       shinfo->ufo_size = 0;
+       shinfo->ip6_frag_id = 0;
+       shinfo->frag_list = NULL;
+-
++      shinfo->zccd = NULL;           /* skbuffs kick off with NO user zero copy descriptors */
++      shinfo->zccd2 = NULL;
+       if (fclone) {
+               struct sk_buff *child = skb + 1;
+               atomic_t *fclone_ref = (atomic_t *) (child + 1);
+@@ -242,7 +243,9 @@
+       shinfo->ufo_size = 0;
+       shinfo->ip6_frag_id = 0;
+       shinfo->frag_list = NULL;
+-
++      shinfo->zccd = NULL;           /* skbuffs kick off with NO user zero copy descriptors */
++      shinfo->zccd2 = NULL;
++      
+       if (fclone) {
+               struct sk_buff *child = skb + 1;
+               atomic_t *fclone_ref = (atomic_t *) (child + 1);
+@@ -287,6 +290,10 @@
+       if (!skb->cloned ||
+           !atomic_sub_return(skb->nohdr ? (1 << SKB_DATAREF_SHIFT) + 1 : 1,
+                              &skb_shinfo(skb)->dataref)) {
++              if (skb_shinfo(skb)->zccd != NULL) /* zero copy callback descriptor? */
++                      zccd_put (skb_shinfo(skb)->zccd); /* release hold */
++              if (skb_shinfo(skb)->zccd2 != NULL) /* 2nd zero copy callback descriptor? */
++                      zccd_put (skb_shinfo(skb)->zccd2); /* release hold */
+               if (skb_shinfo(skb)->nr_frags) {
+                       int i;
+                       for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
+@@ -606,6 +613,14 @@
+       n->data_len  = skb->data_len;
+       n->len       = skb->len;
++      if (skb_shinfo(skb)->zccd != NULL)      /* user zero copy descriptor? */
++              zccd_get (skb_shinfo(skb)->zccd); /* 1 more ref (pages are shared) */
++      skb_shinfo(n)->zccd = skb_shinfo(skb)->zccd;
++
++      if (skb_shinfo(skb)->zccd2 != NULL)     /* 2nd user zero copy descriptor? */
++              zccd_get (skb_shinfo(skb)->zccd2); /* 1 more ref (pages are shared) */
++      skb_shinfo(n)->zccd2 = skb_shinfo(skb)->zccd2;
++
+       if (skb_shinfo(skb)->nr_frags) {
+               int i;
+@@ -649,6 +664,9 @@
+       u8 *data;
+       int size = nhead + (skb->end - skb->head) + ntail;
+       long off;
++      zccd_t *zccd = skb_shinfo(skb)->zccd;   /* stash user zero copy descriptor */
++      zccd_t *zccd2 = skb_shinfo(skb)->zccd2; /* stash 2nd user zero copy descriptor */
++
+       if (skb_shared(skb))
+               BUG();
+@@ -670,6 +688,11 @@
+       if (skb_shinfo(skb)->frag_list)
+               skb_clone_fraglist(skb);
++      if (zccd != NULL)                       /* user zero copy descriptor? */
++              zccd_get (zccd);                /* extra ref (pages are shared) */
++      if (zccd2 != NULL)                      /* 2nd user zero copy descriptor? */
++              zccd_get (zccd2);               /* extra ref (pages are shared) */
++
+       skb_release_data(skb);
+       off = (data + nhead) - skb->head;
+@@ -684,6 +707,8 @@
+       skb->cloned   = 0;
+       skb->nohdr    = 0;
+       atomic_set(&skb_shinfo(skb)->dataref, 1);
++      skb_shinfo(skb)->zccd = zccd;
++      skb_shinfo(skb)->zccd2 = zccd2;
+       return 0;
+ nodata:
+Index: linux-2.6.16.i686/net/ipv4/tcp.c
+===================================================================
+--- linux-2.6.16.i686.orig/net/ipv4/tcp.c      2006-05-30 15:47:12.000000000 +0800
++++ linux-2.6.16.i686/net/ipv4/tcp.c   2006-05-30 21:24:07.000000000 +0800
+@@ -498,8 +498,10 @@
+       }
+ }
++/* Extra parameter: user zero copy descriptor (or NULL if not doing that) */
+ static ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffset,
+-                       size_t psize, int flags)
++                              size_t psize, int flags, zccd_t *zccd)
++
+ {
+       struct tcp_sock *tp = tcp_sk(sk);
+       int mss_now, size_goal;
+@@ -547,6 +549,17 @@
+                       copy = size;
+               i = skb_shinfo(skb)->nr_frags;
++
++              if (zccd != NULL &&             /* this is a zcc I/O */
++                              skb_shinfo(skb)->zccd != NULL && /* skb is part of a zcc I/O */
++                              skb_shinfo(skb)->zccd2 != NULL &&
++                              skb_shinfo(skb)->zccd != zccd && /* not the same one */
++                              skb_shinfo(skb)->zccd2 != zccd)
++              {
++                      tcp_mark_push (tp, skb);
++                      goto new_segment;
++              }
++
+               can_coalesce = skb_can_coalesce(skb, i, page, offset);
+               if (!can_coalesce && i >= MAX_SKB_FRAGS) {
+                       tcp_mark_push(tp, skb);
+@@ -562,6 +575,20 @@
+                       skb_fill_page_desc(skb, i, page, offset, copy);
+               }
++              if (zccd != NULL &&     /* this is a zcc I/O */
++                      skb_shinfo(skb)->zccd != zccd && /* not already referencing this zccd */
++                      skb_shinfo(skb)->zccd2 != zccd)
++              {
++                      zccd_get (zccd);        /* bump ref count */
++
++                      BUG_TRAP (skb_shinfo(skb)->zccd2 == NULL);
++
++                      if (skb_shinfo(skb)->zccd == NULL) /* reference this zccd */
++                              skb_shinfo(skb)->zccd = zccd;
++                      else
++                              skb_shinfo(skb)->zccd2 = zccd;
++              }
++
+               skb->len += copy;
+               skb->data_len += copy;
+               skb->truesize += copy;
+@@ -631,12 +658,37 @@
+       lock_sock(sk);
+       TCP_CHECK_TIMER(sk);
+-      res = do_tcp_sendpages(sk, &page, offset, size, flags);
++      res = do_tcp_sendpages(sk, &page, offset, size, flags,NULL);
++      TCP_CHECK_TIMER(sk);
++      release_sock(sk);
++      return res;
++}
++
++ssize_t tcp_sendpage_zccd(struct socket *sock, struct page *page, int offset, size_t size,
++                          int flags, zccd_t *zccd)
++{
++      ssize_t res;
++      struct sock *sk = sock->sk;
++
++#define TCP_ZC_CSUM_FLAGS (NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM)
++
++      if (!(sk->sk_route_caps & NETIF_F_SG) ||        /* caller shouldn't waste her time */
++          !(sk->sk_route_caps & TCP_ZC_CSUM_FLAGS)) /* on double mapping */
++              BUG ();
++
++#undef TCP_ZC_CSUM_FLAGS
++
++      lock_sock(sk);
++      TCP_CHECK_TIMER(sk);
++
++      res = do_tcp_sendpages(sk, &page, offset, size, flags, zccd);
++
+       TCP_CHECK_TIMER(sk);
+       release_sock(sk);
+       return res;
+ }
++
+ #define TCP_PAGE(sk)  (sk->sk_sndmsg_page)
+ #define TCP_OFF(sk)   (sk->sk_sndmsg_off)
+@@ -1406,6 +1458,202 @@
+       goto out;
+ }
++int tcp_recvpackets (struct sock *sk, struct sk_buff_head *packets,
++                   int len, int nonblock)
++{
++      struct tcp_sock *tp = tcp_sk(sk);
++      int copied;
++      long timeo;
++
++      BUG_TRAP (len > 0);
++      /*BUG_TRAP ((flags & (MSG_OOB | MSG_PEEK | MSG_TRUNC)) == 0);*/
++
++      lock_sock(sk);
++
++      TCP_CHECK_TIMER(sk);
++
++      copied = -ENOTCONN;
++      if (sk->sk_state == TCP_LISTEN)
++              goto out;
++
++      copied = 0;
++      timeo = sock_rcvtimeo(sk, nonblock);
++
++      do {
++              struct sk_buff * skb;
++              u32 offset;
++              unsigned long used;
++              int exhausted;
++              int eaten;
++
++              /* Are we at urgent data? Stop if we have read anything. */
++              if (copied && tp->urg_data && tp->urg_seq == tp->copied_seq)
++                      break;
++
++              /* We need to check signals first, to get correct SIGURG
++               * handling. FIXME: Need to check this doesnt impact 1003.1g
++               * and move it down to the bottom of the loop
++               */
++              if (signal_pending(current)) {
++                      if (copied)
++                              break;
++                      copied = timeo ? sock_intr_errno(timeo) : -EAGAIN;
++                      break;
++              }
++
++              /* Next get a buffer. */
++
++              skb = skb_peek(&sk->sk_receive_queue);
++
++              if (skb == NULL)                /* nothing ready */
++              {
++                      if (copied) {
++                              if (sk->sk_err ||
++                                  sk->sk_state == TCP_CLOSE ||
++                                  (sk->sk_shutdown & RCV_SHUTDOWN) ||
++                                  !timeo ||
++                                  (0))
++                                      break;
++                      } else {
++                              if (sock_flag(sk, SOCK_DONE))
++                                      break;
++
++                              if (sk->sk_err) {
++                                      copied = sock_error(sk);
++                                      break;
++                              }
++
++                              if (sk->sk_shutdown & RCV_SHUTDOWN)
++                                      break;
++
++                              if (sk->sk_state == TCP_CLOSE) {
++                                      if (!(sock_flag(sk, SOCK_DONE))) {
++                                              /* This occurs when user tries to read
++                                               * from never connected socket.
++                                               */
++                                              copied = -ENOTCONN;
++                                              break;
++                                      }
++                                      break;
++                              }
++
++                              if (!timeo) {
++                                      copied = -EAGAIN;
++                                      break;
++                              }
++                      }
++
++                      cleanup_rbuf(sk, copied);
++                      sk_wait_data(sk, &timeo);
++                      continue;
++              }
++
++              BUG_TRAP (atomic_read (&skb->users) == 1);
++
++              exhausted = eaten = 0;
++
++              offset = tp->copied_seq - TCP_SKB_CB(skb)->seq;
++              if (skb->h.th->syn)
++                      offset--;
++
++              used = skb->len - offset;
++
++              if (tp->urg_data) {
++                      u32 urg_offset = tp->urg_seq - tp->copied_seq;
++                      if (urg_offset < used) {
++                              if (!urg_offset) { /* at urgent date */
++                                      if (!(sock_flag(sk, SOCK_URGINLINE))) {
++                                              tp->copied_seq++; /* discard the single byte of urgent data */
++                                              offset++;
++                                              used--;
++                                      }
++                              } else          /* truncate read */
++                                      used = urg_offset;
++                      }
++              }
++
++              BUG_TRAP (used >= 0);
++              if (len < used)
++                      used = len;
++
++              if (used == 0)
++                      exhausted = 1;
++              else
++              {
++                      if (skb_is_nonlinear (skb))
++                      {
++                              int   rc = skb_linearize (skb, GFP_KERNEL);
++
++                              printk ("tcp_recvpackets(): linearising: %d\n", rc);
++
++                              if (rc)
++                              {
++                                      if (!copied)
++                                              copied = rc;
++                                      break;
++                              }
++                      }
++
++                      if ((offset + used) == skb->len) /* consuming the whole packet */
++                      {
++                              __skb_unlink (skb, &sk->sk_receive_queue);
++                              dst_release (skb->dst);
++                              skb_orphan (skb);
++                              __skb_pull (skb, offset);
++                              __skb_queue_tail (packets, skb);
++                              exhausted = eaten = 1;
++                      }
++                      else                    /* consuming only part of the packet */
++                      {
++                              struct sk_buff *skb2 = skb_clone (skb, GFP_KERNEL);
++
++                              if (skb2 == NULL)
++                              {
++                                      if (!copied)
++                                              copied = -ENOMEM;
++                                      break;
++                              }
++
++                              dst_release (skb2->dst);
++                              __skb_pull (skb2, offset);
++                              __skb_trim (skb2, used);
++                              __skb_queue_tail (packets, skb2);
++                      }
++
++                      tp->copied_seq += used;
++                      copied += used;
++                      len -= used;
++              }
++
++              if (tp->urg_data && after(tp->copied_seq,tp->urg_seq)) {
++                      tp->urg_data = 0;
++                      tcp_fast_path_check(sk, tp);
++              }
++
++              if (!exhausted)
++                      continue;
++
++              if (skb->h.th->fin)
++              {
++                      tp->copied_seq++;
++                      if (!eaten)
++                              sk_eat_skb (sk, skb);
++                      break;
++              }
++
++              if (!eaten)
++                      sk_eat_skb (sk, skb);
++
++      } while (len > 0);
++
++ out:
++      /* Clean up data we have read: This will do ACK frames. */
++      cleanup_rbuf(sk, copied);
++      TCP_CHECK_TIMER(sk);
++      release_sock(sk);
++      return copied;
++}
++
+ /*
+  *    State processing on a close. This implements the state shift for
+  *    sending our FIN frame. Note that we only send a FIN for some
+@@ -2139,6 +2387,8 @@
+ EXPORT_SYMBOL(tcp_recvmsg);
+ EXPORT_SYMBOL(tcp_sendmsg);
+ EXPORT_SYMBOL(tcp_sendpage);
++EXPORT_SYMBOL(tcp_sendpage_zccd);
++EXPORT_SYMBOL(tcp_recvpackets);
+ EXPORT_SYMBOL(tcp_setsockopt);
+ EXPORT_SYMBOL(tcp_shutdown);
+ EXPORT_SYMBOL(tcp_statistics);
+Index: linux-2.6.16.i686/include/linux/skbuff.h
+===================================================================
+--- linux-2.6.16.i686.orig/include/linux/skbuff.h      2006-05-30 15:47:11.000000000 +0800
++++ linux-2.6.16.i686/include/linux/skbuff.h   2006-05-30 21:24:07.000000000 +0800
+@@ -128,6 +128,30 @@
+       __u16 size;
+ };
++/* Support for callback when skb data has been released */
++typedef struct zccd                            /* Zero Copy Callback Descriptor */
++{                                              /* (embed as first member of custom struct) */
++      atomic_t        zccd_count;             /* reference count */
++      void           (*zccd_destructor)(struct zccd *); /* callback when refcount reaches zero */
++} zccd_t;
++
++static inline void zccd_init (zccd_t *d, void (*callback)(zccd_t *))
++{
++      atomic_set (&d->zccd_count, 1);
++      d->zccd_destructor = callback;
++}
++
++static inline void zccd_get (zccd_t *d)                /* take a reference */
++{
++      atomic_inc (&d->zccd_count);
++}
++
++static inline void zccd_put (zccd_t *d)                /* release a reference */
++{
++      if (atomic_dec_and_test (&d->zccd_count))
++              (d->zccd_destructor)(d);
++}
++
+ /* This data is invariant across clones and lives at
+  * the end of the header data, ie. at skb->end.
+  */
+@@ -139,6 +163,13 @@
+       unsigned short  ufo_size;
+       unsigned int    ip6_frag_id;
+       struct sk_buff  *frag_list;
++      zccd_t          *zccd;                  /* zero copy descriptor */
++      zccd_t          *zccd2;                 /* 2nd zero copy descriptor */
++      /* NB we expect zero-copy data to be at least 1 packet, so
++      * having 2 zccds means we don't unneccessarily split the packet
++      * where consecutive zero-copy sends abutt.
++      */
++
+       skb_frag_t      frags[MAX_SKB_FRAGS];
+ };
+Index: linux-2.6.16.i686/include/net/tcp.h
+===================================================================
+--- linux-2.6.16.i686.orig/include/net/tcp.h   2006-05-30 15:47:11.000000000 +0800
++++ linux-2.6.16.i686/include/net/tcp.h        2006-05-30 21:24:07.000000000 +0800
+@@ -272,6 +272,9 @@
+ extern int                    tcp_sendmsg(struct kiocb *iocb, struct sock *sk,
+                                           struct msghdr *msg, size_t size);
+ extern ssize_t                        tcp_sendpage(struct socket *sock, struct page *page, int offset, size_t size, int flags);
++extern ssize_t                 tcp_sendpage_zccd(struct socket *sock, struct page *page, int offset, size_t size,
++                                              int flags, zccd_t *zccd);
++
+ extern int                    tcp_ioctl(struct sock *sk, 
+                                         int cmd, 
+@@ -354,6 +357,9 @@
+                                           struct msghdr *msg,
+                                           size_t len, int nonblock, 
+                                           int flags, int *addr_len);
++extern int                     tcp_recvpackets(struct sock *sk,
++                                              struct sk_buff_head *packets,
++                                              int len, int nonblock);
+ extern void                   tcp_parse_options(struct sk_buff *skb,
+                                                 struct tcp_options_received *opt_rx,
diff --git a/lustre/kernel_patches/patches/tcp-zero-copy-2.6-sles10.patch b/lustre/kernel_patches/patches/tcp-zero-copy-2.6-sles10.patch
new file mode 100644 (file)
index 0000000..6e017e3
--- /dev/null
@@ -0,0 +1,450 @@
+Index: linux-2.6.16.21-0.8/net/core/skbuff.c
+===================================================================
+--- linux-2.6.16.21-0.8.orig/net/core/skbuff.c 2006-08-03 21:11:25.000000000 -0600
++++ linux-2.6.16.21-0.8/net/core/skbuff.c      2006-08-03 21:11:30.000000000 -0600
+@@ -170,7 +170,8 @@
+       shinfo->ufo_size = 0;
+       shinfo->ip6_frag_id = 0;
+       shinfo->frag_list = NULL;
+-
++      shinfo->zccd = NULL;           /* skbuffs kick off with NO user zero copy descriptors */
++      shinfo->zccd2 = NULL;
+       if (fclone) {
+               struct sk_buff *child = skb + 1;
+               atomic_t *fclone_ref = (atomic_t *) (child + 1);
+@@ -287,6 +288,10 @@
+       if (!skb->cloned ||
+           !atomic_sub_return(skb->nohdr ? (1 << SKB_DATAREF_SHIFT) + 1 : 1,
+                              &skb_shinfo(skb)->dataref)) {
++              if (skb_shinfo(skb)->zccd != NULL) /* zero copy callback descriptor? */
++                      zccd_put (skb_shinfo(skb)->zccd); /* release hold */
++              if (skb_shinfo(skb)->zccd2 != NULL) /* 2nd zero copy callback descriptor? */
++                      zccd_put (skb_shinfo(skb)->zccd2); /* release hold */
+               if (skb_shinfo(skb)->nr_frags) {
+                       int i;
+                       for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
+@@ -606,6 +611,14 @@
+       n->data_len  = skb->data_len;
+       n->len       = skb->len;
++      if (skb_shinfo(skb)->zccd != NULL)      /* user zero copy descriptor? */
++              zccd_get (skb_shinfo(skb)->zccd); /* 1 more ref (pages are shared) */
++      skb_shinfo(n)->zccd = skb_shinfo(skb)->zccd;
++
++      if (skb_shinfo(skb)->zccd2 != NULL)     /* 2nd user zero copy descriptor? */
++              zccd_get (skb_shinfo(skb)->zccd2); /* 1 more ref (pages are shared) */
++      skb_shinfo(n)->zccd2 = skb_shinfo(skb)->zccd2;
++
+       if (skb_shinfo(skb)->nr_frags) {
+               int i;
+@@ -649,6 +662,9 @@
+       u8 *data;
+       int size = nhead + (skb->end - skb->head) + ntail;
+       long off;
++      zccd_t *zccd = skb_shinfo(skb)->zccd;   /* stash user zero copy descriptor */
++      zccd_t *zccd2 = skb_shinfo(skb)->zccd2; /* stash 2nd user zero copy descriptor */
++
+       if (skb_shared(skb))
+               BUG();
+@@ -670,6 +686,11 @@
+       if (skb_shinfo(skb)->frag_list)
+               skb_clone_fraglist(skb);
++      if (zccd != NULL)                       /* user zero copy descriptor? */
++              zccd_get (zccd);                /* extra ref (pages are shared) */
++      if (zccd2 != NULL)                      /* 2nd user zero copy descriptor? */
++              zccd_get (zccd2);               /* extra ref (pages are shared) */
++
+       skb_release_data(skb);
+       off = (data + nhead) - skb->head;
+@@ -684,6 +705,8 @@
+       skb->cloned   = 0;
+       skb->nohdr    = 0;
+       atomic_set(&skb_shinfo(skb)->dataref, 1);
++      skb_shinfo(skb)->zccd = zccd;
++      skb_shinfo(skb)->zccd2 = zccd2;
+       return 0;
+ nodata:
+Index: linux-2.6.16.21-0.8/net/ipv4/tcp.c
+===================================================================
+--- linux-2.6.16.21-0.8.orig/net/ipv4/tcp.c    2006-08-03 21:11:25.000000000 -0600
++++ linux-2.6.16.21-0.8/net/ipv4/tcp.c 2006-08-03 21:11:30.000000000 -0600
+@@ -498,8 +498,10 @@
+       }
+ }
++/* Extra parameter: user zero copy descriptor (or NULL if not doing that) */
+ static ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffset,
+-                       size_t psize, int flags)
++                              size_t psize, int flags, zccd_t *zccd)
++
+ {
+       struct tcp_sock *tp = tcp_sk(sk);
+       int mss_now, size_goal;
+@@ -547,6 +549,17 @@
+                       copy = size;
+               i = skb_shinfo(skb)->nr_frags;
++
++              if (zccd != NULL &&             /* this is a zcc I/O */
++                              skb_shinfo(skb)->zccd != NULL && /* skb is part of a zcc I/O */
++                              skb_shinfo(skb)->zccd2 != NULL &&
++                              skb_shinfo(skb)->zccd != zccd && /* not the same one */
++                              skb_shinfo(skb)->zccd2 != zccd)
++              {
++                      tcp_mark_push (tp, skb);
++                      goto new_segment;
++              }
++
+               can_coalesce = skb_can_coalesce(skb, i, page, offset);
+               if (!can_coalesce && i >= MAX_SKB_FRAGS) {
+                       tcp_mark_push(tp, skb);
+@@ -562,6 +575,20 @@
+                       skb_fill_page_desc(skb, i, page, offset, copy);
+               }
++              if (zccd != NULL &&     /* this is a zcc I/O */
++                      skb_shinfo(skb)->zccd != zccd && /* not already referencing this zccd */
++                      skb_shinfo(skb)->zccd2 != zccd)
++              {
++                      zccd_get (zccd);        /* bump ref count */
++
++                      BUG_TRAP (skb_shinfo(skb)->zccd2 == NULL);
++
++                      if (skb_shinfo(skb)->zccd == NULL) /* reference this zccd */
++                              skb_shinfo(skb)->zccd = zccd;
++                      else
++                              skb_shinfo(skb)->zccd2 = zccd;
++              }
++
+               skb->len += copy;
+               skb->data_len += copy;
+               skb->truesize += copy;
+@@ -631,12 +658,37 @@
+       lock_sock(sk);
+       TCP_CHECK_TIMER(sk);
+-      res = do_tcp_sendpages(sk, &page, offset, size, flags);
++      res = do_tcp_sendpages(sk, &page, offset, size, flags,NULL);
++      TCP_CHECK_TIMER(sk);
++      release_sock(sk);
++      return res;
++}
++
++ssize_t tcp_sendpage_zccd(struct socket *sock, struct page *page, int offset, size_t size,
++                          int flags, zccd_t *zccd)
++{
++      ssize_t res;
++      struct sock *sk = sock->sk;
++
++#define TCP_ZC_CSUM_FLAGS (NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM)
++
++      if (!(sk->sk_route_caps & NETIF_F_SG) ||        /* caller shouldn't waste her time */
++          !(sk->sk_route_caps & TCP_ZC_CSUM_FLAGS)) /* on double mapping */
++              BUG ();
++
++#undef TCP_ZC_CSUM_FLAGS
++
++      lock_sock(sk);
++      TCP_CHECK_TIMER(sk);
++
++      res = do_tcp_sendpages(sk, &page, offset, size, flags, zccd);
++
+       TCP_CHECK_TIMER(sk);
+       release_sock(sk);
+       return res;
+ }
++
+ #define TCP_PAGE(sk)  (sk->sk_sndmsg_page)
+ #define TCP_OFF(sk)   (sk->sk_sndmsg_off)
+@@ -1482,6 +1534,202 @@
+       goto out;
+ }
++int tcp_recvpackets (struct sock *sk, struct sk_buff_head *packets,
++                   int len, int nonblock)
++{
++      struct tcp_sock *tp = tcp_sk(sk);
++      int copied;
++      long timeo;
++
++      BUG_TRAP (len > 0);
++      /*BUG_TRAP ((flags & (MSG_OOB | MSG_PEEK | MSG_TRUNC)) == 0);*/
++
++      lock_sock(sk);
++
++      TCP_CHECK_TIMER(sk);
++
++      copied = -ENOTCONN;
++      if (sk->sk_state == TCP_LISTEN)
++              goto out;
++
++      copied = 0;
++      timeo = sock_rcvtimeo(sk, nonblock);
++
++      do {
++              struct sk_buff * skb;
++              u32 offset;
++              unsigned long used;
++              int exhausted;
++              int eaten;
++
++              /* Are we at urgent data? Stop if we have read anything. */
++              if (copied && tp->urg_data && tp->urg_seq == tp->copied_seq)
++                      break;
++
++              /* We need to check signals first, to get correct SIGURG
++               * handling. FIXME: Need to check this doesnt impact 1003.1g
++               * and move it down to the bottom of the loop
++               */
++              if (signal_pending(current)) {
++                      if (copied)
++                              break;
++                      copied = timeo ? sock_intr_errno(timeo) : -EAGAIN;
++                      break;
++              }
++
++              /* Next get a buffer. */
++
++              skb = skb_peek(&sk->sk_receive_queue);
++
++              if (skb == NULL)                /* nothing ready */
++              {
++                      if (copied) {
++                              if (sk->sk_err ||
++                                  sk->sk_state == TCP_CLOSE ||
++                                  (sk->sk_shutdown & RCV_SHUTDOWN) ||
++                                  !timeo ||
++                                  (0))
++                                      break;
++                      } else {
++                              if (sock_flag(sk, SOCK_DONE))
++                                      break;
++
++                              if (sk->sk_err) {
++                                      copied = sock_error(sk);
++                                      break;
++                              }
++
++                              if (sk->sk_shutdown & RCV_SHUTDOWN)
++                                      break;
++
++                              if (sk->sk_state == TCP_CLOSE) {
++                                      if (!(sock_flag(sk, SOCK_DONE))) {
++                                              /* This occurs when user tries to read
++                                               * from never connected socket.
++                                               */
++                                              copied = -ENOTCONN;
++                                              break;
++                                      }
++                                      break;
++                              }
++
++                              if (!timeo) {
++                                      copied = -EAGAIN;
++                                      break;
++                              }
++                      }
++
++                      tcp_cleanup_rbuf(sk, copied);
++                      sk_wait_data(sk, &timeo);
++                      continue;
++              }
++
++              BUG_TRAP (atomic_read (&skb->users) == 1);
++
++              exhausted = eaten = 0;
++
++              offset = tp->copied_seq - TCP_SKB_CB(skb)->seq;
++              if (skb->h.th->syn)
++                      offset--;
++
++              used = skb->len - offset;
++
++              if (tp->urg_data) {
++                      u32 urg_offset = tp->urg_seq - tp->copied_seq;
++                      if (urg_offset < used) {
++                              if (!urg_offset) { /* at urgent date */
++                                      if (!(sock_flag(sk, SOCK_URGINLINE))) {
++                                              tp->copied_seq++; /* discard the single byte of urgent data */
++                                              offset++;
++                                              used--;
++                                      }
++                              } else          /* truncate read */
++                                      used = urg_offset;
++                      }
++              }
++
++              BUG_TRAP (used >= 0);
++              if (len < used)
++                      used = len;
++
++              if (used == 0)
++                      exhausted = 1;
++              else
++              {
++                      if (skb_is_nonlinear (skb))
++                      {
++                              int   rc = skb_linearize (skb, GFP_KERNEL);
++
++                              printk ("tcp_recvpackets(): linearising: %d\n", rc);
++
++                              if (rc)
++                              {
++                                      if (!copied)
++                                              copied = rc;
++                                      break;
++                              }
++                      }
++
++                      if ((offset + used) == skb->len) /* consuming the whole packet */
++                      {
++                              __skb_unlink (skb, &sk->sk_receive_queue);
++                              dst_release (skb->dst);
++                              skb_orphan (skb);
++                              __skb_pull (skb, offset);
++                              __skb_queue_tail (packets, skb);
++                              exhausted = eaten = 1;
++                      }
++                      else                    /* consuming only part of the packet */
++                      {
++                              struct sk_buff *skb2 = skb_clone (skb, GFP_KERNEL);
++
++                              if (skb2 == NULL)
++                              {
++                                      if (!copied)
++                                              copied = -ENOMEM;
++                                      break;
++                              }
++
++                              dst_release (skb2->dst);
++                              __skb_pull (skb2, offset);
++                              __skb_trim (skb2, used);
++                              __skb_queue_tail (packets, skb2);
++                      }
++
++                      tp->copied_seq += used;
++                      copied += used;
++                      len -= used;
++              }
++
++              if (tp->urg_data && after(tp->copied_seq,tp->urg_seq)) {
++                      tp->urg_data = 0;
++                      tcp_fast_path_check(sk, tp);
++              }
++
++              if (!exhausted)
++                      continue;
++
++              if (skb->h.th->fin)
++              {
++                      tp->copied_seq++;
++                      if (!eaten)
++                              sk_eat_skb (sk, skb, 0);
++                      break;
++              }
++
++              if (!eaten)
++                      sk_eat_skb (sk, skb, 0);
++
++      } while (len > 0);
++
++ out:
++      /* Clean up data we have read: This will do ACK frames. */
++      tcp_cleanup_rbuf(sk, copied);
++      TCP_CHECK_TIMER(sk);
++      release_sock(sk);
++      return copied;
++}
++
+ /*
+  *    State processing on a close. This implements the state shift for
+  *    sending our FIN frame. Note that we only send a FIN for some
+@@ -2218,6 +2466,8 @@
+ EXPORT_SYMBOL(tcp_recvmsg);
+ EXPORT_SYMBOL(tcp_sendmsg);
+ EXPORT_SYMBOL(tcp_sendpage);
++EXPORT_SYMBOL(tcp_sendpage_zccd);
++EXPORT_SYMBOL(tcp_recvpackets);
+ EXPORT_SYMBOL(tcp_setsockopt);
+ EXPORT_SYMBOL(tcp_shutdown);
+ EXPORT_SYMBOL(tcp_statistics);
+Index: linux-2.6.16.21-0.8/include/linux/skbuff.h
+===================================================================
+--- linux-2.6.16.21-0.8.orig/include/linux/skbuff.h    2006-08-03 21:11:25.000000000 -0600
++++ linux-2.6.16.21-0.8/include/linux/skbuff.h 2006-08-03 21:11:30.000000000 -0600
+@@ -129,6 +129,30 @@
+       __u16 size;
+ };
++/* Support for callback when skb data has been released */
++typedef struct zccd                            /* Zero Copy Callback Descriptor */
++{                                              /* (embed as first member of custom struct) */
++      atomic_t        zccd_count;             /* reference count */
++      void           (*zccd_destructor)(struct zccd *); /* callback when refcount reaches zero */
++} zccd_t;
++
++static inline void zccd_init (zccd_t *d, void (*callback)(zccd_t *))
++{
++      atomic_set (&d->zccd_count, 1);
++      d->zccd_destructor = callback;
++}
++
++static inline void zccd_get (zccd_t *d)                /* take a reference */
++{
++      atomic_inc (&d->zccd_count);
++}
++
++static inline void zccd_put (zccd_t *d)                /* release a reference */
++{
++      if (atomic_dec_and_test (&d->zccd_count))
++              (d->zccd_destructor)(d);
++}
++
+ /* This data is invariant across clones and lives at
+  * the end of the header data, ie. at skb->end.
+  */
+@@ -140,6 +164,13 @@
+       unsigned short  ufo_size;
+       unsigned int    ip6_frag_id;
+       struct sk_buff  *frag_list;
++      zccd_t          *zccd;                  /* zero copy descriptor */
++      zccd_t          *zccd2;                 /* 2nd zero copy descriptor */
++      /* NB we expect zero-copy data to be at least 1 packet, so
++      * having 2 zccds means we don't unneccessarily split the packet
++      * where consecutive zero-copy sends abutt.
++      */
++
+       skb_frag_t      frags[MAX_SKB_FRAGS];
+ };
+Index: linux-2.6.16.21-0.8/include/net/tcp.h
+===================================================================
+--- linux-2.6.16.21-0.8.orig/include/net/tcp.h 2006-08-03 21:11:25.000000000 -0600
++++ linux-2.6.16.21-0.8/include/net/tcp.h      2006-08-03 21:11:30.000000000 -0600
+@@ -272,6 +272,9 @@
+ extern int                    tcp_sendmsg(struct kiocb *iocb, struct sock *sk,
+                                           struct msghdr *msg, size_t size);
+ extern ssize_t                        tcp_sendpage(struct socket *sock, struct page *page, int offset, size_t size, int flags);
++extern ssize_t                 tcp_sendpage_zccd(struct socket *sock, struct page *page, int offset, size_t size,
++                                              int flags, zccd_t *zccd);
++
+ extern int                    tcp_ioctl(struct sock *sk, 
+                                         int cmd, 
+@@ -356,6 +359,9 @@
+                                           struct msghdr *msg,
+                                           size_t len, int nonblock, 
+                                           int flags, int *addr_len);
++extern int                     tcp_recvpackets(struct sock *sk,
++                                              struct sk_buff_head *packets,
++                                              int len, int nonblock);
+ extern void                   tcp_parse_options(struct sk_buff *skb,
+                                                 struct tcp_options_received *opt_rx,
diff --git a/lustre/kernel_patches/patches/tcp-zero-copy-2.6.18-vanilla.patch b/lustre/kernel_patches/patches/tcp-zero-copy-2.6.18-vanilla.patch
new file mode 100644 (file)
index 0000000..cb33b04
--- /dev/null
@@ -0,0 +1,450 @@
+Index: linux-2.6/net/core/skbuff.c
+===================================================================
+--- linux-2.6.orig/net/core/skbuff.c   2006-07-15 21:08:45.000000000 +0800
++++ linux-2.6/net/core/skbuff.c        2006-07-15 21:12:21.000000000 +0800
+@@ -183,7 +183,8 @@ struct sk_buff *__alloc_skb(unsigned int
+       shinfo->gso_type = 0;
+       shinfo->ip6_frag_id = 0;
+       shinfo->frag_list = NULL;
+-
++      shinfo->zccd = NULL;           /* skbuffs kick off with NO user zero copy descriptors */
++      shinfo->zccd2 = NULL;
+       if (fclone) {
+               struct sk_buff *child = skb + 1;
+               atomic_t *fclone_ref = (atomic_t *) (child + 1);
+@@ -283,6 +284,10 @@ static void skb_release_data(struct sk_b
+       if (!skb->cloned ||
+           !atomic_sub_return(skb->nohdr ? (1 << SKB_DATAREF_SHIFT) + 1 : 1,
+                              &skb_shinfo(skb)->dataref)) {
++              if (skb_shinfo(skb)->zccd != NULL) /* zero copy callback descriptor? */
++                      zccd_put (skb_shinfo(skb)->zccd); /* release hold */
++              if (skb_shinfo(skb)->zccd2 != NULL) /* 2nd zero copy callback descriptor? */
++                      zccd_put (skb_shinfo(skb)->zccd2); /* release hold */
+               if (skb_shinfo(skb)->nr_frags) {
+                       int i;
+                       for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
+@@ -618,6 +623,14 @@ struct sk_buff *pskb_copy(struct sk_buff
+       n->data_len  = skb->data_len;
+       n->len       = skb->len;
++      if (skb_shinfo(skb)->zccd != NULL)      /* user zero copy descriptor? */
++              zccd_get (skb_shinfo(skb)->zccd); /* 1 more ref (pages are shared) */
++      skb_shinfo(n)->zccd = skb_shinfo(skb)->zccd;
++
++      if (skb_shinfo(skb)->zccd2 != NULL)     /* 2nd user zero copy descriptor? */
++              zccd_get (skb_shinfo(skb)->zccd2); /* 1 more ref (pages are shared) */
++      skb_shinfo(n)->zccd2 = skb_shinfo(skb)->zccd2;
++
+       if (skb_shinfo(skb)->nr_frags) {
+               int i;
+@@ -661,6 +674,9 @@ int pskb_expand_head(struct sk_buff *skb
+       u8 *data;
+       int size = nhead + (skb->end - skb->head) + ntail;
+       long off;
++      zccd_t *zccd = skb_shinfo(skb)->zccd;   /* stash user zero copy descriptor */
++      zccd_t *zccd2 = skb_shinfo(skb)->zccd2; /* stash 2nd user zero copy descriptor */
++
+       if (skb_shared(skb))
+               BUG();
+@@ -682,6 +698,11 @@ int pskb_expand_head(struct sk_buff *skb
+       if (skb_shinfo(skb)->frag_list)
+               skb_clone_fraglist(skb);
++      if (zccd != NULL)                       /* user zero copy descriptor? */
++              zccd_get (zccd);                /* extra ref (pages are shared) */
++      if (zccd2 != NULL)                      /* 2nd user zero copy descriptor? */
++              zccd_get (zccd2);               /* extra ref (pages are shared) */
++
+       skb_release_data(skb);
+       off = (data + nhead) - skb->head;
+@@ -696,6 +717,8 @@ int pskb_expand_head(struct sk_buff *skb
+       skb->cloned   = 0;
+       skb->nohdr    = 0;
+       atomic_set(&skb_shinfo(skb)->dataref, 1);
++      skb_shinfo(skb)->zccd = zccd;
++      skb_shinfo(skb)->zccd2 = zccd2;
+       return 0;
+ nodata:
+Index: linux-2.6/net/ipv4/tcp.c
+===================================================================
+--- linux-2.6.orig/net/ipv4/tcp.c      2006-07-15 21:08:45.000000000 +0800
++++ linux-2.6/net/ipv4/tcp.c   2006-07-15 22:32:12.000000000 +0800
+@@ -499,8 +499,10 @@ static inline void tcp_push(struct sock 
+       }
+ }
++/* Extra parameter: user zero copy descriptor (or NULL if not doing that) */
+ static ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffset,
+-                       size_t psize, int flags)
++                              size_t psize, int flags, zccd_t *zccd)
++
+ {
+       struct tcp_sock *tp = tcp_sk(sk);
+       int mss_now, size_goal;
+@@ -548,6 +550,17 @@ new_segment:
+                       copy = size;
+               i = skb_shinfo(skb)->nr_frags;
++
++              if (zccd != NULL &&             /* this is a zcc I/O */
++                              skb_shinfo(skb)->zccd != NULL && /* skb is part of a zcc I/O */
++                              skb_shinfo(skb)->zccd2 != NULL &&
++                              skb_shinfo(skb)->zccd != zccd && /* not the same one */
++                              skb_shinfo(skb)->zccd2 != zccd)
++              {
++                      tcp_mark_push (tp, skb);
++                      goto new_segment;
++              }
++
+               can_coalesce = skb_can_coalesce(skb, i, page, offset);
+               if (!can_coalesce && i >= MAX_SKB_FRAGS) {
+                       tcp_mark_push(tp, skb);
+@@ -563,6 +576,20 @@ new_segment:
+                       skb_fill_page_desc(skb, i, page, offset, copy);
+               }
++              if (zccd != NULL &&     /* this is a zcc I/O */
++                      skb_shinfo(skb)->zccd != zccd && /* not already referencing this zccd */
++                      skb_shinfo(skb)->zccd2 != zccd)
++              {
++                      zccd_get (zccd);        /* bump ref count */
++
++                      BUG_TRAP (skb_shinfo(skb)->zccd2 == NULL);
++
++                      if (skb_shinfo(skb)->zccd == NULL) /* reference this zccd */
++                              skb_shinfo(skb)->zccd = zccd;
++                      else
++                              skb_shinfo(skb)->zccd2 = zccd;
++              }
++
+               skb->len += copy;
+               skb->data_len += copy;
+               skb->truesize += copy;
+@@ -628,12 +655,37 @@ ssize_t tcp_sendpage(struct socket *sock
+       lock_sock(sk);
+       TCP_CHECK_TIMER(sk);
+-      res = do_tcp_sendpages(sk, &page, offset, size, flags);
++      res = do_tcp_sendpages(sk, &page, offset, size, flags,NULL);
++      TCP_CHECK_TIMER(sk);
++      release_sock(sk);
++      return res;
++}
++
++ssize_t tcp_sendpage_zccd(struct socket *sock, struct page *page, int offset, size_t size,
++                          int flags, zccd_t *zccd)
++{
++      ssize_t res;
++      struct sock *sk = sock->sk;
++
++#define TCP_ZC_CSUM_FLAGS (NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM)
++
++      if (!(sk->sk_route_caps & NETIF_F_SG) ||        /* caller shouldn't waste her time */
++          !(sk->sk_route_caps & TCP_ZC_CSUM_FLAGS)) /* on double mapping */
++              BUG ();
++
++#undef TCP_ZC_CSUM_FLAGS
++
++      lock_sock(sk);
++      TCP_CHECK_TIMER(sk);
++
++      res = do_tcp_sendpages(sk, &page, offset, size, flags, zccd);
++
+       TCP_CHECK_TIMER(sk);
+       release_sock(sk);
+       return res;
+ }
++
+ #define TCP_PAGE(sk)  (sk->sk_sndmsg_page)
+ #define TCP_OFF(sk)   (sk->sk_sndmsg_off)
+@@ -1477,6 +1529,202 @@ recv_urg:
+       goto out;
+ }
++int tcp_recvpackets (struct sock *sk, struct sk_buff_head *packets,
++                   int len, int nonblock)
++{
++      struct tcp_sock *tp = tcp_sk(sk);
++      int copied;
++      long timeo;
++
++      BUG_TRAP (len > 0);
++      /*BUG_TRAP ((flags & (MSG_OOB | MSG_PEEK | MSG_TRUNC)) == 0);*/
++
++      lock_sock(sk);
++
++      TCP_CHECK_TIMER(sk);
++
++      copied = -ENOTCONN;
++      if (sk->sk_state == TCP_LISTEN)
++              goto out;
++
++      copied = 0;
++      timeo = sock_rcvtimeo(sk, nonblock);
++
++      do {
++              struct sk_buff * skb;
++              u32 offset;
++              unsigned long used;
++              int exhausted;
++              int eaten;
++
++              /* Are we at urgent data? Stop if we have read anything. */
++              if (copied && tp->urg_data && tp->urg_seq == tp->copied_seq)
++                      break;
++
++              /* We need to check signals first, to get correct SIGURG
++               * handling. FIXME: Need to check this doesnt impact 1003.1g
++               * and move it down to the bottom of the loop
++               */
++              if (signal_pending(current)) {
++                      if (copied)
++                              break;
++                      copied = timeo ? sock_intr_errno(timeo) : -EAGAIN;
++                      break;
++              }
++
++              /* Next get a buffer. */
++
++              skb = skb_peek(&sk->sk_receive_queue);
++
++              if (skb == NULL)                /* nothing ready */
++              {
++                      if (copied) {
++                              if (sk->sk_err ||
++                                  sk->sk_state == TCP_CLOSE ||
++                                  (sk->sk_shutdown & RCV_SHUTDOWN) ||
++                                  !timeo ||
++                                  (0))
++                                      break;
++                      } else {
++                              if (sock_flag(sk, SOCK_DONE))
++                                      break;
++
++                              if (sk->sk_err) {
++                                      copied = sock_error(sk);
++                                      break;
++                              }
++
++                              if (sk->sk_shutdown & RCV_SHUTDOWN)
++                                      break;
++
++                              if (sk->sk_state == TCP_CLOSE) {
++                                      if (!(sock_flag(sk, SOCK_DONE))) {
++                                              /* This occurs when user tries to read
++                                               * from never connected socket.
++                                               */
++                                              copied = -ENOTCONN;
++                                              break;
++                                      }
++                                      break;
++                              }
++
++                              if (!timeo) {
++                                      copied = -EAGAIN;
++                                      break;
++                              }
++                      }
++
++                      tcp_cleanup_rbuf(sk, copied);
++                      sk_wait_data(sk, &timeo);
++                      continue;
++              }
++
++              BUG_TRAP (atomic_read (&skb->users) == 1);
++
++              exhausted = eaten = 0;
++
++              offset = tp->copied_seq - TCP_SKB_CB(skb)->seq;
++              if (skb->h.th->syn)
++                      offset--;
++
++              used = skb->len - offset;
++
++              if (tp->urg_data) {
++                      u32 urg_offset = tp->urg_seq - tp->copied_seq;
++                      if (urg_offset < used) {
++                              if (!urg_offset) { /* at urgent date */
++                                      if (!(sock_flag(sk, SOCK_URGINLINE))) {
++                                              tp->copied_seq++; /* discard the single byte of urgent data */
++                                              offset++;
++                                              used--;
++                                      }
++                              } else          /* truncate read */
++                                      used = urg_offset;
++                      }
++              }
++
++              BUG_TRAP (used >= 0);
++              if (len < used)
++                      used = len;
++
++              if (used == 0)
++                      exhausted = 1;
++              else
++              {
++                      if (skb_is_nonlinear (skb))
++                      {
++                              int   rc = skb_linearize (skb);
++
++                              printk ("tcp_recvpackets(): linearising: %d\n", rc);
++
++                              if (rc)
++                              {
++                                      if (!copied)
++                                              copied = rc;
++                                      break;
++                              }
++                      }
++
++                      if ((offset + used) == skb->len) /* consuming the whole packet */
++                      {
++                              __skb_unlink (skb, &sk->sk_receive_queue);
++                              dst_release (skb->dst);
++                              skb_orphan (skb);
++                              __skb_pull (skb, offset);
++                              __skb_queue_tail (packets, skb);
++                              exhausted = eaten = 1;
++                      }
++                      else                    /* consuming only part of the packet */
++                      {
++                              struct sk_buff *skb2 = skb_clone (skb, GFP_KERNEL);
++
++                              if (skb2 == NULL)
++                              {
++                                      if (!copied)
++                                              copied = -ENOMEM;
++                                      break;
++                              }
++
++                              dst_release (skb2->dst);
++                              __skb_pull (skb2, offset);
++                              __skb_trim (skb2, used);
++                              __skb_queue_tail (packets, skb2);
++                      }
++
++                      tp->copied_seq += used;
++                      copied += used;
++                      len -= used;
++              }
++
++              if (tp->urg_data && after(tp->copied_seq,tp->urg_seq)) {
++                      tp->urg_data = 0;
++                      tcp_fast_path_check(sk, tp);
++              }
++
++              if (!exhausted)
++                      continue;
++
++              if (skb->h.th->fin)
++              {
++                      tp->copied_seq++;
++                      if (!eaten)
++                              sk_eat_skb (sk, skb, 0);
++                      break;
++              }
++
++              if (!eaten)
++                      sk_eat_skb (sk, skb, 0);
++
++      } while (len > 0);
++
++ out:
++      /* Clean up data we have read: This will do ACK frames. */
++      tcp_cleanup_rbuf(sk, copied);
++      TCP_CHECK_TIMER(sk);
++      release_sock(sk);
++      return copied;
++}
++
+ /*
+  *    State processing on a close. This implements the state shift for
+  *    sending our FIN frame. Note that we only send a FIN for some
+@@ -2345,6 +2593,8 @@ EXPORT_SYMBOL(tcp_read_sock);
+ EXPORT_SYMBOL(tcp_recvmsg);
+ EXPORT_SYMBOL(tcp_sendmsg);
+ EXPORT_SYMBOL(tcp_sendpage);
++EXPORT_SYMBOL(tcp_sendpage_zccd);
++EXPORT_SYMBOL(tcp_recvpackets);
+ EXPORT_SYMBOL(tcp_setsockopt);
+ EXPORT_SYMBOL(tcp_shutdown);
+ EXPORT_SYMBOL(tcp_statistics);
+Index: linux-2.6/include/linux/skbuff.h
+===================================================================
+--- linux-2.6.orig/include/linux/skbuff.h      2006-07-15 21:08:45.000000000 +0800
++++ linux-2.6/include/linux/skbuff.h   2006-07-15 21:12:21.000000000 +0800
+@@ -128,6 +128,30 @@ struct skb_frag_struct {
+       __u16 size;
+ };
++/* Support for callback when skb data has been released */
++typedef struct zccd                            /* Zero Copy Callback Descriptor */
++{                                              /* (embed as first member of custom struct) */
++      atomic_t        zccd_count;             /* reference count */
++      void           (*zccd_destructor)(struct zccd *); /* callback when refcount reaches zero */
++} zccd_t;
++
++static inline void zccd_init (zccd_t *d, void (*callback)(zccd_t *))
++{
++      atomic_set (&d->zccd_count, 1);
++      d->zccd_destructor = callback;
++}
++
++static inline void zccd_get (zccd_t *d)                /* take a reference */
++{
++      atomic_inc (&d->zccd_count);
++}
++
++static inline void zccd_put (zccd_t *d)                /* release a reference */
++{
++      if (atomic_dec_and_test (&d->zccd_count))
++              (d->zccd_destructor)(d);
++}
++
+ /* This data is invariant across clones and lives at
+  * the end of the header data, ie. at skb->end.
+  */
+@@ -140,6 +164,13 @@ struct skb_shared_info {
+       unsigned short  gso_type;
+       unsigned int    ip6_frag_id;
+       struct sk_buff  *frag_list;
++      zccd_t          *zccd;                  /* zero copy descriptor */
++      zccd_t          *zccd2;                 /* 2nd zero copy descriptor */
++      /* NB we expect zero-copy data to be at least 1 packet, so
++      * having 2 zccds means we don't unneccessarily split the packet
++      * where consecutive zero-copy sends abutt.
++      */
++
+       skb_frag_t      frags[MAX_SKB_FRAGS];
+ };
+Index: linux-2.6/include/net/tcp.h
+===================================================================
+--- linux-2.6.orig/include/net/tcp.h   2006-07-15 21:08:45.000000000 +0800
++++ linux-2.6/include/net/tcp.h        2006-07-15 21:12:21.000000000 +0800
+@@ -278,6 +278,9 @@ extern int                 tcp_v4_tw_remember_stam
+ extern int                    tcp_sendmsg(struct kiocb *iocb, struct sock *sk,
+                                           struct msghdr *msg, size_t size);
+ extern ssize_t                        tcp_sendpage(struct socket *sock, struct page *page, int offset, size_t size, int flags);
++extern ssize_t                 tcp_sendpage_zccd(struct socket *sock, struct page *page, int offset, size_t size,
++                                              int flags, zccd_t *zccd);
++
+ extern int                    tcp_ioctl(struct sock *sk, 
+                                         int cmd, 
+@@ -368,6 +371,9 @@ extern int                 tcp_recvmsg(struct kiocb *i
+                                           struct msghdr *msg,
+                                           size_t len, int nonblock, 
+                                           int flags, int *addr_len);
++extern int                     tcp_recvpackets(struct sock *sk,
++                                              struct sk_buff_head *packets,
++                                              int len, int nonblock);
+ extern void                   tcp_parse_options(struct sk_buff *skb,
+                                                 struct tcp_options_received *opt_rx,
index 1055dee..9030e8c 100644 (file)
@@ -1,22 +1,7 @@
- fs/dcache.c               |   19 ++
- fs/exec.c                 |   17 +-
- fs/namei.c                |  295 +++++++++++++++++++++++++++++++++++++++-------
- fs/namespace.c            |   28 +++-
- fs/open.c                 |  172 +++++++++++++++++++-------
- fs/stat.c                 |   52 +++++---
- include/linux/dcache.h    |   60 +++++++++
- include/linux/fs.h        |   32 ++++
- include/linux/fs_struct.h |    4 
- kernel/exit.c             |    3 
- kernel/fork.c             |    3 
- kernel/ksyms.c            |    1 
- 12 files changed, 558 insertions(+), 128 deletions(-)
-
-Index: linux-2.4.21/fs/dcache.c
-===================================================================
---- linux-2.4.21.orig/fs/dcache.c      2005-06-01 22:51:55.000000000 -0400
-+++ linux-2.4.21/fs/dcache.c   2005-06-01 22:58:09.043064136 -0400
-@@ -187,6 +187,13 @@
+diff -X dontdiff -urp kern_oldest/fs/dcache.c kern_new/fs/dcache.c
+--- kern_oldest/fs/dcache.c    2006-05-01 11:55:39.000000000 -0700
++++ kern_new/fs/dcache.c       2006-05-02 20:21:49.000000000 -0700
+@@ -187,6 +187,13 @@ int d_invalidate(struct dentry * dentry)
                spin_unlock(&dcache_lock);
                return 0;
        }
@@ -30,7 +15,7 @@ Index: linux-2.4.21/fs/dcache.c
        /*
         * Check whether to do a partial shrink_dcache
         * to get rid of unused child entries.
-@@ -848,13 +855,19 @@
+@@ -848,13 +855,19 @@ void d_delete(struct dentry * dentry)
   * Adds a dentry to the hash according to its name.
   */
   
@@ -53,11 +38,10 @@ Index: linux-2.4.21/fs/dcache.c
  }
  
  #define do_switch(x,y) do { \
-Index: linux-2.4.21/fs/exec.c
-===================================================================
---- linux-2.4.21.orig/fs/exec.c        2005-06-01 22:52:05.000000000 -0400
-+++ linux-2.4.21/fs/exec.c     2005-06-01 22:58:09.044063984 -0400
-@@ -116,8 +116,10 @@
+diff -X dontdiff -urp kern_oldest/fs/exec.c kern_new/fs/exec.c
+--- kern_oldest/fs/exec.c      2006-05-01 11:55:39.000000000 -0700
++++ kern_new/fs/exec.c 2006-05-02 20:21:49.000000000 -0700
+@@ -116,8 +116,10 @@ asmlinkage long sys_uselib(const char * 
        struct file * file;
        struct nameidata nd;
        int error;
@@ -69,7 +53,7 @@ Index: linux-2.4.21/fs/exec.c
        if (error)
                goto out;
  
-@@ -129,7 +131,8 @@
+@@ -129,7 +131,8 @@ asmlinkage long sys_uselib(const char * 
        if (error)
                goto exit;
  
@@ -79,7 +63,7 @@ Index: linux-2.4.21/fs/exec.c
        error = PTR_ERR(file);
        if (IS_ERR(file))
                goto out;
-@@ -405,8 +408,10 @@
+@@ -405,8 +408,10 @@ struct file *open_exec(const char *name)
        struct inode *inode;
        struct file *file;
        int err = 0;
@@ -91,7 +75,7 @@ Index: linux-2.4.21/fs/exec.c
        file = ERR_PTR(err);
        if (!err) {
                inode = nd.dentry->d_inode;
-@@ -418,7 +423,8 @@
+@@ -418,7 +423,8 @@ struct file *open_exec(const char *name)
                                err = -EACCES;
                        file = ERR_PTR(err);
                        if (!err) {
@@ -101,7 +85,7 @@ Index: linux-2.4.21/fs/exec.c
                                if (!IS_ERR(file)) {
                                        err = deny_write_access(file);
                                        if (err) {
-@@ -430,6 +436,7 @@
+@@ -430,6 +436,7 @@ out:
                                return file;
                        }
                }
@@ -109,7 +93,7 @@ Index: linux-2.4.21/fs/exec.c
                path_release(&nd);
        }
        goto out;
-@@ -1368,7 +1375,7 @@
+@@ -1383,7 +1390,7 @@ int do_coredump(long signr, int exit_cod
                goto close_fail;
        if (!file->f_op->write)
                goto close_fail;
@@ -118,10 +102,9 @@ Index: linux-2.4.21/fs/exec.c
                goto close_fail;
  
        retval = binfmt->core_dump(signr, regs, file);
-Index: linux-2.4.21/fs/namei.c
-===================================================================
---- linux-2.4.21.orig/fs/namei.c       2005-06-01 22:52:05.000000000 -0400
-+++ linux-2.4.21/fs/namei.c    2005-06-01 23:01:30.065504080 -0400
+diff -X dontdiff -urp kern_oldest/fs/namei.c kern_new/fs/namei.c
+--- kern_oldest/fs/namei.c     2006-05-01 11:55:39.000000000 -0700
++++ kern_new/fs/namei.c        2006-05-02 20:21:49.000000000 -0700
 @@ -94,6 +94,13 @@
   * XEmacs seems to be relying on it...
   */
@@ -136,7 +119,7 @@ Index: linux-2.4.21/fs/namei.c
  /* In order to reduce some races, while at the same time doing additional
   * checking and hopefully speeding things up, we copy filenames to the
   * kernel data space before using them..
-@@ -260,10 +267,19 @@
+@@ -260,10 +267,19 @@ void path_release(struct nameidata *nd)
   * Internal lookup() using the new generic dcache.
   * SMP-safe
   */
@@ -157,7 +140,7 @@ Index: linux-2.4.21/fs/namei.c
        if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
                if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {
                        dput(dentry);
-@@ -281,11 +297,15 @@
+@@ -281,11 +297,15 @@ static struct dentry * cached_lookup(str
   * make sure that nobody added the entry to the dcache in the meantime..
   * SMP-safe
   */
@@ -174,7 +157,7 @@ Index: linux-2.4.21/fs/namei.c
        down(&dir->i_sem);
        /*
         * First re-do the cached lookup just in case it was created
-@@ -300,6 +320,9 @@
+@@ -300,6 +320,9 @@ static struct dentry * real_lookup(struc
                result = ERR_PTR(-ENOMEM);
                if (dentry) {
                        lock_kernel();
@@ -184,7 +167,7 @@ Index: linux-2.4.21/fs/namei.c
                        result = dir->i_op->lookup(dir, dentry);
                        unlock_kernel();
                        if (result)
-@@ -321,6 +344,15 @@
+@@ -321,6 +344,15 @@ static struct dentry * real_lookup(struc
                        dput(result);
                        result = ERR_PTR(-ENOENT);
                }
@@ -200,7 +183,7 @@ Index: linux-2.4.21/fs/namei.c
        }
        return result;
  }
-@@ -332,7 +364,8 @@
+@@ -332,7 +364,8 @@ static struct dentry * real_lookup(struc
   * Without that kind of total limit, nasty chains of consecutive
   * symlinks can cause almost arbitrarily long lookups. 
   */
@@ -210,7 +193,7 @@ Index: linux-2.4.21/fs/namei.c
  {
        int err;
        if (current->link_count >= 8)
-@@ -346,10 +379,12 @@
+@@ -346,10 +379,12 @@ static inline int do_follow_link(struct 
        current->link_count++;
        current->total_link_count++;
        UPDATE_ATIME(dentry->d_inode);
@@ -223,7 +206,7 @@ Index: linux-2.4.21/fs/namei.c
        path_release(nd);
        return -ELOOP;
  }
-@@ -447,7 +482,8 @@
+@@ -447,7 +482,8 @@ static inline void follow_dotdot(struct 
   *
   * We expect 'base' to be positive and a directory.
   */
@@ -233,7 +216,7 @@ Index: linux-2.4.21/fs/namei.c
  {
        struct dentry *dentry;
        struct inode *inode;
-@@ -524,12 +560,12 @@
+@@ -524,12 +560,12 @@ int link_path_walk(const char * name, st
                                break;
                }
                /* This does the actual lookups.. */
@@ -248,7 +231,7 @@ Index: linux-2.4.21/fs/namei.c
                        err = PTR_ERR(dentry);
                        if (IS_ERR(dentry))
                                break;
-@@ -548,7 +584,7 @@
+@@ -548,7 +584,7 @@ int link_path_walk(const char * name, st
  
                if (inode->i_op->follow_link) {
                        struct vfsmount *mnt = mntget(nd->mnt);
@@ -257,7 +240,7 @@ Index: linux-2.4.21/fs/namei.c
                        dput(dentry);
                        mntput(mnt);
                        if (err)
-@@ -565,7 +601,7 @@
+@@ -565,7 +601,7 @@ int link_path_walk(const char * name, st
                        nd->dentry = dentry;
                }
                err = -ENOTDIR; 
@@ -266,7 +249,7 @@ Index: linux-2.4.21/fs/namei.c
                        break;
                continue;
                /* here ends the main loop */
-@@ -592,12 +628,12 @@
+@@ -592,12 +628,12 @@ last_component:
                        if (err < 0)
                                break;
                }
@@ -281,7 +264,7 @@ Index: linux-2.4.21/fs/namei.c
                        err = PTR_ERR(dentry);
                        if (IS_ERR(dentry))
                                break;
-@@ -608,7 +644,7 @@
+@@ -608,7 +644,7 @@ last_component:
                if ((lookup_flags & LOOKUP_FOLLOW)
                    && inode && inode->i_op && inode->i_op->follow_link) {
                        struct vfsmount *mnt = mntget(nd->mnt);
@@ -290,7 +273,7 @@ Index: linux-2.4.21/fs/namei.c
                        dput(dentry);
                        mntput(mnt);
                        if (err)
-@@ -623,7 +659,8 @@
+@@ -623,7 +659,8 @@ last_component:
                        goto no_inode;
                if (lookup_flags & LOOKUP_DIRECTORY) {
                        err = -ENOTDIR; 
@@ -300,7 +283,7 @@ Index: linux-2.4.21/fs/namei.c
                                break;
                }
                goto return_base;
-@@ -641,12 +678,42 @@
+@@ -641,12 +678,42 @@ lookup_parent:
                        nd->last_type = LAST_DOT;
                else if (this.len == 2 && this.name[1] == '.')
                        nd->last_type = LAST_DOTDOT;
@@ -343,7 +326,7 @@ Index: linux-2.4.21/fs/namei.c
                if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
                        err = -ESTALE;
                        if (!dentry->d_op->d_revalidate(dentry, 0)) {
-@@ -660,15 +727,28 @@
+@@ -660,15 +727,28 @@ out_dput:
                dput(dentry);
                break;
        }
@@ -373,7 +356,7 @@ Index: linux-2.4.21/fs/namei.c
  }
  
  /* SMP-safe */
-@@ -753,6 +833,17 @@
+@@ -753,6 +833,17 @@ walk_init_root(const char *name, struct 
  }
  
  /* SMP-safe */
@@ -391,7 +374,7 @@ Index: linux-2.4.21/fs/namei.c
  int path_lookup(const char *path, unsigned flags, struct nameidata *nd)
  {
        int error = 0;
-@@ -767,6 +858,7 @@
+@@ -767,6 +858,7 @@ int path_init(const char *name, unsigned
  {
        nd->last_type = LAST_ROOT; /* if there are only slashes... */
        nd->flags = flags;
@@ -399,7 +382,7 @@ Index: linux-2.4.21/fs/namei.c
        if (*name=='/')
                return walk_init_root(name,nd);
        read_lock(&current->fs->lock);
-@@ -781,7 +873,8 @@
+@@ -781,7 +873,8 @@ int path_init(const char *name, unsigned
   * needs parent already locked. Doesn't follow mounts.
   * SMP-safe.
   */
@@ -409,7 +392,7 @@ Index: linux-2.4.21/fs/namei.c
  {
        struct dentry * dentry;
        struct inode *inode;
-@@ -804,13 +897,16 @@
+@@ -804,13 +897,16 @@ struct dentry * lookup_hash(struct qstr 
                        goto out;
        }
  
@@ -427,7 +410,7 @@ Index: linux-2.4.21/fs/namei.c
                dentry = inode->i_op->lookup(inode, new);
                unlock_kernel();
                if (!dentry)
-@@ -822,6 +918,12 @@
+@@ -822,6 +918,12 @@ out:
        return dentry;
  }
  
@@ -440,7 +423,7 @@ Index: linux-2.4.21/fs/namei.c
  /* SMP-safe */
  struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
  {
-@@ -843,7 +945,7 @@
+@@ -843,7 +945,7 @@ struct dentry * lookup_one_len(const cha
        }
        this.hash = end_name_hash(hash);
  
@@ -449,7 +432,7 @@ Index: linux-2.4.21/fs/namei.c
  access:
        return ERR_PTR(-EACCES);
  }
-@@ -874,6 +976,23 @@
+@@ -874,6 +976,23 @@ int __user_walk(const char *name, unsign
        return err;
  }
  
@@ -473,7 +456,7 @@ Index: linux-2.4.21/fs/namei.c
  /*
   * It's inline, so penalty for filesystems that don't use sticky bit is
   * minimal.
-@@ -971,7 +1090,8 @@
+@@ -971,7 +1090,8 @@ static inline int lookup_flags(unsigned 
        return retval;
  }
  
@@ -483,7 +466,7 @@ Index: linux-2.4.21/fs/namei.c
  {
        int error;
  
-@@ -984,12 +1104,15 @@
+@@ -984,12 +1104,15 @@ int vfs_create(struct inode *dir, struct
                goto exit_lock;
  
        error = -EACCES;        /* shouldn't it be ENOSYS? */
@@ -501,7 +484,7 @@ Index: linux-2.4.21/fs/namei.c
        unlock_kernel();
  exit_lock:
        up(&dir->i_zombie);
-@@ -998,6 +1121,11 @@
+@@ -998,6 +1121,11 @@ exit_lock:
        return error;
  }
  
@@ -513,7 +496,7 @@ Index: linux-2.4.21/fs/namei.c
  /*
   *    open_namei()
   *
-@@ -1012,7 +1140,8 @@
+@@ -1012,7 +1140,8 @@ exit_lock:
   * for symlinks (where the permissions are checked later).
   * SMP-safe
   */
@@ -523,7 +506,7 @@ Index: linux-2.4.21/fs/namei.c
  {
        int acc_mode, error = 0;
        struct inode *inode;
-@@ -1023,11 +1152,14 @@
+@@ -1023,11 +1152,14 @@ int open_namei(const char * pathname, in
  
        acc_mode = ACC_MODE(flag);
  
@@ -539,7 +522,7 @@ Index: linux-2.4.21/fs/namei.c
                if (error)
                        return error;
                dentry = nd->dentry;
-@@ -1037,6 +1169,10 @@
+@@ -1037,6 +1169,10 @@ int open_namei(const char * pathname, in
        /*
         * Create - we need to know the parent.
         */
@@ -550,7 +533,7 @@ Index: linux-2.4.21/fs/namei.c
        error = path_lookup(pathname, LOOKUP_PARENT, nd);
        if (error)
                return error;
-@@ -1052,7 +1188,7 @@
+@@ -1052,7 +1188,7 @@ int open_namei(const char * pathname, in
  
        dir = nd->dentry;
        down(&dir->d_inode->i_sem);
@@ -559,7 +542,7 @@ Index: linux-2.4.21/fs/namei.c
  
  do_last:
        error = PTR_ERR(dentry);
-@@ -1061,11 +1197,12 @@
+@@ -1061,11 +1197,12 @@ do_last:
                goto exit;
        }
  
@@ -573,7 +556,7 @@ Index: linux-2.4.21/fs/namei.c
                up(&dir->d_inode->i_sem);
                dput(nd->dentry);
                nd->dentry = dentry;
-@@ -1169,7 +1306,7 @@
+@@ -1169,7 +1306,7 @@ ok:
                if (!error) {
                        DQUOT_INIT(inode);
                        
@@ -582,7 +565,7 @@ Index: linux-2.4.21/fs/namei.c
                }
                put_write_access(inode);
                if (error)
-@@ -1181,8 +1318,10 @@
+@@ -1181,8 +1318,10 @@ ok:
        return 0;
  
  exit_dput:
@@ -593,7 +576,7 @@ Index: linux-2.4.21/fs/namei.c
        path_release(nd);
        return error;
  
-@@ -1202,7 +1341,10 @@
+@@ -1202,7 +1341,10 @@ do_link:
         */
        UPDATE_ATIME(dentry->d_inode);
        mnt = mntget(nd->mnt);
@@ -604,7 +587,7 @@ Index: linux-2.4.21/fs/namei.c
        dput(dentry);
        mntput(mnt);
        if (error)
-@@ -1225,13 +1367,20 @@
+@@ -1225,13 +1367,20 @@ do_link:
        }
        dir = nd->dentry;
        down(&dir->d_inode->i_sem);
@@ -627,7 +610,7 @@ Index: linux-2.4.21/fs/namei.c
  {
        struct dentry *dentry;
  
-@@ -1239,7 +1388,7 @@
+@@ -1239,7 +1388,7 @@ static struct dentry *lookup_create(stru
        dentry = ERR_PTR(-EEXIST);
        if (nd->last_type != LAST_NORM)
                goto fail;
@@ -636,7 +619,7 @@ Index: linux-2.4.21/fs/namei.c
        if (IS_ERR(dentry))
                goto fail;
        if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
-@@ -1295,7 +1444,20 @@
+@@ -1295,7 +1444,20 @@ asmlinkage long sys_mknod(const char * f
        error = path_lookup(tmp, LOOKUP_PARENT, &nd);
        if (error)
                goto out;
@@ -658,7 +641,7 @@ Index: linux-2.4.21/fs/namei.c
        error = PTR_ERR(dentry);
  
        if (!IS_POSIXACL(nd.dentry->d_inode))
-@@ -1317,6 +1479,7 @@
+@@ -1317,6 +1479,7 @@ asmlinkage long sys_mknod(const char * f
                dput(dentry);
        }
        up(&nd.dentry->d_inode->i_sem);
@@ -666,7 +649,7 @@ Index: linux-2.4.21/fs/namei.c
        path_release(&nd);
  out:
        putname(tmp);
-@@ -1364,7 +1527,18 @@
+@@ -1364,7 +1527,18 @@ asmlinkage long sys_mkdir(const char * p
                error = path_lookup(tmp, LOOKUP_PARENT, &nd);
                if (error)
                        goto out;
@@ -686,7 +669,7 @@ Index: linux-2.4.21/fs/namei.c
                error = PTR_ERR(dentry);
                if (!IS_ERR(dentry)) {
                        if (!IS_POSIXACL(nd.dentry->d_inode))
-@@ -1373,6 +1547,7 @@
+@@ -1373,6 +1547,7 @@ asmlinkage long sys_mkdir(const char * p
                        dput(dentry);
                }
                up(&nd.dentry->d_inode->i_sem);
@@ -694,7 +677,7 @@ Index: linux-2.4.21/fs/namei.c
                path_release(&nd);
  out:
                putname(tmp);
-@@ -1473,8 +1648,16 @@
+@@ -1473,8 +1648,16 @@ asmlinkage long sys_rmdir(const char * p
                        error = -EBUSY;
                        goto exit1;
        }
@@ -712,7 +695,7 @@ Index: linux-2.4.21/fs/namei.c
        error = PTR_ERR(dentry);
        if (!IS_ERR(dentry)) {
                error = vfs_rmdir(nd.dentry->d_inode, dentry);
-@@ -1532,8 +1715,15 @@
+@@ -1532,8 +1715,15 @@ asmlinkage long sys_unlink(const char * 
        error = -EISDIR;
        if (nd.last_type != LAST_NORM)
                goto exit1;
@@ -729,7 +712,7 @@ Index: linux-2.4.21/fs/namei.c
        error = PTR_ERR(dentry);
        if (!IS_ERR(dentry)) {
                /* Why not before? Because we want correct error value */
-@@ -1600,15 +1790,27 @@
+@@ -1600,15 +1790,27 @@ asmlinkage long sys_symlink(const char *
                error = path_lookup(to, LOOKUP_PARENT, &nd);
                if (error)
                        goto out;
@@ -759,7 +742,7 @@ Index: linux-2.4.21/fs/namei.c
                putname(to);
        }
        putname(from);
-@@ -1684,7 +1886,18 @@
+@@ -1684,7 +1886,18 @@ asmlinkage long sys_link(const char * ol
                error = -EXDEV;
                if (old_nd.mnt != nd.mnt)
                        goto out_release;
@@ -779,7 +762,7 @@ Index: linux-2.4.21/fs/namei.c
                error = PTR_ERR(new_dentry);
                if (!IS_ERR(new_dentry)) {
                        error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
-@@ -1728,7 +1941,7 @@
+@@ -1728,7 +1941,7 @@ exit:
   *       locking].
   */
  int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
@@ -788,7 +771,7 @@ Index: linux-2.4.21/fs/namei.c
  {
        int error;
        struct inode *target;
-@@ -1807,7 +2020,7 @@
+@@ -1807,7 +2020,7 @@ out_unlock:
  }
  
  int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
@@ -797,7 +780,7 @@ Index: linux-2.4.21/fs/namei.c
  {
        int error;
  
-@@ -1895,9 +2108,18 @@
+@@ -1895,9 +2108,18 @@ static inline int do_rename(const char *
        if (newnd.last_type != LAST_NORM)
                goto exit2;
  
@@ -817,7 +800,7 @@ Index: linux-2.4.21/fs/namei.c
        error = PTR_ERR(old_dentry);
        if (IS_ERR(old_dentry))
                goto exit3;
-@@ -1913,16 +2135,16 @@
+@@ -1913,16 +2135,16 @@ static inline int do_rename(const char *
                if (newnd.last.name[newnd.last.len])
                        goto exit4;
        }
@@ -836,7 +819,7 @@ Index: linux-2.4.21/fs/namei.c
        dput(new_dentry);
  exit4:
        dput(old_dentry);
-@@ -1973,20 +2195,26 @@
+@@ -1973,20 +2195,26 @@ out:
  }
  
  static inline int
@@ -865,7 +848,7 @@ Index: linux-2.4.21/fs/namei.c
  out:
        if (current->link_count || res || nd->last_type!=LAST_NORM)
                return res;
-@@ -2010,7 +2238,13 @@
+@@ -2010,7 +2238,13 @@ fail:
  
  int vfs_follow_link(struct nameidata *nd, const char *link)
  {
@@ -880,7 +863,7 @@ Index: linux-2.4.21/fs/namei.c
  }
  
  /* get the link contents into pagecache */
-@@ -2052,7 +2286,7 @@
+@@ -2052,7 +2286,7 @@ int page_follow_link(struct dentry *dent
  {
        struct page *page = NULL;
        char *s = page_getlink(dentry, &page);
@@ -889,11 +872,10 @@ Index: linux-2.4.21/fs/namei.c
        if (page) {
                kunmap(page);
                page_cache_release(page);
-Index: linux-2.4.21/fs/namespace.c
-===================================================================
---- linux-2.4.21.orig/fs/namespace.c   2005-06-01 22:51:42.000000000 -0400
-+++ linux-2.4.21/fs/namespace.c        2005-06-01 22:58:09.048063376 -0400
-@@ -98,6 +98,7 @@
+diff -X dontdiff -urp kern_oldest/fs/namespace.c kern_new/fs/namespace.c
+--- kern_oldest/fs/namespace.c 2006-05-01 11:55:39.000000000 -0700
++++ kern_new/fs/namespace.c    2006-05-02 20:21:49.000000000 -0700
+@@ -98,6 +98,7 @@ static void detach_mnt(struct vfsmount *
  {
        old_nd->dentry = mnt->mnt_mountpoint;
        old_nd->mnt = mnt->mnt_parent;
@@ -901,7 +883,7 @@ Index: linux-2.4.21/fs/namespace.c
        mnt->mnt_parent = mnt;
        mnt->mnt_mountpoint = mnt->mnt_root;
        list_del_init(&mnt->mnt_child);
-@@ -109,6 +110,7 @@
+@@ -109,6 +110,7 @@ static void attach_mnt(struct vfsmount *
  {
        mnt->mnt_parent = mntget(nd->mnt);
        mnt->mnt_mountpoint = dget(nd->dentry);
@@ -909,7 +891,7 @@ Index: linux-2.4.21/fs/namespace.c
        list_add(&mnt->mnt_hash, mount_hashtable+hash(nd->mnt, nd->dentry));
        list_add(&mnt->mnt_child, &nd->mnt->mnt_mounts);
        nd->dentry->d_mounted++;
-@@ -488,14 +490,17 @@
+@@ -488,14 +490,17 @@ static int do_loopback(struct nameidata 
  {
        struct nameidata old_nd;
        struct vfsmount *mnt = NULL;
@@ -929,7 +911,7 @@ Index: linux-2.4.21/fs/namespace.c
  
        down_write(&current->namespace->sem);
        err = -EINVAL;
-@@ -518,6 +523,7 @@
+@@ -518,6 +523,7 @@ static int do_loopback(struct nameidata 
        }
  
        up_write(&current->namespace->sem);
@@ -937,7 +919,7 @@ Index: linux-2.4.21/fs/namespace.c
        path_release(&old_nd);
        return err;
  }
-@@ -701,6 +707,7 @@
+@@ -701,6 +707,7 @@ long do_mount(char * dev_name, char * di
                  unsigned long flags, void *data_page)
  {
        struct nameidata nd;
@@ -945,7 +927,7 @@ Index: linux-2.4.21/fs/namespace.c
        int retval = 0;
        int mnt_flags = 0;
  
-@@ -725,9 +732,11 @@
+@@ -725,9 +732,11 @@ long do_mount(char * dev_name, char * di
        flags &= ~(MS_NOSUID|MS_NOEXEC|MS_NODEV);
  
        /* ... and get the mountpoint */
@@ -959,7 +941,7 @@ Index: linux-2.4.21/fs/namespace.c
  
        if (flags & MS_REMOUNT)
                retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags,
-@@ -739,6 +748,8 @@
+@@ -739,6 +748,8 @@ long do_mount(char * dev_name, char * di
        else
                retval = do_add_mount(&nd, type_page, flags, mnt_flags,
                                      dev_name, data_page);
@@ -968,7 +950,7 @@ Index: linux-2.4.21/fs/namespace.c
        path_release(&nd);
        return retval;
  }
-@@ -904,6 +915,8 @@
+@@ -904,6 +915,8 @@ asmlinkage long sys_pivot_root(const cha
  {
        struct vfsmount *tmp;
        struct nameidata new_nd, old_nd, parent_nd, root_parent, user_nd;
@@ -977,7 +959,7 @@ Index: linux-2.4.21/fs/namespace.c
        int error;
  
        if (!capable(CAP_SYS_ADMIN))
-@@ -911,14 +924,14 @@
+@@ -911,14 +924,14 @@ asmlinkage long sys_pivot_root(const cha
  
        lock_kernel();
  
@@ -994,7 +976,7 @@ Index: linux-2.4.21/fs/namespace.c
        if (error)
                goto out1;
  
-@@ -973,8 +986,10 @@
+@@ -973,8 +986,10 @@ out2:
        up(&old_nd.dentry->d_inode->i_zombie);
        up_write(&current->namespace->sem);
        path_release(&user_nd);
@@ -1005,11 +987,10 @@ Index: linux-2.4.21/fs/namespace.c
        path_release(&new_nd);
  out0:
        unlock_kernel();
-Index: linux-2.4.21/fs/open.c
-===================================================================
---- linux-2.4.21.orig/fs/open.c        2005-06-01 22:51:55.000000000 -0400
-+++ linux-2.4.21/fs/open.c     2005-06-01 22:58:09.050063072 -0400
-@@ -19,6 +19,8 @@
+diff -X dontdiff -urp kern_oldest/fs/open.c kern_new/fs/open.c
+--- kern_oldest/fs/open.c      2006-05-01 11:55:39.000000000 -0700
++++ kern_new/fs/open.c 2006-05-02 20:23:34.000000000 -0700
+@@ -20,6 +20,8 @@
  #include <asm/uaccess.h>
  
  #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
@@ -1018,7 +999,7 @@ Index: linux-2.4.21/fs/open.c
  
  int vfs_statfs(struct super_block *sb, struct statfs *buf)
  {
-@@ -169,9 +171,10 @@
+@@ -170,9 +172,10 @@ void fd_install(unsigned int fd, struct 
        write_unlock(&files->file_lock);
  }
  
@@ -1030,7 +1011,7 @@ Index: linux-2.4.21/fs/open.c
        int error;
        struct iattr newattrs;
  
-@@ -183,7 +186,13 @@
+@@ -184,7 +187,13 @@ int do_truncate(struct dentry *dentry, l
        down(&inode->i_sem);
        newattrs.ia_size = length;
        newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
@@ -1045,7 +1026,7 @@ Index: linux-2.4.21/fs/open.c
        up(&inode->i_sem);
        up_write(&inode->i_alloc_sem);
        return error;
-@@ -194,12 +203,13 @@
+@@ -195,12 +204,13 @@ static inline long do_sys_truncate(const
        struct nameidata nd;
        struct inode * inode;
        int error;
@@ -1060,7 +1041,7 @@ Index: linux-2.4.21/fs/open.c
        if (error)
                goto out;
        inode = nd.dentry->d_inode;
-@@ -239,11 +249,13 @@
+@@ -240,11 +250,13 @@ static inline long do_sys_truncate(const
        error = locks_verify_truncate(inode, NULL, length);
        if (!error) {
                DQUOT_INIT(inode);
@@ -1075,7 +1056,7 @@ Index: linux-2.4.21/fs/open.c
        path_release(&nd);
  out:
        return error;
-@@ -291,7 +303,7 @@
+@@ -292,7 +304,7 @@ static inline long do_sys_ftruncate(unsi
  
        error = locks_verify_truncate(inode, file, length);
        if (!error)
@@ -1084,7 +1065,7 @@ Index: linux-2.4.21/fs/open.c
  out_putf:
        fput(file);
  out:
-@@ -336,11 +348,13 @@
+@@ -337,11 +349,13 @@ asmlinkage long sys_utime(char * filenam
        struct inode * inode;
        struct iattr newattrs;
  
@@ -1099,7 +1080,7 @@ Index: linux-2.4.21/fs/open.c
        error = -EROFS;
        if (IS_RDONLY(inode))
                goto dput_and_out;
-@@ -355,11 +369,25 @@
+@@ -356,11 +370,25 @@ asmlinkage long sys_utime(char * filenam
                        goto dput_and_out;
  
                newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
@@ -1126,7 +1107,7 @@ Index: linux-2.4.21/fs/open.c
        error = notify_change(nd.dentry, &newattrs);
  dput_and_out:
        path_release(&nd);
-@@ -380,12 +408,14 @@
+@@ -381,12 +409,14 @@ asmlinkage long sys_utimes(char * filena
        struct inode * inode;
        struct iattr newattrs;
  
@@ -1142,7 +1123,7 @@ Index: linux-2.4.21/fs/open.c
        error = -EROFS;
        if (IS_RDONLY(inode))
                goto dput_and_out;
-@@ -400,7 +430,20 @@
+@@ -401,7 +431,20 @@ asmlinkage long sys_utimes(char * filena
                newattrs.ia_atime = times[0].tv_sec;
                newattrs.ia_mtime = times[1].tv_sec;
                newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
@@ -1164,7 +1145,7 @@ Index: linux-2.4.21/fs/open.c
                if (current->fsuid != inode->i_uid &&
                    (error = permission(inode,MAY_WRITE)) != 0)
                        goto dput_and_out;
-@@ -423,6 +466,7 @@
+@@ -424,6 +467,7 @@ asmlinkage long sys_access(const char * 
        int old_fsuid, old_fsgid;
        kernel_cap_t old_cap;
        int res;
@@ -1172,7 +1153,7 @@ Index: linux-2.4.21/fs/open.c
  
        if (mode & ~S_IRWXO)    /* where's F_OK, X_OK, W_OK, R_OK? */
                return -EINVAL;
-@@ -440,13 +484,14 @@
+@@ -441,13 +485,14 @@ asmlinkage long sys_access(const char * 
        else
                current->cap_effective = current->cap_permitted;
  
@@ -1188,7 +1169,7 @@ Index: linux-2.4.21/fs/open.c
                path_release(&nd);
        }
  
-@@ -461,8 +506,9 @@
+@@ -462,8 +507,9 @@ asmlinkage long sys_chdir(const char * f
  {
        int error;
        struct nameidata nd;
@@ -1199,7 +1180,7 @@ Index: linux-2.4.21/fs/open.c
        if (error)
                goto out;
  
-@@ -473,6 +519,7 @@
+@@ -474,6 +520,7 @@ asmlinkage long sys_chdir(const char * f
        set_fs_pwd(current->fs, nd.mnt, nd.dentry);
  
  dput_and_out:
@@ -1207,7 +1188,7 @@ Index: linux-2.4.21/fs/open.c
        path_release(&nd);
  out:
        return error;
-@@ -512,9 +559,10 @@
+@@ -513,9 +560,10 @@ asmlinkage long sys_chroot(const char * 
  {
        int error;
        struct nameidata nd;
@@ -1220,7 +1201,7 @@ Index: linux-2.4.21/fs/open.c
        if (error)
                goto out;
  
-@@ -530,39 +578,56 @@
+@@ -531,39 +579,56 @@ asmlinkage long sys_chroot(const char * 
        set_fs_altroot();
        error = 0;
  dput_and_out:
@@ -1291,7 +1272,7 @@ Index: linux-2.4.21/fs/open.c
        fput(file);
  out:
        return err;
-@@ -571,30 +636,14 @@
+@@ -572,30 +637,14 @@ out:
  asmlinkage long sys_chmod(const char * filename, mode_t mode)
  {
        struct nameidata nd;
@@ -1307,23 +1288,23 @@ Index: linux-2.4.21/fs/open.c
 -      error = -EROFS;
 -      if (IS_RDONLY(inode))
 -              goto dput_and_out;
--
 -      error = -EPERM;
 -      if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
 -              goto dput_and_out;
++      error = chmod_common(nd.dentry, mode);
  
 -      if (mode == (mode_t) -1)
 -              mode = inode->i_mode;
 -      newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
 -      newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
 -      error = notify_change(nd.dentry, &newattrs);
-+      error = chmod_common(nd.dentry, mode);
+-
 -dput_and_out:
        path_release(&nd);
  out:
        return error;
-@@ -614,6 +663,20 @@
+@@ -615,6 +664,20 @@ static int chown_common(struct dentry * 
        error = -EROFS;
        if (IS_RDONLY(inode))
                goto out;
@@ -1344,36 +1325,59 @@ Index: linux-2.4.21/fs/open.c
        error = -EPERM;
        if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
                goto out;
-@@ -718,6 +781,7 @@
+@@ -701,7 +764,7 @@ asmlinkage long sys_fchown(unsigned int 
+       return error;
+ }
+-static struct file *__dentry_open(struct dentry *, struct vfsmount *, int, struct file *);
++static struct file *__dentry_open(struct dentry *, struct vfsmount *, int, struct file *, struct lookup_intent *);
+ /*
+  * Note that while the flag value (low two bits) for sys_open means:
+@@ -721,6 +784,7 @@ struct file *filp_open(const char * file
  {
        int namei_flags, error;
        struct nameidata nd;
 +      struct lookup_intent it = { .it_op = IT_OPEN };
+       struct file *f;
  
        namei_flags = flags;
-       if ((namei_flags+1) & O_ACCMODE)
-@@ -725,14 +789,15 @@
-       if (namei_flags & O_TRUNC)
-               namei_flags |= 2;
+@@ -734,15 +798,16 @@ struct file *filp_open(const char * file
+       if (f == NULL)
+               return ERR_PTR(error);
  
 -      error = open_namei(filename, namei_flags, mode, &nd);
 -      if (!error)
--              return dentry_open(nd.dentry, nd.mnt, flags);
+-              return __dentry_open(nd.dentry, nd.mnt, flags, f);
 +      error = open_namei_it(filename, namei_flags, mode, &nd, &it);
 +      if (error)
 +              return ERR_PTR(error);
  
+       put_filp(f);
 -      return ERR_PTR(error);
 +      return dentry_open_it(nd.dentry, nd.mnt, flags, &it);
  }
  
 -struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
-+struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
-+                          int flags, struct lookup_intent *it)
++struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt, 
++                      int flags, struct lookup_intent *it)
+ {
+       struct file *f;
+@@ -753,10 +818,10 @@ struct file *dentry_open(struct dentry *
+               return ERR_PTR(-ENFILE);
+       }
+-      return __dentry_open(dentry, mnt, flags, f);
++      return __dentry_open(dentry, mnt, flags, f, it);
+ }
+-static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags, struct file *f)
++static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags, struct file *f, struct lookup_intent *it)
  {
-       struct file * f;
        struct inode *inode;
-@@ -769,7 +834,9 @@
+       static LIST_HEAD(kill_list);
+@@ -788,7 +853,9 @@ static struct file *__dentry_open(struct
        }
  
        if (f->f_op && f->f_op->open) {
@@ -1383,7 +1387,7 @@ Index: linux-2.4.21/fs/open.c
                if (error)
                        goto cleanup_all;
        }
-@@ -785,6 +852,7 @@
+@@ -804,6 +871,7 @@ static struct file *__dentry_open(struct
                }
        }
  
@@ -1391,10 +1395,10 @@ Index: linux-2.4.21/fs/open.c
        return f;
  
  cleanup_all:
-@@ -799,11 +867,17 @@
+@@ -817,11 +885,17 @@ cleanup_all:
+       f->f_vfsmnt = NULL;
  cleanup_file:
        put_filp(f);
- cleanup_dentry:
 +      intent_release(it);
        dput(dentry);
        mntput(mnt);
@@ -1409,10 +1413,9 @@ Index: linux-2.4.21/fs/open.c
  /*
   * Find an empty file descriptor entry, and mark it busy.
   */
-Index: linux-2.4.21/fs/stat.c
-===================================================================
---- linux-2.4.21.orig/fs/stat.c        2005-06-01 22:51:55.000000000 -0400
-+++ linux-2.4.21/fs/stat.c     2005-06-01 22:58:09.051062920 -0400
+diff -X dontdiff -urp kern_oldest/fs/stat.c kern_new/fs/stat.c
+--- kern_oldest/fs/stat.c      2006-05-01 11:55:39.000000000 -0700
++++ kern_new/fs/stat.c 2006-05-02 20:21:49.000000000 -0700
 @@ -17,10 +17,12 @@
   * Revalidate the inode. This is required for proper NFS attribute caching.
   */
@@ -1428,7 +1431,7 @@ Index: linux-2.4.21/fs/stat.c
                return inode->i_op->revalidate(dentry);
        return 0;
  }
-@@ -143,14 +145,16 @@
+@@ -143,14 +145,16 @@ static int cp_new_stat(struct inode * in
  asmlinkage long sys_stat(char * filename, struct __old_kernel_stat * statbuf)
  {
        struct nameidata nd;
@@ -1447,7 +1450,7 @@ Index: linux-2.4.21/fs/stat.c
                path_release(&nd);
        }
        if (error == -ESTALE && !errcnt) {
-@@ -164,14 +168,16 @@
+@@ -164,14 +168,16 @@ again:
  asmlinkage long sys_newstat(char * filename, struct stat * statbuf)
  {
        struct nameidata nd;
@@ -1466,7 +1469,7 @@ Index: linux-2.4.21/fs/stat.c
                path_release(&nd);
        }
        if (error == -ESTALE && !errcnt) {
-@@ -191,14 +197,16 @@
+@@ -191,14 +197,16 @@ again:
  asmlinkage long sys_lstat(char * filename, struct __old_kernel_stat * statbuf)
  {
        struct nameidata nd;
@@ -1485,7 +1488,7 @@ Index: linux-2.4.21/fs/stat.c
                path_release(&nd);
        }
        if (error == -ESTALE && !errcnt) {
-@@ -214,14 +222,16 @@
+@@ -214,14 +222,16 @@ again:
  asmlinkage long sys_newlstat(char * filename, struct stat * statbuf)
  {
        struct nameidata nd;
@@ -1504,7 +1507,7 @@ Index: linux-2.4.21/fs/stat.c
                path_release(&nd);
        }
  
-@@ -248,7 +258,7 @@
+@@ -248,7 +258,7 @@ asmlinkage long sys_fstat(unsigned int f
        if (f) {
                struct dentry * dentry = f->f_dentry;
  
@@ -1513,7 +1516,7 @@ Index: linux-2.4.21/fs/stat.c
                if (!err)
                        err = cp_old_stat(dentry->d_inode, statbuf);
                fput(f);
-@@ -267,7 +277,7 @@
+@@ -267,7 +277,7 @@ asmlinkage long sys_newfstat(unsigned in
        if (f) {
                struct dentry * dentry = f->f_dentry;
  
@@ -1522,7 +1525,7 @@ Index: linux-2.4.21/fs/stat.c
                if (!err)
                        err = cp_new_stat(dentry->d_inode, statbuf);
                fput(f);
-@@ -289,7 +299,7 @@
+@@ -289,7 +299,7 @@ asmlinkage long sys_readlink(const char 
  
                error = -EINVAL;
                if (inode->i_op && inode->i_op->readlink &&
@@ -1531,7 +1534,7 @@ Index: linux-2.4.21/fs/stat.c
                        UPDATE_ATIME(inode);
                        error = inode->i_op->readlink(nd.dentry, buf, bufsiz);
                }
-@@ -364,14 +374,16 @@
+@@ -364,14 +374,16 @@ static long cp_new_stat64(struct inode *
  asmlinkage long sys_stat64(char * filename, struct stat64 * statbuf, long flags)
  {
        struct nameidata nd;
@@ -1550,7 +1553,7 @@ Index: linux-2.4.21/fs/stat.c
                path_release(&nd);
        }
        if (error == -ESTALE && !errcnt) {
-@@ -385,14 +397,16 @@
+@@ -385,14 +397,16 @@ again:
  asmlinkage long sys_lstat64(char * filename, struct stat64 * statbuf, long flags)
  {
        struct nameidata nd;
@@ -1569,7 +1572,7 @@ Index: linux-2.4.21/fs/stat.c
                path_release(&nd);
        }
        if (error == -ESTALE && !errcnt) {
-@@ -412,7 +426,7 @@
+@@ -412,7 +426,7 @@ asmlinkage long sys_fstat64(unsigned lon
        if (f) {
                struct dentry * dentry = f->f_dentry;
  
@@ -1578,10 +1581,9 @@ Index: linux-2.4.21/fs/stat.c
                if (!err)
                        err = cp_new_stat64(dentry->d_inode, statbuf);
                fput(f);
-Index: linux-2.4.21/include/linux/dcache.h
-===================================================================
---- linux-2.4.21.orig/include/linux/dcache.h   2005-06-01 22:52:05.000000000 -0400
-+++ linux-2.4.21/include/linux/dcache.h        2005-06-01 22:58:09.051062920 -0400
+diff -X dontdiff -urp kern_oldest/include/linux/dcache.h kern_new/include/linux/dcache.h
+--- kern_oldest/include/linux/dcache.h 2006-05-01 11:55:39.000000000 -0700
++++ kern_new/include/linux/dcache.h    2006-05-02 20:21:49.000000000 -0700
 @@ -6,6 +6,51 @@
  #include <asm/atomic.h>
  #include <linux/mount.h>
@@ -1634,7 +1636,7 @@ Index: linux-2.4.21/include/linux/dcache.h
  
  /*
   * linux/include/linux/dcache.h
-@@ -96,8 +141,22 @@
+@@ -96,8 +141,22 @@ struct dentry_operations {
        int (*d_delete)(struct dentry *);
        void (*d_release)(struct dentry *);
        void (*d_iput)(struct dentry *, struct inode *);
@@ -1657,7 +1659,7 @@ Index: linux-2.4.21/include/linux/dcache.h
  /* the dentry parameter passed to d_hash and d_compare is the parent
   * directory of the entries to be compared. It is used in case these
   * functions need any directory specific information for determining
-@@ -129,6 +188,7 @@
+@@ -129,6 +188,7 @@ d_iput:            no              no              yes
                                         * s_nfsd_free_path semaphore will be down
                                         */
  #define DCACHE_REFERENCED     0x0008  /* Recently used, don't discard. */
@@ -1665,11 +1667,10 @@ Index: linux-2.4.21/include/linux/dcache.h
  
  extern spinlock_t dcache_lock;
  
-Index: linux-2.4.21/include/linux/fs.h
-===================================================================
---- linux-2.4.21.orig/include/linux/fs.h       2005-06-01 22:57:59.887456000 -0400
-+++ linux-2.4.21/include/linux/fs.h    2005-06-01 22:58:09.053062616 -0400
-@@ -73,6 +73,7 @@
+diff -X dontdiff -urp kern_oldest/include/linux/fs.h kern_new/include/linux/fs.h
+--- kern_oldest/include/linux/fs.h     2006-05-01 12:04:33.000000000 -0700
++++ kern_new/include/linux/fs.h        2006-05-02 20:21:49.000000000 -0700
+@@ -73,6 +73,7 @@ extern int leases_enable, dir_notify_ena
  
  #define FMODE_READ 1
  #define FMODE_WRITE 2
@@ -1677,7 +1678,7 @@ Index: linux-2.4.21/include/linux/fs.h
  
  #define READ 0
  #define WRITE 1
-@@ -365,6 +366,9 @@
+@@ -365,6 +366,9 @@ extern void set_bh_page(struct buffer_he
  #define ATTR_MTIME_SET        256
  #define ATTR_FORCE    512     /* Not a change, but a change it */
  #define ATTR_ATTR_FLAG        1024
@@ -1687,7 +1688,7 @@ Index: linux-2.4.21/include/linux/fs.h
  
  /*
   * This is the Inode Attributes structure, used for notify_change().  It
-@@ -502,6 +506,7 @@
+@@ -502,6 +506,7 @@ struct inode {
        struct pipe_inode_info  *i_pipe;
        struct block_device     *i_bdev;
        struct char_device      *i_cdev;
@@ -1695,7 +1696,7 @@ Index: linux-2.4.21/include/linux/fs.h
  
        unsigned long           i_dnotify_mask; /* Directory notify events */
        struct dnotify_struct   *i_dnotify; /* for directory notifications */
-@@ -604,6 +609,7 @@
+@@ -604,6 +609,7 @@ struct file {
  
        /* needed for tty driver, and maybe others */
        void                    *private_data;
@@ -1703,7 +1704,7 @@ Index: linux-2.4.21/include/linux/fs.h
  
        /* preallocated helper kiobuf to speedup O_DIRECT */
        struct kiobuf           *f_iobuf;
-@@ -736,6 +742,7 @@
+@@ -736,6 +742,7 @@ struct nameidata {
        struct qstr last;
        unsigned int flags;
        int last_type;
@@ -1711,7 +1712,7 @@ Index: linux-2.4.21/include/linux/fs.h
  };
  
  /*
-@@ -856,7 +863,8 @@
+@@ -856,7 +863,8 @@ extern int vfs_symlink(struct inode *, s
  extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
  extern int vfs_rmdir(struct inode *, struct dentry *);
  extern int vfs_unlink(struct inode *, struct dentry *);
@@ -1721,7 +1722,7 @@ Index: linux-2.4.21/include/linux/fs.h
  
  /*
   * File types
-@@ -935,21 +943,32 @@
+@@ -935,21 +943,32 @@ struct file_operations_ext {
  
  struct inode_operations {
        int (*create) (struct inode *,struct dentry *,int);
@@ -1754,7 +1755,7 @@ Index: linux-2.4.21/include/linux/fs.h
        int (*getattr) (struct dentry *, struct iattr *);
        int (*setxattr) (struct dentry *, const char *, const void *, size_t, int);
        ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
-@@ -1151,10 +1170,14 @@
+@@ -1151,10 +1170,14 @@ static inline int get_lease(struct inode
  
  asmlinkage long sys_open(const char *, int, int);
  asmlinkage long sys_close(unsigned int);      /* yes, it's really unsigned */
@@ -1770,7 +1771,7 @@ Index: linux-2.4.21/include/linux/fs.h
  extern int filp_close(struct file *, fl_owner_t id);
  extern char * getname(const char *);
  
-@@ -1446,6 +1469,7 @@
+@@ -1446,6 +1469,7 @@ typedef int (*read_actor_t)(read_descrip
  extern loff_t default_llseek(struct file *file, loff_t offset, int origin);
  
  extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *));
@@ -1778,7 +1779,7 @@ Index: linux-2.4.21/include/linux/fs.h
  extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *));
  extern int FASTCALL(path_walk(const char *, struct nameidata *));
  extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *));
-@@ -1457,6 +1481,8 @@
+@@ -1457,6 +1481,8 @@ extern struct dentry * lookup_one_len(co
  extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
  #define user_path_walk(name,nd)        __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd)
  #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd)
@@ -1787,7 +1788,7 @@ Index: linux-2.4.21/include/linux/fs.h
  
  extern void inode_init_once(struct inode *);
  extern void iput(struct inode *);
-@@ -1625,6 +1651,8 @@
+@@ -1625,6 +1651,8 @@ extern struct file_operations generic_ro
  
  extern int vfs_readlink(struct dentry *, char *, int, const char *);
  extern int vfs_follow_link(struct nameidata *, const char *);
@@ -1796,11 +1797,10 @@ Index: linux-2.4.21/include/linux/fs.h
  extern int page_readlink(struct dentry *, char *, int);
  extern int page_follow_link(struct dentry *, struct nameidata *);
  extern struct inode_operations page_symlink_inode_operations;
-Index: linux-2.4.21/include/linux/fs_struct.h
-===================================================================
---- linux-2.4.21.orig/include/linux/fs_struct.h        2005-06-01 22:51:40.000000000 -0400
-+++ linux-2.4.21/include/linux/fs_struct.h     2005-06-01 22:58:09.054062464 -0400
-@@ -37,10 +37,12 @@
+diff -X dontdiff -urp kern_oldest/include/linux/fs_struct.h kern_new/include/linux/fs_struct.h
+--- kern_oldest/include/linux/fs_struct.h      2006-05-01 11:55:40.000000000 -0700
++++ kern_new/include/linux/fs_struct.h 2006-05-02 20:21:49.000000000 -0700
+@@ -37,10 +37,12 @@ static inline void set_fs_root(struct fs
        write_lock(&fs->lock);
        old_root = fs->root;
        old_rootmnt = fs->rootmnt;
@@ -1813,7 +1813,7 @@ Index: linux-2.4.21/include/linux/fs_struct.h
                dput(old_root);
                mntput(old_rootmnt);
        }
-@@ -60,10 +62,12 @@
+@@ -60,10 +62,12 @@ static inline void set_fs_pwd(struct fs_
        write_lock(&fs->lock);
        old_pwd = fs->pwd;
        old_pwdmnt = fs->pwdmnt;
@@ -1826,11 +1826,10 @@ Index: linux-2.4.21/include/linux/fs_struct.h
                dput(old_pwd);
                mntput(old_pwdmnt);
        }
-Index: linux-2.4.21/kernel/exit.c
-===================================================================
---- linux-2.4.21.orig/kernel/exit.c    2005-06-01 22:52:04.000000000 -0400
-+++ linux-2.4.21/kernel/exit.c 2005-06-01 22:58:09.055062312 -0400
-@@ -367,11 +367,14 @@
+diff -X dontdiff -urp kern_oldest/kernel/exit.c kern_new/kernel/exit.c
+--- kern_oldest/kernel/exit.c  2006-05-01 11:55:39.000000000 -0700
++++ kern_new/kernel/exit.c     2006-05-02 20:21:49.000000000 -0700
+@@ -367,11 +367,14 @@ static inline void __put_fs_struct(struc
  {
        /* No need to hold fs->lock if we are killing it */
        if (atomic_dec_and_test(&fs->count)) {
@@ -1845,11 +1844,10 @@ Index: linux-2.4.21/kernel/exit.c
                        dput(fs->altroot);
                        mntput(fs->altrootmnt);
                }
-Index: linux-2.4.21/kernel/fork.c
-===================================================================
---- linux-2.4.21.orig/kernel/fork.c    2005-06-01 22:52:05.000000000 -0400
-+++ linux-2.4.21/kernel/fork.c 2005-06-01 22:58:09.055062312 -0400
-@@ -473,10 +473,13 @@
+diff -X dontdiff -urp kern_oldest/kernel/fork.c kern_new/kernel/fork.c
+--- kern_oldest/kernel/fork.c  2006-05-01 11:55:39.000000000 -0700
++++ kern_new/kernel/fork.c     2006-05-02 20:21:49.000000000 -0700
+@@ -473,10 +473,13 @@ static inline struct fs_struct *__copy_f
                fs->umask = old->umask;
                read_lock(&old->lock);
                fs->rootmnt = mntget(old->rootmnt);
@@ -1863,11 +1861,10 @@ Index: linux-2.4.21/kernel/fork.c
                        fs->altrootmnt = mntget(old->altrootmnt);
                        fs->altroot = dget(old->altroot);
                } else {
-Index: linux-2.4.21/kernel/ksyms.c
-===================================================================
---- linux-2.4.21.orig/kernel/ksyms.c   2005-06-01 22:57:59.891455392 -0400
-+++ linux-2.4.21/kernel/ksyms.c        2005-06-01 22:58:09.056062160 -0400
-@@ -318,6 +318,7 @@
+diff -X dontdiff -urp kern_oldest/kernel/ksyms.c kern_new/kernel/ksyms.c
+--- kern_oldest/kernel/ksyms.c 2006-05-01 12:04:33.000000000 -0700
++++ kern_new/kernel/ksyms.c    2006-05-02 20:21:49.000000000 -0700
+@@ -319,6 +319,7 @@ EXPORT_SYMBOL(read_cache_page);
  EXPORT_SYMBOL(set_page_dirty);
  EXPORT_SYMBOL(vfs_readlink);
  EXPORT_SYMBOL(vfs_follow_link);
@@ -1875,3 +1872,4 @@ Index: linux-2.4.21/kernel/ksyms.c
  EXPORT_SYMBOL(page_readlink);
  EXPORT_SYMBOL(page_follow_link);
  EXPORT_SYMBOL(page_symlink_inode_operations);
+Only in kern_new: kern_oldest
diff --git a/lustre/kernel_patches/patches/vfs_intent-2.6-fc5-fix.patch b/lustre/kernel_patches/patches/vfs_intent-2.6-fc5-fix.patch
new file mode 100644 (file)
index 0000000..e3a0f09
--- /dev/null
@@ -0,0 +1,20 @@
+Index: linux-2.6.15.i686-cy/include/linux/dcache.h
+===================================================================
+--- linux-2.6.15.i686-cy.orig/include/linux/dcache.h   2006-06-01 23:07:05.000000000 +0800
++++ linux-2.6.15.i686-cy/include/linux/dcache.h        2006-06-01 23:10:21.000000000 +0800
+@@ -4,7 +4,6 @@
+ #ifdef __KERNEL__
+ #include <asm/atomic.h>
+-#include <linux/string.h>
+ #include <linux/list.h>
+ #include <linux/spinlock.h>
+ #include <linux/cache.h>
+@@ -42,6 +41,7 @@
+       const unsigned char *name;
+ };
++struct inode;
+ #include <linux/namei.h>
+ struct dentry_stat_t {
diff --git a/lustre/kernel_patches/patches/vfs_intent-2.6-fc5.patch b/lustre/kernel_patches/patches/vfs_intent-2.6-fc5.patch
new file mode 100644 (file)
index 0000000..4961d1b
--- /dev/null
@@ -0,0 +1,827 @@
+Index: linux-2.6.15-fc5/fs/inode.c
+===================================================================
+--- linux-2.6.15-fc5.orig/fs/inode.c   2006-05-31 04:08:19.000000000 +0800
++++ linux-2.6.15-fc5/fs/inode.c        2006-05-31 17:24:35.000000000 +0800
+@@ -236,6 +236,7 @@
+       inodes_stat.nr_unused--;
+ }
++EXPORT_SYMBOL(__iget);
+ /**
+  * clear_inode - clear an inode
+  * @inode: inode to clear
+Index: linux-2.6.15-fc5/fs/open.c
+===================================================================
+--- linux-2.6.15-fc5.orig/fs/open.c    2006-05-31 04:08:39.000000000 +0800
++++ linux-2.6.15-fc5/fs/open.c 2006-05-31 17:24:35.000000000 +0800
+@@ -224,12 +224,12 @@
+       struct nameidata nd;
+       struct inode * inode;
+       int error;
+-
++      intent_init(&nd.intent, IT_GETATTR);
+       error = -EINVAL;
+       if (length < 0) /* sorry, but loff_t says... */
+               goto out;
+-      error = user_path_walk(path, &nd);
++      error = user_path_walk_it(path, &nd);
+       if (error)
+               goto out;
+       inode = nd.dentry->d_inode;
+@@ -488,6 +488,7 @@
+       int old_fsuid, old_fsgid;
+       kernel_cap_t old_cap;
+       int res;
++      intent_init(&nd.intent, IT_GETATTR);
+       if (mode & ~S_IRWXO)    /* where's F_OK, X_OK, W_OK, R_OK? */
+               return -EINVAL;
+@@ -512,7 +513,7 @@
+       else
+               current->cap_effective = current->cap_permitted;
+-      res = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd);
++      res = __user_walk_fd_it(dfd, filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd);
+       if (!res) {
+               res = vfs_permission(&nd, mode);
+               /* SuS v2 requires we report a read only fs too */
+@@ -538,8 +539,9 @@
+ {
+       struct nameidata nd;
+       int error;
++      intent_init(&nd.intent, IT_GETATTR);
+-      error = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &nd);
++      error = __user_walk_it(filename, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &nd);
+       if (error)
+               goto out;
+@@ -591,8 +593,9 @@
+ {
+       struct nameidata nd;
+       int error;
++      intent_init(&nd.intent, IT_GETATTR);
+-      error = __user_walk(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
++      error = __user_walk_it(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
+       if (error)
+               goto out;
+@@ -815,6 +818,7 @@
+               error = open(inode, f);
+               if (error)
+                       goto cleanup_all;
++              intent_release(f->f_it);
+       }
+       f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
+@@ -841,6 +845,7 @@
+       f->f_dentry = NULL;
+       f->f_vfsmnt = NULL;
+ cleanup_file:
++      intent_release(f->f_it);
+       put_filp(f);
+       dput(dentry);
+       mntput(mnt);
+@@ -866,6 +871,7 @@
+ {
+       int namei_flags, error;
+       struct nameidata nd;
++      intent_init(&nd.intent, IT_OPEN);
+       namei_flags = flags;
+       if ((namei_flags+1) & O_ACCMODE)
+@@ -902,19 +908,19 @@
+ struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
+               int (*open)(struct inode *, struct file *))
+ {
+-      if (IS_ERR(nd->intent.open.file))
++      if (IS_ERR(nd->intent.file))
+               goto out;
+       if (IS_ERR(dentry))
+               goto out_err;
+-      nd->intent.open.file = __dentry_open(dget(dentry), mntget(nd->mnt),
+-                                           nd->intent.open.flags - 1,
+-                                           nd->intent.open.file,
++      nd->intent.file = __dentry_open(dget(dentry), mntget(nd->mnt),
++                                           nd->intent.flags - 1,
++                                           nd->intent.file,
+                                            open);
+ out:
+-      return nd->intent.open.file;
++      return nd->intent.file;
+ out_err:
+       release_open_intent(nd);
+-      nd->intent.open.file = (struct file *)dentry;
++      nd->intent.file = (struct file *)dentry;
+       goto out;
+ }
+ EXPORT_SYMBOL_GPL(lookup_instantiate_filp);
+@@ -931,7 +937,8 @@
+       struct file *filp;
+       /* Pick up the filp from the open intent */
+-      filp = nd->intent.open.file;
++      filp = nd->intent.file;
++      filp->f_it = &nd->intent; 
+       /* Has the filesystem initialised the file for us? */
+       if (filp->f_dentry == NULL)
+               filp = __dentry_open(nd->dentry, nd->mnt, flags, filp, NULL);
+Index: linux-2.6.15-fc5/fs/nfsctl.c
+===================================================================
+--- linux-2.6.15-fc5.orig/fs/nfsctl.c  2006-05-31 04:08:20.000000000 +0800
++++ linux-2.6.15-fc5/fs/nfsctl.c       2006-05-31 17:24:35.000000000 +0800
+@@ -26,6 +26,7 @@
+       struct nameidata nd;
+       int error;
++      intent_init(&nd.intent, IT_OPEN);
+       nd.mnt = do_kern_mount("nfsd", 0, "nfsd", NULL);
+       if (IS_ERR(nd.mnt))
+Index: linux-2.6.15-fc5/fs/namei.c
+===================================================================
+--- linux-2.6.15-fc5.orig/fs/namei.c   2006-05-31 04:08:33.000000000 +0800
++++ linux-2.6.15-fc5/fs/namei.c        2006-05-31 17:24:35.000000000 +0800
+@@ -337,8 +337,19 @@
+       return 0;
+ }
++void intent_release(struct lookup_intent *it)
++{
++      if (!it)
++              return;
++      if (it->it_magic != INTENT_MAGIC)
++              return;
++      if (it->it_op_release)
++              it->it_op_release(it);
++}
++
+ void path_release(struct nameidata *nd)
+ {
++      intent_release(&nd->intent);
+       dput(nd->dentry);
+       mntput(nd->mnt);
+ }
+@@ -359,10 +370,10 @@
+  */
+ void release_open_intent(struct nameidata *nd)
+ {
+-      if (nd->intent.open.file->f_dentry == NULL)
+-              put_filp(nd->intent.open.file);
++      if (nd->intent.file->f_dentry == NULL)
++              put_filp(nd->intent.file);
+       else
+-              fput(nd->intent.open.file);
++              fput(nd->intent.file);
+ }
+ /*
+@@ -440,8 +451,12 @@
+ {
+       struct dentry * result;
+       struct inode *dir = parent->d_inode;
+-
++      int counter = 0;
++      
+       mutex_lock(&dir->i_mutex);
++again:
++      counter++;
++
+       /*
+        * First re-do the cached lookup just in case it was created
+        * while we waited for the directory semaphore..
+@@ -475,13 +490,16 @@
+        * Uhhuh! Nasty case: the cache was re-populated while
+        * we waited on the semaphore. Need to revalidate.
+        */
+-      mutex_unlock(&dir->i_mutex);
+       if (result->d_op && result->d_op->d_revalidate) {
+               if (!result->d_op->d_revalidate(result, nd) && !d_invalidate(result)) {
+                       dput(result);
+-                      result = ERR_PTR(-ENOENT);
++                      if (counter > 10)
++                              result = ERR_PTR(-ESTALE);
++                      if (!IS_ERR(result))
++                              goto again;
+               }
+       }
++      mutex_unlock(&dir->i_mutex);
+       return result;
+ }
+@@ -509,7 +527,9 @@
+ static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *link)
+ {
+       int res = 0;
++      struct lookup_intent it = nd->intent;
+       char *name;
++
+       if (IS_ERR(link))
+               goto fail;
+@@ -519,6 +539,10 @@
+                       /* weird __emul_prefix() stuff did it */
+                       goto out;
+       }
++      intent_init(&nd->intent, it.it_op);
++      nd->intent.it_flags = it.it_flags;
++      nd->intent.it_create_mode = it.it_create_mode;
++      nd->intent.file = it.file;
+       res = link_path_walk(link, nd);
+ out:
+       if (nd->depth || res || nd->last_type!=LAST_NORM)
+@@ -772,6 +796,33 @@
+       return PTR_ERR(dentry);
+ }
++static int revalidate_special(struct nameidata *nd)
++{
++      struct dentry *dentry = nd->dentry;
++      int err, counter = 0;
++
++ revalidate_again:
++      if (!dentry->d_op || !dentry->d_op->d_revalidate)
++              return 0;
++      if (!dentry->d_op->d_revalidate(dentry, nd)) {
++              struct dentry *new;
++              if ((err = permission(dentry->d_parent->d_inode, MAY_EXEC, nd)))
++                      return err;
++              new = real_lookup(dentry->d_parent, &dentry->d_name, nd);
++              if (IS_ERR(new))
++                      return PTR_ERR(new);
++              d_invalidate(dentry);
++              dput(dentry);
++              nd->dentry = dentry = new;
++              counter++;
++              if (counter < 10)
++                      goto revalidate_again;
++              printk("excessive revalidate_it loops\n");
++              return -ESTALE;
++      }
++      return 0;
++}
++
+ /*
+  * Name resolution.
+  * This is the basic name resolution function, turning a pathname into
+@@ -870,7 +921,11 @@
+                       goto out_dput;
+               if (inode->i_op->follow_link) {
++                      int save_flags = nd->flags;
++                      nd->flags |= LOOKUP_LINK_NOTLAST;
+                       err = do_follow_link(&next, nd);
++                      if (!(save_flags & LOOKUP_LINK_NOTLAST))
++                              nd->flags &= ~LOOKUP_LINK_NOTLAST;
+                       if (err)
+                               goto return_err;
+                       err = -ENOENT;
+@@ -905,6 +960,23 @@
+                               inode = nd->dentry->d_inode;
+                               /* fallthrough */
+                       case 1:
++                              nd->flags |= LOOKUP_LAST;
++                              err = revalidate_special(nd);
++                              nd->flags &= ~LOOKUP_LAST;
++                              if (!nd->dentry->d_inode)
++                                      err = -ENOENT;
++                              if (err) {
++                                      path_release(nd);
++                                      goto return_err;
++                              }
++                              if (lookup_flags & LOOKUP_DIRECTORY) {
++                                      err = -ENOTDIR;
++                                      if(!nd->dentry->d_inode->i_op ||
++                                        !nd->dentry->d_inode->i_op->lookup) {
++                                              path_release(nd);
++                                              goto return_err;
++                                      }
++                              }
+                               goto return_reval;
+               }
+               if (nd->dentry->d_op && nd->dentry->d_op->d_hash) {
+@@ -912,7 +984,9 @@
+                       if (err < 0)
+                               break;
+               }
++              nd->flags |= LOOKUP_LAST;
+               err = do_lookup(nd, &this, &next, atomic);
++              nd->flags &= ~LOOKUP_LAST;
+               if (err)
+                       break;
+               inode = next.dentry->d_inode;
+@@ -1154,13 +1228,13 @@
+       if (filp == NULL)
+               return -ENFILE;
+-      nd->intent.open.file = filp;
+-      nd->intent.open.flags = open_flags;
+-      nd->intent.open.create_mode = create_mode;
++      nd->intent.file = filp;
++      nd->intent.flags = open_flags;
++      nd->intent.create_mode = create_mode;
+       err = do_path_lookup(dfd, name, lookup_flags|LOOKUP_OPEN, nd);
+-      if (IS_ERR(nd->intent.open.file)) {
++      if (IS_ERR(nd->intent.file)) {
+               if (err == 0) {
+-                      err = PTR_ERR(nd->intent.open.file);
++                      err = PTR_ERR(nd->intent.file);
+                       path_release(nd);
+               }
+       } else if (err != 0)
+@@ -1263,7 +1337,7 @@
+ }
+ /* SMP-safe */
+-struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
++struct dentry * lookup_one_len_it(const char * name, struct dentry * base, int len, struct nameidata *nd)
+ {
+       unsigned long hash;
+       struct qstr this;
+@@ -1283,11 +1357,17 @@
+       }
+       this.hash = end_name_hash(hash);
+-      return __lookup_hash(&this, base, NULL);
++      return __lookup_hash(&this, base, nd);
+ access:
+       return ERR_PTR(-EACCES);
+ }
++struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
++{
++      return lookup_one_len_it(name, base, len, NULL);
++}
++
++
+ /*
+  *    namei()
+  *
+@@ -1299,8 +1379,9 @@
+  * that namei follows links, while lnamei does not.
+  * SMP-safe
+  */
+-int fastcall __user_walk_fd(int dfd, const char __user *name, unsigned flags,
+-                          struct nameidata *nd)
++
++int fastcall __user_walk_fd_it(int dfd, const char __user *name, unsigned flags,
++                             struct nameidata *nd)
+ {
+       char *tmp = getname(name);
+       int err = PTR_ERR(tmp);
+@@ -1312,9 +1393,22 @@
+       return err;
+ }
++int fastcall __user_walk_fd(int dfd, const char __user *name, unsigned flags,
++                          struct nameidata *nd)
++{
++      intent_init(&nd->intent, IT_LOOKUP);
++      return __user_walk_fd_it(dfd, name, flags, nd); 
++}
++
++int fastcall __user_walk_it(const char __user *name, unsigned flags, struct nameidata *nd)
++{
++      return __user_walk_fd_it(AT_FDCWD, name, flags, nd);
++}
++
+ int fastcall __user_walk(const char __user *name, unsigned flags, struct nameidata *nd)
+ {
+-      return __user_walk_fd(AT_FDCWD, name, flags, nd);
++      intent_init(&nd->intent, IT_LOOKUP);
++      return __user_walk_it(name, flags, nd);
+ }
+ /*
+@@ -1596,6 +1690,8 @@
+       if (flag & O_APPEND)
+               acc_mode |= MAY_APPEND;
++      nd->intent.it_flags = flag;
++      nd->intent.it_create_mode = mode;
+       /*
+        * The simplest case - just a plain lookup.
+        */
+@@ -1610,6 +1706,7 @@
+       /*
+        * Create - we need to know the parent.
+        */
++      nd->intent.it_op |= IT_CREAT;
+       error = path_lookup_create(dfd,pathname,LOOKUP_PARENT,nd,flag,mode);
+       if (error)
+               return error;
+@@ -1626,7 +1723,9 @@
+       dir = nd->dentry;
+       nd->flags &= ~LOOKUP_PARENT;
+       mutex_lock(&dir->d_inode->i_mutex);
++      nd->flags |= LOOKUP_LAST;
+       path.dentry = lookup_hash(nd);
++      nd->flags &= ~LOOKUP_LAST;
+       path.mnt = nd->mnt;
+ do_last:
+@@ -1685,7 +1784,7 @@
+ exit_dput:
+       dput_path(&path, nd);
+ exit:
+-      if (!IS_ERR(nd->intent.open.file))
++      if (!IS_ERR(nd->intent.file))
+               release_open_intent(nd);
+       path_release(nd);
+       return error;
+@@ -1728,7 +1827,9 @@
+       }
+       dir = nd->dentry;
+       mutex_lock(&dir->d_inode->i_mutex);
++      nd->flags |= LOOKUP_LAST;
+       path.dentry = lookup_hash(nd);
++      nd->flags &= ~LOOKUP_LAST;
+       path.mnt = nd->mnt;
+       __putname(nd->last.name);
+       goto do_last;
+@@ -2240,6 +2341,8 @@
+       int error;
+       char * to;
++      intent_init(&nd.intent, IT_LOOKUP);
++        intent_init(&old_nd.intent, IT_LOOKUP);
+       if (flags != 0)
+               return -EINVAL;
+@@ -2247,7 +2350,7 @@
+       if (IS_ERR(to))
+               return PTR_ERR(to);
+-      error = __user_walk_fd(olddfd, oldname, 0, &old_nd);
++      error = __user_walk_fd_it(olddfd, oldname, 0, &old_nd);
+       if (error)
+               goto exit;
+       error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd);
+Index: linux-2.6.15-fc5/fs/stat.c
+===================================================================
+--- linux-2.6.15-fc5.orig/fs/stat.c    2006-05-31 04:08:20.000000000 +0800
++++ linux-2.6.15-fc5/fs/stat.c 2006-05-31 17:24:35.000000000 +0800
+@@ -38,7 +38,7 @@
+ EXPORT_SYMBOL(generic_fillattr);
+-int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
++int vfs_getattr_it(struct vfsmount *mnt, struct dentry *dentry, struct lookup_intent *it, struct kstat *stat)
+ {
+       struct inode *inode = dentry->d_inode;
+       int retval;
+@@ -47,6 +47,8 @@
+       if (retval)
+               return retval;
++      if (inode->i_op->getattr_it)
++              return inode->i_op->getattr_it(mnt, dentry, it, stat);
+       if (inode->i_op->getattr)
+               return inode->i_op->getattr(mnt, dentry, stat);
+@@ -61,6 +63,11 @@
+       return 0;
+ }
++int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
++{
++      return vfs_getattr_it(mnt, dentry, NULL, stat);
++}
++
+ EXPORT_SYMBOL(vfs_getattr);
+ int vfs_stat_fd(int dfd, char __user *name, struct kstat *stat)
+@@ -68,9 +75,10 @@
+       struct nameidata nd;
+       int error;
+-      error = __user_walk_fd(dfd, name, LOOKUP_FOLLOW, &nd);
++      intent_init(&nd.intent, IT_GETATTR);
++      error = __user_walk_fd_it(dfd, name, LOOKUP_FOLLOW, &nd);
+       if (!error) {
+-              error = vfs_getattr(nd.mnt, nd.dentry, stat);
++              error = vfs_getattr_it(nd.mnt, nd.dentry, &nd.intent, stat);
+               path_release(&nd);
+       }
+       return error;
+@@ -88,9 +96,10 @@
+       struct nameidata nd;
+       int error;
+-      error = __user_walk_fd(dfd, name, 0, &nd);
++      intent_init(&nd.intent, IT_GETATTR);
++      error = __user_walk_fd_it(dfd, name, 0, &nd);
+       if (!error) {
+-              error = vfs_getattr(nd.mnt, nd.dentry, stat);
++              error = vfs_getattr_it(nd.mnt, nd.dentry, &nd.intent, stat);
+               path_release(&nd);
+       }
+       return error;
+@@ -107,9 +116,12 @@
+ {
+       struct file *f = fget(fd);
+       int error = -EBADF;
++      struct nameidata nd;
++      intent_init(&nd.intent, IT_GETATTR);
+       if (f) {
+-              error = vfs_getattr(f->f_vfsmnt, f->f_dentry, stat);
++              error = vfs_getattr_it(f->f_vfsmnt, f->f_dentry, &nd.intent, stat);
++              intent_release(&nd.intent);
+               fput(f);
+       }
+       return error;
+Index: linux-2.6.15-fc5/fs/namespace.c
+===================================================================
+--- linux-2.6.15-fc5.orig/fs/namespace.c       2006-05-31 04:08:33.000000000 +0800
++++ linux-2.6.15-fc5/fs/namespace.c    2006-05-31 17:24:35.000000000 +0800
+@@ -74,6 +74,7 @@
+               INIT_LIST_HEAD(&mnt->mnt_share);
+               INIT_LIST_HEAD(&mnt->mnt_slave_list);
+               INIT_LIST_HEAD(&mnt->mnt_slave);
++              INIT_LIST_HEAD(&mnt->mnt_lustre_list);  
+               if (name) {
+                       int size = strlen(name) + 1;
+                       char *newname = kmalloc(size, GFP_KERNEL);
+@@ -154,6 +155,7 @@
+ static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd)
+ {
++      memset(old_nd, 0, sizeof(*old_nd));
+       old_nd->dentry = mnt->mnt_mountpoint;
+       old_nd->mnt = mnt->mnt_parent;
+       mnt->mnt_parent = mnt;
+@@ -272,6 +274,9 @@
+ {
+       struct super_block *sb = mnt->mnt_sb;
+       dput(mnt->mnt_root);
++      spin_lock(&dcache_lock);
++      list_del(&mnt->mnt_lustre_list);
++      spin_unlock(&dcache_lock);
+       free_vfsmnt(mnt);
+       deactivate_super(sb);
+ }
+@@ -538,6 +543,8 @@
+        */
+       lock_kernel();
++      if (sb->s_op->umount_lustre)
++              sb->s_op->umount_lustre(sb);
+       if ((flags & MNT_FORCE) && sb->s_op->umount_begin)
+               sb->s_op->umount_begin(sb);
+       unlock_kernel();
+@@ -870,6 +877,7 @@
+               return err;
+       if (!old_name || !*old_name)
+               return -EINVAL;
++      intent_init(&old_nd.intent, IT_LOOKUP);
+       err = path_lookup(old_name, LOOKUP_FOLLOW, &old_nd);
+       if (err)
+               return err;
+@@ -955,6 +963,7 @@
+               return -EPERM;
+       if (!old_name || !*old_name)
+               return -EINVAL;
++      intent_init(&old_nd.intent, IT_LOOKUP);
+       err = path_lookup(old_name, LOOKUP_FOLLOW, &old_nd);
+       if (err)
+               return err;
+@@ -1270,6 +1279,7 @@
+       int retval = 0;
+       int mnt_flags = 0;
++      intent_init(&nd.intent, IT_LOOKUP);
+       /* Discard magic */
+       if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
+               flags &= ~MS_MGC_MSK;
+Index: linux-2.6.15-fc5/fs/exec.c
+===================================================================
+--- linux-2.6.15-fc5.orig/fs/exec.c    2006-05-31 04:08:33.000000000 +0800
++++ linux-2.6.15-fc5/fs/exec.c 2006-05-31 17:24:35.000000000 +0800
+@@ -127,7 +127,9 @@
+       struct nameidata nd;
+       int error;
+-      error = __user_path_lookup_open(library, LOOKUP_FOLLOW, &nd, FMODE_READ);
++      intent_init(&nd.intent, IT_OPEN);
++      error = __user_path_lookup_open(library, LOOKUP_FOLLOW, &nd, 
++                                      FMODE_READ | FMODE_EXEC);
+       if (error)
+               goto out;
+@@ -477,7 +479,9 @@
+       int err;
+       struct file *file;
+-      err = path_lookup_open(AT_FDCWD, name, LOOKUP_FOLLOW, &nd, FMODE_READ);
++      intent_init(&nd.intent, IT_OPEN);
++      err = path_lookup_open(AT_FDCWD, name, LOOKUP_FOLLOW, &nd, 
++                             FMODE_READ | FMODE_EXEC);
+       file = ERR_PTR(err);
+       if (!err) {
+Index: linux-2.6.15-fc5/include/linux/dcache.h
+===================================================================
+--- linux-2.6.15-fc5.orig/include/linux/dcache.h       2006-05-31 04:08:33.000000000 +0800
++++ linux-2.6.15-fc5/include/linux/dcache.h    2006-05-31 17:24:41.000000000 +0800
+@@ -4,6 +4,7 @@
+ #ifdef __KERNEL__
+ #include <asm/atomic.h>
++#include <linux/string.h>
+ #include <linux/list.h>
+ #include <linux/spinlock.h>
+ #include <linux/cache.h>
+@@ -36,6 +37,8 @@
+       const unsigned char *name;
+ };
++#include <linux/namei.h>
++
+ struct dentry_stat_t {
+       int nr_dentry;
+       int nr_unused;
+Index: linux-2.6.15-fc5/include/linux/fs.h
+===================================================================
+--- linux-2.6.15-fc5.orig/include/linux/fs.h   2006-05-31 04:08:33.000000000 +0800
++++ linux-2.6.15-fc5/include/linux/fs.h        2006-05-31 17:24:35.000000000 +0800
+@@ -59,6 +59,7 @@
+ #define FMODE_READ 1
+ #define FMODE_WRITE 2
++#define FMODE_EXEC 4
+ /* Internal kernel extensions */
+ #define FMODE_LSEEK   4
+@@ -265,6 +266,8 @@
+ #define ATTR_KILL_SUID        2048
+ #define ATTR_KILL_SGID        4096
+ #define ATTR_FILE     8192
++#define ATTR_RAW              16384    /* file system, not vfs will massage attrs */
++#define ATTR_FROM_OPEN        32768    /* called from open path, ie O_TRUNC */
+ /*
+  * This is the Inode Attributes structure, used for notify_change().  It
+@@ -499,6 +502,7 @@
+       struct block_device     *i_bdev;
+       struct cdev             *i_cdev;
+       int                     i_cindex;
++      void                    *i_filterdata;
+       __u32                   i_generation;
+@@ -646,6 +650,7 @@
+       spinlock_t              f_ep_lock;
+ #endif /* #ifdef CONFIG_EPOLL */
+       struct address_space    *f_mapping;
++      struct lookup_intent    *f_it;
+ };
+ extern spinlock_t files_lock;
+ #define file_list_lock() spin_lock(&files_lock);
+@@ -1043,7 +1048,9 @@
+       void (*truncate) (struct inode *);
+       int (*permission) (struct inode *, int, struct nameidata *);
+       int (*setattr) (struct dentry *, struct iattr *);
++      int (*setattr_raw) (struct inode *, struct iattr *);
+       int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
++      int (*getattr_it) (struct vfsmount *, struct dentry *, struct lookup_intent *, struct kstat *);
+       int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
+       ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
+       ssize_t (*listxattr) (struct dentry *, char *, size_t);
+@@ -1084,6 +1091,7 @@
+       int (*remount_fs) (struct super_block *, int *, char *);
+       void (*clear_inode) (struct inode *);
+       void (*umount_begin) (struct super_block *);
++      void (*umount_lustre) (struct super_block *);
+       int (*show_options)(struct seq_file *, struct vfsmount *);
+@@ -1286,6 +1294,7 @@
+ extern int may_umount(struct vfsmount *);
+ extern void umount_tree(struct vfsmount *, int, struct list_head *);
+ extern void release_mounts(struct list_head *);
++struct vfsmount *do_kern_mount(const char *type, int flags, const char *name, void *data);
+ extern long do_mount(char *, char *, char *, unsigned long, void *);
+ extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int);
+ extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *,
+@@ -1347,6 +1356,7 @@
+                       int mode);
+ extern struct file *filp_open(const char *, int, int);
+ extern struct file * dentry_open(struct dentry *, struct vfsmount *, int);
++extern struct file * dentry_open_it(struct dentry *, struct vfsmount *, int, struct lookup_intent *);
+ extern int filp_close(struct file *, fl_owner_t id);
+ extern char * getname(const char __user *);
+Index: linux-2.6.15-fc5/include/linux/namei.h
+===================================================================
+--- linux-2.6.15-fc5.orig/include/linux/namei.h        2006-05-31 04:08:39.000000000 +0800
++++ linux-2.6.15-fc5/include/linux/namei.h     2006-05-31 17:24:35.000000000 +0800
+@@ -5,10 +5,39 @@
+ struct vfsmount;
++#define IT_OPEN                (1)
++#define IT_CREAT       (1<<1)
++#define IT_READDIR     (1<<2)
++#define IT_GETATTR     (1<<3)
++#define IT_LOOKUP      (1<<4)
++#define IT_UNLINK      (1<<5)
++#define IT_TRUNC       (1<<6)
++#define IT_GETXATTR    (1<<7)
++
++struct lustre_intent_data {
++      int     it_disposition;
++      int     it_status;
++      __u64   it_lock_handle;
++      void    *it_data;
++      int     it_lock_mode;
++};
++
++#define INTENT_MAGIC 0x19620323
++
++#define it_flags flags
++#define it_create_mode create_mode
++#define lookup_intent open_intent
++
+ struct open_intent {
+-      int     flags;
+-      int     create_mode;
+-      struct file *file;
++              int     it_magic;
++              void    (*it_op_release)(struct open_intent *);
++              int     it_op;
++              int     flags;
++              int     create_mode;
++      struct  file *file;
++              union {
++                struct lustre_intent_data lustre;
++              } d;
+ };
+ enum { MAX_NESTED_LINKS = 8 };
+@@ -22,12 +51,16 @@
+       unsigned        depth;
+       char *saved_names[MAX_NESTED_LINKS + 1];
+-      /* Intent data */
+-      union {
+-              struct open_intent open;
+-      } intent;
++      struct lookup_intent intent;
+ };
++static inline void intent_init(struct lookup_intent *it, int op)
++{
++      memset(it, 0, sizeof(*it));
++      it->it_magic = INTENT_MAGIC;
++      it->it_op = op;
++}
++
+ /*
+  * Type of the last component on LOOKUP_PARENT
+  */
+@@ -49,7 +82,8 @@
+ #define LOOKUP_NOALT          32
+ #define LOOKUP_REVAL          64
+ #define LOOKUP_ATOMIC         128
+-
++#define LOOKUP_LAST           (0x1000)
++#define LOOKUP_LINK_NOTLAST   (0x2000)
+ /*
+  * Intent data
+  */
+@@ -59,10 +93,19 @@
+ extern int FASTCALL(__user_walk(const char __user *, unsigned, struct nameidata *));
+ extern int FASTCALL(__user_walk_fd(int dfd, const char __user *, unsigned, struct nameidata *));
++extern int FASTCALL(__user_walk_fd_it(int dfd, const char __user *, unsigned, struct nameidata *));
+ #define user_path_walk(name,nd) \
+       __user_walk_fd(AT_FDCWD, name, LOOKUP_FOLLOW, nd)
+ #define user_path_walk_link(name,nd) \
+       __user_walk_fd(AT_FDCWD, name, 0, nd)
++
++extern int FASTCALL(__user_walk_it(const char __user *name, unsigned flags, struct nameidata *nd));
++#define user_path_walk_it(name,nd) \
++      __user_walk_it(name, LOOKUP_FOLLOW, nd)
++#define user_path_walk_link_it(name,nd) \
++      __user_walk_it(name, 0, nd)
++extern void intent_release(struct lookup_intent *);
++
+ extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *));
+ extern int FASTCALL(path_walk(const char *, struct nameidata *));
+ extern int FASTCALL(link_path_walk(const char *, struct nameidata *));
+Index: linux-2.6.15-fc5/include/linux/mount.h
+===================================================================
+--- linux-2.6.15-fc5.orig/include/linux/mount.h        2006-05-31 04:08:22.000000000 +0800
++++ linux-2.6.15-fc5/include/linux/mount.h     2006-05-31 17:24:35.000000000 +0800
+@@ -46,6 +46,8 @@
+       struct list_head mnt_slave;     /* slave list entry */
+       struct vfsmount *mnt_master;    /* slave is on master->mnt_slave_list */
+       struct namespace *mnt_namespace; /* containing namespace */
++      struct list_head mnt_lustre_list; /* GNS mount list */
++      unsigned long mnt_last_used;    /* for GNS auto-umount (jiffies) */
+       int mnt_pinned;
+ };
diff --git a/lustre/kernel_patches/patches/vfs_intent-2.6-sles10.patch b/lustre/kernel_patches/patches/vfs_intent-2.6-sles10.patch
new file mode 100644 (file)
index 0000000..393cf78
--- /dev/null
@@ -0,0 +1,863 @@
+Index: linux-2.6.16.21-0.8/fs/inode.c
+===================================================================
+--- linux-2.6.16.21-0.8.orig/fs/inode.c        2006-08-03 23:38:13.000000000 -0600
++++ linux-2.6.16.21-0.8/fs/inode.c     2006-08-03 23:38:24.000000000 -0600
+@@ -236,6 +236,7 @@
+       inodes_stat.nr_unused--;
+ }
++EXPORT_SYMBOL(__iget);
+ /**
+  * clear_inode - clear an inode
+  * @inode: inode to clear
+Index: linux-2.6.16.21-0.8/fs/open.c
+===================================================================
+--- linux-2.6.16.21-0.8.orig/fs/open.c 2006-08-03 23:38:13.000000000 -0600
++++ linux-2.6.16.21-0.8/fs/open.c      2006-08-03 23:49:51.000000000 -0600
+@@ -224,12 +224,12 @@
+       struct nameidata nd;
+       struct inode * inode;
+       int error;
+-
++      intent_init(&nd.intent, IT_GETATTR);
+       error = -EINVAL;
+       if (length < 0) /* sorry, but loff_t says... */
+               goto out;
+-      error = user_path_walk(path, &nd);
++      error = user_path_walk_it(path, &nd);
+       if (error)
+               goto out;
+       inode = nd.dentry->d_inode;
+@@ -494,6 +494,7 @@
+       int old_fsuid, old_fsgid;
+       kernel_cap_t old_cap;
+       int res;
++      intent_init(&nd.intent, IT_GETATTR);
+       if (mode & ~S_IRWXO)    /* where's F_OK, X_OK, W_OK, R_OK? */
+               return -EINVAL;
+@@ -518,7 +519,7 @@
+       else
+               current->cap_effective = current->cap_permitted;
+-      res = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd);
++      res = __user_walk_fd_it(dfd, filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd);
+       if (!res) {
+               res = vfs_permission(&nd, mode);
+               /* SuS v2 requires we report a read only fs too */
+@@ -544,8 +545,9 @@
+ {
+       struct nameidata nd;
+       int error;
++      intent_init(&nd.intent, IT_GETATTR);
+-      error = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &nd);
++      error = __user_walk_it(filename, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &nd);
+       if (error)
+               goto out;
+@@ -595,8 +597,9 @@
+ {
+       struct nameidata nd;
+       int error;
++      intent_init(&nd.intent, IT_GETATTR);
+-      error = __user_walk(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
++      error = __user_walk_it(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
+       if (error)
+               goto out;
+@@ -817,6 +820,7 @@
+               error = open(inode, f);
+               if (error)
+                       goto cleanup_all;
++              intent_release(f->f_it);
+       }
+       f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
+@@ -843,6 +847,7 @@
+       f->f_dentry = NULL;
+       f->f_vfsmnt = NULL;
+ cleanup_file:
++      intent_release(f->f_it);
+       put_filp(f);
+       dput(dentry);
+       mntput(mnt);
+@@ -868,6 +873,7 @@
+ {
+       int namei_flags, error;
+       struct nameidata nd;
++      intent_init(&nd.intent, IT_OPEN);
+       namei_flags = flags;
+       if ((namei_flags+1) & O_ACCMODE)
+@@ -904,19 +910,19 @@
+ struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
+               int (*open)(struct inode *, struct file *))
+ {
+-      if (IS_ERR(nd->intent.open.file))
++      if (IS_ERR(nd->intent.file))
+               goto out;
+       if (IS_ERR(dentry))
+               goto out_err;
+-      nd->intent.open.file = __dentry_open(dget(dentry), mntget(nd->mnt),
+-                                           nd->intent.open.flags - 1,
+-                                           nd->intent.open.file,
++      nd->intent.file = __dentry_open(dget(dentry), mntget(nd->mnt),
++                                           nd->intent.flags - 1,
++                                           nd->intent.file,
+                                            open);
+ out:
+-      return nd->intent.open.file;
++      return nd->intent.file;
+ out_err:
+       release_open_intent(nd);
+-      nd->intent.open.file = (struct file *)dentry;
++      nd->intent.file = (struct file *)dentry;
+       goto out;
+ }
+ EXPORT_SYMBOL_GPL(lookup_instantiate_filp);
+@@ -933,7 +939,8 @@
+       struct file *filp;
+       /* Pick up the filp from the open intent */
+-      filp = nd->intent.open.file;
++      filp = nd->intent.file;
++      filp->f_it = &nd->intent;
+       /* Has the filesystem initialised the file for us? */
+       if (filp->f_dentry == NULL)
+               filp = __dentry_open(nd->dentry, nd->mnt, flags, filp, NULL);
+Index: linux-2.6.16.21-0.8/fs/nfsctl.c
+===================================================================
+--- linux-2.6.16.21-0.8.orig/fs/nfsctl.c       2006-08-03 23:38:13.000000000 -0600
++++ linux-2.6.16.21-0.8/fs/nfsctl.c    2006-08-03 23:38:25.000000000 -0600
+@@ -26,6 +26,7 @@
+       struct nameidata nd;
+       int error;
++      intent_init(&nd.intent, IT_OPEN);
+       nd.mnt = do_kern_mount("nfsd", 0, "nfsd", NULL);
+       if (IS_ERR(nd.mnt))
+Index: linux-2.6.16.21-0.8/fs/namei.c
+===================================================================
+--- linux-2.6.16.21-0.8.orig/fs/namei.c        2006-08-03 23:38:13.000000000 -0600
++++ linux-2.6.16.21-0.8/fs/namei.c     2006-08-03 23:49:51.000000000 -0600
+@@ -337,8 +337,19 @@
+       return 0;
+ }
++void intent_release(struct lookup_intent *it)
++{
++      if (!it)
++              return;
++      if (it->it_magic != INTENT_MAGIC)
++              return;
++      if (it->it_op_release)
++              it->it_op_release(it);
++}
++
+ void path_release(struct nameidata *nd)
+ {
++      intent_release(&nd->intent);
+       dput(nd->dentry);
+       mntput(nd->mnt);
+ }
+@@ -359,10 +370,10 @@
+  */
+ void release_open_intent(struct nameidata *nd)
+ {
+-      if (nd->intent.open.file->f_dentry == NULL)
+-              put_filp(nd->intent.open.file);
++      if (nd->intent.file->f_dentry == NULL)
++              put_filp(nd->intent.file);
+       else
+-              fput(nd->intent.open.file);
++              fput(nd->intent.file);
+ }
+ /*
+@@ -440,8 +451,12 @@
+ {
+       struct dentry * result;
+       struct inode *dir = parent->d_inode;
++      int counter = 0;
+       mutex_lock(&dir->i_mutex);
++again:
++      counter++;
++
+       /*
+        * First re-do the cached lookup just in case it was created
+        * while we waited for the directory semaphore..
+@@ -475,13 +490,16 @@
+        * Uhhuh! Nasty case: the cache was re-populated while
+        * we waited on the semaphore. Need to revalidate.
+        */
+-      mutex_unlock(&dir->i_mutex);
+       if (result->d_op && result->d_op->d_revalidate) {
+               if (!result->d_op->d_revalidate(result, nd) && !d_invalidate(result)) {
+                       dput(result);
+-                      result = ERR_PTR(-ENOENT);
++                      if (counter > 10)
++                              result = ERR_PTR(-ESTALE);
++                      if (!IS_ERR(result))
++                              goto again;
+               }
+       }
++      mutex_unlock(&dir->i_mutex);
+       return result;
+ }
+@@ -509,7 +527,9 @@
+ static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *link)
+ {
+       int res = 0;
++      struct lookup_intent it = nd->intent;
+       char *name;
++
+       if (IS_ERR(link))
+               goto fail;
+@@ -519,6 +539,10 @@
+                       /* weird __emul_prefix() stuff did it */
+                       goto out;
+       }
++      intent_init(&nd->intent, it.it_op);
++      nd->intent.it_flags = it.it_flags;
++      nd->intent.it_create_mode = it.it_create_mode;
++      nd->intent.file = it.file;
+       res = link_path_walk(link, nd);
+ out:
+       if (nd->depth || res || nd->last_type!=LAST_NORM)
+@@ -768,6 +792,33 @@
+       return PTR_ERR(dentry);
+ }
++static int revalidate_special(struct nameidata *nd)
++{
++      struct dentry *dentry = nd->dentry;
++      int err, counter = 0;
++
++ revalidate_again:
++      if (!dentry->d_op || !dentry->d_op->d_revalidate)
++              return 0;
++      if (!dentry->d_op->d_revalidate(dentry, nd)) {
++              struct dentry *new;
++              if ((err = permission(dentry->d_parent->d_inode, MAY_EXEC, nd)))
++                      return err;
++              new = real_lookup(dentry->d_parent, &dentry->d_name, nd);
++              if (IS_ERR(new))
++                      return PTR_ERR(new);
++              d_invalidate(dentry);
++              dput(dentry);
++              nd->dentry = dentry = new;
++              counter++;
++              if (counter < 10)
++                      goto revalidate_again;
++              printk("excessive revalidate_it loops\n");
++              return -ESTALE;
++      }
++      return 0;
++}
++
+ /*
+  * Name resolution.
+  * This is the basic name resolution function, turning a pathname into
+@@ -864,7 +915,11 @@
+                       goto out_dput;
+               if (inode->i_op->follow_link) {
++                      int save_flags = nd->flags;
++                      nd->flags |= LOOKUP_LINK_NOTLAST;
+                       err = do_follow_link(&next, nd);
++                      if (!(save_flags & LOOKUP_LINK_NOTLAST))
++                              nd->flags &= ~LOOKUP_LINK_NOTLAST;
+                       if (err)
+                               goto return_err;
+                       err = -ENOENT;
+@@ -899,6 +954,23 @@
+                               inode = nd->dentry->d_inode;
+                               /* fallthrough */
+                       case 1:
++                              nd->flags |= LOOKUP_LAST;
++                              err = revalidate_special(nd);
++                              nd->flags &= ~LOOKUP_LAST;
++                              if (!nd->dentry->d_inode)
++                                      err = -ENOENT;
++                              if (err) {
++                                      path_release(nd);
++                                      goto return_err;
++                              }
++                              if (lookup_flags & LOOKUP_DIRECTORY) {
++                                      err = -ENOTDIR;
++                                      if(!nd->dentry->d_inode->i_op ||
++                                        !nd->dentry->d_inode->i_op->lookup) {
++                                              path_release(nd);
++                                              goto return_err;
++                                      }
++                              }
+                               goto return_reval;
+               }
+               if (nd->dentry->d_op && nd->dentry->d_op->d_hash) {
+@@ -906,7 +978,9 @@
+                       if (err < 0)
+                               break;
+               }
++              nd->flags |= LOOKUP_LAST;
+               err = do_lookup(nd, &this, &next);
++              nd->flags &= ~LOOKUP_LAST;
+               if (err)
+                       break;
+               inode = next.dentry->d_inode;
+@@ -1148,13 +1222,13 @@
+       if (filp == NULL)
+               return -ENFILE;
+-      nd->intent.open.file = filp;
+-      nd->intent.open.flags = open_flags;
+-      nd->intent.open.create_mode = create_mode;
++      nd->intent.file = filp;
++      nd->intent.flags = open_flags;
++      nd->intent.create_mode = create_mode;
+       err = do_path_lookup(dfd, name, lookup_flags|LOOKUP_OPEN, nd);
+-      if (IS_ERR(nd->intent.open.file)) {
++      if (IS_ERR(nd->intent.file)) {
+               if (err == 0) {
+-                      err = PTR_ERR(nd->intent.open.file);
++                      err = PTR_ERR(nd->intent.file);
+                       path_release(nd);
+               }
+       } else if (err != 0)
+@@ -1257,7 +1331,7 @@
+ }
+ /* SMP-safe */
+-struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
++struct dentry * lookup_one_len_it(const char * name, struct dentry * base, int len, struct nameidata *nd)
+ {
+       unsigned long hash;
+       struct qstr this;
+@@ -1277,11 +1351,17 @@
+       }
+       this.hash = end_name_hash(hash);
+-      return __lookup_hash(&this, base, NULL);
++      return __lookup_hash(&this, base, nd);
+ access:
+       return ERR_PTR(-EACCES);
+ }
++struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
++{
++      return lookup_one_len_it(name, base, len, NULL);
++}
++
++
+ /*
+  *    namei()
+  *
+@@ -1293,8 +1373,9 @@
+  * that namei follows links, while lnamei does not.
+  * SMP-safe
+  */
+-int fastcall __user_walk_fd(int dfd, const char __user *name, unsigned flags,
+-                          struct nameidata *nd)
++
++int fastcall __user_walk_fd_it(int dfd, const char __user *name, unsigned flags,
++                             struct nameidata *nd)
+ {
+       char *tmp = getname(name);
+       int err = PTR_ERR(tmp);
+@@ -1306,9 +1387,22 @@
+       return err;
+ }
++int fastcall __user_walk_fd(int dfd, const char __user *name, unsigned flags,
++                          struct nameidata *nd)
++{
++      intent_init(&nd->intent, IT_LOOKUP);
++      return __user_walk_fd_it(dfd, name, flags, nd);
++}
++
++int fastcall __user_walk_it(const char __user *name, unsigned flags, struct nameidata *nd)
++{
++      return __user_walk_fd_it(AT_FDCWD, name, flags, nd);
++}
++
+ int fastcall __user_walk(const char __user *name, unsigned flags, struct nameidata *nd)
+ {
+-      return __user_walk_fd(AT_FDCWD, name, flags, nd);
++      intent_init(&nd->intent, IT_LOOKUP);
++      return __user_walk_it(name, flags, nd);
+ }
+ /*
+@@ -1588,6 +1682,8 @@
+       if (flag & O_APPEND)
+               acc_mode |= MAY_APPEND;
++      nd->intent.it_flags = flag;
++      nd->intent.it_create_mode = mode;
+       /*
+        * The simplest case - just a plain lookup.
+        */
+@@ -1602,6 +1698,7 @@
+       /*
+        * Create - we need to know the parent.
+        */
++      nd->intent.it_op |= IT_CREAT;
+       error = path_lookup_create(dfd,pathname,LOOKUP_PARENT,nd,flag,mode);
+       if (error)
+               return error;
+@@ -1618,7 +1715,9 @@
+       dir = nd->dentry;
+       nd->flags &= ~LOOKUP_PARENT;
+       mutex_lock(&dir->d_inode->i_mutex);
++      nd->flags |= LOOKUP_LAST;
+       path.dentry = lookup_hash(nd);
++      nd->flags &= ~LOOKUP_LAST;
+       path.mnt = nd->mnt;
+ do_last:
+@@ -1628,9 +1727,9 @@
+               goto exit;
+       }
+-      if (IS_ERR(nd->intent.open.file)) {
++      if (IS_ERR(nd->intent.file)) {
+               mutex_unlock(&dir->d_inode->i_mutex);
+-              error = PTR_ERR(nd->intent.open.file);
++              error = PTR_ERR(nd->intent.file);
+               goto exit_dput;
+       }
+@@ -1683,7 +1782,7 @@
+ exit_dput:
+       dput_path(&path, nd);
+ exit:
+-      if (!IS_ERR(nd->intent.open.file))
++      if (!IS_ERR(nd->intent.file))
+               release_open_intent(nd);
+       path_release(nd);
+       return error;
+@@ -1726,7 +1825,9 @@
+       }
+       dir = nd->dentry;
+       mutex_lock(&dir->d_inode->i_mutex);
++      nd->flags |= LOOKUP_LAST;
+       path.dentry = lookup_hash(nd);
++      nd->flags &= ~LOOKUP_LAST;
+       path.mnt = nd->mnt;
+       __putname(nd->last.name);
+       goto do_last;
+@@ -2238,6 +2339,8 @@
+       int error;
+       char * to;
++      intent_init(&nd.intent, IT_LOOKUP);
++        intent_init(&old_nd.intent, IT_LOOKUP);
+       if (flags != 0)
+               return -EINVAL;
+@@ -2245,7 +2348,7 @@
+       if (IS_ERR(to))
+               return PTR_ERR(to);
+-      error = __user_walk_fd(olddfd, oldname, 0, &old_nd);
++      error = __user_walk_fd_it(olddfd, oldname, 0, &old_nd);
+       if (error)
+               goto exit;
+       error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd);
+Index: linux-2.6.16.21-0.8/fs/stat.c
+===================================================================
+--- linux-2.6.16.21-0.8.orig/fs/stat.c 2006-08-03 23:38:13.000000000 -0600
++++ linux-2.6.16.21-0.8/fs/stat.c      2006-08-03 23:38:25.000000000 -0600
+@@ -38,7 +38,7 @@
+ EXPORT_SYMBOL(generic_fillattr);
+-int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
++int vfs_getattr_it(struct vfsmount *mnt, struct dentry *dentry, struct lookup_intent *it, struct kstat *stat)
+ {
+       struct inode *inode = dentry->d_inode;
+       int retval;
+@@ -47,6 +47,8 @@
+       if (retval)
+               return retval;
++      if (inode->i_op->getattr_it)
++              return inode->i_op->getattr_it(mnt, dentry, it, stat);
+       if (inode->i_op->getattr)
+               return inode->i_op->getattr(mnt, dentry, stat);
+@@ -61,6 +63,11 @@
+       return 0;
+ }
++int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
++{
++      return vfs_getattr_it(mnt, dentry, NULL, stat);
++}
++
+ EXPORT_SYMBOL(vfs_getattr);
+ int vfs_stat_fd(int dfd, char __user *name, struct kstat *stat)
+@@ -68,9 +75,10 @@
+       struct nameidata nd;
+       int error;
+-      error = __user_walk_fd(dfd, name, LOOKUP_FOLLOW, &nd);
++      intent_init(&nd.intent, IT_GETATTR);
++      error = __user_walk_fd_it(dfd, name, LOOKUP_FOLLOW, &nd);
+       if (!error) {
+-              error = vfs_getattr(nd.mnt, nd.dentry, stat);
++              error = vfs_getattr_it(nd.mnt, nd.dentry, &nd.intent, stat);
+               path_release(&nd);
+       }
+       return error;
+@@ -88,9 +96,10 @@
+       struct nameidata nd;
+       int error;
+-      error = __user_walk_fd(dfd, name, 0, &nd);
++      intent_init(&nd.intent, IT_GETATTR);
++      error = __user_walk_fd_it(dfd, name, 0, &nd);
+       if (!error) {
+-              error = vfs_getattr(nd.mnt, nd.dentry, stat);
++              error = vfs_getattr_it(nd.mnt, nd.dentry, &nd.intent, stat);
+               path_release(&nd);
+       }
+       return error;
+@@ -107,9 +116,12 @@
+ {
+       struct file *f = fget(fd);
+       int error = -EBADF;
++      struct nameidata nd;
++      intent_init(&nd.intent, IT_GETATTR);
+       if (f) {
+-              error = vfs_getattr(f->f_vfsmnt, f->f_dentry, stat);
++              error = vfs_getattr_it(f->f_vfsmnt, f->f_dentry, &nd.intent, stat);
++              intent_release(&nd.intent);
+               fput(f);
+       }
+       return error;
+Index: linux-2.6.16.21-0.8/fs/namespace.c
+===================================================================
+--- linux-2.6.16.21-0.8.orig/fs/namespace.c    2006-08-03 23:38:14.000000000 -0600
++++ linux-2.6.16.21-0.8/fs/namespace.c 2006-08-03 23:49:51.000000000 -0600
+@@ -75,6 +75,7 @@
+               INIT_LIST_HEAD(&mnt->mnt_share);
+               INIT_LIST_HEAD(&mnt->mnt_slave_list);
+               INIT_LIST_HEAD(&mnt->mnt_slave);
++              INIT_LIST_HEAD(&mnt->mnt_lustre_list);
+               if (name) {
+                       int size = strlen(name) + 1;
+                       char *newname = kmalloc(size, GFP_KERNEL);
+@@ -155,6 +156,7 @@
+ static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd)
+ {
++      memset(old_nd, 0, sizeof(*old_nd));
+       old_nd->dentry = mnt->mnt_mountpoint;
+       old_nd->mnt = mnt->mnt_parent;
+       mnt->mnt_parent = mnt;
+@@ -273,6 +275,9 @@
+ {
+       struct super_block *sb = mnt->mnt_sb;
+       dput(mnt->mnt_root);
++      spin_lock(&dcache_lock);
++      list_del(&mnt->mnt_lustre_list);
++      spin_unlock(&dcache_lock);
+       free_vfsmnt(mnt);
+       deactivate_super(sb);
+ }
+@@ -539,6 +544,8 @@
+        */
+       lock_kernel();
++      if (sb->s_op->umount_lustre)
++              sb->s_op->umount_lustre(sb);
+       if ((flags & MNT_FORCE) && sb->s_op->umount_begin)
+               sb->s_op->umount_begin(sb);
+       unlock_kernel();
+@@ -871,6 +878,7 @@
+               return err;
+       if (!old_name || !*old_name)
+               return -EINVAL;
++      intent_init(&old_nd.intent, IT_LOOKUP);
+       err = path_lookup(old_name, LOOKUP_FOLLOW, &old_nd);
+       if (err)
+               return err;
+@@ -956,6 +964,7 @@
+               return -EPERM;
+       if (!old_name || !*old_name)
+               return -EINVAL;
++      intent_init(&old_nd.intent, IT_LOOKUP);
+       err = path_lookup(old_name, LOOKUP_FOLLOW, &old_nd);
+       if (err)
+               return err;
+@@ -1271,6 +1280,7 @@
+       int retval = 0;
+       int mnt_flags = 0;
++      intent_init(&nd.intent, IT_LOOKUP);
+       /* Discard magic */
+       if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
+               flags &= ~MS_MGC_MSK;
+Index: linux-2.6.16.21-0.8/fs/exec.c
+===================================================================
+--- linux-2.6.16.21-0.8.orig/fs/exec.c 2006-08-03 23:38:14.000000000 -0600
++++ linux-2.6.16.21-0.8/fs/exec.c      2006-08-03 23:49:51.000000000 -0600
+@@ -128,7 +128,9 @@
+       struct nameidata nd;
+       int error;
+-      error = __user_path_lookup_open(library, LOOKUP_FOLLOW, &nd, FMODE_READ);
++      intent_init(&nd.intent, IT_OPEN);
++      error = __user_path_lookup_open(library, LOOKUP_FOLLOW, &nd,
++                                      FMODE_READ | FMODE_EXEC);
+       if (error)
+               goto out;
+@@ -478,7 +480,9 @@
+       int err;
+       struct file *file;
+-      err = path_lookup_open(AT_FDCWD, name, LOOKUP_FOLLOW, &nd, FMODE_READ);
++      intent_init(&nd.intent, IT_OPEN);
++      err = path_lookup_open(AT_FDCWD, name, LOOKUP_FOLLOW, &nd,
++                             FMODE_READ | FMODE_EXEC);
+       file = ERR_PTR(err);
+       if (!err) {
+Index: linux-2.6.16.21-0.8/include/linux/dcache.h
+===================================================================
+--- linux-2.6.16.21-0.8.orig/include/linux/dcache.h    2006-08-03 23:38:14.000000000 -0600
++++ linux-2.6.16.21-0.8/include/linux/dcache.h 2006-08-03 23:48:00.000000000 -0600
+@@ -4,6 +4,7 @@
+ #ifdef __KERNEL__
+ #include <asm/atomic.h>
++#include <linux/string.h>
+ #include <linux/list.h>
+ #include <linux/spinlock.h>
+ #include <linux/cache.h>
+@@ -36,6 +37,8 @@
+       const unsigned char *name;
+ };
++#include <linux/namei.h>
++
+ struct dentry_stat_t {
+       int nr_dentry;
+       int nr_unused;
+Index: linux-2.6.16.21-0.8/include/linux/fs.h
+===================================================================
+--- linux-2.6.16.21-0.8.orig/include/linux/fs.h        2006-08-03 23:38:14.000000000 -0600
++++ linux-2.6.16.21-0.8/include/linux/fs.h     2006-08-03 23:48:00.000000000 -0600
+@@ -59,6 +59,7 @@
+ #define FMODE_READ 1
+ #define FMODE_WRITE 2
++#define FMODE_EXEC 4
+ /* Internal kernel extensions */
+ #define FMODE_LSEEK   4
+@@ -265,6 +266,8 @@
+ #define ATTR_KILL_SUID        2048
+ #define ATTR_KILL_SGID        4096
+ #define ATTR_FILE     8192
++#define ATTR_RAW              16384   /* file system, not vfs will massage attrs */
++#define ATTR_FROM_OPEN        65536   /* called from open path, ie O_TRUNC */
+ #define ATTR_NO_BLOCK 32768   /* Return EAGAIN and don't block on long truncates */
+ /*
+@@ -500,6 +503,7 @@
+       struct block_device     *i_bdev;
+       struct cdev             *i_cdev;
+       int                     i_cindex;
++      void                    *i_filterdata;
+       __u32                   i_generation;
+@@ -647,6 +651,7 @@
+       spinlock_t              f_ep_lock;
+ #endif /* #ifdef CONFIG_EPOLL */
+       struct address_space    *f_mapping;
++      struct lookup_intent    *f_it;
+ };
+ extern spinlock_t files_lock;
+ #define file_list_lock() spin_lock(&files_lock);
+@@ -1049,7 +1054,9 @@
+       void (*truncate) (struct inode *);
+       int (*permission) (struct inode *, int, struct nameidata *);
+       int (*setattr) (struct dentry *, struct iattr *);
++      int (*setattr_raw) (struct inode *, struct iattr *);
+       int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
++      int (*getattr_it) (struct vfsmount *, struct dentry *, struct lookup_intent *, struct kstat *);
+       int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
+       ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
+       ssize_t (*listxattr) (struct dentry *, char *, size_t);
+@@ -1090,6 +1097,7 @@
+       int (*remount_fs) (struct super_block *, int *, char *);
+       void (*clear_inode) (struct inode *);
+       void (*umount_begin) (struct super_block *);
++      void (*umount_lustre) (struct super_block *);
+       int (*show_options)(struct seq_file *, struct vfsmount *);
+@@ -1292,6 +1300,7 @@
+ extern int may_umount(struct vfsmount *);
+ extern void umount_tree(struct vfsmount *, int, struct list_head *);
+ extern void release_mounts(struct list_head *);
++struct vfsmount *do_kern_mount(const char *type, int flags, const char *name, void *data);
+ extern long do_mount(char *, char *, char *, unsigned long, void *);
+ extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int);
+ extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *,
+@@ -1353,6 +1362,7 @@
+                       int mode);
+ extern struct file *filp_open(const char *, int, int);
+ extern struct file * dentry_open(struct dentry *, struct vfsmount *, int);
++extern struct file * dentry_open_it(struct dentry *, struct vfsmount *, int, struct lookup_intent *);
+ extern int filp_close(struct file *, fl_owner_t id);
+ extern char * getname(const char __user *);
+Index: linux-2.6.16.21-0.8/include/linux/namei.h
+===================================================================
+--- linux-2.6.16.21-0.8.orig/include/linux/namei.h     2006-08-03 23:38:14.000000000 -0600
++++ linux-2.6.16.21-0.8/include/linux/namei.h  2006-08-03 23:38:25.000000000 -0600
+@@ -5,10 +5,39 @@
+ struct vfsmount;
++#define IT_OPEN                (1)
++#define IT_CREAT       (1<<1)
++#define IT_READDIR     (1<<2)
++#define IT_GETATTR     (1<<3)
++#define IT_LOOKUP      (1<<4)
++#define IT_UNLINK      (1<<5)
++#define IT_TRUNC       (1<<6)
++#define IT_GETXATTR    (1<<7)
++
++struct lustre_intent_data {
++      int     it_disposition;
++      int     it_status;
++      __u64   it_lock_handle;
++      void    *it_data;
++      int     it_lock_mode;
++};
++
++#define INTENT_MAGIC 0x19620323
++
++#define it_flags flags
++#define it_create_mode create_mode
++#define lookup_intent open_intent
++
+ struct open_intent {
+-      int     flags;
+-      int     create_mode;
+-      struct file *file;
++              int     it_magic;
++              void    (*it_op_release)(struct open_intent *);
++              int     it_op;
++              int     flags;
++              int     create_mode;
++      struct  file *file;
++              union {
++                struct lustre_intent_data lustre;
++              } d;
+ };
+ enum { MAX_NESTED_LINKS = 8 };
+@@ -22,12 +51,16 @@
+       unsigned        depth;
+       char *saved_names[MAX_NESTED_LINKS + 1];
+-      /* Intent data */
+-      union {
+-              struct open_intent open;
+-      } intent;
++      struct lookup_intent intent;
+ };
++static inline void intent_init(struct lookup_intent *it, int op)
++{
++      memset(it, 0, sizeof(*it));
++      it->it_magic = INTENT_MAGIC;
++      it->it_op = op;
++}
++
+ /*
+  * Type of the last component on LOOKUP_PARENT
+  */
+@@ -48,6 +81,8 @@
+ #define LOOKUP_PARENT         16
+ #define LOOKUP_NOALT          32
+ #define LOOKUP_REVAL          64
++#define LOOKUP_LAST           (0x1000)
++#define LOOKUP_LINK_NOTLAST   (0x2000)
+ /*
+  * Intent data
+  */
+@@ -57,10 +92,19 @@
+ extern int FASTCALL(__user_walk(const char __user *, unsigned, struct nameidata *));
+ extern int FASTCALL(__user_walk_fd(int dfd, const char __user *, unsigned, struct nameidata *));
++extern int FASTCALL(__user_walk_fd_it(int dfd, const char __user *, unsigned, struct nameidata *));
+ #define user_path_walk(name,nd) \
+       __user_walk_fd(AT_FDCWD, name, LOOKUP_FOLLOW, nd)
+ #define user_path_walk_link(name,nd) \
+       __user_walk_fd(AT_FDCWD, name, 0, nd)
++
++extern int FASTCALL(__user_walk_it(const char __user *name, unsigned flags, struct nameidata *nd));
++#define user_path_walk_it(name,nd) \
++      __user_walk_it(name, LOOKUP_FOLLOW, nd)
++#define user_path_walk_link_it(name,nd) \
++      __user_walk_it(name, 0, nd)
++extern void intent_release(struct lookup_intent *);
++
+ extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *));
+ extern int FASTCALL(path_walk(const char *, struct nameidata *));
+ extern int FASTCALL(link_path_walk(const char *, struct nameidata *));
+Index: linux-2.6.16.21-0.8/include/linux/mount.h
+===================================================================
+--- linux-2.6.16.21-0.8.orig/include/linux/mount.h     2006-08-03 23:38:14.000000000 -0600
++++ linux-2.6.16.21-0.8/include/linux/mount.h  2006-08-03 23:38:25.000000000 -0600
+@@ -46,6 +46,8 @@
+       struct list_head mnt_slave;     /* slave list entry */
+       struct vfsmount *mnt_master;    /* slave is on master->mnt_slave_list */
+       struct namespace *mnt_namespace; /* containing namespace */
++      struct list_head mnt_lustre_list; /* GNS mount list */
++      unsigned long mnt_last_used;    /* for GNS auto-umount (jiffies) */
+       int mnt_pinned;
+ };
+Index: linux-2.6.16.21-0.8/fs/9p/vfs_inode.c
+===================================================================
+--- linux-2.6.16.21-0.8.orig/fs/9p/vfs_inode.c 2006-08-03 21:55:41.000000000 -0600
++++ linux-2.6.16.21-0.8/fs/9p/vfs_inode.c      2006-08-03 23:41:18.000000000 -0600
+@@ -469,7 +469,7 @@
+       perm = unixmode2p9mode(v9ses, mode);
+       if (nd && nd->flags & LOOKUP_OPEN)
+-              flags = nd->intent.open.flags - 1;
++              flags = nd->intent.flags - 1;
+       else
+               flags = O_RDWR;
+Index: linux-2.6.16.21-0.8/fs/fuse/dir.c
+===================================================================
+--- linux-2.6.16.21-0.8.orig/fs/fuse/dir.c     2006-08-03 21:55:41.000000000 -0600
++++ linux-2.6.16.21-0.8/fs/fuse/dir.c  2006-08-03 23:48:58.000000000 -0600
+@@ -242,7 +242,7 @@
+       struct fuse_entry_out outentry;
+       struct fuse_file *ff;
+       struct file *file;
+-      int flags = nd->intent.open.flags - 1;
++      int flags = nd->intent.flags - 1;
+       err = -ENOSYS;
+       if (fc->no_create)
diff --git a/lustre/kernel_patches/patches/vfs_intent-2.6.18-vanilla.patch b/lustre/kernel_patches/patches/vfs_intent-2.6.18-vanilla.patch
new file mode 100644 (file)
index 0000000..6e86bde
--- /dev/null
@@ -0,0 +1,824 @@
+Index: linux-2.6/fs/inode.c
+===================================================================
+--- linux-2.6.orig/fs/inode.c  2006-07-15 21:04:02.000000000 +0800
++++ linux-2.6/fs/inode.c       2006-07-15 21:04:08.000000000 +0800
+@@ -234,6 +234,7 @@ void __iget(struct inode * inode)
+       inodes_stat.nr_unused--;
+ }
++EXPORT_SYMBOL(__iget);
+ /**
+  * clear_inode - clear an inode
+  * @inode: inode to clear
+Index: linux-2.6/fs/open.c
+===================================================================
+--- linux-2.6.orig/fs/open.c   2006-07-15 21:04:02.000000000 +0800
++++ linux-2.6/fs/open.c        2006-07-15 21:04:08.000000000 +0800
+@@ -225,12 +225,12 @@ static long do_sys_truncate(const char _
+       struct nameidata nd;
+       struct inode * inode;
+       int error;
+-
++      intent_init(&nd.intent, IT_GETATTR);
+       error = -EINVAL;
+       if (length < 0) /* sorry, but loff_t says... */
+               goto out;
+-      error = user_path_walk(path, &nd);
++      error = user_path_walk_it(path, &nd);
+       if (error)
+               goto out;
+       inode = nd.dentry->d_inode;
+@@ -495,6 +495,7 @@ asmlinkage long sys_faccessat(int dfd, c
+       int old_fsuid, old_fsgid;
+       kernel_cap_t old_cap;
+       int res;
++      intent_init(&nd.intent, IT_GETATTR);
+       if (mode & ~S_IRWXO)    /* where's F_OK, X_OK, W_OK, R_OK? */
+               return -EINVAL;
+@@ -519,7 +520,7 @@ asmlinkage long sys_faccessat(int dfd, c
+       else
+               current->cap_effective = current->cap_permitted;
+-      res = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd);
++      res = __user_walk_fd_it(dfd, filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd);
+       if (!res) {
+               res = vfs_permission(&nd, mode);
+               /* SuS v2 requires we report a read only fs too */
+@@ -545,8 +546,9 @@ asmlinkage long sys_chdir(const char __u
+ {
+       struct nameidata nd;
+       int error;
++      intent_init(&nd.intent, IT_GETATTR);
+-      error = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &nd);
++      error = __user_walk_it(filename, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &nd);
+       if (error)
+               goto out;
+@@ -596,8 +598,9 @@ asmlinkage long sys_chroot(const char __
+ {
+       struct nameidata nd;
+       int error;
++      intent_init(&nd.intent, IT_GETATTR);
+-      error = __user_walk(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
++      error = __user_walk_it(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
+       if (error)
+               goto out;
+@@ -823,6 +826,7 @@ static struct file *__dentry_open(struct
+               error = open(inode, f);
+               if (error)
+                       goto cleanup_all;
++              intent_release(f->f_it);
+       }
+       f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
+@@ -849,6 +853,7 @@ cleanup_all:
+       f->f_dentry = NULL;
+       f->f_vfsmnt = NULL;
+ cleanup_file:
++      intent_release(f->f_it);
+       put_filp(f);
+       dput(dentry);
+       mntput(mnt);
+@@ -874,6 +879,7 @@ static struct file *do_filp_open(int dfd
+ {
+       int namei_flags, error;
+       struct nameidata nd;
++      intent_init(&nd.intent, IT_OPEN);
+       namei_flags = flags;
+       if ((namei_flags+1) & O_ACCMODE)
+@@ -914,19 +920,19 @@ EXPORT_SYMBOL(filp_open);
+ struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
+               int (*open)(struct inode *, struct file *))
+ {
+-      if (IS_ERR(nd->intent.open.file))
++      if (IS_ERR(nd->intent.file))
+               goto out;
+       if (IS_ERR(dentry))
+               goto out_err;
+-      nd->intent.open.file = __dentry_open(dget(dentry), mntget(nd->mnt),
+-                                           nd->intent.open.flags - 1,
+-                                           nd->intent.open.file,
++      nd->intent.file = __dentry_open(dget(dentry), mntget(nd->mnt),
++                                           nd->intent.flags - 1,
++                                           nd->intent.file,
+                                            open);
+ out:
+-      return nd->intent.open.file;
++      return nd->intent.file;
+ out_err:
+       release_open_intent(nd);
+-      nd->intent.open.file = (struct file *)dentry;
++      nd->intent.file = (struct file *)dentry;
+       goto out;
+ }
+ EXPORT_SYMBOL_GPL(lookup_instantiate_filp);
+@@ -943,7 +949,8 @@ struct file *nameidata_to_filp(struct na
+       struct file *filp;
+       /* Pick up the filp from the open intent */
+-      filp = nd->intent.open.file;
++      filp = nd->intent.file;
++      filp->f_it = &nd->intent;
+       /* Has the filesystem initialised the file for us? */
+       if (filp->f_dentry == NULL)
+               filp = __dentry_open(nd->dentry, nd->mnt, flags, filp, NULL);
+Index: linux-2.6/fs/nfsctl.c
+===================================================================
+--- linux-2.6.orig/fs/nfsctl.c 2006-07-15 21:04:02.000000000 +0800
++++ linux-2.6/fs/nfsctl.c      2006-07-15 21:04:08.000000000 +0800
+@@ -25,6 +25,7 @@ static struct file *do_open(char *name, 
+       struct nameidata nd;
+       int error;
++      intent_init(&nd.intent, IT_OPEN);
+       nd.mnt = do_kern_mount("nfsd", 0, "nfsd", NULL);
+       if (IS_ERR(nd.mnt))
+Index: linux-2.6/fs/namei.c
+===================================================================
+--- linux-2.6.orig/fs/namei.c  2006-07-15 21:04:02.000000000 +0800
++++ linux-2.6/fs/namei.c       2006-07-15 21:04:36.000000000 +0800
+@@ -337,8 +337,19 @@ int deny_write_access(struct file * file
+       return 0;
+ }
++void intent_release(struct lookup_intent *it)
++{
++      if (!it)
++              return;
++      if (it->it_magic != INTENT_MAGIC)
++              return;
++      if (it->it_op_release)
++              it->it_op_release(it);
++}
++
+ void path_release(struct nameidata *nd)
+ {
++      intent_release(&nd->intent);
+       dput(nd->dentry);
+       mntput(nd->mnt);
+ }
+@@ -359,10 +370,10 @@ void path_release_on_umount(struct namei
+  */
+ void release_open_intent(struct nameidata *nd)
+ {
+-      if (nd->intent.open.file->f_dentry == NULL)
+-              put_filp(nd->intent.open.file);
++      if (nd->intent.file->f_dentry == NULL)
++              put_filp(nd->intent.file);
+       else
+-              fput(nd->intent.open.file);
++              fput(nd->intent.file);
+ }
+ /*
+@@ -440,8 +451,12 @@ static struct dentry * real_lookup(struc
+ {
+       struct dentry * result;
+       struct inode *dir = parent->d_inode;
++      int counter = 0;
+       mutex_lock(&dir->i_mutex);
++again:
++      counter++;
++
+       /*
+        * First re-do the cached lookup just in case it was created
+        * while we waited for the directory semaphore..
+@@ -475,13 +490,16 @@ static struct dentry * real_lookup(struc
+        * Uhhuh! Nasty case: the cache was re-populated while
+        * we waited on the semaphore. Need to revalidate.
+        */
+-      mutex_unlock(&dir->i_mutex);
+       if (result->d_op && result->d_op->d_revalidate) {
+               if (!result->d_op->d_revalidate(result, nd) && !d_invalidate(result)) {
+                       dput(result);
+-                      result = ERR_PTR(-ENOENT);
++                      if (counter > 10)
++                              result = ERR_PTR(-ESTALE);
++                      if (!IS_ERR(result))
++                              goto again;
+               }
+       }
++      mutex_unlock(&dir->i_mutex);
+       return result;
+ }
+@@ -509,7 +527,9 @@ walk_init_root(const char *name, struct 
+ static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *link)
+ {
+       int res = 0;
++      struct lookup_intent it = nd->intent;
+       char *name;
++
+       if (IS_ERR(link))
+               goto fail;
+@@ -519,6 +539,10 @@ static __always_inline int __vfs_follow_
+                       /* weird __emul_prefix() stuff did it */
+                       goto out;
+       }
++      intent_init(&nd->intent, it.it_op);
++      nd->intent.it_flags = it.it_flags;
++      nd->intent.it_create_mode = it.it_create_mode;
++      nd->intent.file = it.file;
+       res = link_path_walk(link, nd);
+ out:
+       if (nd->depth || res || nd->last_type!=LAST_NORM)
+@@ -771,6 +795,33 @@ fail:
+       return PTR_ERR(dentry);
+ }
++static int revalidate_special(struct nameidata *nd)
++{
++      struct dentry *dentry = nd->dentry;
++      int err, counter = 0;
++
++ revalidate_again:
++      if (!dentry->d_op || !dentry->d_op->d_revalidate)
++              return 0;
++      if (!dentry->d_op->d_revalidate(dentry, nd)) {
++              struct dentry *new;
++              if ((err = permission(dentry->d_parent->d_inode, MAY_EXEC, nd)))
++                      return err;
++              new = real_lookup(dentry->d_parent, &dentry->d_name, nd);
++              if (IS_ERR(new))
++                      return PTR_ERR(new);
++              d_invalidate(dentry);
++              dput(dentry);
++              nd->dentry = dentry = new;
++              counter++;
++              if (counter < 10)
++                      goto revalidate_again;
++              printk("excessive revalidate_it loops\n");
++              return -ESTALE;
++      }
++      return 0;
++}
++
+ /*
+  * Name resolution.
+  * This is the basic name resolution function, turning a pathname into
+@@ -867,7 +918,11 @@ static fastcall int __link_path_walk(con
+                       goto out_dput;
+               if (inode->i_op->follow_link) {
++                      int save_flags = nd->flags;
++                      nd->flags |= LOOKUP_LINK_NOTLAST;
+                       err = do_follow_link(&next, nd);
++                      if (!(save_flags & LOOKUP_LINK_NOTLAST))
++                              nd->flags &= ~LOOKUP_LINK_NOTLAST;
+                       if (err)
+                               goto return_err;
+                       err = -ENOENT;
+@@ -902,6 +957,23 @@ last_component:
+                               inode = nd->dentry->d_inode;
+                               /* fallthrough */
+                       case 1:
++                              nd->flags |= LOOKUP_LAST;
++                              err = revalidate_special(nd);
++                              nd->flags &= ~LOOKUP_LAST;
++                              if (!nd->dentry->d_inode)
++                                      err = -ENOENT;
++                              if (err) {
++                                      path_release(nd);
++                                      goto return_err;
++                              }
++                              if (lookup_flags & LOOKUP_DIRECTORY) {
++                                      err = -ENOTDIR;
++                                      if(!nd->dentry->d_inode->i_op ||
++                                        !nd->dentry->d_inode->i_op->lookup) {
++                                              path_release(nd);
++                                              goto return_err;
++                                      }
++                              }
+                               goto return_reval;
+               }
+               if (nd->dentry->d_op && nd->dentry->d_op->d_hash) {
+@@ -909,7 +981,9 @@ last_component:
+                       if (err < 0)
+                               break;
+               }
++              nd->flags |= LOOKUP_LAST;
+               err = do_lookup(nd, &this, &next);
++              nd->flags &= ~LOOKUP_LAST;
+               if (err)
+                       break;
+               inode = next.dentry->d_inode;
+@@ -1152,13 +1226,13 @@ static int __path_lookup_intent_open(int
+       if (filp == NULL)
+               return -ENFILE;
+-      nd->intent.open.file = filp;
+-      nd->intent.open.flags = open_flags;
+-      nd->intent.open.create_mode = create_mode;
++      nd->intent.file = filp;
++      nd->intent.flags = open_flags;
++      nd->intent.create_mode = create_mode;
+       err = do_path_lookup(dfd, name, lookup_flags|LOOKUP_OPEN, nd);
+-      if (IS_ERR(nd->intent.open.file)) {
++      if (IS_ERR(nd->intent.file)) {
+               if (err == 0) {
+-                      err = PTR_ERR(nd->intent.open.file);
++                      err = PTR_ERR(nd->intent.file);
+                       path_release(nd);
+               }
+       } else if (err != 0)
+@@ -1261,7 +1335,7 @@ static struct dentry *lookup_hash(struct
+ }
+ /* SMP-safe */
+-struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
++struct dentry * lookup_one_len_it(const char * name, struct dentry * base, int len, struct nameidata *nd)
+ {
+       unsigned long hash;
+       struct qstr this;
+@@ -1281,11 +1355,17 @@ struct dentry * lookup_one_len(const cha
+       }
+       this.hash = end_name_hash(hash);
+-      return __lookup_hash(&this, base, NULL);
++      return __lookup_hash(&this, base, nd);
+ access:
+       return ERR_PTR(-EACCES);
+ }
++struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
++{
++      return lookup_one_len_it(name, base, len, NULL);
++}
++
++
+ /*
+  *    namei()
+  *
+@@ -1297,8 +1377,9 @@ access:
+  * that namei follows links, while lnamei does not.
+  * SMP-safe
+  */
+-int fastcall __user_walk_fd(int dfd, const char __user *name, unsigned flags,
+-                          struct nameidata *nd)
++
++int fastcall __user_walk_fd_it(int dfd, const char __user *name, unsigned flags,
++                             struct nameidata *nd)
+ {
+       char *tmp = getname(name);
+       int err = PTR_ERR(tmp);
+@@ -1310,9 +1391,22 @@ int fastcall __user_walk_fd(int dfd, con
+       return err;
+ }
++int fastcall __user_walk_fd(int dfd, const char __user *name, unsigned flags,
++                          struct nameidata *nd)
++{
++      intent_init(&nd->intent, IT_LOOKUP);
++      return __user_walk_fd_it(dfd, name, flags, nd);
++}
++
++int fastcall __user_walk_it(const char __user *name, unsigned flags, struct nameidata *nd)
++{
++      return __user_walk_fd_it(AT_FDCWD, name, flags, nd);
++}
++
+ int fastcall __user_walk(const char __user *name, unsigned flags, struct nameidata *nd)
+ {
+-      return __user_walk_fd(AT_FDCWD, name, flags, nd);
++      intent_init(&nd->intent, IT_LOOKUP);
++      return __user_walk_it(name, flags, nd);
+ }
+ /*
+@@ -1593,6 +1687,8 @@ int open_namei(int dfd, const char *path
+       if (flag & O_APPEND)
+               acc_mode |= MAY_APPEND;
++      nd->intent.it_flags = flag;
++      nd->intent.it_create_mode = mode;
+       /*
+        * The simplest case - just a plain lookup.
+        */
+@@ -1607,6 +1703,7 @@ int open_namei(int dfd, const char *path
+       /*
+        * Create - we need to know the parent.
+        */
++      nd->intent.it_op |= IT_CREAT;
+       error = path_lookup_create(dfd,pathname,LOOKUP_PARENT,nd,flag,mode);
+       if (error)
+               return error;
+@@ -1623,7 +1720,9 @@ int open_namei(int dfd, const char *path
+       dir = nd->dentry;
+       nd->flags &= ~LOOKUP_PARENT;
+       mutex_lock(&dir->d_inode->i_mutex);
++      nd->flags |= LOOKUP_LAST;
+       path.dentry = lookup_hash(nd);
++      nd->flags &= ~LOOKUP_LAST;
+       path.mnt = nd->mnt;
+ do_last:
+@@ -1633,9 +1732,9 @@ do_last:
+               goto exit;
+       }
+-      if (IS_ERR(nd->intent.open.file)) {
++      if (IS_ERR(nd->intent.file)) {
+               mutex_unlock(&dir->d_inode->i_mutex);
+-              error = PTR_ERR(nd->intent.open.file);
++              error = PTR_ERR(nd->intent.file);
+               goto exit_dput;
+       }
+@@ -1688,7 +1787,7 @@ ok:
+ exit_dput:
+       dput_path(&path, nd);
+ exit:
+-      if (!IS_ERR(nd->intent.open.file))
++      if (!IS_ERR(nd->intent.file))
+               release_open_intent(nd);
+       path_release(nd);
+       return error;
+@@ -1731,7 +1830,9 @@ do_link:
+       }
+       dir = nd->dentry;
+       mutex_lock(&dir->d_inode->i_mutex);
++      nd->flags |= LOOKUP_LAST;
+       path.dentry = lookup_hash(nd);
++      nd->flags &= ~LOOKUP_LAST;
+       path.mnt = nd->mnt;
+       __putname(nd->last.name);
+       goto do_last;
+@@ -2243,6 +2344,9 @@ asmlinkage long sys_linkat(int olddfd, c
+       int error;
+       char * to;
++      intent_init(&nd.intent, IT_LOOKUP);
++      intent_init(&old_nd.intent, IT_LOOKUP);
++
+       if ((flags & ~AT_SYMLINK_FOLLOW) != 0)
+               return -EINVAL;
+@@ -2250,7 +2354,7 @@ asmlinkage long sys_linkat(int olddfd, c
+       if (IS_ERR(to))
+               return PTR_ERR(to);
+-      error = __user_walk_fd(olddfd, oldname,
++      error = __user_walk_fd_it(olddfd, oldname,
+                              flags & AT_SYMLINK_FOLLOW ? LOOKUP_FOLLOW : 0,
+                              &old_nd);
+       if (error)
+Index: linux-2.6/fs/stat.c
+===================================================================
+--- linux-2.6.orig/fs/stat.c   2006-07-15 21:04:02.000000000 +0800
++++ linux-2.6/fs/stat.c        2006-07-15 21:04:08.000000000 +0800
+@@ -37,7 +37,7 @@ void generic_fillattr(struct inode *inod
+ EXPORT_SYMBOL(generic_fillattr);
+-int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
++int vfs_getattr_it(struct vfsmount *mnt, struct dentry *dentry, struct lookup_intent *it, struct kstat *stat)
+ {
+       struct inode *inode = dentry->d_inode;
+       int retval;
+@@ -46,6 +46,8 @@ int vfs_getattr(struct vfsmount *mnt, st
+       if (retval)
+               return retval;
++      if (inode->i_op->getattr_it)
++              return inode->i_op->getattr_it(mnt, dentry, it, stat);
+       if (inode->i_op->getattr)
+               return inode->i_op->getattr(mnt, dentry, stat);
+@@ -60,6 +62,11 @@ int vfs_getattr(struct vfsmount *mnt, st
+       return 0;
+ }
++int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
++{
++      return vfs_getattr_it(mnt, dentry, NULL, stat);
++}
++
+ EXPORT_SYMBOL(vfs_getattr);
+ int vfs_stat_fd(int dfd, char __user *name, struct kstat *stat)
+@@ -67,9 +74,10 @@ int vfs_stat_fd(int dfd, char __user *na
+       struct nameidata nd;
+       int error;
+-      error = __user_walk_fd(dfd, name, LOOKUP_FOLLOW, &nd);
++      intent_init(&nd.intent, IT_GETATTR);
++      error = __user_walk_fd_it(dfd, name, LOOKUP_FOLLOW, &nd);
+       if (!error) {
+-              error = vfs_getattr(nd.mnt, nd.dentry, stat);
++              error = vfs_getattr_it(nd.mnt, nd.dentry, &nd.intent, stat);
+               path_release(&nd);
+       }
+       return error;
+@@ -87,9 +95,10 @@ int vfs_lstat_fd(int dfd, char __user *n
+       struct nameidata nd;
+       int error;
+-      error = __user_walk_fd(dfd, name, 0, &nd);
++      intent_init(&nd.intent, IT_GETATTR);
++      error = __user_walk_fd_it(dfd, name, 0, &nd);
+       if (!error) {
+-              error = vfs_getattr(nd.mnt, nd.dentry, stat);
++              error = vfs_getattr_it(nd.mnt, nd.dentry, &nd.intent, stat);
+               path_release(&nd);
+       }
+       return error;
+@@ -106,9 +115,12 @@ int vfs_fstat(unsigned int fd, struct ks
+ {
+       struct file *f = fget(fd);
+       int error = -EBADF;
++      struct nameidata nd;
++      intent_init(&nd.intent, IT_GETATTR);
+       if (f) {
+-              error = vfs_getattr(f->f_vfsmnt, f->f_dentry, stat);
++              error = vfs_getattr_it(f->f_vfsmnt, f->f_dentry, &nd.intent, stat);
++              intent_release(&nd.intent);
+               fput(f);
+       }
+       return error;
+Index: linux-2.6/fs/namespace.c
+===================================================================
+--- linux-2.6.orig/fs/namespace.c      2006-07-15 21:04:02.000000000 +0800
++++ linux-2.6/fs/namespace.c   2006-07-15 21:04:08.000000000 +0800
+@@ -73,6 +73,7 @@ struct vfsmount *alloc_vfsmnt(const char
+               INIT_LIST_HEAD(&mnt->mnt_share);
+               INIT_LIST_HEAD(&mnt->mnt_slave_list);
+               INIT_LIST_HEAD(&mnt->mnt_slave);
++              INIT_LIST_HEAD(&mnt->mnt_lustre_list);
+               if (name) {
+                       int size = strlen(name) + 1;
+                       char *newname = kmalloc(size, GFP_KERNEL);
+@@ -162,6 +163,7 @@ static void __touch_namespace(struct nam
+ static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd)
+ {
++      memset(old_nd, 0, sizeof(*old_nd));
+       old_nd->dentry = mnt->mnt_mountpoint;
+       old_nd->mnt = mnt->mnt_parent;
+       mnt->mnt_parent = mnt;
+@@ -280,6 +282,9 @@ static inline void __mntput(struct vfsmo
+ {
+       struct super_block *sb = mnt->mnt_sb;
+       dput(mnt->mnt_root);
++      spin_lock(&dcache_lock);
++      list_del(&mnt->mnt_lustre_list);
++      spin_unlock(&dcache_lock);
+       free_vfsmnt(mnt);
+       deactivate_super(sb);
+ }
+@@ -582,6 +587,8 @@ static int do_umount(struct vfsmount *mn
+        */
+       lock_kernel();
++      if (sb->s_op->umount_lustre)
++              sb->s_op->umount_lustre(sb);
+       if (sb->s_op->umount_begin)
+               sb->s_op->umount_begin(mnt, flags);
+       unlock_kernel();
+@@ -914,6 +921,7 @@ static int do_loopback(struct nameidata 
+               return err;
+       if (!old_name || !*old_name)
+               return -EINVAL;
++      intent_init(&old_nd.intent, IT_LOOKUP);
+       err = path_lookup(old_name, LOOKUP_FOLLOW, &old_nd);
+       if (err)
+               return err;
+@@ -999,6 +1007,7 @@ static int do_move_mount(struct nameidat
+               return -EPERM;
+       if (!old_name || !*old_name)
+               return -EINVAL;
++      intent_init(&old_nd.intent, IT_LOOKUP);
+       err = path_lookup(old_name, LOOKUP_FOLLOW, &old_nd);
+       if (err)
+               return err;
+@@ -1388,6 +1397,7 @@ long do_mount(char *dev_name, char *dir_
+       int retval = 0;
+       int mnt_flags = 0;
++      intent_init(&nd.intent, IT_LOOKUP);
+       /* Discard magic */
+       if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
+               flags &= ~MS_MGC_MSK;
+Index: linux-2.6/fs/exec.c
+===================================================================
+--- linux-2.6.orig/fs/exec.c   2006-07-15 21:04:02.000000000 +0800
++++ linux-2.6/fs/exec.c        2006-07-15 21:04:08.000000000 +0800
+@@ -127,6 +127,7 @@ asmlinkage long sys_uselib(const char __
+       struct nameidata nd;
+       int error;
++      intent_init(&nd.intent, IT_OPEN);
+       error = __user_path_lookup_open(library, LOOKUP_FOLLOW, &nd, FMODE_READ|FMODE_EXEC);
+       if (error)
+               goto out;
+@@ -477,6 +478,7 @@ struct file *open_exec(const char *name)
+       int err;
+       struct file *file;
++      intent_init(&nd.intent, IT_OPEN);
+       err = path_lookup_open(AT_FDCWD, name, LOOKUP_FOLLOW, &nd, FMODE_READ|FMODE_EXEC);
+       file = ERR_PTR(err);
+Index: linux-2.6/include/linux/dcache.h
+===================================================================
+--- linux-2.6.orig/include/linux/dcache.h      2006-07-15 21:04:02.000000000 +0800
++++ linux-2.6/include/linux/dcache.h   2006-07-15 21:04:08.000000000 +0800
+@@ -4,6 +4,7 @@
+ #ifdef __KERNEL__
+ #include <asm/atomic.h>
++#include <linux/string.h>
+ #include <linux/list.h>
+ #include <linux/spinlock.h>
+ #include <linux/cache.h>
+@@ -36,6 +37,8 @@ struct qstr {
+       const unsigned char *name;
+ };
++#include <linux/namei.h>
++
+ struct dentry_stat_t {
+       int nr_dentry;
+       int nr_unused;
+Index: linux-2.6/include/linux/fs.h
+===================================================================
+--- linux-2.6.orig/include/linux/fs.h  2006-07-15 21:04:02.000000000 +0800
++++ linux-2.6/include/linux/fs.h       2006-07-15 21:04:08.000000000 +0800
+@@ -280,6 +280,8 @@ typedef void (dio_iodone_t)(struct kiocb
+ #define ATTR_KILL_SUID        2048
+ #define ATTR_KILL_SGID        4096
+ #define ATTR_FILE     8192
++#define ATTR_RAW              16384    /* file system, not vfs will massage attrs */
++#define ATTR_FROM_OPEN        32768    /* called from open path, ie O_TRUNC */
+ /*
+  * This is the Inode Attributes structure, used for notify_change().  It
+@@ -533,6 +535,7 @@ struct inode {
+       struct block_device     *i_bdev;
+       struct cdev             *i_cdev;
+       int                     i_cindex;
++      void                    *i_filterdata;
+       __u32                   i_generation;
+@@ -699,6 +702,7 @@ struct file {
+       spinlock_t              f_ep_lock;
+ #endif /* #ifdef CONFIG_EPOLL */
+       struct address_space    *f_mapping;
++      struct lookup_intent    *f_it;
+ };
+ extern spinlock_t files_lock;
+ #define file_list_lock() spin_lock(&files_lock);
+@@ -1099,7 +1103,9 @@ struct inode_operations {
+       void (*truncate) (struct inode *);
+       int (*permission) (struct inode *, int, struct nameidata *);
+       int (*setattr) (struct dentry *, struct iattr *);
++      int (*setattr_raw) (struct inode *, struct iattr *);
+       int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
++      int (*getattr_it) (struct vfsmount *, struct dentry *, struct lookup_intent *, struct kstat *);
+       int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
+       ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
+       ssize_t (*listxattr) (struct dentry *, char *, size_t);
+@@ -1140,6 +1146,7 @@ struct super_operations {
+       int (*remount_fs) (struct super_block *, int *, char *);
+       void (*clear_inode) (struct inode *);
+       void (*umount_begin) (struct vfsmount *, int);
++      void (*umount_lustre) (struct super_block *);
+       int (*show_options)(struct seq_file *, struct vfsmount *);
+       int (*show_stats)(struct seq_file *, struct vfsmount *);
+@@ -1362,6 +1369,7 @@ extern int may_umount_tree(struct vfsmou
+ extern int may_umount(struct vfsmount *);
+ extern void umount_tree(struct vfsmount *, int, struct list_head *);
+ extern void release_mounts(struct list_head *);
++struct vfsmount *do_kern_mount(const char *type, int flags, const char *name, void *data);
+ extern long do_mount(char *, char *, char *, unsigned long, void *);
+ extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int);
+ extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *,
+@@ -1423,6 +1431,7 @@ extern long do_sys_open(int fdf, const c
+                       int mode);
+ extern struct file *filp_open(const char *, int, int);
+ extern struct file * dentry_open(struct dentry *, struct vfsmount *, int);
++extern struct file * dentry_open_it(struct dentry *, struct vfsmount *, int, struct lookup_intent *);
+ extern int filp_close(struct file *, fl_owner_t id);
+ extern char * getname(const char __user *);
+Index: linux-2.6/include/linux/namei.h
+===================================================================
+--- linux-2.6.orig/include/linux/namei.h       2006-07-15 21:04:02.000000000 +0800
++++ linux-2.6/include/linux/namei.h    2006-07-15 21:04:08.000000000 +0800
+@@ -5,10 +5,39 @@
+ struct vfsmount;
++#define IT_OPEN                (1)
++#define IT_CREAT       (1<<1)
++#define IT_READDIR     (1<<2)
++#define IT_GETATTR     (1<<3)
++#define IT_LOOKUP      (1<<4)
++#define IT_UNLINK      (1<<5)
++#define IT_TRUNC       (1<<6)
++#define IT_GETXATTR    (1<<7)
++
++struct lustre_intent_data {
++      int     it_disposition;
++      int     it_status;
++      __u64   it_lock_handle;
++      void    *it_data;
++      int     it_lock_mode;
++};
++
++#define INTENT_MAGIC 0x19620323
++
++#define it_flags flags
++#define it_create_mode create_mode
++#define lookup_intent open_intent
++
+ struct open_intent {
+-      int     flags;
+-      int     create_mode;
+-      struct file *file;
++              int     it_magic;
++              void    (*it_op_release)(struct open_intent *);
++              int     it_op;
++              int     flags;
++              int     create_mode;
++      struct  file *file;
++              union {
++                struct lustre_intent_data lustre;
++              } d;
+ };
+ enum { MAX_NESTED_LINKS = 5 };
+@@ -22,12 +51,16 @@ struct nameidata {
+       unsigned        depth;
+       char *saved_names[MAX_NESTED_LINKS + 1];
+-      /* Intent data */
+-      union {
+-              struct open_intent open;
+-      } intent;
++      struct lookup_intent intent;
+ };
++static inline void intent_init(struct lookup_intent *it, int op)
++{
++      memset(it, 0, sizeof(*it));
++      it->it_magic = INTENT_MAGIC;
++      it->it_op = op;
++}
++
+ /*
+  * Type of the last component on LOOKUP_PARENT
+  */
+@@ -48,6 +81,8 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LA
+ #define LOOKUP_PARENT         16
+ #define LOOKUP_NOALT          32
+ #define LOOKUP_REVAL          64
++#define LOOKUP_LAST           (0x1000)
++#define LOOKUP_LINK_NOTLAST   (0x2000)
+ /*
+  * Intent data
+  */
+@@ -57,10 +92,19 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LA
+ extern int FASTCALL(__user_walk(const char __user *, unsigned, struct nameidata *));
+ extern int FASTCALL(__user_walk_fd(int dfd, const char __user *, unsigned, struct nameidata *));
++extern int FASTCALL(__user_walk_fd_it(int dfd, const char __user *, unsigned, struct nameidata *));
+ #define user_path_walk(name,nd) \
+       __user_walk_fd(AT_FDCWD, name, LOOKUP_FOLLOW, nd)
+ #define user_path_walk_link(name,nd) \
+       __user_walk_fd(AT_FDCWD, name, 0, nd)
++
++extern int FASTCALL(__user_walk_it(const char __user *name, unsigned flags, struct nameidata *nd));
++#define user_path_walk_it(name,nd) \
++      __user_walk_it(name, LOOKUP_FOLLOW, nd)
++#define user_path_walk_link_it(name,nd) \
++      __user_walk_it(name, 0, nd)
++extern void intent_release(struct lookup_intent *);
++
+ extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *));
+ extern int FASTCALL(path_walk(const char *, struct nameidata *));
+ extern int FASTCALL(link_path_walk(const char *, struct nameidata *));
+Index: linux-2.6/include/linux/mount.h
+===================================================================
+--- linux-2.6.orig/include/linux/mount.h       2006-07-15 21:04:02.000000000 +0800
++++ linux-2.6/include/linux/mount.h    2006-07-15 21:04:08.000000000 +0800
+@@ -53,6 +53,8 @@ struct vfsmount {
+       struct list_head mnt_slave;     /* slave list entry */
+       struct vfsmount *mnt_master;    /* slave is on master->mnt_slave_list */
+       struct namespace *mnt_namespace; /* containing namespace */
++      struct list_head mnt_lustre_list; /* GNS mount list */
++      unsigned long mnt_last_used;    /* for GNS auto-umount (jiffies) */
+       int mnt_pinned;
+ };
diff --git a/lustre/kernel_patches/patches/vfs_nointent-2.6-fc5.patch b/lustre/kernel_patches/patches/vfs_nointent-2.6-fc5.patch
new file mode 100644 (file)
index 0000000..35e0138
--- /dev/null
@@ -0,0 +1,472 @@
+Index: linux-2.6.16.i686/net/unix/af_unix.c
+===================================================================
+--- linux-2.6.16.i686.orig/net/unix/af_unix.c  2006-03-20 13:53:29.000000000 +0800
++++ linux-2.6.16.i686/net/unix/af_unix.c       2006-05-30 22:27:40.000000000 +0800
+@@ -673,6 +673,7 @@
+       int err = 0;
+       
+       if (sunname->sun_path[0]) {
++              intent_init(&nd.intent, IT_LOOKUP);
+               err = path_lookup(sunname->sun_path, LOOKUP_FOLLOW, &nd);
+               if (err)
+                       goto fail;
+Index: linux-2.6.16.i686/fs/open.c
+===================================================================
+--- linux-2.6.16.i686.orig/fs/open.c   2006-05-30 22:10:06.000000000 +0800
++++ linux-2.6.16.i686/fs/open.c        2006-05-30 22:27:40.000000000 +0800
+@@ -197,9 +197,10 @@
+ }
+ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
+-      struct file *filp)
++      struct file *filp, int called_from_open)
+ {
+       int err;
++      struct inode_operations *op = dentry->d_inode->i_op;
+       struct iattr newattrs;
+       /* Not pretty: "inode->i_size" shouldn't really be signed. But it is. */
+@@ -214,7 +215,17 @@
+       }
+       mutex_lock(&dentry->d_inode->i_mutex);
+-      err = notify_change(dentry, &newattrs);
++      if (called_from_open)
++                newattrs.ia_valid |= ATTR_FROM_OPEN;
++        if (op->setattr_raw) {
++                newattrs.ia_valid |= ATTR_RAW;
++                newattrs.ia_ctime = CURRENT_TIME;
++                down_write(&dentry->d_inode->i_alloc_sem);
++                err = op->setattr_raw(dentry->d_inode, &newattrs);
++                up_write(&dentry->d_inode->i_alloc_sem);
++        } else
++                err = notify_change(dentry, &newattrs);
++
+       mutex_unlock(&dentry->d_inode->i_mutex);
+       return err;
+ }
+@@ -269,7 +280,7 @@
+       error = locks_verify_truncate(inode, NULL, length);
+       if (!error) {
+               DQUOT_INIT(inode);
+-              error = do_truncate(nd.dentry, length, 0, NULL);
++              error = do_truncate(nd.dentry, length, 0, NULL, 0);
+       }
+       put_write_access(inode);
+@@ -321,7 +332,7 @@
+       error = locks_verify_truncate(inode, file, length);
+       if (!error)
+-              error = do_truncate(dentry, length, 0, file);
++              error = do_truncate(dentry, length, 0, file, 0);
+ out_putf:
+       fput(file);
+ out:
+@@ -406,9 +417,20 @@
+                   (error = vfs_permission(&nd, MAY_WRITE)) != 0)
+                       goto dput_and_out;
+       }
+-      mutex_lock(&inode->i_mutex);
+-      error = notify_change(nd.dentry, &newattrs);
+-      mutex_unlock(&inode->i_mutex);
++      if (inode->i_op->setattr_raw) {
++              struct inode_operations *op = nd.dentry->d_inode->i_op;
++ 
++              newattrs.ia_valid |= ATTR_RAW;
++              error = op->setattr_raw(inode, &newattrs);
++              /* the file system wants to use normal vfs path now */
++              if (error != -EOPNOTSUPP)
++                      goto dput_and_out;
++      } else {
++              mutex_lock(&inode->i_mutex);
++              error = notify_change(nd.dentry, &newattrs);
++              mutex_unlock(&inode->i_mutex);
++      }
++
+ dput_and_out:
+       path_release(&nd);
+ out:
+@@ -623,77 +645,74 @@
+ }
+ EXPORT_SYMBOL_GPL(sys_chroot);
+-
+-asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
++  
++int chmod_common(struct dentry *dentry, mode_t mode)
+ {
+-      struct inode * inode;
+-      struct dentry * dentry;
+-      struct file * file;
+-      int err = -EBADF;
+-      struct iattr newattrs;
+-
+-      file = fget(fd);
+-      if (!file)
+-              goto out;
+-
+-      dentry = file->f_dentry;
+-      inode = dentry->d_inode;
+-
+-      err = -EROFS;
+-      if (IS_RDONLY(inode))
+-              goto out_putf;
+-      err = -EPERM;
+-      if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+-              goto out_putf;
++      struct inode * inode = dentry->d_inode;
++      struct iattr newattrs;
++      int error = -EROFS;
++  
++      if (IS_RDONLY(inode))
++              goto out;
++      
++      if (inode->i_op->setattr_raw) {
++              struct inode_operations *op = dentry->d_inode->i_op;
++ 
++              newattrs.ia_mode = mode;
++              newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
++              newattrs.ia_valid |= ATTR_RAW;
++              error = op->setattr_raw(inode, &newattrs);
++              /* the file system wants to use normal vfs path now */
++              if (error != -EOPNOTSUPP)
++                      goto out;
++      }
++  
++      error = -EPERM;
++      if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
++              goto out;
++ 
+       mutex_lock(&inode->i_mutex);
+-      if (mode == (mode_t) -1)
+-              mode = inode->i_mode;
+-      newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
+-      newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
+-      err = notify_change(dentry, &newattrs);
++      if (mode == (mode_t) -1)
++              mode = inode->i_mode;
++      newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
++      newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
++      error = notify_change(dentry, &newattrs);
+       mutex_unlock(&inode->i_mutex);
++out:
++      return error;
++}
+-out_putf:
+-      fput(file);
++asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
++{
++      struct file * file;
++      int err = -EBADF;
++ 
++      file = fget(fd);
++      if (!file)
++              goto out;
++ 
++      err = chmod_common(file->f_dentry, mode);
++      fput(file);
+ out:
+-      return err;
++      return err;
+ }
+ asmlinkage long sys_fchmodat(int dfd, const char __user *filename,
+                            mode_t mode)
+ {
+       struct nameidata nd;
+-      struct inode * inode;
+       int error;
+-      struct iattr newattrs;
+       error = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &nd);
+       if (error)
+               goto out;
+-      inode = nd.dentry->d_inode;
+-
+-      error = -EROFS;
+-      if (IS_RDONLY(inode))
+-              goto dput_and_out;
+-
+-      error = -EPERM;
+-      if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+-              goto dput_and_out;
+-
+-      mutex_lock(&inode->i_mutex);
+-      if (mode == (mode_t) -1)
+-              mode = inode->i_mode;
+-      newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
+-      newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
+-      error = notify_change(nd.dentry, &newattrs);
+-      mutex_unlock(&inode->i_mutex);
+-
+-dput_and_out:
+-      path_release(&nd);
++      error = chmod_common(nd.dentry, mode);
++      path_release(&nd);
+ out:
+-      return error;
++      return error;
+ }
++
+ asmlinkage long sys_chmod(const char __user *filename, mode_t mode)
+ {
+       return sys_fchmodat(AT_FDCWD, filename, mode);
+@@ -714,6 +733,18 @@
+       if (IS_RDONLY(inode))
+               goto out;
+       error = -EPERM;
++      if (inode->i_op->setattr_raw) {
++              struct inode_operations *op = dentry->d_inode->i_op;
++
++              newattrs.ia_uid = user;
++              newattrs.ia_gid = group;
++              newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME;
++              newattrs.ia_valid |= ATTR_RAW;
++              error = op->setattr_raw(inode, &newattrs);
++              /* the file system wants to use normal vfs path now */
++              if (error != -EOPNOTSUPP)
++                      return error;
++      }
+       if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+               goto out;
+       newattrs.ia_valid =  ATTR_CTIME;
+Index: linux-2.6.16.i686/fs/namei.c
+===================================================================
+--- linux-2.6.16.i686.orig/fs/namei.c  2006-05-30 22:24:53.000000000 +0800
++++ linux-2.6.16.i686/fs/namei.c       2006-05-30 22:27:51.000000000 +0800
+@@ -1644,7 +1644,7 @@
+               if (!error) {
+                       DQUOT_INIT(inode);
+                       
+-                      error = do_truncate(dentry, 0, ATTR_MTIME|ATTR_CTIME, NULL);
++                      error = do_truncate(dentry, 0, ATTR_MTIME|ATTR_CTIME, NULL, 1);
+               }
+               put_write_access(inode);
+               if (error)
+@@ -1912,6 +1912,7 @@
+       char * tmp;
+       struct dentry * dentry;
+       struct nameidata nd;
++      intent_init(&nd.intent, IT_LOOKUP);
+       if (S_ISDIR(mode))
+               return -EPERM;
+@@ -1922,6 +1923,15 @@
+       error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd);
+       if (error)
+               goto out;
++
++      if (nd.dentry->d_inode->i_op->mknod_raw) {
++              struct inode_operations *op = nd.dentry->d_inode->i_op;
++              error = op->mknod_raw(&nd, mode, dev);
++              /* the file system wants to use normal vfs path now */
++              if (error != -EOPNOTSUPP)
++                      goto out2;
++      }
++
+       dentry = lookup_create(&nd, 0);
+       error = PTR_ERR(dentry);
+@@ -1948,6 +1958,7 @@
+               dput(dentry);
+       }
+       mutex_unlock(&nd.dentry->d_inode->i_mutex);
++out2:
+       path_release(&nd);
+ out:
+       putname(tmp);
+@@ -1993,9 +2004,18 @@
+               struct dentry *dentry;
+               struct nameidata nd;
++              intent_init(&nd.intent, IT_LOOKUP);
+               error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd);
+               if (error)
+                       goto out;
++              if (nd.dentry->d_inode->i_op->mkdir_raw) {
++                      struct inode_operations *op = nd.dentry->d_inode->i_op;
++                      error = op->mkdir_raw(&nd, mode);
++                      /* the file system wants to use normal vfs path now */
++                      if (error != -EOPNOTSUPP)
++                              goto out2;
++              }
++
+               dentry = lookup_create(&nd, 1);
+               error = PTR_ERR(dentry);
+               if (!IS_ERR(dentry)) {
+@@ -2005,6 +2025,7 @@
+                       dput(dentry);
+               }
+               mutex_unlock(&nd.dentry->d_inode->i_mutex);
++out2:
+               path_release(&nd);
+ out:
+               putname(tmp);
+@@ -2085,6 +2106,7 @@
+       char * name;
+       struct dentry *dentry;
+       struct nameidata nd;
++      intent_init(&nd.intent, IT_LOOKUP);
+       name = getname(pathname);
+       if(IS_ERR(name))
+@@ -2105,6 +2127,14 @@
+                       error = -EBUSY;
+                       goto exit1;
+       }
++      if (nd.dentry->d_inode->i_op->rmdir_raw) {
++                struct inode_operations *op = nd.dentry->d_inode->i_op;
++
++                error = op->rmdir_raw(&nd);
++                /* the file system wants to use normal vfs path now */
++                if (error != -EOPNOTSUPP)
++                        goto exit1;
++        }
+       mutex_lock(&nd.dentry->d_inode->i_mutex);
+       dentry = lookup_hash(&nd);
+       error = PTR_ERR(dentry);
+@@ -2168,6 +2198,7 @@
+       struct dentry *dentry;
+       struct nameidata nd;
+       struct inode *inode = NULL;
++      intent_init(&nd.intent, IT_LOOKUP);
+       name = getname(pathname);
+       if(IS_ERR(name))
+@@ -2179,6 +2210,13 @@
+       error = -EISDIR;
+       if (nd.last_type != LAST_NORM)
+               goto exit1;
++      if (nd.dentry->d_inode->i_op->unlink_raw) {
++              struct inode_operations *op = nd.dentry->d_inode->i_op;
++              error = op->unlink_raw(&nd);
++                /* the file system wants to use normal vfs path now */
++              if (error != -EOPNOTSUPP)
++                       goto exit1;
++        }
+       mutex_lock(&nd.dentry->d_inode->i_mutex);
+       dentry = lookup_hash(&nd);
+       error = PTR_ERR(dentry);
+@@ -2261,9 +2299,17 @@
+               struct dentry *dentry;
+               struct nameidata nd;
++              intent_init(&nd.intent, IT_LOOKUP);
+               error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd);
+               if (error)
+                       goto out;
++              if (nd.dentry->d_inode->i_op->symlink_raw) {
++                      struct inode_operations *op = nd.dentry->d_inode->i_op;
++                      error = op->symlink_raw(&nd, from);
++                      /* the file system wants to use normal vfs path now */
++                      if (error != -EOPNOTSUPP)
++                              goto out2;
++              }
+               dentry = lookup_create(&nd, 0);
+               error = PTR_ERR(dentry);
+               if (!IS_ERR(dentry)) {
+@@ -2271,6 +2317,7 @@
+                       dput(dentry);
+               }
+               mutex_unlock(&nd.dentry->d_inode->i_mutex);
++out2:         
+               path_release(&nd);
+ out:
+               putname(to);
+@@ -2358,6 +2405,13 @@
+       error = -EXDEV;
+       if (old_nd.mnt != nd.mnt)
+               goto out_release;
++      if (nd.dentry->d_inode->i_op->link_raw) {
++              struct inode_operations *op = nd.dentry->d_inode->i_op;
++              error = op->link_raw(&old_nd, &nd);
++              /* the file system wants to use normal vfs path now */
++              if (error != -EOPNOTSUPP)
++                      goto out_release;
++      }
+       new_dentry = lookup_create(&nd, 0);
+       error = PTR_ERR(new_dentry);
+       if (!IS_ERR(new_dentry)) {
+@@ -2534,6 +2588,8 @@
+       struct dentry * old_dentry, *new_dentry;
+       struct dentry * trap;
+       struct nameidata oldnd, newnd;
++      intent_init(&oldnd.intent, IT_LOOKUP);
++      intent_init(&newnd.intent, IT_LOOKUP);
+       error = do_path_lookup(olddfd, oldname, LOOKUP_PARENT, &oldnd);
+       if (error)
+@@ -2556,6 +2612,13 @@
+       if (newnd.last_type != LAST_NORM)
+               goto exit2;
++      if (old_dir->d_inode->i_op->rename_raw) {
++              error = old_dir->d_inode->i_op->rename_raw(&oldnd, &newnd);
++              /* the file system wants to use normal vfs path now */
++              if (error != -EOPNOTSUPP)
++                      goto exit2;
++      }
++
+       trap = lock_rename(new_dir, old_dir);
+       old_dentry = lookup_hash(&oldnd);
+@@ -2587,8 +2650,7 @@
+       if (new_dentry == trap)
+               goto exit5;
+-      error = vfs_rename(old_dir->d_inode, old_dentry,
+-                                 new_dir->d_inode, new_dentry);
++      error = vfs_rename(old_dir->d_inode, old_dentry, new_dir->d_inode, new_dentry);
+ exit5:
+       dput(new_dentry);
+ exit4:
+Index: linux-2.6.16.i686/fs/exec.c
+===================================================================
+--- linux-2.6.16.i686.orig/fs/exec.c   2006-05-30 21:33:00.000000000 +0800
++++ linux-2.6.16.i686/fs/exec.c        2006-05-30 22:27:40.000000000 +0800
+@@ -1517,7 +1517,7 @@
+               goto close_fail;
+       if (!file->f_op->write)
+               goto close_fail;
+-      if (do_truncate(file->f_dentry, 0, 0, file) != 0)
++      if (do_truncate(file->f_dentry, 0, 0, file, 0) != 0)
+               goto close_fail;
+       retval = binfmt->core_dump(signr, regs, file);
+Index: linux-2.6.16.i686/include/linux/fs.h
+===================================================================
+--- linux-2.6.16.i686.orig/include/linux/fs.h  2006-05-30 21:33:00.000000000 +0800
++++ linux-2.6.16.i686/include/linux/fs.h       2006-05-30 22:27:40.000000000 +0800
+@@ -1035,13 +1035,20 @@
+       int (*create) (struct inode *,struct dentry *,int, struct nameidata *);
+       struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
+       int (*link) (struct dentry *,struct inode *,struct dentry *);
++      int (*link_raw) (struct nameidata *,struct nameidata *);
+       int (*unlink) (struct inode *,struct dentry *);
++      int (*unlink_raw) (struct nameidata *);
+       int (*symlink) (struct inode *,struct dentry *,const char *);
++      int (*symlink_raw) (struct nameidata *,const char *);
+       int (*mkdir) (struct inode *,struct dentry *,int);
++      int (*mkdir_raw) (struct nameidata *,int);
+       int (*rmdir) (struct inode *,struct dentry *);
++      int (*rmdir_raw) (struct nameidata *);
+       int (*mknod) (struct inode *,struct dentry *,int,dev_t);
++      int (*mknod_raw) (struct nameidata *,int,dev_t);
+       int (*rename) (struct inode *, struct dentry *,
+                       struct inode *, struct dentry *);
++      int (*rename_raw) (struct nameidata *, struct nameidata *);
+       int (*readlink) (struct dentry *, char __user *,int);
+       void * (*follow_link) (struct dentry *, struct nameidata *);
+       void (*put_link) (struct dentry *, struct nameidata *, void *);
+@@ -1351,7 +1358,7 @@
+ /* fs/open.c */
+ extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs,
+-                     struct file *filp);
++                     struct file *filp, int called_from_open);
+ extern long do_sys_open(int fdf, const char __user *filename, int flags,
+                       int mode);
+ extern struct file *filp_open(const char *, int, int);
diff --git a/lustre/kernel_patches/patches/vfs_nointent-2.6-sles10.patch b/lustre/kernel_patches/patches/vfs_nointent-2.6-sles10.patch
new file mode 100644 (file)
index 0000000..aba3c8b
--- /dev/null
@@ -0,0 +1,453 @@
+Index: linux-2.6.16.21-0.8/net/unix/af_unix.c
+===================================================================
+--- linux-2.6.16.21-0.8.orig/net/unix/af_unix.c        2006-08-03 01:34:33.000000000 -0600
++++ linux-2.6.16.21-0.8/net/unix/af_unix.c     2006-08-03 01:35:38.000000000 -0600
+@@ -673,6 +673,7 @@
+       int err = 0;
+       
+       if (sunname->sun_path[0]) {
++              intent_init(&nd.intent, IT_LOOKUP);
+               err = path_lookup(sunname->sun_path, LOOKUP_FOLLOW, &nd);
+               if (err)
+                       goto fail;
+Index: linux-2.6.16.21-0.8/fs/open.c
+===================================================================
+--- linux-2.6.16.21-0.8.orig/fs/open.c 2006-08-03 01:34:33.000000000 -0600
++++ linux-2.6.16.21-0.8/fs/open.c      2006-08-03 02:54:31.000000000 -0600
+@@ -197,9 +197,10 @@
+ }
+ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
+-      struct file *filp)
++      struct file *filp, int called_from_open)
+ {
+       int err;
++      struct inode_operations *op = dentry->d_inode->i_op;
+       struct iattr newattrs;
+       /* Not pretty: "inode->i_size" shouldn't really be signed. But it is. */
+@@ -214,7 +215,17 @@
+       }
+       mutex_lock(&dentry->d_inode->i_mutex);
+-      err = notify_change(dentry, &newattrs);
++      if (called_from_open)
++                newattrs.ia_valid |= ATTR_FROM_OPEN;
++        if (op->setattr_raw) {
++                newattrs.ia_valid |= ATTR_RAW;
++                newattrs.ia_ctime = CURRENT_TIME;
++                down_write(&dentry->d_inode->i_alloc_sem);
++                err = op->setattr_raw(dentry->d_inode, &newattrs);
++                up_write(&dentry->d_inode->i_alloc_sem);
++        } else
++                err = notify_change(dentry, &newattrs);
++
+       mutex_unlock(&dentry->d_inode->i_mutex);
+       return err;
+ }
+@@ -269,7 +280,7 @@
+       error = locks_verify_truncate(inode, NULL, length);
+       if (!error) {
+               DQUOT_INIT(inode);
+-              error = do_truncate(nd.dentry, length, 0, NULL);
++              error = do_truncate(nd.dentry, length, 0, NULL, 0);
+       }
+       put_write_access(inode);
+@@ -321,7 +332,7 @@
+       error = locks_verify_truncate(inode, file, length);
+       if (!error)
+-              error = do_truncate(dentry, length, 0, file);
++              error = do_truncate(dentry, length, 0, file, 0);
+ out_putf:
+       fput(file);
+ out:
+@@ -406,9 +417,20 @@
+                   (error = vfs_permission(&nd, MAY_WRITE)) != 0)
+                       goto dput_and_out;
+       }
+-      mutex_lock(&inode->i_mutex);
+-      error = notify_change(nd.dentry, &newattrs);
+-      mutex_unlock(&inode->i_mutex);
++      if (inode->i_op->setattr_raw) {
++              struct inode_operations *op = nd.dentry->d_inode->i_op;
++
++              newattrs.ia_valid |= ATTR_RAW;
++              error = op->setattr_raw(inode, &newattrs);
++              /* the file system wants to use normal vfs path now */
++              if (error != -EOPNOTSUPP)
++                      goto dput_and_out;
++      } else {
++              mutex_lock(&inode->i_mutex);
++              error = notify_change(nd.dentry, &newattrs);
++              mutex_unlock(&inode->i_mutex);
++      }
++
+ dput_and_out:
+       path_release(&nd);
+ out:
+@@ -620,36 +642,52 @@
+       return error;
+ }
++int chmod_common(struct dentry *dentry, mode_t mode)
++{
++      struct inode * inode = dentry->d_inode;
++      struct iattr newattrs;
++      int error = -EROFS;
++
++      if (IS_RDONLY(inode))
++              goto out;
++
++      if (inode->i_op->setattr_raw) {
++              struct inode_operations *op = dentry->d_inode->i_op;
++
++              newattrs.ia_mode = mode;
++              newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
++              newattrs.ia_valid |= ATTR_RAW;
++              error = op->setattr_raw(inode, &newattrs);
++              /* the file system wants to use normal vfs path now */
++              if (error != -EOPNOTSUPP)
++                    goto out;
++      }
++
++      error = -EPERM;
++      if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
++              goto out;
++
++      mutex_lock(&inode->i_mutex);
++      if (mode == (mode_t) -1)
++              mode = inode->i_mode;
++      newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
++      newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
++      error = notify_change(dentry, &newattrs);
++      mutex_unlock(&inode->i_mutex);
++out:
++      return error;
++}
++
+ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
+ {
+-      struct inode * inode;
+-      struct dentry * dentry;
+       struct file * file;
+       int err = -EBADF;
+-      struct iattr newattrs;
+       file = fget(fd);
+       if (!file)
+               goto out;
+-      dentry = file->f_dentry;
+-      inode = dentry->d_inode;
+-
+-      err = -EROFS;
+-      if (IS_RDONLY(inode))
+-              goto out_putf;
+-      err = -EPERM;
+-      if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+-              goto out_putf;
+-      mutex_lock(&inode->i_mutex);
+-      if (mode == (mode_t) -1)
+-              mode = inode->i_mode;
+-      newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
+-      newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
+-      err = notify_change(dentry, &newattrs);
+-      mutex_unlock(&inode->i_mutex);
+-
+-out_putf:
++        err = chmod_common(file->f_dentry, mode);
+       fput(file);
+ out:
+       return err;
+@@ -659,32 +697,12 @@
+                            mode_t mode)
+ {
+       struct nameidata nd;
+-      struct inode * inode;
+       int error;
+-      struct iattr newattrs;
+       error = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &nd);
+       if (error)
+               goto out;
+-      inode = nd.dentry->d_inode;
+-
+-      error = -EROFS;
+-      if (IS_RDONLY(inode))
+-              goto dput_and_out;
+-
+-      error = -EPERM;
+-      if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+-              goto dput_and_out;
+-
+-      mutex_lock(&inode->i_mutex);
+-      if (mode == (mode_t) -1)
+-              mode = inode->i_mode;
+-      newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
+-      newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
+-      error = notify_change(nd.dentry, &newattrs);
+-      mutex_unlock(&inode->i_mutex);
+-
+-dput_and_out:
++      error = chmod_common(nd.dentry, mode);
+       path_release(&nd);
+ out:
+       return error;
+@@ -710,6 +728,18 @@
+       if (IS_RDONLY(inode))
+               goto out;
+       error = -EPERM;
++      if (inode->i_op->setattr_raw) {
++              struct inode_operations *op = dentry->d_inode->i_op;
++
++              newattrs.ia_uid = user;
++              newattrs.ia_gid = group;
++              newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME;
++              newattrs.ia_valid |= ATTR_RAW;
++              error = op->setattr_raw(inode, &newattrs);
++              /* the file system wants to use normal vfs path now */
++              if (error != -EOPNOTSUPP)
++                      return error;
++      }
+       if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+               goto out;
+       newattrs.ia_valid =  ATTR_CTIME;
+Index: linux-2.6.16.21-0.8/fs/namei.c
+===================================================================
+--- linux-2.6.16.21-0.8.orig/fs/namei.c        2006-08-03 01:34:33.000000000 -0600
++++ linux-2.6.16.21-0.8/fs/namei.c     2006-08-03 02:54:31.000000000 -0600
+@@ -1637,7 +1637,7 @@
+               if (!error) {
+                       DQUOT_INIT(inode);
+                       
+-                      error = do_truncate(dentry, 0, ATTR_MTIME|ATTR_CTIME, NULL);
++                      error = do_truncate(dentry, 0, ATTR_MTIME|ATTR_CTIME, NULL, 1);
+               }
+               put_write_access(inode);
+               if (error)
+@@ -1911,6 +1911,7 @@
+       char * tmp;
+       struct dentry * dentry;
+       struct nameidata nd;
++      intent_init(&nd.intent, IT_LOOKUP);
+       if (S_ISDIR(mode))
+               return -EPERM;
+@@ -1921,6 +1922,15 @@
+       error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd);
+       if (error)
+               goto out;
++
++      if (nd.dentry->d_inode->i_op->mknod_raw) {
++              struct inode_operations *op = nd.dentry->d_inode->i_op;
++              error = op->mknod_raw(&nd, mode, dev);
++              /* the file system wants to use normal vfs path now */
++              if (error != -EOPNOTSUPP)
++                      goto out2;
++      }
++
+       dentry = lookup_create(&nd, 0);
+       error = PTR_ERR(dentry);
+@@ -1947,6 +1957,7 @@
+               dput(dentry);
+       }
+       mutex_unlock(&nd.dentry->d_inode->i_mutex);
++out2:
+       path_release(&nd);
+ out:
+       putname(tmp);
+@@ -1992,9 +2003,18 @@
+               struct dentry *dentry;
+               struct nameidata nd;
++              intent_init(&nd.intent, IT_LOOKUP);
+               error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd);
+               if (error)
+                       goto out;
++              if (nd.dentry->d_inode->i_op->mkdir_raw) {
++                      struct inode_operations *op = nd.dentry->d_inode->i_op;
++                      error = op->mkdir_raw(&nd, mode);
++                      /* the file system wants to use normal vfs path now */
++                      if (error != -EOPNOTSUPP)
++                              goto out2;
++              }
++
+               dentry = lookup_create(&nd, 1);
+               error = PTR_ERR(dentry);
+               if (!IS_ERR(dentry)) {
+@@ -2004,6 +2024,7 @@
+                       dput(dentry);
+               }
+               mutex_unlock(&nd.dentry->d_inode->i_mutex);
++out2:
+               path_release(&nd);
+ out:
+               putname(tmp);
+@@ -2084,6 +2105,7 @@
+       char * name;
+       struct dentry *dentry;
+       struct nameidata nd;
++      intent_init(&nd.intent, IT_LOOKUP);
+       name = getname(pathname);
+       if(IS_ERR(name))
+@@ -2104,6 +2126,14 @@
+                       error = -EBUSY;
+                       goto exit1;
+       }
++      if (nd.dentry->d_inode->i_op->rmdir_raw) {
++                struct inode_operations *op = nd.dentry->d_inode->i_op;
++
++                error = op->rmdir_raw(&nd);
++                /* the file system wants to use normal vfs path now */
++                if (error != -EOPNOTSUPP)
++                        goto exit1;
++        }
+       mutex_lock(&nd.dentry->d_inode->i_mutex);
+       dentry = lookup_hash(&nd);
+       error = PTR_ERR(dentry);
+@@ -2167,6 +2197,7 @@
+       struct dentry *dentry;
+       struct nameidata nd;
+       struct inode *inode = NULL;
++      intent_init(&nd.intent, IT_LOOKUP);
+       name = getname(pathname);
+       if(IS_ERR(name))
+@@ -2178,6 +2209,13 @@
+       error = -EISDIR;
+       if (nd.last_type != LAST_NORM)
+               goto exit1;
++      if (nd.dentry->d_inode->i_op->unlink_raw) {
++              struct inode_operations *op = nd.dentry->d_inode->i_op;
++              error = op->unlink_raw(&nd);
++                /* the file system wants to use normal vfs path now */
++              if (error != -EOPNOTSUPP)
++                       goto exit1;
++        }
+       mutex_lock(&nd.dentry->d_inode->i_mutex);
+       dentry = lookup_hash(&nd);
+       error = PTR_ERR(dentry);
+@@ -2260,9 +2298,17 @@
+               struct dentry *dentry;
+               struct nameidata nd;
++              intent_init(&nd.intent, IT_LOOKUP);
+               error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd);
+               if (error)
+                       goto out;
++              if (nd.dentry->d_inode->i_op->symlink_raw) {
++                      struct inode_operations *op = nd.dentry->d_inode->i_op;
++                      error = op->symlink_raw(&nd, from);
++                      /* the file system wants to use normal vfs path now */
++                      if (error != -EOPNOTSUPP)
++                              goto out2;
++              }
+               dentry = lookup_create(&nd, 0);
+               error = PTR_ERR(dentry);
+               if (!IS_ERR(dentry)) {
+@@ -2270,6 +2316,7 @@
+                       dput(dentry);
+               }
+               mutex_unlock(&nd.dentry->d_inode->i_mutex);
++out2:
+               path_release(&nd);
+ out:
+               putname(to);
+@@ -2357,6 +2404,13 @@
+       error = -EXDEV;
+       if (old_nd.mnt != nd.mnt)
+               goto out_release;
++      if (nd.dentry->d_inode->i_op->link_raw) {
++              struct inode_operations *op = nd.dentry->d_inode->i_op;
++              error = op->link_raw(&old_nd, &nd);
++              /* the file system wants to use normal vfs path now */
++              if (error != -EOPNOTSUPP)
++                      goto out_release;
++      }
+       new_dentry = lookup_create(&nd, 0);
+       error = PTR_ERR(new_dentry);
+       if (!IS_ERR(new_dentry)) {
+@@ -2533,6 +2587,8 @@
+       struct dentry * old_dentry, *new_dentry;
+       struct dentry * trap;
+       struct nameidata oldnd, newnd;
++      intent_init(&oldnd.intent, IT_LOOKUP);
++      intent_init(&newnd.intent, IT_LOOKUP);
+       error = do_path_lookup(olddfd, oldname, LOOKUP_PARENT, &oldnd);
+       if (error)
+@@ -2555,6 +2611,13 @@
+       if (newnd.last_type != LAST_NORM)
+               goto exit2;
++      if (old_dir->d_inode->i_op->rename_raw) {
++              error = old_dir->d_inode->i_op->rename_raw(&oldnd, &newnd);
++              /* the file system wants to use normal vfs path now */
++              if (error != -EOPNOTSUPP)
++                      goto exit2;
++      }
++
+       trap = lock_rename(new_dir, old_dir);
+       old_dentry = lookup_hash(&oldnd);
+@@ -2586,8 +2649,7 @@
+       if (new_dentry == trap)
+               goto exit5;
+-      error = vfs_rename(old_dir->d_inode, old_dentry,
+-                                 new_dir->d_inode, new_dentry);
++      error = vfs_rename(old_dir->d_inode, old_dentry, new_dir->d_inode, new_dentry);
+ exit5:
+       dput(new_dentry);
+ exit4:
+Index: linux-2.6.16.21-0.8/fs/exec.c
+===================================================================
+--- linux-2.6.16.21-0.8.orig/fs/exec.c 2006-08-03 01:34:33.000000000 -0600
++++ linux-2.6.16.21-0.8/fs/exec.c      2006-08-03 01:35:38.000000000 -0600
+@@ -1524,7 +1524,7 @@
+               goto close_fail;
+       if (!file->f_op->write)
+               goto close_fail;
+-      if (do_truncate(file->f_dentry, 0, 0, file) != 0)
++      if (do_truncate(file->f_dentry, 0, 0, file, 0) != 0)
+               goto close_fail;
+       retval = binfmt->core_dump(signr, regs, file);
+Index: linux-2.6.16.21-0.8/include/linux/fs.h
+===================================================================
+--- linux-2.6.16.21-0.8.orig/include/linux/fs.h        2006-08-03 01:34:33.000000000 -0600
++++ linux-2.6.16.21-0.8/include/linux/fs.h     2006-08-03 01:35:38.000000000 -0600
+@@ -1041,13 +1041,20 @@
+       int (*create) (struct inode *,struct dentry *,int, struct nameidata *);
+       struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
+       int (*link) (struct dentry *,struct inode *,struct dentry *);
++      int (*link_raw) (struct nameidata *,struct nameidata *);
+       int (*unlink) (struct inode *,struct dentry *);
++      int (*unlink_raw) (struct nameidata *);
+       int (*symlink) (struct inode *,struct dentry *,const char *);
++      int (*symlink_raw) (struct nameidata *,const char *);
+       int (*mkdir) (struct inode *,struct dentry *,int);
++      int (*mkdir_raw) (struct nameidata *,int);
+       int (*rmdir) (struct inode *,struct dentry *);
++      int (*rmdir_raw) (struct nameidata *);
+       int (*mknod) (struct inode *,struct dentry *,int,dev_t);
++      int (*mknod_raw) (struct nameidata *,int,dev_t);
+       int (*rename) (struct inode *, struct dentry *,
+                       struct inode *, struct dentry *);
++      int (*rename_raw) (struct nameidata *, struct nameidata *);
+       int (*readlink) (struct dentry *, char __user *,int);
+       void * (*follow_link) (struct dentry *, struct nameidata *);
+       void (*put_link) (struct dentry *, struct nameidata *, void *);
+@@ -1357,7 +1364,7 @@
+ /* fs/open.c */
+ extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs,
+-                     struct file *filp);
++                     struct file *filp, int called_from_open);
+ extern long do_sys_open(int fdf, const char __user *filename, int flags,
+                       int mode);
+ extern struct file *filp_open(const char *, int, int);
diff --git a/lustre/kernel_patches/patches/vfs_nointent-2.6.18-vanilla.patch b/lustre/kernel_patches/patches/vfs_nointent-2.6.18-vanilla.patch
new file mode 100644 (file)
index 0000000..3caa54c
--- /dev/null
@@ -0,0 +1,451 @@
+Index: linux-2.6/net/unix/af_unix.c
+===================================================================
+--- linux-2.6.orig/net/unix/af_unix.c  2006-07-15 21:01:06.000000000 +0800
++++ linux-2.6/net/unix/af_unix.c       2006-07-15 21:01:13.000000000 +0800
+@@ -706,6 +706,7 @@ static struct sock *unix_find_other(stru
+       int err = 0;
+       
+       if (sunname->sun_path[0]) {
++              intent_init(&nd.intent, IT_LOOKUP);
+               err = path_lookup(sunname->sun_path, LOOKUP_FOLLOW, &nd);
+               if (err)
+                       goto fail;
+Index: linux-2.6/fs/open.c
+===================================================================
+--- linux-2.6.orig/fs/open.c   2006-07-15 21:01:10.000000000 +0800
++++ linux-2.6/fs/open.c        2006-07-15 21:01:31.000000000 +0800
+@@ -198,9 +198,10 @@ out:
+ }
+ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
+-      struct file *filp)
++      struct file *filp, int called_from_open)
+ {
+       int err;
++      struct inode_operations *op = dentry->d_inode->i_op;
+       struct iattr newattrs;
+       /* Not pretty: "inode->i_size" shouldn't really be signed. But it is. */
+@@ -215,7 +216,17 @@ int do_truncate(struct dentry *dentry, l
+       }
+       mutex_lock(&dentry->d_inode->i_mutex);
+-      err = notify_change(dentry, &newattrs);
++      if (called_from_open)
++                newattrs.ia_valid |= ATTR_FROM_OPEN;
++        if (op->setattr_raw) {
++                newattrs.ia_valid |= ATTR_RAW;
++                newattrs.ia_ctime = CURRENT_TIME;
++                down_write(&dentry->d_inode->i_alloc_sem);
++                err = op->setattr_raw(dentry->d_inode, &newattrs);
++                up_write(&dentry->d_inode->i_alloc_sem);
++        } else
++                err = notify_change(dentry, &newattrs);
++
+       mutex_unlock(&dentry->d_inode->i_mutex);
+       return err;
+ }
+@@ -270,7 +281,7 @@ static long do_sys_truncate(const char _
+       error = locks_verify_truncate(inode, NULL, length);
+       if (!error) {
+               DQUOT_INIT(inode);
+-              error = do_truncate(nd.dentry, length, 0, NULL);
++              error = do_truncate(nd.dentry, length, 0, NULL, 0);
+       }
+       put_write_access(inode);
+@@ -322,7 +333,7 @@ static long do_sys_ftruncate(unsigned in
+       error = locks_verify_truncate(inode, file, length);
+       if (!error)
+-              error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file);
++              error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file, 0);
+ out_putf:
+       fput(file);
+ out:
+@@ -407,9 +418,20 @@ asmlinkage long sys_utime(char __user * 
+                   (error = vfs_permission(&nd, MAY_WRITE)) != 0)
+                       goto dput_and_out;
+       }
+-      mutex_lock(&inode->i_mutex);
+-      error = notify_change(nd.dentry, &newattrs);
+-      mutex_unlock(&inode->i_mutex);
++      if (inode->i_op->setattr_raw) {
++              struct inode_operations *op = nd.dentry->d_inode->i_op;
++ 
++              newattrs.ia_valid |= ATTR_RAW;
++              error = op->setattr_raw(inode, &newattrs);
++              /* the file system wants to use normal vfs path now */
++              if (error != -EOPNOTSUPP)
++                      goto dput_and_out;
++      } else {
++              mutex_lock(&inode->i_mutex);
++              error = notify_change(nd.dentry, &newattrs);
++              mutex_unlock(&inode->i_mutex);
++      }
++
+ dput_and_out:
+       path_release(&nd);
+ out:
+@@ -621,38 +643,53 @@ out:
+       return error;
+ }
+-asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
++int chmod_common(struct dentry *dentry, mode_t mode)
+ {
+-      struct inode * inode;
+-      struct dentry * dentry;
+-      struct file * file;
+-      int err = -EBADF;
++      struct inode * inode = dentry->d_inode;
+       struct iattr newattrs;
+-
+-      file = fget(fd);
+-      if (!file)
++      int error = -EROFS;
++ 
++      if (IS_RDONLY(inode))
+               goto out;
+-      dentry = file->f_dentry;
+-      inode = dentry->d_inode;
++      if (inode->i_op->setattr_raw) {
++              struct inode_operations *op = dentry->d_inode->i_op;
+-      audit_inode(NULL, inode);
++              newattrs.ia_mode = mode;
++              newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
++              newattrs.ia_valid |= ATTR_RAW;
++              error = op->setattr_raw(inode, &newattrs);
++              /* the file system wants to use normal vfs path now */
++              if (error != -EOPNOTSUPP)
++                      goto out;
++      }
+-      err = -EROFS;
+-      if (IS_RDONLY(inode))
+-              goto out_putf;
+-      err = -EPERM;
++      error = -EPERM;
+       if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+-              goto out_putf;
++              goto out;
++
+       mutex_lock(&inode->i_mutex);
+       if (mode == (mode_t) -1)
+               mode = inode->i_mode;
+       newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
+       newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
+-      err = notify_change(dentry, &newattrs);
++      error = notify_change(dentry, &newattrs);
+       mutex_unlock(&inode->i_mutex);
++out:
++      return error;
++}
+-out_putf:
++
++asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
++{
++      struct file * file;
++      int err = -EBADF;
++
++      file = fget(fd);
++      if (!file)
++              goto out;
++
++      err = chmod_common(file->f_dentry, mode);
+       fput(file);
+ out:
+       return err;
+@@ -662,32 +699,12 @@ asmlinkage long sys_fchmodat(int dfd, co
+                            mode_t mode)
+ {
+       struct nameidata nd;
+-      struct inode * inode;
+       int error;
+-      struct iattr newattrs;
+       error = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &nd);
+       if (error)
+               goto out;
+-      inode = nd.dentry->d_inode;
+-
+-      error = -EROFS;
+-      if (IS_RDONLY(inode))
+-              goto dput_and_out;
+-
+-      error = -EPERM;
+-      if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+-              goto dput_and_out;
+-
+-      mutex_lock(&inode->i_mutex);
+-      if (mode == (mode_t) -1)
+-              mode = inode->i_mode;
+-      newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
+-      newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
+-      error = notify_change(nd.dentry, &newattrs);
+-      mutex_unlock(&inode->i_mutex);
+-
+-dput_and_out:
++      error = chmod_common(nd.dentry, mode);
+       path_release(&nd);
+ out:
+       return error;
+@@ -713,6 +730,18 @@ static int chown_common(struct dentry * 
+       if (IS_RDONLY(inode))
+               goto out;
+       error = -EPERM;
++      if (inode->i_op->setattr_raw) {
++              struct inode_operations *op = dentry->d_inode->i_op;
++
++              newattrs.ia_uid = user;
++              newattrs.ia_gid = group;
++              newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME;
++              newattrs.ia_valid |= ATTR_RAW;
++              error = op->setattr_raw(inode, &newattrs);
++              /* the file system wants to use normal vfs path now */
++              if (error != -EOPNOTSUPP)
++                      return error;
++      }
+       if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+               goto out;
+       newattrs.ia_valid =  ATTR_CTIME;
+Index: linux-2.6/fs/namei.c
+===================================================================
+--- linux-2.6.orig/fs/namei.c  2006-07-15 21:01:10.000000000 +0800
++++ linux-2.6/fs/namei.c       2006-07-15 21:01:13.000000000 +0800
+@@ -1642,7 +1642,7 @@ int may_open(struct nameidata *nd, int a
+               if (!error) {
+                       DQUOT_INIT(inode);
+                       
+-                      error = do_truncate(dentry, 0, ATTR_MTIME|ATTR_CTIME, NULL);
++                      error = do_truncate(dentry, 0, ATTR_MTIME|ATTR_CTIME, NULL, 1);
+               }
+               put_write_access(inode);
+               if (error)
+@@ -1916,6 +1916,7 @@ asmlinkage long sys_mknodat(int dfd, con
+       char * tmp;
+       struct dentry * dentry;
+       struct nameidata nd;
++      intent_init(&nd.intent, IT_LOOKUP);
+       if (S_ISDIR(mode))
+               return -EPERM;
+@@ -1926,6 +1927,15 @@ asmlinkage long sys_mknodat(int dfd, con
+       error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd);
+       if (error)
+               goto out;
++
++      if (nd.dentry->d_inode->i_op->mknod_raw) {
++              struct inode_operations *op = nd.dentry->d_inode->i_op;
++              error = op->mknod_raw(&nd, mode, dev);
++              /* the file system wants to use normal vfs path now */
++              if (error != -EOPNOTSUPP)
++                      goto out2;
++      }
++
+       dentry = lookup_create(&nd, 0);
+       error = PTR_ERR(dentry);
+@@ -1952,6 +1962,7 @@ asmlinkage long sys_mknodat(int dfd, con
+               dput(dentry);
+       }
+       mutex_unlock(&nd.dentry->d_inode->i_mutex);
++out2:
+       path_release(&nd);
+ out:
+       putname(tmp);
+@@ -1997,9 +2008,18 @@ asmlinkage long sys_mkdirat(int dfd, con
+               struct dentry *dentry;
+               struct nameidata nd;
++              intent_init(&nd.intent, IT_LOOKUP);
+               error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd);
+               if (error)
+                       goto out;
++              if (nd.dentry->d_inode->i_op->mkdir_raw) {
++                      struct inode_operations *op = nd.dentry->d_inode->i_op;
++                      error = op->mkdir_raw(&nd, mode);
++                      /* the file system wants to use normal vfs path now */
++                      if (error != -EOPNOTSUPP)
++                              goto out2;
++              }
++
+               dentry = lookup_create(&nd, 1);
+               error = PTR_ERR(dentry);
+               if (!IS_ERR(dentry)) {
+@@ -2009,6 +2029,7 @@ asmlinkage long sys_mkdirat(int dfd, con
+                       dput(dentry);
+               }
+               mutex_unlock(&nd.dentry->d_inode->i_mutex);
++out2:
+               path_release(&nd);
+ out:
+               putname(tmp);
+@@ -2089,6 +2110,7 @@ static long do_rmdir(int dfd, const char
+       char * name;
+       struct dentry *dentry;
+       struct nameidata nd;
++      intent_init(&nd.intent, IT_LOOKUP);
+       name = getname(pathname);
+       if(IS_ERR(name))
+@@ -2109,6 +2131,14 @@ static long do_rmdir(int dfd, const char
+                       error = -EBUSY;
+                       goto exit1;
+       }
++      if (nd.dentry->d_inode->i_op->rmdir_raw) {
++              struct inode_operations *op = nd.dentry->d_inode->i_op;
++
++              error = op->rmdir_raw(&nd);
++              /* the file system wants to use normal vfs path now */
++              if (error != -EOPNOTSUPP)
++                      goto exit1;
++      }
+       mutex_lock_nested(&nd.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
+       dentry = lookup_hash(&nd);
+       error = PTR_ERR(dentry);
+@@ -2172,6 +2202,7 @@ static long do_unlinkat(int dfd, const c
+       struct dentry *dentry;
+       struct nameidata nd;
+       struct inode *inode = NULL;
++      intent_init(&nd.intent, IT_LOOKUP);
+       name = getname(pathname);
+       if(IS_ERR(name))
+@@ -2183,6 +2214,13 @@ static long do_unlinkat(int dfd, const c
+       error = -EISDIR;
+       if (nd.last_type != LAST_NORM)
+               goto exit1;
++      if (nd.dentry->d_inode->i_op->unlink_raw) {
++              struct inode_operations *op = nd.dentry->d_inode->i_op;
++              error = op->unlink_raw(&nd);
++              /* the file system wants to use normal vfs path now */
++              if (error != -EOPNOTSUPP)
++              goto exit1;
++      }
+       mutex_lock_nested(&nd.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
+       dentry = lookup_hash(&nd);
+       error = PTR_ERR(dentry);
+@@ -2265,9 +2303,17 @@ asmlinkage long sys_symlinkat(const char
+               struct dentry *dentry;
+               struct nameidata nd;
++              intent_init(&nd.intent, IT_LOOKUP);
+               error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd);
+               if (error)
+                       goto out;
++              if (nd.dentry->d_inode->i_op->symlink_raw) {
++                      struct inode_operations *op = nd.dentry->d_inode->i_op;
++                      error = op->symlink_raw(&nd, from);
++                      /* the file system wants to use normal vfs path now */
++                      if (error != -EOPNOTSUPP)
++                              goto out2;
++              }
+               dentry = lookup_create(&nd, 0);
+               error = PTR_ERR(dentry);
+               if (!IS_ERR(dentry)) {
+@@ -2275,6 +2321,7 @@ asmlinkage long sys_symlinkat(const char
+                       dput(dentry);
+               }
+               mutex_unlock(&nd.dentry->d_inode->i_mutex);
++out2:         
+               path_release(&nd);
+ out:
+               putname(to);
+@@ -2365,6 +2412,13 @@ asmlinkage long sys_linkat(int olddfd, c
+       error = -EXDEV;
+       if (old_nd.mnt != nd.mnt)
+               goto out_release;
++      if (nd.dentry->d_inode->i_op->link_raw) {
++              struct inode_operations *op = nd.dentry->d_inode->i_op;
++              error = op->link_raw(&old_nd, &nd);
++              /* the file system wants to use normal vfs path now */
++              if (error != -EOPNOTSUPP)
++                      goto out_release;
++      }
+       new_dentry = lookup_create(&nd, 0);
+       error = PTR_ERR(new_dentry);
+       if (!IS_ERR(new_dentry)) {
+@@ -2541,6 +2595,8 @@ static int do_rename(int olddfd, const c
+       struct dentry * old_dentry, *new_dentry;
+       struct dentry * trap;
+       struct nameidata oldnd, newnd;
++      intent_init(&oldnd.intent, IT_LOOKUP);
++      intent_init(&newnd.intent, IT_LOOKUP);
+       error = do_path_lookup(olddfd, oldname, LOOKUP_PARENT, &oldnd);
+       if (error)
+@@ -2563,6 +2619,13 @@ static int do_rename(int olddfd, const c
+       if (newnd.last_type != LAST_NORM)
+               goto exit2;
++      if (old_dir->d_inode->i_op->rename_raw) {
++              error = old_dir->d_inode->i_op->rename_raw(&oldnd, &newnd);
++              /* the file system wants to use normal vfs path now */
++              if (error != -EOPNOTSUPP)
++                      goto exit2;
++      }
++
+       trap = lock_rename(new_dir, old_dir);
+       old_dentry = lookup_hash(&oldnd);
+@@ -2594,8 +2657,7 @@ static int do_rename(int olddfd, const c
+       if (new_dentry == trap)
+               goto exit5;
+-      error = vfs_rename(old_dir->d_inode, old_dentry,
+-                                 new_dir->d_inode, new_dentry);
++      error = vfs_rename(old_dir->d_inode, old_dentry, new_dir->d_inode, new_dentry);
+ exit5:
+       dput(new_dentry);
+ exit4:
+Index: linux-2.6/fs/exec.c
+===================================================================
+--- linux-2.6.orig/fs/exec.c   2006-07-15 21:01:10.000000000 +0800
++++ linux-2.6/fs/exec.c        2006-07-15 21:01:13.000000000 +0800
+@@ -1533,7 +1533,7 @@ int do_coredump(long signr, int exit_cod
+               goto close_fail;
+       if (!file->f_op->write)
+               goto close_fail;
+-      if (do_truncate(file->f_dentry, 0, 0, file) != 0)
++      if (do_truncate(file->f_dentry, 0, 0, file, 0) != 0)
+               goto close_fail;
+       retval = binfmt->core_dump(signr, regs, file);
+Index: linux-2.6/include/linux/fs.h
+===================================================================
+--- linux-2.6.orig/include/linux/fs.h  2006-07-15 21:01:10.000000000 +0800
++++ linux-2.6/include/linux/fs.h       2006-07-15 21:01:13.000000000 +0800
+@@ -1090,13 +1090,20 @@ struct inode_operations {
+       int (*create) (struct inode *,struct dentry *,int, struct nameidata *);
+       struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
+       int (*link) (struct dentry *,struct inode *,struct dentry *);
++      int (*link_raw) (struct nameidata *,struct nameidata *);
+       int (*unlink) (struct inode *,struct dentry *);
++      int (*unlink_raw) (struct nameidata *);
+       int (*symlink) (struct inode *,struct dentry *,const char *);
++      int (*symlink_raw) (struct nameidata *,const char *);
+       int (*mkdir) (struct inode *,struct dentry *,int);
++      int (*mkdir_raw) (struct nameidata *,int);
+       int (*rmdir) (struct inode *,struct dentry *);
++      int (*rmdir_raw) (struct nameidata *);
+       int (*mknod) (struct inode *,struct dentry *,int,dev_t);
++      int (*mknod_raw) (struct nameidata *,int,dev_t);
+       int (*rename) (struct inode *, struct dentry *,
+                       struct inode *, struct dentry *);
++      int (*rename_raw) (struct nameidata *, struct nameidata *);
+       int (*readlink) (struct dentry *, char __user *,int);
+       void * (*follow_link) (struct dentry *, struct nameidata *);
+       void (*put_link) (struct dentry *, struct nameidata *, void *);
+@@ -1426,7 +1433,7 @@ static inline int break_lease(struct ino
+ /* fs/open.c */
+ extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs,
+-                     struct file *filp);
++                     struct file *filp, int called_from_open);
+ extern long do_sys_open(int fdf, const char __user *filename, int flags,
+                       int mode);
+ extern struct file *filp_open(const char *, int, int);
diff --git a/lustre/kernel_patches/patches/vfs_races-2.6.18-vanilla.patch b/lustre/kernel_patches/patches/vfs_races-2.6.18-vanilla.patch
new file mode 100644 (file)
index 0000000..36b2e65
--- /dev/null
@@ -0,0 +1,61 @@
+Index: linux-2.6/fs/dcache.c
+===================================================================
+--- linux-2.6.orig/fs/dcache.c 2006-07-15 16:08:36.000000000 +0800
++++ linux-2.6/fs/dcache.c      2006-07-15 16:10:41.000000000 +0800
+@@ -226,6 +226,13 @@ int d_invalidate(struct dentry * dentry)
+               spin_unlock(&dcache_lock);
+               return 0;
+       }
++
++      /* network invalidation by Lustre */
++      if (dentry->d_flags & DCACHE_LUSTRE_INVALID) {
++              spin_unlock(&dcache_lock);
++              return 0;
++      }
++
+       /*
+        * Check whether to do a partial shrink_dcache
+        * to get rid of unused child entries.
+@@ -1242,17 +1249,26 @@ static void __d_rehash(struct dentry * e
+  * Adds a dentry to the hash according to its name.
+  */
+  
+-void d_rehash(struct dentry * entry)
++void d_rehash_cond(struct dentry * entry, int lock)
+ {
+       struct hlist_head *list = d_hash(entry->d_parent, entry->d_name.hash);
+-      spin_lock(&dcache_lock);
++      if (lock)
++              spin_lock(&dcache_lock);
+       spin_lock(&entry->d_lock);
+       __d_rehash(entry, list);
+       spin_unlock(&entry->d_lock);
+-      spin_unlock(&dcache_lock);
++      if (lock)
++              spin_unlock(&dcache_lock);
+ }
++EXPORT_SYMBOL(d_rehash_cond);
++
++void d_rehash(struct dentry * entry)
++{
++      d_rehash_cond(entry, 1);
++ }
++
+ #define do_switch(x,y) do { \
+       __typeof__ (x) __tmp = x; \
+       x = y; y = __tmp; } while (0)
+Index: linux-2.6/include/linux/dcache.h
+===================================================================
+--- linux-2.6.orig/include/linux/dcache.h      2006-07-15 16:10:33.000000000 +0800
++++ linux-2.6/include/linux/dcache.h   2006-07-15 16:10:41.000000000 +0800
+@@ -176,6 +176,8 @@ d_iput:            no              no              no       yes
+ #define DCACHE_REFERENCED     0x0008  /* Recently used, don't discard. */
+ #define DCACHE_UNHASHED               0x0010  
++#define DCACHE_LUSTRE_INVALID     0x0020  /* Lustre invalidated */
++
+ #define DCACHE_INOTIFY_PARENT_WATCHED 0x0020 /* Parent inode is watched */
diff --git a/lustre/kernel_patches/series/2.6-fc5.series b/lustre/kernel_patches/series/2.6-fc5.series
new file mode 100644 (file)
index 0000000..c9abdd0
--- /dev/null
@@ -0,0 +1,20 @@
+lustre_version.patch
+vfs_intent-2.6-fc5.patch 
+vfs_nointent-2.6-fc5.patch 
+vfs_races-2.6.12.patch
+ext3-wantedi-misc-2.6-suse.patch 
+jbd-2.6.10-jcberr.patch
+nfs-cifs-intent-2.6-fc5.patch 
+iopen-misc-2.6.12.patch
+export-truncate-2.6-suse.patch 
+export_symbols-2.6.12.patch 
+dev_read_only-2.6-fc5.patch 
+export-2.6-fc5.patch 
+lookup_bdev_init_intent.patch
+8kstack-2.6.12.patch
+remove-suid-2.6-suse.patch
+export-show_task-2.6-fc5.patch 
+sd_iostats-2.6-rhel4.patch 
+export_symbol_numa-2.6-fc5.patch 
+tcp-zero-copy-2.6-fc5.patch
+vfs_intent-2.6-fc5-fix.patch
diff --git a/lustre/kernel_patches/series/2.6-rhel4-titech.series b/lustre/kernel_patches/series/2.6-rhel4-titech.series
new file mode 100644 (file)
index 0000000..4d881fe
--- /dev/null
@@ -0,0 +1,30 @@
+lustre_version.patch
+vfs_intent-2.6-rhel4.patch
+vfs_nointent-2.6-rhel4.patch
+vfs_races-2.6-rhel4.patch
+ext3-wantedi-misc-2.6-suse.patch 
+nfs-cifs-intent-2.6-rhel4.patch 
+iopen-misc-2.6-suse.patch 
+export-truncate-2.6-suse.patch 
+export_symbols-2.6-rhel4.patch 
+dev_read_only-2.6-suse.patch 
+export-log-2.6-rhel4.patch
+lookup_bdev_init_intent.patch
+remove-suid-2.6-suse.patch
+export-show_task-2.6-vanilla.patch
+sd_iostats-2.6-rhel4.patch 
+fsprivate-2.6.patch
+export_symbol_numa.patch 
+qsnet-rhel4-2.6.patch
+linux-2.6-binutils-2.16.patch
+compile-fixes-2.6.9-rhel4-22.patch
+vm-tunables-rhel4.patch 
+tcp-zero-copy-2.6.9-rhel4.patch
+iallocsem_consistency.patch
+raid5-stats.patch
+raid5-configurable-cachesize.patch
+raid5-large-io.patch
+raid5-stripe-by-stripe-handling.patch
+raid5-optimize-memcpy.patch
+raid5-merge-ios.patch
+raid5-serialize-ovelapping-reqs.patch
index 1c08d3b..1c9aeb7 100644 (file)
@@ -17,8 +17,13 @@ fsprivate-2.6.patch
 export_symbol_numa.patch 
 qsnet-rhel4-2.6.patch
 linux-2.6-binutils-2.16.patch
-compile-fixes-2.6.9-rhel4-22.patch
 vm-tunables-rhel4.patch 
 2.6-rhel4-kgdb-ga.patch
 tcp-zero-copy-2.6.9-rhel4.patch
 iallocsem_consistency.patch
+raid5-stats.patch
+raid5-configurable-cachesize.patch
+raid5-large-io.patch
+raid5-stripe-by-stripe-handling.patch
+raid5-merge-ios.patch
+raid5-serialize-ovelapping-reqs.patch
diff --git a/lustre/kernel_patches/series/2.6-sles10.series b/lustre/kernel_patches/series/2.6-sles10.series
new file mode 100644 (file)
index 0000000..0b06087
--- /dev/null
@@ -0,0 +1,20 @@
+lustre_version.patch
+vfs_intent-2.6-sles10.patch
+vfs_nointent-2.6-sles10.patch
+vfs_races-2.6.12.patch
+ext3-wantedi-misc-2.6-suse.patch 
+jbd-2.6.10-jcberr.patch
+nfs-cifs-intent-2.6-fc5.patch 
+iopen-misc-2.6.12.patch
+export-truncate-2.6-suse.patch 
+export_symbols-2.6.12.patch 
+dev_read_only-2.6-fc5.patch 
+export-2.6-fc5.patch 
+lookup_bdev_init_intent.patch
+8kstack-2.6.12.patch
+remove-suid-2.6-suse.patch
+export-show_task-2.6-fc5.patch 
+sd_iostats-2.6-rhel4.patch 
+export_symbol_numa-2.6-fc5.patch 
+tcp-zero-copy-2.6-sles10.patch
+vfs_intent-2.6-fc5-fix.patch
diff --git a/lustre/kernel_patches/series/2.6.18-vanilla.series b/lustre/kernel_patches/series/2.6.18-vanilla.series
new file mode 100644 (file)
index 0000000..0ac21df
--- /dev/null
@@ -0,0 +1,20 @@
+lustre_version.patch
+vfs_intent-2.6.18-vanilla.patch 
+vfs_nointent-2.6.18-vanilla.patch 
+vfs_races-2.6.18-vanilla.patch
+ext3-wantedi-misc-2.6.18-vanilla.patch 
+jbd-jcberr-2.6.18-vanilla.patch
+nfs-cifs-intent-2.6.18-vanilla.patch 
+iopen-misc-2.6.18-vanilla.patch
+export-truncate-2.6.18-vanilla.patch 
+export_symbols-2.6.18-vanilla.patch 
+dev_read_only-2.6.18-vanilla.patch 
+export-2.6.18-vanilla.patch 
+lookup_bdev_init_intent.patch
+8kstack-2.6.12.patch
+remove-suid-2.6-suse.patch
+export-show_task-2.6.18-vanilla.patch 
+sd_iostats-2.6-rhel4.patch 
+export_symbol_numa-2.6-fc5.patch 
+tcp-zero-copy-2.6.18-vanilla.patch
+vfs_intent-2.6-fc5-fix.patch
index d846b4d..2545ff9 100644 (file)
@@ -47,3 +47,4 @@ ext3-extents-2.4.24.patch
 ext3-extents-asyncdel-2.4.24.patch
 ext3-nlinks-2.4.20-hp_pnnl.patch 
 export-zap-page-range.patch
+ext3-sector_t-overflow-2.4.patch
diff --git a/lustre/kernel_patches/series/ldiskfs-2.6-fc3.series b/lustre/kernel_patches/series/ldiskfs-2.6-fc3.series
new file mode 100644 (file)
index 0000000..5395486
--- /dev/null
@@ -0,0 +1,22 @@
+ext3-wantedi-2.6-rhel4.patch
+ext3-san-jdike-2.6-suse.patch
+iopen-2.6-rhel4.patch 
+export_symbols-ext3-2.6-suse.patch
+ext3-map_inode_page-2.6-suse.patch
+ext3-ea-in-inode-2.6-rhel4.patch
+export-ext3-2.6-rhel4.patch
+ext3-include-fixes-2.6-rhel4.patch
+ext3-extents-2.6.9-rhel4.patch
+ext3-mballoc2-2.6.9-rhel4.patch 
+ext3-nlinks-2.6.9.patch
+ext3-ialloc-2.6.patch
+ext3-lookup-dotdot-2.6.9.patch
+ext3-tall-htree.patch
+ext3-htree-path.patch
+ext3-htree-r5-hash.patch
+ext3-htree-path-ops.patch
+ext3-hash-selection.patch
+ext3-htree-comments.patch
+ext3-iam-ops.patch
+ext3-iam-separate.patch 
+ext3-iam-uapi.patch 
diff --git a/lustre/kernel_patches/series/ldiskfs-2.6-fc5.series b/lustre/kernel_patches/series/ldiskfs-2.6-fc5.series
new file mode 100644 (file)
index 0000000..1c853bd
--- /dev/null
@@ -0,0 +1,12 @@
+ext3-wantedi-2.6-rhel4.patch
+ext3-san-jdike-2.6-suse.patch
+iopen-2.6-fc5.patch
+ext3-map_inode_page-2.6-suse.patch
+export-ext3-2.6-rhel4.patch
+ext3-include-fixes-2.6-rhel4.patch
+ext3-extents-2.6.15.patch
+ext3-mballoc2-2.6-fc5.patch
+ext3-nlinks-2.6.9.patch
+ext3-ialloc-2.6.patch
+ext3-remove-cond_resched-calls-2.6.12.patch
+ext3-filterdata-2.6.15.patch
index f6d42cd..2f2f413 100644 (file)
@@ -16,6 +16,9 @@ ext3-htree-r5-hash.patch
 ext3-htree-path-ops.patch
 ext3-hash-selection.patch
 ext3-htree-comments.patch
+ext3-lookup-dotdot-2.6.9.patch
+ext3-sector_t-overflow-2.6.9-rhel4.patch
+ext3-check-jbd-errors-2.6.9.patch
 ext3-iam-ops.patch
 ext3-iam-separate.patch 
 ext3-iam-uapi.patch 
index 2584c1d..f3be0ea 100644 (file)
@@ -12,3 +12,6 @@ ext3-nlinks-2.6.7.patch
 ext3-rename-reserve-2.6-suse.patch
 ext3-htree-dot-2.6.5-suse.patch 
 ext3-ialloc-2.6.patch
+ext3-lookup-dotdot-2.6.9.patch
+ext3-sector_t-overflow-2.6.5-suse.patch
+ext3-check-jbd-errors-2.6.5.patch
index 7d0a383..53c060b 100644 (file)
@@ -11,3 +11,5 @@ ext3-ialloc-2.6.patch
 ext3-remove-cond_resched-calls-2.6.12.patch
 ext3-htree-dot-2.6.patch
 ext3-external-journal-2.6.12.patch
+ext3-lookup-dotdot-2.6.9.patch
+ext3-sector_t-overflow-2.6.12.patch
diff --git a/lustre/kernel_patches/series/ldiskfs-2.6.18-vanilla.series b/lustre/kernel_patches/series/ldiskfs-2.6.18-vanilla.series
new file mode 100644 (file)
index 0000000..f379cec
--- /dev/null
@@ -0,0 +1,13 @@
+ext3-wantedi-2.6-rhel4.patch
+ext3-san-jdike-2.6-suse.patch
+iopen-2.6-fc5.patch
+ext3-map_inode_page-2.6-suse.patch
+export-ext3-2.6-rhel4.patch
+ext3-include-fixes-2.6-rhel4.patch
+ext3-extents-2.6.18-vanilla.patch
+ext3-mballoc2-2.6.18-vanilla.patch
+ext3-nlinks-2.6.9.patch
+ext3-ialloc-2.6.patch
+ext3-remove-cond_resched-calls-2.6.12.patch
+ext3-filterdata-2.6.15.patch
+ext3-multi-mount-protection-2.6.18-vanilla.patch
index bc6e9f6..5e6223e 100644 (file)
@@ -51,3 +51,5 @@ statfs64-cast-unsigned-2.4-rhel.patch
 fsprivate-2.4.patch
 nfsd_iallocsem.patch
 linux-2.4.24-jbd-handle-EIO-rhel3.patch
+ext3-lookup-dotdot-2.4.20.patch 
+ext3-sector_t-overflow-2.4.patch
index e0b9c23..794642b 100644 (file)
@@ -41,3 +41,4 @@ fsprivate-2.4-suse.patch
 nfsd_iallocsem.patch
 linux-2.4.24-jbd-handle-EIO.patch
 ext3-ialloc-2.4.21-suse2.patch 
+ext3-sector_t-overflow-2.4.patch
diff --git a/lustre/kernel_patches/series/suse-2.4.21-jvn b/lustre/kernel_patches/series/suse-2.4.21-jvn
deleted file mode 100644 (file)
index 74e9445..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-configurable-x86-stack-2.4.21-suse-171.patch
-configurable-x86_64-2.4.21.patch
-dev_read_only_2.4.20-rh.patch
-exports_2.4.20-rh-hp.patch
-lustre_version.patch
-vfs_intent-2.4.21-suse-171.patch 
-invalidate_show.patch
-export-truncate.patch
-iod-stock-24-exports_hp.patch
-ext3-htree-2.4.21-chaos.patch
-linux-2.4.21-xattr-0.8.54-suse-171.patch 
-ext3-orphan_lock-2.4.22-rh.patch 
-ext3-noread-2.4.21-suse2.patch
-ext3-delete_thread-2.4.21-suse-171.patch 
-extN-wantedi-2.4.21-suse2.patch
-ext3-san-2.4.20.patch
-ext3-map_inode_page-2.4.21-suse2.patch 
-ext3-error-export.patch
-iopen-2.4.21-chaos.patch
-jbd-dont-account-blocks-twice.patch
-jbd-commit-tricks.patch
-ext3-no-write-super-chaos.patch
-add_page_private.patch
-nfs_export_kernel-2.4.21-suse2.patch
-ext3-raw-lookup.patch
-ext3-ea-in-inode-2.4.21-sles.patch 
-listman-2.4.20.patch
-ext3-truncate-buffer-head.patch
-lookup-stack-symbols-2.4.21-suse-171.patch 
-fsprivate-2.4-suse.patch
-nfsd_iallocsem.patch
index a8ee3e0..5011ae1 100644 (file)
@@ -47,3 +47,4 @@ uml-exprt-clearuser.patch
 fsprivate-2.4.patch
 nfsd_iallocsem.patch
 linux-2.4.24-jbd-handle-EIO.patch
+ext3-sector_t-overflow-2.4.patch
index bb22e80..7c2e3d9 100644 (file)
@@ -43,3 +43,4 @@ kallsyms-2.4.29.patch
 fsprivate-2.4.patch
 nfsd_iallocsem.patch
 linux-2.4.24-jbd-handle-EIO.patch
+ext3-sector_t-overflow-2.4.patch
index 3bd5fd2..5ee53f9 100644 (file)
@@ -45,3 +45,4 @@ remove-suid-2.4-rhel.patch
 kallsyms-2.4.29.patch
 fsprivate-2.4.patch
 nfsd_iallocsem.patch
+ext3-sector_t-overflow-2.4.patch
diff --git a/lustre/kernel_patches/targets/2.6-fc5.target.in b/lustre/kernel_patches/targets/2.6-fc5.target.in
new file mode 100644 (file)
index 0000000..fe27302
--- /dev/null
@@ -0,0 +1,18 @@
+lnxmaj="2.6.15"
+lnxrel="fc5"
+
+KERNEL=linux-${lnxmaj}-${lnxrel}.tar.bz2
+SERIES=2.6-fc5.series
+VERSION=${lnxmaj}
+EXTRA_VERSION=${lnxrel}_lustre.@VERSION@
+RHBUILD=1
+LINUX26=1
+LUSTRE_VERSION=@VERSION@
+
+BASE_ARCHS="i686"
+BIGMEM_ARCHS=""
+BOOT_ARCHS=""
+JENSEN_ARCHS=""
+SMP_ARCHS="i686"
+UP_ARCHS=""
+
diff --git a/lustre/kernel_patches/targets/2.6-patchless.target.in b/lustre/kernel_patches/targets/2.6-patchless.target.in
new file mode 100644 (file)
index 0000000..ed2a120
--- /dev/null
@@ -0,0 +1,25 @@
+lnxmaj="2.6.16"
+lnxrel="22"
+
+KERNEL=linux-${lnxmaj}-${lnxrel}.tar.bz2
+SERIES=
+VERSION=${lnxmaj}
+EXTRA_VERSION=${lnxrel}
+RHBUILD=1
+LINUX26=1
+LUSTRE_VERSION=@VERSION@
+
+BASE_ARCHS="i686 x86_64 ia64"
+BIGMEM_ARCHS=""
+BOOT_ARCHS=""
+JENSEN_ARCHS=""
+SMP_ARCHS="i686 x86_64 ia64"
+UP_ARCHS=""
+
+# Modules in this kernel do not build with gcc 4 or gcc 2.96
+for cc in gcc33 gcc32 ; do
+    if which $cc >/dev/null 2>/dev/null ; then
+        export CC=$cc
+        break
+    fi
+done
index b89f5a8..8b55026 100644 (file)
@@ -1,5 +1,5 @@
 lnxmaj="2.6.9"
-lnxrel="34.EL"
+lnxrel="42.EL"
 
 KERNEL=linux-${lnxmaj}-${lnxrel}.tar.bz2
 SERIES=2.6-rhel4.series
index a0a2633..e4d8f5c 100644 (file)
@@ -1,5 +1,5 @@
 lnxmaj="2.6.5"
-lnxrel="7.244"
+lnxrel="7.267"
 
 KERNEL=linux-$lnxmaj-$lnxrel.tar.bz2
 # they include our patches
index 7af0f35..48d8eea 100644 (file)
@@ -1,5 +1,5 @@
 lnxmaj="2.4.21"
-lnxrel="37.EL"
+lnxrel="40.EL"
 
 KERNEL=linux-${lnxmaj}-${lnxrel}.tar.bz2
 SERIES=rhel-2.4.21
index bc48f94..29121c2 100644 (file)
@@ -19,4 +19,3 @@ NB - The patches in the ldiskfs series should not be applied to the kernel.
 UNSUPPORTED KERNELS; BEING PHASED OUT; MAY BE MISSING CRITICAL BUG FIXES:
 hp-pnnl-2.4.20     linux-2.4.20-hp4_pnnl1   same as vanilla but no uml  ia64
 vanilla-2.4.24     linux-2.4.24             patch with uml-2.4.24-6     um
-suse-2.4.21-jvn    linux-2.4.21-241         sles8 2.4 kernel            i386
index 9db3f3f..d639b74 100644 (file)
@@ -701,9 +701,8 @@ int lustre_read_dquot(struct lustre_dquot *dquot)
         struct lustre_disk_dqblk ddquot, empty;
         int ret = 0;
 
-        filp = dquot->dq_info->qi_files[type];
-
-        if (!filp || !dquot->dq_info) { /* Invalidated quota? */
+        /* Invalidated quota? */
+        if (!dquot->dq_info || !(filp = dquot->dq_info->qi_files[type])) {
                 printk(KERN_ERR "VFS: Quota invalidated while reading!\n");
                 return -EIO;
         }
index 7601bce..63f2ad5 100644 (file)
 #include <lustre_dlm.h>
 #include <lustre_lib.h>
 
-/* invariants:
- - only the owner of the lock changes l_owner/l_depth
- - if a non-owner changes or checks the variables a spin lock is taken
-*/
-
-void l_lock_init(struct lustre_lock *lock)
-{
-        sema_init(&lock->l_sem, 1);
-        spin_lock_init(&lock->l_spin);
-}
-
-void l_lock(struct lustre_lock *lock)
+/*
+ * ldlm locking uses resource to serialize access to locks
+ * but there is a case when we change resource of lock upon
+ * enqueue reply. we rely on that lock->l_resource = new_res
+ * is atomic
+ */
+struct ldlm_resource * lock_res_and_lock(struct ldlm_lock *lock)
 {
-        int owner = 0;
-
-        spin_lock(&lock->l_spin);
-        if (lock->l_owner == cfs_current())
-                owner = 1;
-        spin_unlock(&lock->l_spin);
-
-        /* This is safe to increment outside the spinlock because we
-         * can only have 1 CPU running on the current task
-         * (i.e. l_owner == current), regardless of the number of CPUs.
-         */
-        if (owner) {
-                ++lock->l_depth;
-        } else {
-                mutex_down(&lock->l_sem);
-                spin_lock(&lock->l_spin);
-                lock->l_owner = cfs_current();
-                lock->l_depth = 0;
-                spin_unlock(&lock->l_spin);
-        }
+        struct ldlm_resource *res = lock->l_resource;
+
+        if (!res->lr_namespace->ns_client) {
+                /* on server-side resource of lock doesn't change */
+                lock_res(res);
+                return res;
+        } 
+
+        lock_bitlock(lock);
+        res = lock->l_resource;
+        lock_res(res);
+        return res;
 }
 
-void l_unlock(struct lustre_lock *lock)
+void unlock_res_and_lock(struct ldlm_lock *lock)
 {
-        LASSERTF(lock->l_owner == cfs_current(), "lock %p, current %p\n",
-                 lock->l_owner, cfs_current());
-        LASSERTF(lock->l_depth >= 0, "depth %d\n", lock->l_depth);
+        struct ldlm_resource *res = lock->l_resource;
 
-        spin_lock(&lock->l_spin);
-        if (--lock->l_depth < 0) {
-                lock->l_owner = NULL;
-                spin_unlock(&lock->l_spin);
-                mutex_up(&lock->l_sem);
+        if (!res->lr_namespace->ns_client) {
+                /* on server-side resource of lock doesn't change */
+                unlock_res(res);
                 return;
         }
-        spin_unlock(&lock->l_spin);
-}
-
-int l_has_lock(struct lustre_lock *lock)
-{
-        int depth = -1, owner = 0;
-
-        spin_lock(&lock->l_spin);
-        if (lock->l_owner == cfs_current()) {
-                depth = lock->l_depth;
-                owner = 1;
-        }
-        spin_unlock(&lock->l_spin);
 
-        if (depth >= 0)
-                CDEBUG(D_INFO, "lock_depth: %d\n", depth);
-        return owner;
+        unlock_res(res);
+        unlock_bitlock(lock);
 }
 
-#ifdef __KERNEL__
-void l_check_ns_lock(struct ldlm_namespace *ns)
-{
-        static cfs_time_t next_msg;
-
-        if (!l_has_lock(&ns->ns_lock) && cfs_time_after(cfs_time_current(), next_msg)) {
-                CERROR("namespace %s lock not held when it should be; tell "
-                       "phil\n", ns->ns_name);
-                libcfs_debug_dumpstack(NULL);
-                next_msg = cfs_time_shift(60);
-        }
-}
-
-void l_check_no_ns_lock(struct ldlm_namespace *ns)
-{
-        static cfs_time_t next_msg;
-
-        if (l_has_lock(&ns->ns_lock) && cfs_time_after(cfs_time_current(), next_msg)) {
-                CERROR("namespace %s lock held illegally; tell phil\n",
-                       ns->ns_name);
-                libcfs_debug_dumpstack(NULL);
-                next_msg = cfs_time_shift(60);
-        }
-}
-
-#else
-void l_check_ns_lock(struct ldlm_namespace *ns)
-{
-        if (!l_has_lock(&ns->ns_lock)) {
-                CERROR("namespace %s lock not held when it should be; tell "
-                       "phil\n", ns->ns_name);
-        }
-}
-
-void l_check_no_ns_lock(struct ldlm_namespace *ns)
-{
-        if (l_has_lock(&ns->ns_lock)) {
-                CERROR("namespace %s lock held illegally; tell phil\n",
-                       ns->ns_name);
-        }
-}
-#endif /* __KERNEL__ */
index 205ff14..77970c3 100644 (file)
@@ -174,7 +174,8 @@ static void ldlm_extent_policy(struct ldlm_resource *res,
  */
 static int
 ldlm_extent_compat_queue(struct list_head *queue, struct ldlm_lock *req,
-                         int send_cbs, int *flags, ldlm_error_t *err)
+                         int *flags, ldlm_error_t *err,
+                         struct list_head *work_list)
 {
         struct list_head *tmp;
         struct ldlm_lock *lock;
@@ -298,18 +299,18 @@ ldlm_extent_compat_queue(struct list_head *queue, struct ldlm_lock *req,
                         continue;
                 }
 
-                if (!send_cbs)
+                if (!work_list)
                         RETURN(0);
 
                 compat = 0;
                 if (lock->l_blocking_ast)
-                        ldlm_add_ast_work_item(lock, req, NULL, 0);
+                        ldlm_add_ast_work_item(lock, req, work_list);
         }
 
         RETURN(compat);
 destroylock:
         list_del_init(&req->l_res_link);
-        ldlm_lock_destroy(req);
+        ldlm_lock_destroy_nolock(req);
         *err = compat;
         RETURN(compat);
 }
@@ -324,7 +325,7 @@ destroylock:
   *   - the caller has NOT initialized req->lr_tmp, so we must
   *   - must call this function with the ns lock held once */
 int ldlm_process_extent_lock(struct ldlm_lock *lock, int *flags, int first_enq,
-                             ldlm_error_t *err)
+                             ldlm_error_t *err, struct list_head *work_list)
 {
         struct ldlm_resource *res = lock->l_resource;
         struct list_head rpc_list = CFS_LIST_HEAD_INIT(rpc_list);
@@ -332,6 +333,7 @@ int ldlm_process_extent_lock(struct ldlm_lock *lock, int *flags, int first_enq,
         ENTRY;
 
         LASSERT(list_empty(&res->lr_converting));
+        check_res_locked(res);
         *err = ELDLM_OK;
 
         if (!first_enq) {
@@ -341,12 +343,11 @@ int ldlm_process_extent_lock(struct ldlm_lock *lock, int *flags, int first_enq,
                  * flags should always be zero here, and if that ever stops
                  * being true, we want to find out. */
                 LASSERT(*flags == 0);
-                LASSERT(res->lr_tmp != NULL);
-                rc = ldlm_extent_compat_queue(&res->lr_granted, lock, 0, flags,
-                                              err);
+                rc = ldlm_extent_compat_queue(&res->lr_granted, lock, flags,
+                                              err, NULL);
                 if (rc == 1) {
-                        rc = ldlm_extent_compat_queue(&res->lr_waiting, lock, 0,
-                                                      flags, err);
+                        rc = ldlm_extent_compat_queue(&res->lr_waiting, lock,
+                                                      flags, err, NULL);
                 }
                 if (rc == 0)
                         RETURN(LDLM_ITER_STOP);
@@ -354,31 +355,26 @@ int ldlm_process_extent_lock(struct ldlm_lock *lock, int *flags, int first_enq,
                 ldlm_resource_unlink_lock(lock);
 
                 ldlm_extent_policy(res, lock, flags);
-                ldlm_grant_lock(lock, NULL, 0, 1);
+                ldlm_grant_lock(lock, work_list);
                 RETURN(LDLM_ITER_CONTINUE);
         }
 
  restart:
-        LASSERT(res->lr_tmp == NULL);
-        res->lr_tmp = &rpc_list;
-        rc = ldlm_extent_compat_queue(&res->lr_granted, lock, 1, flags, err);
+        rc = ldlm_extent_compat_queue(&res->lr_granted, lock, flags, err, &rpc_list);
         if (rc < 0)
                 GOTO(out, rc); /* lock was destroyed */
-        if (rc == 2) {
-                res->lr_tmp = NULL;
+        if (rc == 2)
                 goto grant;
-        }
 
-        rc2 = ldlm_extent_compat_queue(&res->lr_waiting, lock, 1, flags, err);
+        rc2 = ldlm_extent_compat_queue(&res->lr_waiting, lock, flags, err, &rpc_list);
         if (rc2 < 0)
                 GOTO(out, rc = rc2); /* lock was destroyed */
-        res->lr_tmp = NULL;
 
         if (rc + rc2 == 2) {
         grant:
                 ldlm_extent_policy(res, lock, flags);
                 ldlm_resource_unlink_lock(lock);
-                ldlm_grant_lock(lock, NULL, 0, 0);
+                ldlm_grant_lock(lock, NULL);
         } else {
                 /* If either of the compat_queue()s returned failure, then we
                  * have ASTs to send and must go onto the waiting list.
@@ -388,16 +384,19 @@ int ldlm_process_extent_lock(struct ldlm_lock *lock, int *flags, int first_enq,
                  * re-ordered!  Causes deadlock, because ASTs aren't sent! */
                 if (list_empty(&lock->l_res_link))
                         ldlm_resource_add_lock(res, &res->lr_waiting, lock);
-                l_unlock(&res->lr_namespace->ns_lock);
-                rc = ldlm_run_ast_work(res->lr_namespace, &rpc_list);
-                l_lock(&res->lr_namespace->ns_lock);
+                unlock_res(res);
+                rc = ldlm_run_bl_ast_work(&rpc_list);
+                lock_res(res);
                 if (rc == -ERESTART)
                         GOTO(restart, -ERESTART);
                 *flags |= LDLM_FL_BLOCK_GRANTED;
+                /* this way we force client to wait for the lock
+                 * endlessly once the lock is enqueued -bzzz */
+                *flags |= LDLM_FL_NO_TIMEOUT;
+
         }
         rc = 0;
 out:
-        res->lr_tmp = NULL;
         RETURN(rc);
 }
 
index c86ee5c..9bf73d4 100644 (file)
@@ -91,7 +91,7 @@ ldlm_flock_destroy(struct ldlm_lock *lock, ldlm_mode_t mode, int flags)
                 ldlm_lock_decref_internal(lock, mode);
         }
 
-        ldlm_lock_destroy(lock);
+        ldlm_lock_destroy_nolock(lock);
         EXIT;
 }
 
@@ -124,7 +124,7 @@ restart:
 
 int
 ldlm_process_flock_lock(struct ldlm_lock *req, int *flags, int first_enq,
-                        ldlm_error_t *err)
+                        ldlm_error_t *err, struct list_head *work_list)
 {
         struct ldlm_resource *res = req->l_resource;
         struct ldlm_namespace *ns = res->lr_namespace;
@@ -393,20 +393,18 @@ ldlm_process_flock_lock(struct ldlm_lock *req, int *flags, int first_enq,
                                                     = CFS_LIST_HEAD_INIT(rpc_list);
                                 int rc;
 restart:
-                                res->lr_tmp = &rpc_list;
-                                ldlm_reprocess_queue(res, &res->lr_waiting);
-                                res->lr_tmp = NULL;
-
-                                l_unlock(&ns->ns_lock);
-                                rc = ldlm_run_ast_work(res->lr_namespace,
-                                                       &rpc_list);
-                                l_lock(&ns->ns_lock);
+                                ldlm_reprocess_queue(res, &res->lr_waiting,
+                                                     &rpc_list);
+
+                                unlock_res(res);
+                                rc = ldlm_run_bl_ast_work(&rpc_list);
+                                lock_res(res);
                                 if (rc == -ERESTART)
                                         GOTO(restart, -ERESTART);
                        }
                 } else {
                         LASSERT(req->l_completion_ast);
-                        ldlm_add_ast_work_item(req, NULL, NULL, 0);
+                        ldlm_add_ast_work_item(req, NULL, work_list);
                 }
         }
 
@@ -453,7 +451,6 @@ ldlm_flock_completion_ast(struct ldlm_lock *lock, int flags, void *data)
         struct ldlm_namespace *ns;
         cfs_flock_t *getlk = lock->l_ast_data;
         struct ldlm_flock_wait_data fwd;
-        unsigned long irqflags;
         struct obd_device *obd;
         struct obd_import *imp = NULL;
         ldlm_error_t err;
@@ -481,9 +478,9 @@ ldlm_flock_completion_ast(struct ldlm_lock *lock, int flags, void *data)
                 imp = obd->u.cli.cl_import;
 
         if (imp != NULL) {
-                spin_lock_irqsave(&imp->imp_lock, irqflags);
+                spin_lock(&imp->imp_lock);
                 fwd.fwd_generation = imp->imp_generation;
-                spin_unlock_irqrestore(&imp->imp_lock, irqflags);
+                spin_unlock(&imp->imp_lock);
         }
 
         lwi = LWI_TIMEOUT_INTR(0, NULL, ldlm_flock_interrupted_wait, &fwd);
@@ -500,7 +497,7 @@ granted:
 
         LDLM_DEBUG(lock, "client-side enqueue granted");
         ns = lock->l_resource->lr_namespace;
-        l_lock(&ns->ns_lock);
+        lock_res(lock->l_resource);
 
         /* take lock off the deadlock detection waitq. */
         list_del_init(&lock->l_flock_waitq);
@@ -531,11 +528,11 @@ granted:
 
                 /* We need to reprocess the lock to do merges or splits
                  * with existing locks owned by this process. */
-                ldlm_process_flock_lock(lock, &noreproc, 1, &err);
+                ldlm_process_flock_lock(lock, &noreproc, 1, &err, NULL);
                 if (flags == 0)
                         cfs_waitq_signal(&lock->l_waitq);
         }
-        l_unlock(&ns->ns_lock);
+        unlock_res(lock->l_resource);
         RETURN(0);
 }
 EXPORT_SYMBOL(ldlm_flock_completion_ast);
@@ -552,8 +549,8 @@ int ldlm_flock_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
         ns = lock->l_resource->lr_namespace;
 
         /* take lock off the deadlock detection waitq. */
-        l_lock(&ns->ns_lock);
+        lock_res_and_lock(lock);
         list_del_init(&lock->l_flock_waitq);
-        l_unlock(&ns->ns_lock);
+        unlock_res_and_lock(lock);
         RETURN(0);
 }
index 8c473dd..da1823d 100644 (file)
@@ -35,7 +35,7 @@
 /* Determine if the lock is compatible with all locks on the queue. */
 static int
 ldlm_inodebits_compat_queue(struct list_head *queue, struct ldlm_lock *req,
-                            int send_cbs)
+                            struct list_head *work_list)
 {
         struct list_head *tmp;
         struct ldlm_lock *lock;
@@ -61,12 +61,12 @@ ldlm_inodebits_compat_queue(struct list_head *queue, struct ldlm_lock *req,
                 if (!(lock->l_policy_data.l_inodebits.bits & req_bits))
                         continue;
 
-                if (!send_cbs)
+                if (!work_list)
                         RETURN(0);
 
                 compat = 0;
                 if (lock->l_blocking_ast)
-                        ldlm_add_ast_work_item(lock, req, NULL, 0);
+                        ldlm_add_ast_work_item(lock, req, work_list);
         }
 
         RETURN(compat);
@@ -82,7 +82,8 @@ ldlm_inodebits_compat_queue(struct list_head *queue, struct ldlm_lock *req,
   *   - the caller has NOT initialized req->lr_tmp, so we must
   *   - must call this function with the ns lock held once */
 int ldlm_process_inodebits_lock(struct ldlm_lock *lock, int *flags,
-                                int first_enq, ldlm_error_t *err)
+                                int first_enq, ldlm_error_t *err,
+                                struct list_head *work_list)
 {
         struct ldlm_resource *res = lock->l_resource;
         struct list_head rpc_list = CFS_LIST_HEAD_INIT(rpc_list);
@@ -90,27 +91,25 @@ int ldlm_process_inodebits_lock(struct ldlm_lock *lock, int *flags,
         ENTRY;
 
         LASSERT(list_empty(&res->lr_converting));
+        check_res_locked(res);
 
         if (!first_enq) {
-                LASSERT(res->lr_tmp != NULL);
-                rc = ldlm_inodebits_compat_queue(&res->lr_granted, lock, 0);
+                LASSERT(work_list != NULL);
+                rc = ldlm_inodebits_compat_queue(&res->lr_granted, lock, NULL);
                 if (!rc)
                         RETURN(LDLM_ITER_STOP);
-                rc = ldlm_inodebits_compat_queue(&res->lr_waiting, lock, 0);
+                rc = ldlm_inodebits_compat_queue(&res->lr_waiting, lock, NULL);
                 if (!rc)
                         RETURN(LDLM_ITER_STOP);
 
                 ldlm_resource_unlink_lock(lock);
-                ldlm_grant_lock(lock, NULL, 0, 1);
+                ldlm_grant_lock(lock, work_list);
                 RETURN(LDLM_ITER_CONTINUE);
         }
 
  restart:
-        LASSERT(res->lr_tmp == NULL);
-        res->lr_tmp = &rpc_list;
-        rc = ldlm_inodebits_compat_queue(&res->lr_granted, lock, 1);
-        rc += ldlm_inodebits_compat_queue(&res->lr_waiting, lock, 1);
-        res->lr_tmp = NULL;
+        rc = ldlm_inodebits_compat_queue(&res->lr_granted, lock, &rpc_list);
+        rc += ldlm_inodebits_compat_queue(&res->lr_waiting, lock, &rpc_list);
 
         if (rc != 2) {
                 /* If either of the compat_queue()s returned 0, then we
@@ -121,15 +120,15 @@ int ldlm_process_inodebits_lock(struct ldlm_lock *lock, int *flags,
                  * re-ordered!  Causes deadlock, because ASTs aren't sent! */
                 if (list_empty(&lock->l_res_link))
                         ldlm_resource_add_lock(res, &res->lr_waiting, lock);
-                l_unlock(&res->lr_namespace->ns_lock);
-                rc = ldlm_run_ast_work(res->lr_namespace, &rpc_list);
-                l_lock(&res->lr_namespace->ns_lock);
+                unlock_res(res);
+                rc = ldlm_run_bl_ast_work(&rpc_list);
+                lock_res(res);
                 if (rc == -ERESTART)
                         GOTO(restart, -ERESTART);
                 *flags |= LDLM_FL_BLOCK_GRANTED;
         } else {
                 ldlm_resource_unlink_lock(lock);
-                ldlm_grant_lock(lock, NULL, 0, 0);
+                ldlm_grant_lock(lock, NULL);
         }
         RETURN(0);
 }
index 7e7c000..6decf99 100644 (file)
@@ -11,12 +11,12 @@ typedef enum {
 int ldlm_cancel_lru(struct ldlm_namespace *ns, ldlm_sync_t sync);
 
 /* ldlm_resource.c */
+int ldlm_resource_putref_locked(struct ldlm_resource *res);
 void ldlm_resource_insert_lock_after(struct ldlm_lock *original,
                                      struct ldlm_lock *new);
 
 /* ldlm_lock.c */
-void ldlm_grant_lock(struct ldlm_lock *lock, void *data, int datalen,
-                     int run_ast);
+void ldlm_grant_lock(struct ldlm_lock *lock, struct list_head *work_list);
 struct ldlm_lock *
 ldlm_lock_create(struct ldlm_namespace *ns,
                  const struct lustre_handle *parent_lock_handle,
@@ -29,9 +29,13 @@ ldlm_error_t ldlm_lock_enqueue(struct ldlm_namespace *, struct ldlm_lock **,
 void ldlm_lock_addref_internal(struct ldlm_lock *, __u32 mode);
 void ldlm_lock_decref_internal(struct ldlm_lock *, __u32 mode);
 void ldlm_add_ast_work_item(struct ldlm_lock *lock, struct ldlm_lock *new,
-                            void *data, int datalen);
-int ldlm_reprocess_queue(struct ldlm_resource *res, struct list_head *queue);
-int ldlm_run_ast_work(struct ldlm_namespace *, struct list_head *rpc_list);
+                                struct list_head *work_list);
+int ldlm_reprocess_queue(struct ldlm_resource *res, struct list_head *queue,
+                         struct list_head *work_list);
+int ldlm_run_bl_ast_work(struct list_head *rpc_list);
+int ldlm_run_cp_ast_work(struct list_head *rpc_list);
+int ldlm_lock_remove_from_lru_nolock(struct ldlm_lock *lock);
+void ldlm_lock_destroy_nolock(struct ldlm_lock *lock);
 
 /* ldlm_lockd.c */
 int ldlm_bl_to_thread(struct ldlm_namespace *ns, struct ldlm_lock_desc *ld,
@@ -41,19 +45,20 @@ void ldlm_handle_bl_callback(struct ldlm_namespace *ns,
 
 /* ldlm_plain.c */
 int ldlm_process_plain_lock(struct ldlm_lock *lock, int *flags, int first_enq,
-                            ldlm_error_t *err);
+                            ldlm_error_t *err, struct list_head *work_list);
 
 /* ldlm_extent.c */
 int ldlm_process_extent_lock(struct ldlm_lock *lock, int *flags, int first_enq,
-                             ldlm_error_t *err);
+                             ldlm_error_t *err, struct list_head *work_list);
 
 /* ldlm_flock.c */
-int ldlm_process_flock_lock(struct ldlm_lock *lock, int *flags, int first_enq,
-                            ldlm_error_t *err);
+int ldlm_process_flock_lock(struct ldlm_lock *req, int *flags, int first_enq,
+                            ldlm_error_t *err, struct list_head *work_list);
 
 /* ldlm_inodebits.c */
 int ldlm_process_inodebits_lock(struct ldlm_lock *lock, int *flags,
-                                int first_enq, ldlm_error_t *err);
+                                int first_enq, ldlm_error_t *err,
+                                struct list_head *work_list);
 
 /* l_lock.c */
 void l_check_ns_lock(struct ldlm_namespace *ns);
index 09bae06..6999b4b 100644 (file)
@@ -73,6 +73,7 @@ static int import_set_conn(struct obd_import *imp, struct obd_uuid *uuid,
                         if (priority) {
                                 list_del(&item->oic_item);
                                 list_add(&item->oic_item, &imp->imp_conn_list);
+                                item->oic_last_attempt = 0;
                         }
                         CDEBUG(D_HA, "imp %p@%s: found existing conn %s%s\n",
                                imp, imp->imp_obd->obd_name, uuid->uuid,
@@ -85,6 +86,7 @@ static int import_set_conn(struct obd_import *imp, struct obd_uuid *uuid,
         if (create) {
                 imp_conn->oic_conn = ptlrpc_conn;
                 imp_conn->oic_uuid = *uuid;
+                item->oic_last_attempt = 0;
                 if (priority)
                         list_add(&imp_conn->oic_item, &imp->imp_conn_list);
                 else
@@ -122,7 +124,6 @@ int client_import_add_conn(struct obd_import *imp, struct obd_uuid *uuid,
 int client_import_del_conn(struct obd_import *imp, struct obd_uuid *uuid)
 {
         struct obd_import_conn *imp_conn;
-        struct obd_import_conn *cur_conn;
         struct obd_export *dlmexp;
         int rc = -ENOENT;
         ENTRY;
@@ -138,12 +139,8 @@ int client_import_del_conn(struct obd_import *imp, struct obd_uuid *uuid)
                         continue;
                 LASSERT(imp_conn->oic_conn);
 
-                cur_conn = list_entry(imp->imp_conn_list.next,
-                                      struct obd_import_conn,
-                                      oic_item);
-
                 /* is current conn? */
-                if (imp_conn == cur_conn) {
+                if (imp_conn == imp->imp_conn_current) {
                         LASSERT(imp_conn->oic_conn == imp->imp_connection);
 
                         if (imp->imp_state != LUSTRE_IMP_CLOSED &&
@@ -263,8 +260,13 @@ int client_obd_setup(struct obd_device *obddev, struct lustre_cfg *lcfg)
         spin_lock_init(&cli->cl_write_page_hist.oh_lock);
         spin_lock_init(&cli->cl_read_offset_hist.oh_lock);
         spin_lock_init(&cli->cl_write_offset_hist.oh_lock);
-        cli->cl_max_pages_per_rpc = PTLRPC_MAX_BRW_PAGES;
-        if (num_physpages >> (20 - PAGE_SHIFT) <= 128 /* MB */) {
+        /*
+            cli->cl_max_pages_per_rpc = PTLRPC_MAX_BRW_PAGES;
+            This filed value is seted at connect time by ocd_brw_size.
+        */
+        if (!strcmp(name, LUSTRE_MDC_NAME)) {
+                cli->cl_max_rpcs_in_flight = MDC_MAX_RIF_DEFAULT;
+        } else if (num_physpages >> (20 - PAGE_SHIFT) <= 128 /* MB */) {
                 cli->cl_max_rpcs_in_flight = 2;
         } else if (num_physpages >> (20 - PAGE_SHIFT) <= 256 /* MB */) {
                 cli->cl_max_rpcs_in_flight = 3;
@@ -438,6 +440,11 @@ int client_disconnect_export(struct obd_export *exp)
         if (cli->cl_conn_count)
                 GOTO(out_no_disconnect, rc = 0);
 
+        /* Mark import deactivated now, so we don't try to reconnect if any
+         * of the cleanup RPCs fails (e.g. ldlm cancel, etc).  We don't
+         * fully deactivate the import, or that would drop all requests. */
+        imp->imp_deactive = 1;
+
         /* Some non-replayable imports (MDS's OSCs) are pinged, so just
          * delete it regardless.  (It's safe to delete an import that was
          * never added.) */
@@ -446,7 +453,8 @@ int client_disconnect_export(struct obd_export *exp)
         if (obd->obd_namespace != NULL) {
                 /* obd_no_recov == local only */
                 ldlm_cli_cancel_unused(obd->obd_namespace, NULL,
-                                       obd->obd_no_recov, NULL);
+                                       obd->obd_no_recov ? LDLM_FL_LOCAL_ONLY:0,
+                                       NULL);
                 ldlm_namespace_free(obd->obd_namespace, obd->obd_no_recov);
                 obd->obd_namespace = NULL;
         }
@@ -456,7 +464,6 @@ int client_disconnect_export(struct obd_export *exp)
                 rc = ptlrpc_disconnect_import(imp);
 
         ptlrpc_invalidate_import(imp);
-        imp->imp_deactive = 1;
         ptlrpc_free_rq_pool(imp->imp_rq_pool);
         class_destroy_import(imp);
         cli->cl_import = NULL;
@@ -513,7 +520,7 @@ int target_handle_reconnect(struct lustre_handle *conn, struct obd_export *exp,
 
 int target_handle_connect(struct ptlrpc_request *req, svc_handler_t handler)
 {
-        struct obd_device *target;
+        struct obd_device *target, *targref = NULL;
         struct obd_export *export = NULL;
         struct obd_import *revimp;
         struct lustre_handle conn;
@@ -523,15 +530,14 @@ int target_handle_connect(struct ptlrpc_request *req, svc_handler_t handler)
         struct list_head *p;
         char *str, *tmp;
         int rc = 0, abort_recovery;
-        unsigned long flags;
         struct obd_connect_data *data;
-        int size = sizeof(*data);
+        int size[2] = { sizeof(struct ptlrpc_body), sizeof(*data) };
         ENTRY;
 
         OBD_RACE(OBD_FAIL_TGT_CONN_RACE);
 
-        LASSERT_REQSWAB (req, 0);
-        str = lustre_msg_string(req->rq_reqmsg, 0, sizeof(tgtuuid) - 1);
+        LASSERT_REQSWAB(req, REQ_REC_OFF);
+        str = lustre_msg_string(req->rq_reqmsg, REQ_REC_OFF, sizeof(tgtuuid)-1);
         if (str == NULL) {
                 DEBUG_REQ(D_ERROR, req, "bad target UUID for connect");
                 GOTO(out, rc = -EINVAL);
@@ -558,8 +564,14 @@ int target_handle_connect(struct ptlrpc_request *req, svc_handler_t handler)
                 GOTO(out, rc = -ENODEV);
         }
 
-        LASSERT_REQSWAB (req, 1);
-        str = lustre_msg_string(req->rq_reqmsg, 1, sizeof(cluuid) - 1);
+        /* Make sure the target isn't cleaned up while we're here. Yes, 
+           there's still a race between the above check and our incref here. 
+           Really, class_uuid2obd should take the ref. */
+        targref = class_incref(target);
+
+        LASSERT_REQSWAB(req, REQ_REC_OFF + 1);
+        str = lustre_msg_string(req->rq_reqmsg, REQ_REC_OFF + 1,
+                                sizeof(cluuid) - 1);
         if (str == NULL) {
                 DEBUG_REQ(D_ERROR, req, "bad client UUID for connect");
                 GOTO(out, rc = -EINVAL);
@@ -588,14 +600,15 @@ int target_handle_connect(struct ptlrpc_request *req, svc_handler_t handler)
         if (abort_recovery)
                 target_abort_recovery(target);
 
-        tmp = lustre_msg_buf(req->rq_reqmsg, 2, sizeof conn);
+        tmp = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF + 2, sizeof conn);
         if (tmp == NULL)
                 GOTO(out, rc = -EPROTO);
 
         memcpy(&conn, tmp, sizeof conn);
 
-        data = lustre_swab_reqbuf(req, 3, sizeof(*data), lustre_swab_connect);
-        rc = lustre_pack_reply(req, 1, &size, NULL);
+        data = lustre_swab_reqbuf(req, REQ_REC_OFF + 3, sizeof(*data),
+                                  lustre_swab_connect);
+        rc = lustre_pack_reply(req, 2, size, NULL);
         if (rc)
                 GOTO(out, rc);
 
@@ -612,7 +625,7 @@ int target_handle_connect(struct ptlrpc_request *req, svc_handler_t handler)
                                   OBD_OCD_VERSION_MINOR(data->ocd_version),
                                   OBD_OCD_VERSION_PATCH(data->ocd_version),
                                   OBD_OCD_VERSION_FIX(data->ocd_version));
-                        data = lustre_msg_buf(req->rq_repmsg, 0,
+                        data = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
                                               offsetof(typeof(*data),
                                                        ocd_version) +
                                               sizeof(data->ocd_version));
@@ -652,7 +665,7 @@ int target_handle_connect(struct ptlrpc_request *req, svc_handler_t handler)
         if (!export) {
                 spin_unlock(&target->obd_dev_lock);
                 OBD_FAIL_TIMEOUT(OBD_FAIL_TGT_DELAY_CONNECT, 2 * obd_timeout);
-        } else if (req->rq_reqmsg->conn_cnt == 1) {
+        } else if (lustre_msg_get_conn_cnt(req->rq_reqmsg) == 1) {
                 CERROR("%s: NID %s (%s) reconnected with 1 conn_cnt; "
                        "cookies not random?\n", target->obd_name,
                        libcfs_nid2str(req->rq_peer.nid), cluuid.uuid);
@@ -706,19 +719,23 @@ int target_handle_connect(struct ptlrpc_request *req, svc_handler_t handler)
         /* Return only the parts of obd_connect_data that we understand, so the
          * client knows that we don't understand the rest. */
         if (data)
-                memcpy(lustre_msg_buf(req->rq_repmsg, 0, sizeof(*data)), data,
-                       sizeof(*data));
+                memcpy(lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
+                                      sizeof(*data)),
+                       data, sizeof(*data));
 
         /* If all else goes well, this is our RPC return code. */
         req->rq_status = 0;
 
-        req->rq_repmsg->handle = conn;
+        lustre_msg_set_handle(req->rq_repmsg, &conn);
 
         /* ownership of this export ref transfers to the request AFTER we
          * drop any previous reference the request had, but we don't want
          * that to go to zero before we get our new export reference. */
         export = class_conn2export(&conn);
-        LASSERT(export != NULL);
+        if (!export) {
+                DEBUG_REQ(D_ERROR, req, "Missing export!\n");
+                GOTO(out, rc = -ENODEV);
+        }
 
         /* If the client and the server are the same node, we will already
          * have an export that really points to the client's DLM export,
@@ -732,16 +749,18 @@ int target_handle_connect(struct ptlrpc_request *req, svc_handler_t handler)
 
         req->rq_export = export;
 
-        spin_lock_irqsave(&export->exp_lock, flags);
-        if (export->exp_conn_cnt >= req->rq_reqmsg->conn_cnt) {
+        spin_lock(&export->exp_lock);
+        if (export->exp_conn_cnt >= lustre_msg_get_conn_cnt(req->rq_reqmsg)) {
                 CERROR("%s: %s already connected at higher conn_cnt: %d > %d\n",
                        cluuid.uuid, libcfs_nid2str(req->rq_peer.nid),
-                       export->exp_conn_cnt, req->rq_reqmsg->conn_cnt);
-                spin_unlock_irqrestore(&export->exp_lock, flags);
+                       export->exp_conn_cnt,
+                       lustre_msg_get_conn_cnt(req->rq_reqmsg));
+                       
+                spin_unlock(&export->exp_lock);
                 GOTO(out, rc = -EALREADY);
         }
-        export->exp_conn_cnt = req->rq_reqmsg->conn_cnt;
-        spin_unlock_irqrestore(&export->exp_lock, flags);
+        export->exp_conn_cnt = lustre_msg_get_conn_cnt(req->rq_reqmsg);
+        spin_unlock(&export->exp_lock);
 
         /* request from liblustre?  Don't evict it for not pinging. */
         if (lustre_msg_get_op_flags(req->rq_reqmsg) & MSG_CONNECT_LIBCLIENT) {
@@ -763,7 +782,8 @@ int target_handle_connect(struct ptlrpc_request *req, svc_handler_t handler)
         if (target->obd_recovering)
                 target->obd_connected_clients++;
 
-        memcpy(&conn, lustre_msg_buf(req->rq_reqmsg, 2, sizeof conn),
+        memcpy(&conn,
+               lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF + 2, sizeof conn),
                sizeof conn);
 
         if (export->exp_imp_reverse != NULL)
@@ -774,10 +794,18 @@ int target_handle_connect(struct ptlrpc_request *req, svc_handler_t handler)
         revimp->imp_remote_handle = conn;
         revimp->imp_dlm_fake = 1;
         revimp->imp_state = LUSTRE_IMP_FULL;
+
+        if (lustre_msg_get_op_flags(req->rq_reqmsg) & MSG_CONNECT_NEXT_VER) {
+                revimp->imp_msg_magic = LUSTRE_MSG_MAGIC_V2;
+                lustre_msg_add_op_flags(req->rq_repmsg, MSG_CONNECT_NEXT_VER);
+        }
+
         class_import_put(revimp);
 out:
         if (export)
                 export->exp_connecting = 0;
+        if (targref) 
+                class_decref(targref);
         if (rc)
                 req->rq_status = rc;
         RETURN(rc);
@@ -788,7 +816,7 @@ int target_handle_disconnect(struct ptlrpc_request *req)
         int rc;
         ENTRY;
 
-        rc = lustre_pack_reply(req, 0, NULL, NULL);
+        rc = lustre_pack_reply(req, 1, NULL, NULL);
         if (rc)
                 RETURN(rc);
 
@@ -866,7 +894,7 @@ static void abort_recovery_queue(struct obd_device *obd)
                 DEBUG_REQ(D_ERROR, req, "aborted:");
                 req->rq_status = -ENOTCONN;
                 req->rq_type = PTL_RPC_MSG_ERR;
-                rc = lustre_pack_reply(req, 0, NULL, NULL);
+                rc = lustre_pack_reply(req, 1, NULL, NULL);
                 if (rc == 0) {
                         ptlrpc_reply(req);
                 } else {
@@ -1008,7 +1036,7 @@ static int check_for_next_transno(struct obd_device *obd)
         req = list_entry(obd->obd_recovery_queue.next,
                          struct ptlrpc_request, rq_list);
         max = obd->obd_max_recoverable_clients;
-        req_transno = req->rq_reqmsg->transno;
+        req_transno = lustre_msg_get_transno(req->rq_reqmsg);
         connected = obd->obd_connected_clients;
         completed = max - obd->obd_recoverable_clients;
         queue_len = obd->obd_requests_queued_for_recovery;
@@ -1035,7 +1063,7 @@ static int check_for_next_transno(struct obd_device *obd)
                 wake_up = 1;
         }
         spin_unlock_bh(&obd->obd_processing_task_lock);
-        LASSERT(req->rq_reqmsg->transno >= next_transno);
+        LASSERT(lustre_msg_get_transno(req->rq_reqmsg) >= next_transno);
         return wake_up;
 }
 
@@ -1052,12 +1080,13 @@ static void process_recovery_queue(struct obd_device *obd)
                 req = list_entry(obd->obd_recovery_queue.next,
                                  struct ptlrpc_request, rq_list);
 
-                if (req->rq_reqmsg->transno != obd->obd_next_recovery_transno) {
+                if (lustre_msg_get_transno(req->rq_reqmsg) !=
+                    obd->obd_next_recovery_transno) {
                         spin_unlock_bh(&obd->obd_processing_task_lock);
                         CDEBUG(D_HA, "Waiting for transno "LPD64" (1st is "
                                LPD64")\n",
                                obd->obd_next_recovery_transno,
-                               req->rq_reqmsg->transno);
+                               lustre_msg_get_transno(req->rq_reqmsg));
                         l_wait_event(obd->obd_next_transno_waitq,
                                      check_for_next_transno(obd), &lwi);
                         spin_lock_bh(&obd->obd_processing_task_lock);
@@ -1103,7 +1132,7 @@ int target_queue_recovery_request(struct ptlrpc_request *req,
 {
         struct list_head *tmp;
         int inserted = 0;
-        __u64 transno = req->rq_reqmsg->transno;
+        __u64 transno = lustre_msg_get_transno(req->rq_reqmsg);
         struct ptlrpc_request *saved_req;
         struct lustre_msg *reqmsg;
 
@@ -1171,7 +1200,7 @@ int target_queue_recovery_request(struct ptlrpc_request *req,
                 struct ptlrpc_request *reqiter =
                         list_entry(tmp, struct ptlrpc_request, rq_list);
 
-                if (reqiter->rq_reqmsg->transno > transno) {
+                if (lustre_msg_get_transno(reqiter->rq_reqmsg) > transno) {
                         list_add_tail(&req->rq_list, &reqiter->rq_list);
                         inserted = 1;
                         break;
@@ -1219,7 +1248,7 @@ int target_queue_final_reply(struct ptlrpc_request *req, int rc)
 
         if (rc) {
                 /* Just like ptlrpc_error, but without the sending. */
-                rc = lustre_pack_reply(req, 0, NULL, NULL);
+                rc = lustre_pack_reply(req, 1, NULL, NULL);
                 LASSERT(rc == 0); /* XXX handle this */
                 req->rq_type = PTL_RPC_MSG_ERR;
         }
@@ -1303,7 +1332,6 @@ void
 target_send_reply(struct ptlrpc_request *req, int rc, int fail_id)
 {
         int                        netrc;
-        unsigned long              flags;
         struct ptlrpc_reply_state *rs;
         struct obd_device         *obd;
         struct obd_export         *exp;
@@ -1341,7 +1369,7 @@ target_send_reply(struct ptlrpc_request *req, int rc, int fail_id)
         rs->rs_transno   = req->rq_transno;
         rs->rs_export    = exp;
 
-        spin_lock_irqsave (&obd->obd_uncommitted_replies_lock, flags);
+        spin_lock(&obd->obd_uncommitted_replies_lock);
 
         if (rs->rs_transno > obd->obd_last_committed) {
                 /* not committed already */
@@ -1354,11 +1382,11 @@ target_send_reply(struct ptlrpc_request *req, int rc, int fail_id)
 
         list_add_tail (&rs->rs_exp_list, &exp->exp_outstanding_replies);
 
-        spin_unlock_irqrestore (&exp->exp_lock, flags);
+        spin_unlock(&exp->exp_lock);
 
         netrc = target_send_reply_msg (req, rc, fail_id);
 
-        spin_lock_irqsave (&svc->srv_lock, flags);
+        spin_lock(&svc->srv_lock);
 
         svc->srv_n_difficult_replies++;
 
@@ -1383,12 +1411,13 @@ target_send_reply(struct ptlrpc_request *req, int rc, int fail_id)
                 rs->rs_scheduled = 0;           /* allow notifier to schedule */
         }
 
-        spin_unlock_irqrestore (&svc->srv_lock, flags);
+        spin_unlock(&svc->srv_lock);
 }
 
 int target_handle_ping(struct ptlrpc_request *req)
 {
-        return lustre_pack_reply(req, 0, NULL, NULL);
+        obd_ping(req->rq_export);
+        return lustre_pack_reply(req, 1, NULL, NULL);
 }
 
 void target_committed_to_req(struct ptlrpc_request *req)
@@ -1396,7 +1425,8 @@ void target_committed_to_req(struct ptlrpc_request *req)
         struct obd_device *obd = req->rq_export->exp_obd;
 
         if (!obd->obd_no_transno && req->rq_repmsg != NULL)
-                req->rq_repmsg->last_committed = obd->obd_last_committed;
+                lustre_msg_set_last_committed(req->rq_repmsg,
+                                              obd->obd_last_committed);
         else
                 DEBUG_REQ(D_IOCTL, req, "not sending last_committed update");
 
@@ -1412,8 +1442,12 @@ int target_handle_qc_callback(struct ptlrpc_request *req)
         struct obd_quotactl *oqctl;
         struct client_obd *cli = &req->rq_export->exp_obd->u.cli;
 
-        oqctl = lustre_swab_reqbuf(req, 0, sizeof(*oqctl),
+        oqctl = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*oqctl),
                                    lustre_swab_obd_quotactl);
+        if (oqctl == NULL) {
+                CERROR("Can't unpack obd_quotactl\n");
+                RETURN(-EPROTO);
+        }
 
         cli->cl_qchk_stat = oqctl->qc_stat;
 
@@ -1427,20 +1461,23 @@ int target_handle_dqacq_callback(struct ptlrpc_request *req)
         struct obd_device *master_obd;
         struct lustre_quota_ctxt *qctxt;
         struct qunit_data *qdata, *rep;
-        int rc = 0, repsize = sizeof(struct qunit_data);
+        int rc = 0;
+        int repsize[2] = { sizeof(struct ptlrpc_body),
+                           sizeof(struct qunit_data) };
         ENTRY;
-
-        rc = lustre_pack_reply(req, 1, &repsize, NULL);
+        
+        rc = lustre_pack_reply(req, 2, repsize, NULL);
         if (rc) {
                 CERROR("packing reply failed!: rc = %d\n", rc);
                 RETURN(rc);
         }
-        rep = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*rep));
+        rep = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF, sizeof(*rep));
         LASSERT(rep);
-
-        qdata = lustre_swab_reqbuf(req, 0, sizeof(*qdata), lustre_swab_qdata);
+        
+        qdata = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*qdata),
+                                   lustre_swab_qdata);
         if (qdata == NULL) {
-                CERROR("unpacking request buffer failed!");
+                CERROR("Can't unpack qunit_data\n");
                 RETURN(-EPROTO);
         }
 
@@ -1450,9 +1487,10 @@ int target_handle_dqacq_callback(struct ptlrpc_request *req)
         qctxt = &master_obd->u.obt.obt_qctxt;
 
         LASSERT(qctxt->lqc_handler);
-        rc = qctxt->lqc_handler(master_obd, qdata, req->rq_reqmsg->opc);
+        rc = qctxt->lqc_handler(master_obd, qdata,
+                                lustre_msg_get_opc(req->rq_reqmsg));
         if (rc && rc != -EDQUOT)
-                CDEBUG_EX(rc == -EBUSY  ? D_QUOTA : D_ERROR,
+                CDEBUG(rc == -EBUSY  ? D_QUOTA : D_ERROR,
                        "dqacq failed! (rc:%d)\n", rc);
 
         /* the qd_count might be changed in lqc_handler */
index 43c4611..e4e5ef3 100644 (file)
@@ -28,6 +28,7 @@
 
 #ifdef __KERNEL__
 # include <libcfs/libcfs.h>
+# include <linux/lustre_intent.h>
 #else
 # include <liblustre.h>
 # include <libcfs/kp30.h>
@@ -49,6 +50,7 @@ char *ldlm_lockname[] = {
         [LCK_NL] "NL",
         [LCK_GROUP] "GROUP"
 };
+
 char *ldlm_typename[] = {
         [LDLM_PLAIN] "PLN",
         [LDLM_EXTENT] "EXT",
@@ -82,7 +84,6 @@ char *ldlm_it2str(int it)
 }
 
 extern cfs_mem_cache_t *ldlm_lock_slab;
-struct lustre_lock ldlm_handle_lock;
 
 static ldlm_processing_policy ldlm_processing_policy_table[] = {
         [LDLM_PLAIN] ldlm_process_plain_lock,
@@ -124,50 +125,59 @@ void ldlm_lock_put(struct ldlm_lock *lock)
 {
         ENTRY;
 
+        LASSERT(lock->l_resource != LP_POISON);
+        LASSERT(atomic_read(&lock->l_refc) > 0);
         if (atomic_dec_and_test(&lock->l_refc)) {
-                struct ldlm_namespace *ns = lock->l_resource->lr_namespace;
-                struct obd_export *export = NULL;
+                struct ldlm_resource *res;
 
-                l_lock(&ns->ns_lock);
                 LDLM_DEBUG(lock, "final lock_put on destroyed lock, freeing it.");
+
+                lock_res_and_lock(lock);
+                res = lock->l_resource;
                 LASSERT(lock->l_destroyed);
                 LASSERT(list_empty(&lock->l_res_link));
 
-                spin_lock(&ns->ns_counter_lock);
-                ns->ns_locks--;
-                spin_unlock(&ns->ns_counter_lock);
-
-                ldlm_resource_putref(lock->l_resource);
-                lock->l_resource = NULL;
-                export = lock->l_export;
-
                 if (lock->l_parent)
                         LDLM_LOCK_PUT(lock->l_parent);
+                unlock_res_and_lock(lock);
+
+                atomic_dec(&res->lr_namespace->ns_locks);
+                ldlm_resource_putref(res);
+                lock->l_resource = NULL;
+                if (lock->l_export)
+                        class_export_put(lock->l_export);
 
                 if (lock->l_lvb_data != NULL)
                         OBD_FREE(lock->l_lvb_data, lock->l_lvb_len);
 
                 OBD_SLAB_FREE(lock, ldlm_lock_slab, sizeof(*lock));
-                l_unlock(&ns->ns_lock);
-                if (export)
-                        class_export_put(export);
         }
 
         EXIT;
 }
 
-void ldlm_lock_remove_from_lru(struct ldlm_lock *lock)
+int ldlm_lock_remove_from_lru_nolock(struct ldlm_lock *lock)
 {
-        ENTRY;
-        l_lock(&lock->l_resource->lr_namespace->ns_lock);
+        int rc = 0;
         if (!list_empty(&lock->l_lru)) {
                 LASSERT(lock->l_resource->lr_type != LDLM_FLOCK);
                 list_del_init(&lock->l_lru);
                 lock->l_resource->lr_namespace->ns_nr_unused--;
                 LASSERT(lock->l_resource->lr_namespace->ns_nr_unused >= 0);
+                rc = 1;
         }
-        l_unlock(&lock->l_resource->lr_namespace->ns_lock);
+        return rc;
+}
+
+int ldlm_lock_remove_from_lru(struct ldlm_lock *lock)
+{
+        int rc;
+        ENTRY;
+        spin_lock(&lock->l_resource->lr_namespace->ns_unused_lock);
+        rc = ldlm_lock_remove_from_lru_nolock(lock);
+        spin_unlock(&lock->l_resource->lr_namespace->ns_unused_lock);
         EXIT;
+        return rc;
 }
 
 /* This used to have a 'strict' flag, which recovery would use to mark an
@@ -175,10 +185,9 @@ void ldlm_lock_remove_from_lru(struct ldlm_lock *lock)
  * shall explain why it's gone: with the new hash table scheme, once you call
  * ldlm_lock_destroy, you can never drop your final references on this lock.
  * Because it's not in the hash table anymore.  -phil */
-void ldlm_lock_destroy(struct ldlm_lock *lock)
+int ldlm_lock_destroy_internal(struct ldlm_lock *lock)
 {
         ENTRY;
-        l_lock(&lock->l_resource->lr_namespace->ns_lock);
 
         if (!list_empty(&lock->l_children)) {
                 LDLM_ERROR(lock, "still has children (%p)!",
@@ -200,13 +209,17 @@ void ldlm_lock_destroy(struct ldlm_lock *lock)
 
         if (lock->l_destroyed) {
                 LASSERT(list_empty(&lock->l_lru));
-                l_unlock(&lock->l_resource->lr_namespace->ns_lock);
                 EXIT;
-                return;
+                return 0;
         }
         lock->l_destroyed = 1;
 
+        if (lock->l_export)
+                spin_lock(&lock->l_export->exp_ldlm_data.led_lock);
         list_del_init(&lock->l_export_chain);
+        if (lock->l_export)
+                spin_unlock(&lock->l_export->exp_ldlm_data.led_lock);
+
         ldlm_lock_remove_from_lru(lock);
         class_handle_unhash(&lock->l_handle);
 
@@ -220,9 +233,32 @@ void ldlm_lock_destroy(struct ldlm_lock *lock)
         if (lock->l_export && lock->l_completion_ast)
                 lock->l_completion_ast(lock, 0);
 #endif
+        EXIT;
+        return 1;
+}
 
-        l_unlock(&lock->l_resource->lr_namespace->ns_lock);
-        LDLM_LOCK_PUT(lock);
+void ldlm_lock_destroy(struct ldlm_lock *lock)
+{
+        int first;
+        ENTRY;
+        lock_res_and_lock(lock);
+        first = ldlm_lock_destroy_internal(lock);
+        unlock_res_and_lock(lock);
+
+        /* drop reference from hashtable only for first destroy */
+        if (first)
+                LDLM_LOCK_PUT(lock);
+        EXIT;
+}
+
+void ldlm_lock_destroy_nolock(struct ldlm_lock *lock)
+{
+        int first;
+        ENTRY;
+        first = ldlm_lock_destroy_internal(lock);
+        /* drop reference from hashtable only for first destroy */
+        if (first)
+                LDLM_LOCK_PUT(lock);
         EXIT;
 }
 
@@ -255,22 +291,24 @@ static struct ldlm_lock *ldlm_lock_new(struct ldlm_lock *parent,
 
         atomic_set(&lock->l_refc, 2);
         CFS_INIT_LIST_HEAD(&lock->l_children);
-        CFS_INIT_LIST_HEAD(&lock->l_childof);
         CFS_INIT_LIST_HEAD(&lock->l_res_link);
         CFS_INIT_LIST_HEAD(&lock->l_lru);
         CFS_INIT_LIST_HEAD(&lock->l_export_chain);
         CFS_INIT_LIST_HEAD(&lock->l_pending_chain);
+        CFS_INIT_LIST_HEAD(&lock->l_tmp);
+        CFS_INIT_LIST_HEAD(&lock->l_bl_ast);
+        CFS_INIT_LIST_HEAD(&lock->l_cp_ast);
         cfs_waitq_init(&lock->l_waitq);
+        lock->l_blocking_lock = NULL;
+        lock->l_pidb = 0;
 
-        spin_lock(&resource->lr_namespace->ns_counter_lock);
-        resource->lr_namespace->ns_locks++;
-        spin_unlock(&resource->lr_namespace->ns_counter_lock);
+        atomic_inc(&resource->lr_namespace->ns_locks);
 
         if (parent != NULL) {
-                l_lock(&parent->l_resource->lr_namespace->ns_lock);
+                spin_lock(&resource->lr_namespace->ns_hash_lock);
                 lock->l_parent = LDLM_LOCK_GET(parent);
                 list_add(&lock->l_childof, &parent->l_children);
-                l_unlock(&parent->l_resource->lr_namespace->ns_lock);
+                spin_unlock(&resource->lr_namespace->ns_hash_lock);
         }
 
         CFS_INIT_LIST_HEAD(&lock->l_handle.h_link);
@@ -283,13 +321,17 @@ int ldlm_lock_change_resource(struct ldlm_namespace *ns, struct ldlm_lock *lock,
                               struct ldlm_res_id new_resid)
 {
         struct ldlm_resource *oldres = lock->l_resource;
+        struct ldlm_resource *newres;
+        int type;
         ENTRY;
 
-        l_lock(&ns->ns_lock);
+        LASSERT(ns->ns_client != 0);
+
+        lock_res_and_lock(lock);
         if (memcmp(&new_resid, &lock->l_resource->lr_name,
                    sizeof(lock->l_resource->lr_name)) == 0) {
                 /* Nothing to do */
-                l_unlock(&ns->ns_lock);
+                unlock_res_and_lock(lock);
                 RETURN(0);
         }
 
@@ -298,18 +340,27 @@ int ldlm_lock_change_resource(struct ldlm_namespace *ns, struct ldlm_lock *lock,
         /* This function assumes that the lock isn't on any lists */
         LASSERT(list_empty(&lock->l_res_link));
 
-        lock->l_resource = ldlm_resource_get(ns, NULL, new_resid,
-                                             lock->l_resource->lr_type, 1);
-        if (lock->l_resource == NULL) {
-                l_unlock(&ns->ns_lock);
+        type = oldres->lr_type;
+        unlock_res_and_lock(lock);
+
+        newres = ldlm_resource_get(ns, NULL, new_resid, type, 1);
+        if (newres == NULL) {
                 LBUG();
                 RETURN(-ENOMEM);
         }
 
+        lock_res_and_lock(lock);
+        LASSERT(memcmp(&new_resid, &lock->l_resource->lr_name,
+                       sizeof(lock->l_resource->lr_name)) != 0);
+        lock_res(newres);
+        lock->l_resource = newres;
+        unlock_res(newres);
+        unlock_res(oldres);
+        unlock_bitlock(lock);
+
         /* ...and the flowers are still standing! */
         ldlm_resource_putref(oldres);
 
-        l_unlock(&ns->ns_lock);
         RETURN(0);
 }
 
@@ -343,17 +394,19 @@ struct ldlm_lock *__ldlm_handle2lock(const struct lustre_handle *handle,
         ns = lock->l_resource->lr_namespace;
         LASSERT(ns != NULL);
 
-        l_lock(&ns->ns_lock);
+        lock_res_and_lock(lock);
 
         /* It's unlikely but possible that someone marked the lock as
          * destroyed after we did handle2object on it */
         if (lock->l_destroyed) {
+                unlock_res_and_lock(lock);
                 CDEBUG(D_INFO, "lock already destroyed: lock %p\n", lock);
                 LDLM_LOCK_PUT(lock);
                 GOTO(out, retval);
         }
 
         if (flags && (lock->l_flags & flags)) {
+                unlock_res_and_lock(lock);
                 LDLM_LOCK_PUT(lock);
                 GOTO(out, retval);
         }
@@ -361,10 +414,10 @@ struct ldlm_lock *__ldlm_handle2lock(const struct lustre_handle *handle,
         if (flags)
                 lock->l_flags |= flags;
 
+        unlock_res_and_lock(lock);
         retval = lock;
         EXIT;
  out:
-        l_unlock(&ns->ns_lock);
         return retval;
 }
 
@@ -372,11 +425,7 @@ struct ldlm_lock *ldlm_handle2lock_ns(struct ldlm_namespace *ns,
                                       const struct lustre_handle *handle)
 {
         struct ldlm_lock *retval = NULL;
-
-        l_lock(&ns->ns_lock);
         retval = __ldlm_handle2lock(handle, 0);
-        l_unlock(&ns->ns_lock);
-
         return retval;
 }
 
@@ -426,42 +475,46 @@ void ldlm_lock2desc(struct ldlm_lock *lock, struct ldlm_lock_desc *desc)
         }
 }
 
-void ldlm_add_ast_work_item(struct ldlm_lock *lock, struct ldlm_lock *new,
-                            void *data, int datalen)
+void ldlm_add_bl_work_item(struct ldlm_lock *lock, struct ldlm_lock *new,
+                           struct list_head *work_list)
 {
-        struct ldlm_ast_work *w;
-        ENTRY;
-
-        l_lock(&lock->l_resource->lr_namespace->ns_lock);
-        if (new && (lock->l_flags & LDLM_FL_AST_SENT))
-                GOTO(out, 0);
-
-        CDEBUG(D_OTHER, "lock %p incompatible; sending blocking AST.\n", lock);
-
-        OBD_ALLOC(w, sizeof(*w));
-        if (!w) {
-                LBUG();
-                GOTO(out, 0);
-        }
-
-        w->w_data = data;
-        w->w_datalen = datalen;
-        if (new) {
+        if ((lock->l_flags & LDLM_FL_AST_SENT) == 0) {
                 LDLM_DEBUG(lock, "lock incompatible; sending blocking AST.");
                 lock->l_flags |= LDLM_FL_AST_SENT;
                 /* If the enqueuing client said so, tell the AST recipient to
                  * discard dirty data, rather than writing back. */
                 if (new->l_flags & LDLM_AST_DISCARD_DATA)
                         lock->l_flags |= LDLM_FL_DISCARD_DATA;
-                w->w_blocking = 1;
-                ldlm_lock2desc(new, &w->w_desc);
+                LASSERT(list_empty(&lock->l_bl_ast));
+                list_add(&lock->l_bl_ast, work_list);
+                LDLM_LOCK_GET(lock);
+                LASSERT(lock->l_blocking_lock == NULL);
+                lock->l_blocking_lock = LDLM_LOCK_GET(new);
+        }
+}
+
+void ldlm_add_cp_work_item(struct ldlm_lock *lock, struct list_head *work_list)
+{
+        if ((lock->l_flags & LDLM_FL_CP_REQD) == 0) {
+                lock->l_flags |= LDLM_FL_CP_REQD;
+                LDLM_DEBUG(lock, "lock granted; sending completion AST.");
+                LASSERT(list_empty(&lock->l_cp_ast));
+                list_add(&lock->l_cp_ast, work_list);
+                LDLM_LOCK_GET(lock);
         }
+}
 
-        w->w_lock = LDLM_LOCK_GET(lock);
-        list_add(&w->w_list, lock->l_resource->lr_tmp);
+/* must be called with lr_lock held */
+void ldlm_add_ast_work_item(struct ldlm_lock *lock, struct ldlm_lock *new,
+                                struct list_head *work_list)
+{
+        ENTRY;
+        check_res_locked(lock->l_resource);
+        if (new)
+                ldlm_add_bl_work_item(lock, new, work_list);
+        else 
+                ldlm_add_cp_work_item(lock, work_list);
         EXIT;
- out:
-        l_unlock(&lock->l_resource->lr_namespace->ns_lock);
 }
 
 void ldlm_lock_addref(struct lustre_handle *lockh, __u32 mode)
@@ -469,14 +522,13 @@ void ldlm_lock_addref(struct lustre_handle *lockh, __u32 mode)
         struct ldlm_lock *lock;
 
         lock = ldlm_handle2lock(lockh);
+        LASSERT(lock != NULL);
         ldlm_lock_addref_internal(lock, mode);
         LDLM_LOCK_PUT(lock);
 }
 
-/* only called for local locks */
-void ldlm_lock_addref_internal(struct ldlm_lock *lock, __u32 mode)
+void ldlm_lock_addref_internal_nolock(struct ldlm_lock *lock, __u32 mode)
 {
-        l_lock(&lock->l_resource->lr_namespace->ns_lock);
         ldlm_lock_remove_from_lru(lock);
         if (mode & (LCK_NL | LCK_CR | LCK_PR))
                 lock->l_readers++;
@@ -485,7 +537,14 @@ void ldlm_lock_addref_internal(struct ldlm_lock *lock, __u32 mode)
         lock->l_last_used = cfs_time_current();
         LDLM_LOCK_GET(lock);
         LDLM_DEBUG(lock, "ldlm_lock_addref(%s)", ldlm_lockname[mode]);
-        l_unlock(&lock->l_resource->lr_namespace->ns_lock);
+}
+
+/* only called for local locks */
+void ldlm_lock_addref_internal(struct ldlm_lock *lock, __u32 mode)
+{
+        lock_res_and_lock(lock);
+        ldlm_lock_addref_internal_nolock(lock, mode);
+        unlock_res_and_lock(lock);
 }
 
 void ldlm_lock_decref_internal(struct ldlm_lock *lock, __u32 mode)
@@ -493,8 +552,10 @@ void ldlm_lock_decref_internal(struct ldlm_lock *lock, __u32 mode)
         struct ldlm_namespace *ns;
         ENTRY;
 
+        lock_res_and_lock(lock);
+
         ns = lock->l_resource->lr_namespace;
-        l_lock(&ns->ns_lock);
+
         LDLM_DEBUG(lock, "ldlm_lock_decref(%s)", ldlm_lockname[mode]);
         if (mode & (LCK_NL | LCK_CR | LCK_PR)) {
                 LASSERT(lock->l_readers > 0);
@@ -525,8 +586,9 @@ void ldlm_lock_decref_internal(struct ldlm_lock *lock, __u32 mode)
 
                 LDLM_LOCK_GET(lock); /* dropped by bl thread */
                 ldlm_lock_remove_from_lru(lock);
-                l_unlock(&ns->ns_lock);
-                if (ldlm_bl_to_thread(ns, NULL, lock) != 0)
+                unlock_res_and_lock(lock);
+                if ((lock->l_flags & LDLM_FL_ATOMIC_CB) ||
+                                ldlm_bl_to_thread(ns, NULL, lock) != 0)
                         ldlm_handle_bl_callback(ns, NULL, lock);
         } else if (ns->ns_client == LDLM_NAMESPACE_CLIENT &&
                    !lock->l_readers && !lock->l_writers &&
@@ -535,12 +597,14 @@ void ldlm_lock_decref_internal(struct ldlm_lock *lock, __u32 mode)
                  * reference, put it on the LRU. */
                 LASSERT(list_empty(&lock->l_lru));
                 LASSERT(ns->ns_nr_unused >= 0);
+                spin_lock(&ns->ns_unused_lock);
                 list_add_tail(&lock->l_lru, &ns->ns_unused_list);
                 ns->ns_nr_unused++;
-                l_unlock(&ns->ns_lock);
+                spin_unlock(&ns->ns_unused_lock);
+                unlock_res_and_lock(lock);
                 ldlm_cancel_lru(ns, LDLM_ASYNC);
         } else {
-                l_unlock(&ns->ns_lock);
+                unlock_res_and_lock(lock);
         }
 
         LDLM_LOCK_PUT(lock);    /* matches the ldlm_lock_get in addref */
@@ -565,10 +629,10 @@ void ldlm_lock_decref_and_cancel(struct lustre_handle *lockh, __u32 mode)
 
         LASSERT(lock != NULL);
 
-        l_lock(&lock->l_resource->lr_namespace->ns_lock);
         LDLM_DEBUG(lock, "ldlm_lock_decref(%s)", ldlm_lockname[mode]);
+        lock_res_and_lock(lock);
         lock->l_flags |= LDLM_FL_CBPENDING;
-        l_unlock(&lock->l_resource->lr_namespace->ns_lock);
+        unlock_res_and_lock(lock);
         ldlm_lock_decref_internal(lock, mode);
         LDLM_LOCK_PUT(lock);
 }
@@ -577,24 +641,25 @@ void ldlm_lock_decref_and_cancel(struct lustre_handle *lockh, __u32 mode)
  *  - ldlm_lock_enqueue
  *  - ldlm_reprocess_queue
  *  - ldlm_lock_convert
+ *
+ * must be called with lr_lock held
  */
-void ldlm_grant_lock(struct ldlm_lock *lock, void *data, int datalen,
-                     int run_ast)
+void ldlm_grant_lock(struct ldlm_lock *lock, struct list_head *work_list)
 {
         struct ldlm_resource *res = lock->l_resource;
         ENTRY;
 
-        l_lock(&lock->l_resource->lr_namespace->ns_lock);
+        check_res_locked(res);
+
         lock->l_granted_mode = lock->l_req_mode;
         ldlm_resource_add_lock(res, &res->lr_granted, lock);
 
         if (lock->l_granted_mode < res->lr_most_restr)
                 res->lr_most_restr = lock->l_granted_mode;
 
-        if (run_ast && lock->l_completion_ast != NULL)
-                ldlm_add_ast_work_item(lock, NULL, data, datalen);
+        if (work_list && lock->l_completion_ast != NULL)
+                ldlm_add_ast_work_item(lock, NULL, work_list);
 
-        l_unlock(&lock->l_resource->lr_namespace->ns_lock);
         EXIT;
 }
 
@@ -658,7 +723,7 @@ static struct ldlm_lock *search_queue(struct list_head *queue, ldlm_mode_t mode,
                 if (flags & LDLM_FL_TEST_LOCK)
                         LDLM_LOCK_GET(lock);
                 else
-                        ldlm_lock_addref_internal(lock, mode);
+                        ldlm_lock_addref_internal_nolock(lock, mode);
                 return lock;
         }
 
@@ -667,10 +732,10 @@ static struct ldlm_lock *search_queue(struct list_head *queue, ldlm_mode_t mode,
 
 void ldlm_lock_allow_match(struct ldlm_lock *lock)
 {
-        l_lock(&lock->l_resource->lr_namespace->ns_lock);
+        lock_res_and_lock(lock);
         lock->l_flags |= LDLM_FL_CAN_MATCH;
         cfs_waitq_signal(&lock->l_waitq);
-        l_unlock(&lock->l_resource->lr_namespace->ns_lock);
+        unlock_res_and_lock(lock);
 }
 
 /* Can be called in two ways:
@@ -719,7 +784,7 @@ int ldlm_lock_match(struct ldlm_namespace *ns, int flags,
                 RETURN(0);
         }
 
-        l_lock(&ns->ns_lock);
+        lock_res(res);
 
         lock = search_queue(&res->lr_granted, mode, policy, old_lock, flags);
         if (lock != NULL)
@@ -735,8 +800,8 @@ int ldlm_lock_match(struct ldlm_namespace *ns, int flags,
 
         EXIT;
  out:
+        unlock_res(res);
         ldlm_resource_putref(res);
-        l_unlock(&ns->ns_lock);
 
         if (lock) {
                 ldlm_lock2handle(lock, lockh);
@@ -756,7 +821,8 @@ int ldlm_lock_match(struct ldlm_namespace *ns, int flags,
                                 }
                         }
 
-                        lwi = LWI_TIMEOUT_INTR(cfs_time_seconds(obd_timeout), NULL,NULL,NULL);
+                        lwi = LWI_TIMEOUT_INTR(cfs_time_seconds(obd_timeout), NULL,
+                                               LWI_ON_SIGNAL_NOOP, NULL);
 
                         /* XXX FIXME see comment on CAN_MATCH in lustre_dlm.h */
                         l_wait_event(lock->l_waitq,
@@ -765,13 +831,11 @@ int ldlm_lock_match(struct ldlm_namespace *ns, int flags,
         }
  out2:
         if (rc) {
-                l_lock(&ns->ns_lock);
                 LDLM_DEBUG(lock, "matched ("LPU64" "LPU64")",
                            (type == LDLM_PLAIN || type == LDLM_IBITS) ?
                                 res_id->name[2] : policy->l_extent.start,
                            (type == LDLM_PLAIN || type == LDLM_IBITS) ?
                                 res_id->name[3] : policy->l_extent.end);
-                l_unlock(&ns->ns_lock);
         } else if (!(flags & LDLM_FL_TEST_LOCK)) {/*less verbose for test-only*/
                 LDLM_DEBUG_NOLOCK("not matched ns %p type %u mode %u res "
                                   LPU64"/"LPU64" ("LPU64" "LPU64")", ns,
@@ -876,7 +940,7 @@ ldlm_error_t ldlm_lock_enqueue(struct ldlm_namespace *ns,
                 }
         }
 
-        l_lock(&ns->ns_lock);
+        lock_res_and_lock(lock);
         if (local && lock->l_req_mode == lock->l_granted_mode) {
                 /* The server returned a blocked lock, but it was granted before
                  * we got a chance to actually enqueue it.  We don't need to do
@@ -908,7 +972,7 @@ ldlm_error_t ldlm_lock_enqueue(struct ldlm_namespace *ns,
                 else if (*flags & (LDLM_FL_BLOCK_WAIT | LDLM_FL_BLOCK_GRANTED))
                         ldlm_resource_add_lock(res, &res->lr_waiting, lock);
                 else
-                        ldlm_grant_lock(lock, NULL, 0, 0);
+                        ldlm_grant_lock(lock, NULL);
                 GOTO(out, ELDLM_OK);
         } else if (*flags & LDLM_FL_REPLAY) {
                 if (*flags & LDLM_FL_BLOCK_CONV) {
@@ -918,22 +982,23 @@ ldlm_error_t ldlm_lock_enqueue(struct ldlm_namespace *ns,
                         ldlm_resource_add_lock(res, &res->lr_waiting, lock);
                         GOTO(out, ELDLM_OK);
                 } else if (*flags & LDLM_FL_BLOCK_GRANTED) {
-                        ldlm_grant_lock(lock, NULL, 0, 0);
+                        ldlm_grant_lock(lock, NULL);
                         GOTO(out, ELDLM_OK);
                 }
                 /* If no flags, fall through to normal enqueue path. */
         }
 
         policy = ldlm_processing_policy_table[res->lr_type];
-        policy(lock, flags, 1, &rc);
+        policy(lock, flags, 1, &rc, NULL);
         GOTO(out, rc);
 out:
-        l_unlock(&ns->ns_lock);
+        unlock_res_and_lock(lock);
         return rc;
 }
 
 /* Must be called with namespace taken: queue is waiting or converting. */
-int ldlm_reprocess_queue(struct ldlm_resource *res, struct list_head *queue)
+int ldlm_reprocess_queue(struct ldlm_resource *res, struct list_head *queue,
+                         struct list_head *work_list)
 {
         struct list_head *tmp, *pos;
         ldlm_processing_policy policy;
@@ -942,6 +1007,8 @@ int ldlm_reprocess_queue(struct ldlm_resource *res, struct list_head *queue)
         ldlm_error_t err;
         ENTRY;
 
+        check_res_locked(res);
+
         policy = ldlm_processing_policy_table[res->lr_type];
         LASSERT(policy);
 
@@ -952,7 +1019,7 @@ int ldlm_reprocess_queue(struct ldlm_resource *res, struct list_head *queue)
                 CDEBUG(D_INFO, "Reprocessing lock %p\n", pending);
 
                 flags = 0;
-                rc = policy(pending, &flags, 0, &err);
+                rc = policy(pending, &flags, 0, &err, work_list);
                 if (rc != LDLM_ITER_CONTINUE)
                         break;
         }
@@ -960,49 +1027,79 @@ int ldlm_reprocess_queue(struct ldlm_resource *res, struct list_head *queue)
         RETURN(rc);
 }
 
-int ldlm_run_ast_work(struct ldlm_namespace *ns, struct list_head *rpc_list)
+int ldlm_run_bl_ast_work(struct list_head *rpc_list)
 {
         struct list_head *tmp, *pos;
-        int rc, retval = 0;
+        struct ldlm_lock_desc d;
+        int rc = 0, retval = 0;
         ENTRY;
 
-        l_check_no_ns_lock(ns);
-
         list_for_each_safe(tmp, pos, rpc_list) {
-                struct ldlm_ast_work *w =
-                        list_entry(tmp, struct ldlm_ast_work, w_list);
-
-                /* It's possible to receive a completion AST before we've set
-                 * the l_completion_ast pointer: either because the AST arrived
-                 * before the reply, or simply because there's a small race
-                 * window between receiving the reply and finishing the local
-                 * enqueue. (bug 842)
-                 *
-                 * This can't happen with the blocking_ast, however, because we
-                 * will never call the local blocking_ast until we drop our
-                 * reader/writer reference, which we won't do until we get the
-                 * reply and finish enqueueing. */
-                LASSERT(w->w_lock != NULL);
-                if (w->w_blocking) {
-                        LASSERT(w->w_lock->l_blocking_ast != NULL);
-                        rc = w->w_lock->l_blocking_ast
-                                (w->w_lock, &w->w_desc, w->w_data,
-                                 LDLM_CB_BLOCKING);
-                } else if (w->w_lock->l_completion_ast != NULL) {
-                        rc = w->w_lock->l_completion_ast(w->w_lock, w->w_flags,
-                                                         w->w_data);
-                } else {
-                        rc = 0;
-                }
+                struct ldlm_lock *lock =
+                        list_entry(tmp, struct ldlm_lock, l_bl_ast);
+
+                /* nobody should touch l_bl_ast */
+                lock_res_and_lock(lock);
+                list_del_init(&lock->l_bl_ast);
+
+                LASSERT(lock->l_flags & LDLM_FL_AST_SENT);
+                LASSERT(lock->l_bl_ast_run == 0);
+                LASSERT(lock->l_blocking_lock);
+                lock->l_bl_ast_run++;
+                unlock_res_and_lock(lock);
+
+                ldlm_lock2desc(lock->l_blocking_lock, &d);
+
+                LDLM_LOCK_PUT(lock->l_blocking_lock);
+                lock->l_blocking_lock = NULL;
+                rc = lock->l_blocking_ast(lock, &d, NULL, LDLM_CB_BLOCKING);
 
                 if (rc == -ERESTART)
                         retval = rc;
                 else if (rc)
                         CDEBUG(D_DLMTRACE, "Failed AST - should clean & "
                                "disconnect client\n");
-                LDLM_LOCK_PUT(w->w_lock);
-                list_del(&w->w_list);
-                OBD_FREE(w, sizeof(*w));
+                LDLM_LOCK_PUT(lock);
+        }
+        RETURN(retval);
+}
+
+int ldlm_run_cp_ast_work(struct list_head *rpc_list)
+{
+        struct list_head *tmp, *pos;
+        int rc = 0, retval = 0;
+        ENTRY;
+
+        /* It's possible to receive a completion AST before we've set
+         * the l_completion_ast pointer: either because the AST arrived
+         * before the reply, or simply because there's a small race
+         * window between receiving the reply and finishing the local
+         * enqueue. (bug 842)
+         *
+         * This can't happen with the blocking_ast, however, because we
+         * will never call the local blocking_ast until we drop our
+         * reader/writer reference, which we won't do until we get the
+         * reply and finish enqueueing. */
+        
+        list_for_each_safe(tmp, pos, rpc_list) {
+                struct ldlm_lock *lock =
+                        list_entry(tmp, struct ldlm_lock, l_cp_ast);
+
+                /* nobody should touch l_cp_ast */
+                lock_res_and_lock(lock);
+                list_del_init(&lock->l_cp_ast);
+                LASSERT(lock->l_flags & LDLM_FL_CP_REQD);
+                lock->l_flags &= ~LDLM_FL_CP_REQD;
+                unlock_res_and_lock(lock);
+
+                if (lock->l_completion_ast != NULL)
+                        rc = lock->l_completion_ast(lock, 0, 0);
+                if (rc == -ERESTART)
+                        retval = rc;
+                else if (rc)
+                        CDEBUG(D_DLMTRACE, "Failed AST - should clean & "
+                               "disconnect client\n");
+                LDLM_LOCK_PUT(lock);
         }
         RETURN(retval);
 }
@@ -1015,28 +1112,32 @@ static int reprocess_one_queue(struct ldlm_resource *res, void *closure)
 
 void ldlm_reprocess_all_ns(struct ldlm_namespace *ns)
 {
+        struct list_head *tmp;
         int i, rc;
 
         ENTRY;
-        l_lock(&ns->ns_lock);
+        spin_lock(&ns->ns_hash_lock);
         for (i = 0; i < RES_HASH_SIZE; i++) {
-                struct list_head *tmp, *next;
-                list_for_each_safe(tmp, next, &(ns->ns_hash[i])) {
+                tmp = ns->ns_hash[i].next;
+                while (tmp != &(ns->ns_hash[i])) {
                         struct ldlm_resource *res =
                                 list_entry(tmp, struct ldlm_resource, lr_hash);
 
                         ldlm_resource_getref(res);
-                        l_unlock(&ns->ns_lock);
+                        spin_unlock(&ns->ns_hash_lock);
+
                         rc = reprocess_one_queue(res, NULL);
-                        l_lock(&ns->ns_lock);
-                        next = tmp->next;
-                        ldlm_resource_putref(res);
+
+                        spin_lock(&ns->ns_hash_lock);
+                        tmp = tmp->next;
+                        ldlm_resource_putref_locked(res);
+
                         if (rc == LDLM_ITER_STOP)
                                 GOTO(out, rc);
                 }
         }
  out:
-        l_unlock(&ns->ns_lock);
+        spin_unlock(&ns->ns_hash_lock);
         EXIT;
 }
 
@@ -1053,17 +1154,13 @@ void ldlm_reprocess_all(struct ldlm_resource *res)
         }
 
  restart:
-        l_lock(&res->lr_namespace->ns_lock);
-        res->lr_tmp = &rpc_list;
-
-        rc = ldlm_reprocess_queue(res, &res->lr_converting);
+        lock_res(res);
+        rc = ldlm_reprocess_queue(res, &res->lr_converting, &rpc_list);
         if (rc == LDLM_ITER_CONTINUE)
-                ldlm_reprocess_queue(res, &res->lr_waiting);
+                ldlm_reprocess_queue(res, &res->lr_waiting, &rpc_list);
+        unlock_res(res);
 
-        res->lr_tmp = NULL;
-        l_unlock(&res->lr_namespace->ns_lock);
-
-        rc = ldlm_run_ast_work(res->lr_namespace, &rpc_list);
+        rc = ldlm_run_cp_ast_work(&rpc_list);
         if (rc == -ERESTART) {
                 LASSERT(list_empty(&rpc_list));
                 goto restart;
@@ -1073,23 +1170,19 @@ void ldlm_reprocess_all(struct ldlm_resource *res)
 
 void ldlm_cancel_callback(struct ldlm_lock *lock)
 {
-        struct ldlm_namespace *ns;
-
-        ns = lock->l_resource->lr_namespace;
-        l_lock(&ns->ns_lock);
+        check_res_locked(lock->l_resource);
         if (!(lock->l_flags & LDLM_FL_CANCEL)) {
                 lock->l_flags |= LDLM_FL_CANCEL;
                 if (lock->l_blocking_ast) {
-                        l_unlock(&ns->ns_lock);
                         // l_check_no_ns_lock(ns);
+                        unlock_res_and_lock(lock);
                         lock->l_blocking_ast(lock, NULL, lock->l_ast_data,
                                              LDLM_CB_CANCELING);
-                        return;
+                        lock_res_and_lock(lock);
                 } else {
                         LDLM_DEBUG(lock, "no blocking ast");
                 }
         }
-        l_unlock(&ns->ns_lock);
 }
 
 void ldlm_lock_cancel(struct ldlm_lock *lock)
@@ -1098,12 +1191,12 @@ void ldlm_lock_cancel(struct ldlm_lock *lock)
         struct ldlm_namespace *ns;
         ENTRY;
 
+        ldlm_del_waiting_lock(lock);
+        lock_res_and_lock(lock);
+        
         res = lock->l_resource;
         ns = res->lr_namespace;
 
-        l_lock(&ns->ns_lock);
-        ldlm_del_waiting_lock(lock);
-
         /* Please do not, no matter how tempting, remove this LBUG without
          * talking to me first. -phik */
         if (lock->l_readers || lock->l_writers) {
@@ -1114,8 +1207,10 @@ void ldlm_lock_cancel(struct ldlm_lock *lock)
         ldlm_cancel_callback(lock);
 
         ldlm_resource_unlink_lock(lock);
+        unlock_res_and_lock(lock);
+        
         ldlm_lock_destroy(lock);
-        l_unlock(&ns->ns_lock);
+
         EXIT;
 }
 
@@ -1134,23 +1229,26 @@ int ldlm_lock_set_data(struct lustre_handle *lockh, void *data)
 
 void ldlm_cancel_locks_for_export(struct obd_export *exp)
 {
-        struct ldlm_namespace *ns = exp->exp_obd->obd_namespace;
         struct ldlm_lock *lock;
         struct ldlm_resource *res;
 
-        l_lock(&ns->ns_lock);
+        spin_lock(&exp->exp_ldlm_data.led_lock);
         while(!list_empty(&exp->exp_ldlm_data.led_held_locks)) {
                 lock = list_entry(exp->exp_ldlm_data.led_held_locks.next,
                                   struct ldlm_lock, l_export_chain);
                 res = ldlm_resource_getref(lock->l_resource);
+                LDLM_LOCK_GET(lock);
+                spin_unlock(&exp->exp_ldlm_data.led_lock);
+
                 LDLM_DEBUG(lock, "export %p", exp);
                 ldlm_lock_cancel(lock);
-                l_unlock(&ns->ns_lock);
                 ldlm_reprocess_all(res);
+
                 ldlm_resource_putref(res);
-                l_lock(&ns->ns_lock);
+                LDLM_LOCK_PUT(lock);
+                spin_lock(&exp->exp_ldlm_data.led_lock);
         }
-        l_unlock(&ns->ns_lock);
+        spin_unlock(&exp->exp_ldlm_data.led_lock);
 }
 
 struct ldlm_resource *ldlm_lock_convert(struct ldlm_lock *lock, int new_mode,
@@ -1172,11 +1270,11 @@ struct ldlm_resource *ldlm_lock_convert(struct ldlm_lock *lock, int new_mode,
         LASSERTF(new_mode == LCK_PW && lock->l_granted_mode == LCK_PR,
                  "new_mode %u, granted %u\n", new_mode, lock->l_granted_mode);
 
+        lock_res_and_lock(lock);
+
         res = lock->l_resource;
         ns = res->lr_namespace;
 
-        l_lock(&ns->ns_lock);
-
         old_mode = lock->l_req_mode;
         lock->l_req_mode = new_mode;
         ldlm_resource_unlink_lock(lock);
@@ -1192,9 +1290,7 @@ struct ldlm_resource *ldlm_lock_convert(struct ldlm_lock *lock, int new_mode,
                                    *flags);
                         LBUG();
 
-                        res->lr_tmp = &rpc_list;
-                        ldlm_grant_lock(lock, NULL, 0, 0);
-                        res->lr_tmp = NULL;
+                        ldlm_grant_lock(lock, &rpc_list);
                         granted = 1;
                         /* FIXME: completion handling not with ns_lock held ! */
                         if (lock->l_completion_ast)
@@ -1204,9 +1300,7 @@ struct ldlm_resource *ldlm_lock_convert(struct ldlm_lock *lock, int new_mode,
                 int pflags = 0;
                 ldlm_processing_policy policy;
                 policy = ldlm_processing_policy_table[res->lr_type];
-                res->lr_tmp = &rpc_list;
-                rc = policy(lock, &pflags, 0, &err);
-                res->lr_tmp = NULL;
+                rc = policy(lock, &pflags, 0, &err, &rpc_list);
                 if (rc == LDLM_ITER_STOP) {
                         lock->l_req_mode = old_mode;
                         ldlm_resource_add_lock(res, &res->lr_granted, lock);
@@ -1216,11 +1310,10 @@ struct ldlm_resource *ldlm_lock_convert(struct ldlm_lock *lock, int new_mode,
                         granted = 1;
                 }
         }
-
-        l_unlock(&ns->ns_lock);
+        unlock_res_and_lock(lock);
 
         if (granted)
-                ldlm_run_ast_work(ns, &rpc_list);
+                ldlm_run_cp_ast_work(&rpc_list);
         RETURN(res);
 }
 
@@ -1232,50 +1325,50 @@ void ldlm_lock_dump(int level, struct ldlm_lock *lock, int pos)
                 return;
 
         if (!lock) {
-                CDEBUG_EX(level, "  NULL LDLM lock\n");
+                CDEBUG(level, "  NULL LDLM lock\n");
                 return;
         }
 
-        CDEBUG_EX(level," -- Lock dump: %p/"LPX64" (rc: %d) (pos: %d) (pid: %d)\n",
+        CDEBUG(level," -- Lock dump: %p/"LPX64" (rc: %d) (pos: %d) (pid: %d)\n",
                lock, lock->l_handle.h_cookie, atomic_read(&lock->l_refc),
                pos, lock->l_pid);
         if (lock->l_conn_export != NULL)
                 obd = lock->l_conn_export->exp_obd;
         if (lock->l_export && lock->l_export->exp_connection) {
-                CDEBUG_EX(level, "  Node: NID %s (rhandle: "LPX64")\n",
+                CDEBUG(level, "  Node: NID %s (rhandle: "LPX64")\n",
                      libcfs_nid2str(lock->l_export->exp_connection->c_peer.nid),
                      lock->l_remote_handle.cookie);
         } else if (obd == NULL) {
-                CDEBUG_EX(level, "  Node: local\n");
+                CDEBUG(level, "  Node: local\n");
         } else {
                 struct obd_import *imp = obd->u.cli.cl_import;
-                CDEBUG_EX(level, "  Node: NID %s (rhandle: "LPX64")\n",
+                CDEBUG(level, "  Node: NID %s (rhandle: "LPX64")\n",
                        libcfs_nid2str(imp->imp_connection->c_peer.nid),
                        lock->l_remote_handle.cookie);
         }
-        CDEBUG_EX(level, "  Resource: %p ("LPU64"/"LPU64"/"LPU64")\n", 
+        CDEBUG(level, "  Resource: %p ("LPU64"/"LPU64"/"LPU64")\n", 
                   lock->l_resource,
                   lock->l_resource->lr_name.name[0],
                   lock->l_resource->lr_name.name[1],
                   lock->l_resource->lr_name.name[2]);
-        CDEBUG_EX(level, "  Req mode: %s, grant mode: %s, rc: %u, read: %d, "
+        CDEBUG(level, "  Req mode: %s, grant mode: %s, rc: %u, read: %d, "
                "write: %d flags: %#x\n", ldlm_lockname[lock->l_req_mode],
                ldlm_lockname[lock->l_granted_mode],
                atomic_read(&lock->l_refc), lock->l_readers, lock->l_writers,
                lock->l_flags);
         if (lock->l_resource->lr_type == LDLM_EXTENT)
-                CDEBUG_EX(level, "  Extent: "LPU64" -> "LPU64
+                CDEBUG(level, "  Extent: "LPU64" -> "LPU64
                        " (req "LPU64"-"LPU64")\n",
                        lock->l_policy_data.l_extent.start,
                        lock->l_policy_data.l_extent.end,
                        lock->l_req_extent.start, lock->l_req_extent.end);
         else if (lock->l_resource->lr_type == LDLM_FLOCK)
-                CDEBUG_EX(level, "  Pid: %d Extent: "LPU64" -> "LPU64"\n",
+                CDEBUG(level, "  Pid: %d Extent: "LPU64" -> "LPU64"\n",
                        lock->l_policy_data.l_flock.pid,
                        lock->l_policy_data.l_flock.start,
                        lock->l_policy_data.l_flock.end);
        else if (lock->l_resource->lr_type == LDLM_IBITS)
-                CDEBUG_EX(level, "  Bits: "LPX64"\n",
+                CDEBUG(level, "  Bits: "LPX64"\n",
                        lock->l_policy_data.l_inodebits.bits);
 }
 
index 1d555e7..b12a4bf 100644 (file)
@@ -58,9 +58,18 @@ inline cfs_time_t round_timeout(cfs_time_t timeout)
         return cfs_time_seconds((int)cfs_duration_sec(cfs_time_sub(timeout, 0)) + 1);
 }
 
+/* timeout for initial callback (AST) reply */
+static inline unsigned int ldlm_get_rq_timeout(unsigned int ldlm_timeout,
+                                               unsigned int obd_timeout)
+{
+        unsigned int timeout = min(ldlm_timeout, obd_timeout / 3);
+
+        return timeout < 1 ? 1 : timeout;
+}
+
 #ifdef __KERNEL__
 /* w_l_spinlock protects both waiting_locks_list and expired_lock_thread */
-static spinlock_t waiting_locks_spinlock;
+static spinlock_t waiting_locks_spinlock;   /* BH lock (timer) */
 static struct list_head waiting_locks_list;
 static cfs_timer_t waiting_locks_timer;
 
@@ -249,11 +258,31 @@ static void waiting_locks_callback(unsigned long unused)
  *
  * Called with the namespace lock held.
  */
-static int ldlm_add_waiting_lock(struct ldlm_lock *lock)
+static int __ldlm_add_waiting_lock(struct ldlm_lock *lock)
 {
         cfs_time_t timeout_rounded;
 
-        l_check_ns_lock(lock->l_resource->lr_namespace);
+        if (!list_empty(&lock->l_pending_chain))
+                return 0;
+
+        lock->l_callback_timeout =cfs_time_add(cfs_time_current(),
+                                               cfs_time_seconds(obd_timeout)/2);
+
+        timeout_rounded = round_timeout(lock->l_callback_timeout);
+
+        if (cfs_time_before(timeout_rounded, cfs_timer_deadline(&waiting_locks_timer)) ||
+            !cfs_timer_is_armed(&waiting_locks_timer)) {
+                cfs_timer_arm(&waiting_locks_timer, timeout_rounded);
+
+        }
+        list_add_tail(&lock->l_pending_chain, &waiting_locks_list); /* FIFO */
+        return 1;
+}
+
+static int ldlm_add_waiting_lock(struct ldlm_lock *lock)
+{
+        int ret;
+
         LASSERT(!(lock->l_flags & LDLM_FL_CANCEL_ON_BLOCK));
 
         spin_lock_bh(&waiting_locks_spinlock);
@@ -268,25 +297,12 @@ static int ldlm_add_waiting_lock(struct ldlm_lock *lock)
                 return 0;
         }
 
-        if (!list_empty(&lock->l_pending_chain)) {
-                spin_unlock_bh(&waiting_locks_spinlock);
-                LDLM_DEBUG(lock, "not re-adding to wait list");
-                return 0;
-        }
-
-        lock->l_callback_timeout =cfs_time_add(cfs_time_current(),
-                                               cfs_time_seconds(obd_timeout)/2);
-
-        timeout_rounded = round_timeout(lock->l_callback_timeout);
-
-        if (cfs_time_before(timeout_rounded, cfs_timer_deadline(&waiting_locks_timer)) ||
-            !cfs_timer_is_armed(&waiting_locks_timer)) {
-                cfs_timer_arm(&waiting_locks_timer, timeout_rounded);
-        }
-        list_add_tail(&lock->l_pending_chain, &waiting_locks_list); /* FIFO */
+        ret = __ldlm_add_waiting_lock(lock);
         spin_unlock_bh(&waiting_locks_spinlock);
-        LDLM_DEBUG(lock, "adding to wait list");
-        return 1;
+
+        LDLM_DEBUG(lock, "%sadding to wait list",
+                   ret == 0 ? "not re-" : "");
+        return ret;
 }
 
 /*
@@ -296,25 +312,12 @@ static int ldlm_add_waiting_lock(struct ldlm_lock *lock)
  *
  * Called with namespace lock held.
  */
-int ldlm_del_waiting_lock(struct ldlm_lock *lock)
+int __ldlm_del_waiting_lock(struct ldlm_lock *lock)
 {
         struct list_head *list_next;
 
-        l_check_ns_lock(lock->l_resource->lr_namespace);
-
-        if (lock->l_export == NULL) {
-                /* We don't have a "waiting locks list" on clients. */
-                LDLM_DEBUG(lock, "client lock: no-op");
+        if (list_empty(&lock->l_pending_chain))
                 return 0;
-        }
-
-        spin_lock_bh(&waiting_locks_spinlock);
-
-        if (list_empty(&lock->l_pending_chain)) {
-                spin_unlock_bh(&waiting_locks_spinlock);
-                LDLM_DEBUG(lock, "wasn't waiting");
-                return 0;
-        }
 
         list_next = lock->l_pending_chain.next;
         if (lock->l_pending_chain.prev == &waiting_locks_list) {
@@ -332,8 +335,53 @@ int ldlm_del_waiting_lock(struct ldlm_lock *lock)
         }
         list_del_init(&lock->l_pending_chain);
 
+        return 1;
+}
+
+int ldlm_del_waiting_lock(struct ldlm_lock *lock)
+{
+        int ret;
+
+        if (lock->l_export == NULL) {
+                /* We don't have a "waiting locks list" on clients. */
+                LDLM_DEBUG(lock, "client lock: no-op");
+                return 0;
+        }
+
+        spin_lock_bh(&waiting_locks_spinlock);
+        ret = __ldlm_del_waiting_lock(lock);
+        spin_unlock_bh(&waiting_locks_spinlock);
+
+        LDLM_DEBUG(lock, "%s", ret == 0 ? "wasn't waiting" : "removed");
+        return ret;
+}
+
+/*
+ * Prolong the lock
+ * 
+ * Called with namespace lock held.
+ */
+int ldlm_refresh_waiting_lock(struct ldlm_lock *lock)
+{
+        if (lock->l_export == NULL) {
+                /* We don't have a "waiting locks list" on clients. */
+                LDLM_DEBUG(lock, "client lock: no-op");
+                return 0;
+        }
+
+        spin_lock_bh(&waiting_locks_spinlock);
+
+        if (list_empty(&lock->l_pending_chain)) {
+                spin_unlock_bh(&waiting_locks_spinlock);
+                LDLM_DEBUG(lock, "wasn't waiting");
+                return 0;
+        }
+
+        __ldlm_del_waiting_lock(lock);
+        __ldlm_add_waiting_lock(lock);
         spin_unlock_bh(&waiting_locks_spinlock);
-        LDLM_DEBUG(lock, "removed");
+
+        LDLM_DEBUG(lock, "refreshed");
         return 1;
 }
 
@@ -350,6 +398,10 @@ int ldlm_del_waiting_lock(struct ldlm_lock *lock)
         RETURN(0);
 }
 
+int ldlm_refresh_waiting_lock(struct ldlm_lock *lock)
+{
+        RETURN(0);
+}
 #endif /* __KERNEL__ */
 
 static void ldlm_failed_ast(struct ldlm_lock *lock, int rc,
@@ -392,25 +444,23 @@ static int ldlm_handle_ast_error(struct ldlm_lock *lock,
                         ldlm_lock_cancel(lock);
                         rc = -ERESTART;
                 } else {
-                        l_lock(&lock->l_resource->lr_namespace->ns_lock);
                         ldlm_del_waiting_lock(lock);
-                        l_unlock(&lock->l_resource->lr_namespace->ns_lock);
                         ldlm_failed_ast(lock, rc, ast_type);
                 }
         } else if (rc) {
-                l_lock(&lock->l_resource->lr_namespace->ns_lock);
                 if (rc == -EINVAL)
                         LDLM_DEBUG(lock, "client (nid %s) returned %d"
                                    " from %s AST - normal race",
                                    libcfs_nid2str(peer.nid),
-                                   req->rq_repmsg->status, ast_type);
+                                   lustre_msg_get_status(req->rq_repmsg),
+                                   ast_type);
                 else
                         LDLM_ERROR(lock, "client (nid %s) returned %d "
                                    "from %s AST", libcfs_nid2str(peer.nid),
                                    (req->rq_repmsg != NULL) ?
-                                   req->rq_repmsg->status : 0, ast_type);
+                                   lustre_msg_get_status(req->rq_repmsg) : 0,
+                                   ast_type);
                 ldlm_lock_cancel(lock);
-                l_unlock(&lock->l_resource->lr_namespace->ns_lock);
                 /* Server-side AST functions are called from ldlm_reprocess_all,
                  * which needs to be told to please restart its reprocessing. */
                 rc = -ERESTART;
@@ -425,8 +475,9 @@ int ldlm_server_blocking_ast(struct ldlm_lock *lock,
 {
         struct ldlm_request *body;
         struct ptlrpc_request *req;
-        int rc = 0, size = sizeof(*body);
-        int instant_cancel = 0;
+        int size[] = { [MSG_PTLRPC_BODY_OFF] = sizeof(struct ptlrpc_body),
+                       [DLM_LOCKREQ_OFF]     = sizeof(*body) };
+        int instant_cancel = 0, rc = 0;
         ENTRY;
 
         if (flag == LDLM_CB_CANCELING) {
@@ -436,25 +487,34 @@ int ldlm_server_blocking_ast(struct ldlm_lock *lock,
 
         LASSERT(lock);
 
-        l_lock(&lock->l_resource->lr_namespace->ns_lock);
+        req = ptlrpc_prep_req(lock->l_export->exp_imp_reverse,
+                              LUSTRE_DLM_VERSION, LDLM_BL_CALLBACK, 2, size,
+                              NULL);
+        if (req == NULL)
+                RETURN(-ENOMEM);
+
+        lock_res(lock->l_resource);
         if (lock->l_granted_mode != lock->l_req_mode) {
                 /* this blocking AST will be communicated as part of the
                  * completion AST instead */
+                unlock_res(lock->l_resource);
+                ptlrpc_req_finished(req);
                 LDLM_DEBUG(lock, "lock not granted, not sending blocking AST");
-                l_unlock(&lock->l_resource->lr_namespace->ns_lock);
                 RETURN(0);
         }
 
         if (lock->l_destroyed) {
                 /* What's the point? */
-                l_unlock(&lock->l_resource->lr_namespace->ns_lock);
+                unlock_res(lock->l_resource);
+                ptlrpc_req_finished(req);
                 RETURN(0);
         }
 
 #if 0
         if (CURRENT_SECONDS - lock->l_export->exp_last_request_time > 30){
+                unlock_res(lock->l_resource);
+                ptlrpc_req_finished(req);
                 ldlm_failed_ast(lock, -ETIMEDOUT, "Not-attempted blocking");
-                l_unlock(&lock->l_resource->lr_namespace->ns_lock);
                 RETURN(-ETIMEDOUT);
         }
 #endif
@@ -462,30 +522,23 @@ int ldlm_server_blocking_ast(struct ldlm_lock *lock,
         if (lock->l_flags & LDLM_FL_CANCEL_ON_BLOCK)
                 instant_cancel = 1;
 
-        req = ptlrpc_prep_req(lock->l_export->exp_imp_reverse,
-                              LUSTRE_DLM_VERSION, LDLM_BL_CALLBACK,
-                              1, &size, NULL);
-        if (req == NULL) {
-                l_unlock(&lock->l_resource->lr_namespace->ns_lock);
-                RETURN(-ENOMEM);
-        }
-
-        body = lustre_msg_buf(req->rq_reqmsg, 0, sizeof (*body));
+        body = lustre_msg_buf(req->rq_reqmsg, DLM_LOCKREQ_OFF, sizeof(*body));
         body->lock_handle1 = lock->l_remote_handle;
         body->lock_desc = *desc;
         body->lock_flags |= (lock->l_flags & LDLM_AST_FLAGS);
 
         LDLM_DEBUG(lock, "server preparing blocking AST");
-        req->rq_replen = lustre_msg_size(0, NULL);
-        if (instant_cancel)
+        ptlrpc_req_set_repsize(req, 1, NULL);
+        if (instant_cancel) {
+                unlock_res(lock->l_resource);
                 ldlm_lock_cancel(lock);
-        else if (lock->l_granted_mode == lock->l_req_mode)
+        } else if (lock->l_granted_mode == lock->l_req_mode) {
                 ldlm_add_waiting_lock(lock);
-
-        l_unlock(&lock->l_resource->lr_namespace->ns_lock);
+                unlock_res(lock->l_resource);
+        }
 
         req->rq_send_state = LUSTRE_IMP_FULL;
-        req->rq_timeout = ldlm_timeout; /* timeout for initial AST reply */
+        req->rq_timeout = ldlm_get_rq_timeout(ldlm_timeout, obd_timeout);
         if (unlikely(instant_cancel)) {
                 rc = ptl_send_rpc(req, 1);
         } else {
@@ -509,7 +562,9 @@ int ldlm_server_completion_ast(struct ldlm_lock *lock, int flags, void *data)
         struct ptlrpc_request *req;
         struct timeval granted_time;
         long total_enqueue_wait;
-        int rc = 0, size[2] = {sizeof(*body)}, buffers = 1, instant_cancel = 0;
+        int size[3] = { [MSG_PTLRPC_BODY_OFF] = sizeof(struct ptlrpc_body),
+                        [DLM_LOCKREQ_OFF]     = sizeof(*body) };
+        int rc = 0, buffers = 2, instant_cancel = 0;
         ENTRY;
 
         LASSERT(lock != NULL);
@@ -522,62 +577,64 @@ int ldlm_server_completion_ast(struct ldlm_lock *lock, int flags, void *data)
                 LDLM_ERROR(lock, "enqueue wait took %luus from %lu",
                            total_enqueue_wait, lock->l_enqueued_time.tv_sec);
 
-        mutex_down(&lock->l_resource->lr_lvb_sem);
+        lock_res_and_lock(lock);
         if (lock->l_resource->lr_lvb_len) {
-                buffers = 2;
-                size[1] = lock->l_resource->lr_lvb_len;
+                size[DLM_REQ_REC_OFF] = lock->l_resource->lr_lvb_len;
+                buffers = 3;
         }
-        mutex_up(&lock->l_resource->lr_lvb_sem);
+        unlock_res_and_lock(lock);
 
         req = ptlrpc_prep_req(lock->l_export->exp_imp_reverse,
-                              LUSTRE_DLM_VERSION, LDLM_CP_CALLBACK,
-                              buffers, size, NULL);
+                              LUSTRE_DLM_VERSION, LDLM_CP_CALLBACK, buffers,
+                              size, NULL);
         if (req == NULL)
                 RETURN(-ENOMEM);
 
-        body = lustre_msg_buf(req->rq_reqmsg, 0, sizeof (*body));
+        body = lustre_msg_buf(req->rq_reqmsg, DLM_LOCKREQ_OFF, sizeof(*body));
         body->lock_handle1 = lock->l_remote_handle;
         body->lock_flags = flags;
         ldlm_lock2desc(lock, &body->lock_desc);
 
-        if (buffers == 2) {
+        if (buffers == 3) {
                 void *lvb;
 
-                mutex_down(&lock->l_resource->lr_lvb_sem);
-                lvb = lustre_msg_buf(req->rq_reqmsg, 1,
+                lvb = lustre_msg_buf(req->rq_reqmsg, DLM_REQ_REC_OFF,
                                      lock->l_resource->lr_lvb_len);
+                lock_res_and_lock(lock);
                 memcpy(lvb, lock->l_resource->lr_lvb_data,
                        lock->l_resource->lr_lvb_len);
-                mutex_up(&lock->l_resource->lr_lvb_sem);
+                unlock_res_and_lock(lock);
         }
 
         LDLM_DEBUG(lock, "server preparing completion AST (after %ldus wait)",
                    total_enqueue_wait);
-        req->rq_replen = lustre_msg_size(0, NULL);
+        ptlrpc_req_set_repsize(req, 1, NULL);
 
         req->rq_send_state = LUSTRE_IMP_FULL;
-        req->rq_timeout = ldlm_timeout; /* timeout for initial AST reply */
+        req->rq_timeout = ldlm_get_rq_timeout(ldlm_timeout, obd_timeout);
 
         /* We only send real blocking ASTs after the lock is granted */
-        l_lock(&lock->l_resource->lr_namespace->ns_lock);
+        lock_res_and_lock(lock);
         if (lock->l_flags & LDLM_FL_AST_SENT) {
                 body->lock_flags |= LDLM_FL_AST_SENT;
 
                 /* We might get here prior to ldlm_handle_enqueue setting
-                   LDLM_FL_CANCEL_ON_BLOCK flag. Then we will put this lock into
-                   waiting list, but this is safe and similar code in
-                   ldlm_handle_enqueue will call ldlm_lock_cancel() still, that
-                   would not only cancel the loc, but will also remove it from
-                   waiting list */
+                 * LDLM_FL_CANCEL_ON_BLOCK flag. Then we will put this lock
+                 * into waiting list, but this is safe and similar code in
+                 * ldlm_handle_enqueue will call ldlm_lock_cancel() still,
+                 * that would not only cancel the lock, but will also remove
+                 * it from waiting list */
                 if (lock->l_flags & LDLM_FL_CANCEL_ON_BLOCK) {
+                        unlock_res_and_lock(lock);
                         ldlm_lock_cancel(lock);
                         instant_cancel = 1;
+                        lock_res_and_lock(lock);
                 } else {
                         ldlm_add_waiting_lock(lock); /* start the lock-timeout
                                                          clock */
                 }
         }
-        l_unlock(&lock->l_resource->lr_namespace->ns_lock);
+        unlock_res_and_lock(lock);
 
         rc = ptlrpc_queue_wait(req);
         if (rc != 0)
@@ -597,28 +654,31 @@ int ldlm_server_glimpse_ast(struct ldlm_lock *lock, void *data)
         struct ldlm_resource *res = lock->l_resource;
         struct ldlm_request *body;
         struct ptlrpc_request *req;
-        int rc = 0, size = sizeof(*body);
+        int size[] = { [MSG_PTLRPC_BODY_OFF] = sizeof(struct ptlrpc_body),
+                       [DLM_LOCKREQ_OFF]     = sizeof(*body) };
+        int rc = 0;
         ENTRY;
 
         LASSERT(lock != NULL);
 
         req = ptlrpc_prep_req(lock->l_export->exp_imp_reverse,
-                              LUSTRE_DLM_VERSION, LDLM_GL_CALLBACK,
-                              1, &size, NULL);
+                              LUSTRE_DLM_VERSION, LDLM_GL_CALLBACK, 2, size,
+                              NULL);
         if (req == NULL)
                 RETURN(-ENOMEM);
 
-        body = lustre_msg_buf(req->rq_reqmsg, 0, sizeof(*body));
+        body = lustre_msg_buf(req->rq_reqmsg, DLM_LOCKREQ_OFF, sizeof(*body));
         body->lock_handle1 = lock->l_remote_handle;
         ldlm_lock2desc(lock, &body->lock_desc);
 
-        mutex_down(&lock->l_resource->lr_lvb_sem);
-        size = lock->l_resource->lr_lvb_len;
-        mutex_up(&lock->l_resource->lr_lvb_sem);
-        req->rq_replen = lustre_msg_size(1, &size);
+        lock_res_and_lock(lock);
+        size[REPLY_REC_OFF] = lock->l_resource->lr_lvb_len;
+        unlock_res_and_lock(lock);
+        res = lock->l_resource;
+        ptlrpc_req_set_repsize(req, 2, size);
 
         req->rq_send_state = LUSTRE_IMP_FULL;
-        req->rq_timeout = ldlm_timeout; /* timeout for initial AST reply */
+        req->rq_timeout = ldlm_get_rq_timeout(ldlm_timeout, obd_timeout);
 
         rc = ptlrpc_queue_wait(req);
         if (rc == -ELDLM_NO_LOCK_DATA)
@@ -627,7 +687,7 @@ int ldlm_server_glimpse_ast(struct ldlm_lock *lock, void *data)
                 rc = ldlm_handle_ast_error(lock, req, rc, "glimpse");
         else
                 rc = res->lr_namespace->ns_lvbo->lvbo_update
-                        (res, req->rq_repmsg, 0, 1);
+                        (res, req->rq_repmsg, REPLY_REC_OFF, 1);
         ptlrpc_req_finished(req);
         RETURN(rc);
 }
@@ -636,20 +696,19 @@ static struct ldlm_lock *
 find_existing_lock(struct obd_export *exp,
                    const struct lustre_handle *remote_hdl)
 {
-        struct obd_device *obd = exp->exp_obd;
         struct list_head *iter;
 
-        l_lock(&obd->obd_namespace->ns_lock);
+        spin_lock(&exp->exp_ldlm_data.led_lock);
         list_for_each(iter, &exp->exp_ldlm_data.led_held_locks) {
                 struct ldlm_lock *lock;
                 lock = list_entry(iter, struct ldlm_lock, l_export_chain);
                 if (lock->l_remote_handle.cookie == remote_hdl->cookie) {
                         LDLM_LOCK_GET(lock);
-                        l_unlock(&obd->obd_namespace->ns_lock);
+                        spin_unlock(&exp->exp_ldlm_data.led_lock);
                         return lock;
                 }
         }
-        l_unlock(&obd->obd_namespace->ns_lock);
+        spin_unlock(&exp->exp_ldlm_data.led_lock);
         return NULL;
 }
 
@@ -664,7 +723,9 @@ int ldlm_handle_enqueue0(struct ldlm_namespace *ns,
                          const struct ldlm_callback_suite *cbs)
 {
         struct ldlm_reply *dlm_rep;
-        int rc = 0, size[2] = {sizeof(*dlm_rep)};
+        int size[3] = { [MSG_PTLRPC_BODY_OFF] = sizeof(struct ptlrpc_body),
+                        [DLM_LOCKREPLY_OFF]   = sizeof(*dlm_rep) };
+        int rc = 0;
         __u32 flags;
         ldlm_error_t err = ELDLM_OK;
         struct ldlm_lock *lock = NULL;
@@ -746,18 +807,17 @@ int ldlm_handle_enqueue0(struct ldlm_namespace *ns,
         LDLM_DEBUG(lock, "server-side enqueue handler, new lock created");
 
         OBD_FAIL_TIMEOUT(OBD_FAIL_LDLM_ENQUEUE_BLOCKED, obd_timeout * 2);
-        l_lock(&lock->l_resource->lr_namespace->ns_lock);
         /* Don't enqueue a lock onto the export if it has already
          * been evicted.  Cancel it now instead. (bug 3822) */
         if (req->rq_export->exp_failed) {
                 LDLM_ERROR(lock, "lock on destroyed export %p", req->rq_export);
-                l_unlock(&lock->l_resource->lr_namespace->ns_lock);
                 GOTO(out, rc = -ENOTCONN);
         }
         lock->l_export = class_export_get(req->rq_export);
+        spin_lock(&lock->l_export->exp_ldlm_data.led_lock);
         list_add(&lock->l_export_chain,
                  &lock->l_export->exp_ldlm_data.led_held_locks);
-        l_unlock(&lock->l_resource->lr_namespace->ns_lock);
+        spin_unlock(&lock->l_export->exp_ldlm_data.led_lock);
 
 existing_lock:
 
@@ -766,14 +826,14 @@ existing_lock:
                  * local_lock_enqueue by the policy function. */
                 cookie = req;
         } else {
-                int buffers = 1;
+                int buffers = 2;
 
-                mutex_down(&lock->l_resource->lr_lvb_sem);
+                lock_res_and_lock(lock);
                 if (lock->l_resource->lr_lvb_len) {
-                        size[1] = lock->l_resource->lr_lvb_len;
-                        buffers = 2;
+                        size[DLM_REPLY_REC_OFF] = lock->l_resource->lr_lvb_len;
+                        buffers = 3;
                 }
-                mutex_up(&lock->l_resource->lr_lvb_sem);
+                unlock_res_and_lock(lock);
 
                 if (OBD_FAIL_CHECK_ONCE(OBD_FAIL_LDLM_ENQUEUE_EXTENT_ERR))
                         GOTO(out, rc = -ENOMEM);
@@ -792,7 +852,8 @@ existing_lock:
         if (err)
                 GOTO(out, err);
 
-        dlm_rep = lustre_msg_buf(req->rq_repmsg, 0, sizeof (*dlm_rep));
+        dlm_rep = lustre_msg_buf(req->rq_repmsg, DLM_LOCKREPLY_OFF,
+                                 sizeof(*dlm_rep));
         dlm_rep->lock_flags = flags;
 
         ldlm_lock2desc(lock, &dlm_rep->lock_desc);
@@ -800,7 +861,7 @@ existing_lock:
 
         /* We never send a blocking AST until the lock is granted, but
          * we can tell it right now */
-        l_lock(&lock->l_resource->lr_namespace->ns_lock);
+        lock_res_and_lock(lock);
 
         /* Now take into account flags to be inherited from original lock
            request both in reply to client and in our own lock flags. */
@@ -815,9 +876,11 @@ existing_lock:
                 rc = -ENOTCONN;
         } else if (lock->l_flags & LDLM_FL_AST_SENT) {
                 dlm_rep->lock_flags |= LDLM_FL_AST_SENT;
-                if (dlm_rep->lock_flags & LDLM_FL_CANCEL_ON_BLOCK)
+                if (dlm_rep->lock_flags & LDLM_FL_CANCEL_ON_BLOCK) {
+                        unlock_res_and_lock(lock);
                         ldlm_lock_cancel(lock);
-                else if (lock->l_granted_mode == lock->l_req_mode)
+                        lock_res_and_lock(lock);
+                } else if (lock->l_granted_mode == lock->l_req_mode)
                         ldlm_add_waiting_lock(lock);
         }
         /* Make sure we never ever grant usual metadata locks to liblustre
@@ -834,24 +897,24 @@ existing_lock:
                         LDLM_ERROR(lock, "sync lock");
                         if (dlm_req->lock_flags & LDLM_FL_HAS_INTENT) {
                                 struct ldlm_intent *it;
-                                it = lustre_msg_buf(req->rq_reqmsg, 1,
+                                it = lustre_msg_buf(req->rq_reqmsg,
+                                                    DLM_INTENT_IT_OFF,
                                                     sizeof(*it));
                                 if (it != NULL) {
-                                        CERROR("This is intent %s ("
-                                               LPU64 ")\n",
+                                        CERROR("This is intent %s ("LPU64")\n",
                                                ldlm_it2str(it->opc), it->opc);
                                 }
                         }
                 }
         }
 
-        l_unlock(&lock->l_resource->lr_namespace->ns_lock);
+        unlock_res_and_lock(lock);
 
         EXIT;
  out:
         req->rq_status = err;
         if (req->rq_reply_state == NULL) {
-                err = lustre_pack_reply(req, 0, NULL, NULL);
+                err = lustre_pack_reply(req, 1, NULL, NULL);
                 if (rc == 0)
                         rc = err;
                 req->rq_status = rc;
@@ -860,27 +923,28 @@ existing_lock:
         /* The LOCK_CHANGED code in ldlm_lock_enqueue depends on this
          * ldlm_reprocess_all.  If this moves, revisit that code. -phil */
         if (lock) {
-                l_lock(&lock->l_resource->lr_namespace->ns_lock);
                 LDLM_DEBUG(lock, "server-side enqueue handler, sending reply"
                            "(err=%d, rc=%d)", err, rc);
-                l_unlock(&lock->l_resource->lr_namespace->ns_lock);
 
                 if (rc == 0) {
-                        mutex_down(&lock->l_resource->lr_lvb_sem);
-                        size[1] = lock->l_resource->lr_lvb_len;
-                        if (size[1] > 0) {
+                        lock_res_and_lock(lock);
+                        size[DLM_REPLY_REC_OFF] = lock->l_resource->lr_lvb_len;
+                        if (size[DLM_REPLY_REC_OFF] > 0) {
                                 void *lvb = lustre_msg_buf(req->rq_repmsg,
-                                                           1, size[1]);
+                                                       DLM_REPLY_REC_OFF,
+                                                       size[DLM_REPLY_REC_OFF]);
                                 LASSERTF(lvb != NULL, "req %p, lock %p\n",
                                          req, lock);
 
                                 memcpy(lvb, lock->l_resource->lr_lvb_data,
-                                       size[1]);
+                                       size[DLM_REPLY_REC_OFF]);
                         }
-                        mutex_up(&lock->l_resource->lr_lvb_sem);
+                        unlock_res_and_lock(lock);
                 } else {
+                        lock_res_and_lock(lock);
                         ldlm_resource_unlink_lock(lock);
-                        ldlm_lock_destroy(lock);
+                        ldlm_lock_destroy_nolock(lock);
+                        unlock_res_and_lock(lock);
                 }
 
                 if (!err && dlm_req->lock_desc.l_resource.lr_type != LDLM_FLOCK)
@@ -909,7 +973,7 @@ int ldlm_handle_enqueue(struct ptlrpc_request *req,
         };
 
 
-        dlm_req = lustre_swab_reqbuf(req, MDS_REQ_INTENT_LOCKREQ_OFF,
+        dlm_req = lustre_swab_reqbuf(req, DLM_LOCKREQ_OFF,
                                      sizeof *dlm_req, lustre_swab_ldlm_request);
         if (dlm_req != NULL) {
                 rc = ldlm_handle_enqueue0(req->rq_export->exp_obd->obd_namespace,
@@ -926,34 +990,41 @@ int ldlm_handle_convert0(struct ptlrpc_request *req,
 {
         struct ldlm_reply *dlm_rep;
         struct ldlm_lock *lock;
-        int rc, size = sizeof(*dlm_rep);
+        int rc;
+        int size[2] = { [MSG_PTLRPC_BODY_OFF] = sizeof(struct ptlrpc_body),
+                        [DLM_LOCKREPLY_OFF]   = sizeof(*dlm_rep) };
         ENTRY;
 
-        rc = lustre_pack_reply(req, 1, &size, NULL);
+        dlm_req = lustre_swab_reqbuf(req, DLM_LOCKREQ_OFF, sizeof(*dlm_req),
+                                     lustre_swab_ldlm_request);
+        if (dlm_req == NULL) {
+                CERROR ("Can't unpack dlm_req\n");
+                RETURN (-EFAULT);
+        }
+
+        rc = lustre_pack_reply(req, 2, size, NULL);
         if (rc) {
                 CERROR("out of memory\n");
                 RETURN(-ENOMEM);
         }
-        dlm_rep = lustre_msg_buf(req->rq_repmsg, 0, sizeof (*dlm_rep));
+        dlm_rep = lustre_msg_buf(req->rq_repmsg, DLM_LOCKREPLY_OFF,
+                                 sizeof(*dlm_rep));
         dlm_rep->lock_flags = dlm_req->lock_flags;
 
         lock = ldlm_handle2lock(&dlm_req->lock_handle1);
         if (!lock) {
                 req->rq_status = EINVAL;
         } else {
-                void *res;
-                l_lock(&lock->l_resource->lr_namespace->ns_lock);
+                void *res = NULL;
+
                 LDLM_DEBUG(lock, "server-side convert handler START");
-                l_unlock(&lock->l_resource->lr_namespace->ns_lock);
+
                 do_gettimeofday(&lock->l_enqueued_time);
                 res = ldlm_lock_convert(lock, dlm_req->lock_desc.l_req_mode,
                                         &dlm_rep->lock_flags);
                 if (res) {
-                        l_lock(&lock->l_resource->lr_namespace->ns_lock);
                         if (ldlm_del_waiting_lock(lock))
-                                CDEBUG(D_DLMTRACE,"converted waiting lock %p\n",
-                                       lock);
-                        l_unlock(&lock->l_resource->lr_namespace->ns_lock);
+                                LDLM_DEBUG(lock, "converted waiting lock");
                         req->rq_status = 0;
                 } else {
                         req->rq_status = EDEADLOCK;
@@ -963,9 +1034,7 @@ int ldlm_handle_convert0(struct ptlrpc_request *req,
         if (lock) {
                 if (!req->rq_status)
                         ldlm_reprocess_all(lock->l_resource);
-                l_lock(&lock->l_resource->lr_namespace->ns_lock);
                 LDLM_DEBUG(lock, "server-side convert handler END");
-                l_unlock(&lock->l_resource->lr_namespace->ns_lock);
                 LDLM_LOCK_PUT(lock);
         } else
                 LDLM_DEBUG_NOLOCK("server-side convert handler END");
@@ -997,14 +1066,14 @@ int ldlm_handle_cancel(struct ptlrpc_request *req)
         int rc;
         ENTRY;
 
-        dlm_req = lustre_swab_reqbuf(req, 0, sizeof (*dlm_req),
-                                      lustre_swab_ldlm_request);
+        dlm_req = lustre_swab_reqbuf(req, DLM_LOCKREQ_OFF, sizeof(*dlm_req),
+                                     lustre_swab_ldlm_request);
         if (dlm_req == NULL) {
                 CERROR("bad request buffer for cancel\n");
                 RETURN(-EFAULT);
         }
 
-        rc = lustre_pack_reply(req, 0, NULL, NULL);
+        rc = lustre_pack_reply(req, 1, NULL, NULL);
         if (rc) {
                 CERROR("out of memory\n");
                 RETURN(-ENOMEM);
@@ -1022,10 +1091,8 @@ int ldlm_handle_cancel(struct ptlrpc_request *req)
                                   dlm_req->lock_handle1.cookie);
                 req->rq_status = ESTALE;
         } else {
-                res = lock->l_resource;
-                l_lock(&res->lr_namespace->ns_lock);
                 LDLM_DEBUG(lock, "server-side cancel handler START");
-                l_unlock(&res->lr_namespace->ns_lock);
+                res = lock->l_resource;
                 if (res && res->lr_namespace->ns_lvbo &&
                     res->lr_namespace->ns_lvbo->lvbo_update) {
                         (void)res->lr_namespace->ns_lvbo->lvbo_update
@@ -1033,11 +1100,9 @@ int ldlm_handle_cancel(struct ptlrpc_request *req)
                                 //(res, req->rq_reqmsg, 1);
                 }
 
-                l_lock(&res->lr_namespace->ns_lock);
                 ldlm_lock_cancel(lock);
                 if (ldlm_del_waiting_lock(lock))
                         CDEBUG(D_DLMTRACE, "cancelled waiting lock %p\n", lock);
-                l_unlock(&res->lr_namespace->ns_lock);
                 req->rq_status = rc;
         }
 
@@ -1046,9 +1111,7 @@ int ldlm_handle_cancel(struct ptlrpc_request *req)
 
         if (lock) {
                 ldlm_reprocess_all(lock->l_resource);
-                l_lock(&lock->l_resource->lr_namespace->ns_lock);
                 LDLM_DEBUG(lock, "server-side cancel handler END");
-                l_unlock(&lock->l_resource->lr_namespace->ns_lock);
                 LDLM_LOCK_PUT(lock);
         }
 
@@ -1061,33 +1124,29 @@ void ldlm_handle_bl_callback(struct ldlm_namespace *ns,
         int do_ast;
         ENTRY;
 
-        l_lock(&ns->ns_lock);
         LDLM_DEBUG(lock, "client blocking AST callback handler START");
 
+        lock_res_and_lock(lock);
         lock->l_flags |= LDLM_FL_CBPENDING;
 
         if (lock->l_flags & LDLM_FL_CANCEL_ON_BLOCK)
                 lock->l_flags |= LDLM_FL_CANCEL;
 
         do_ast = (!lock->l_readers && !lock->l_writers);
+        unlock_res_and_lock(lock);
 
         if (do_ast) {
                 LDLM_DEBUG(lock, "already unused, calling "
                            "callback (%p)", lock->l_blocking_ast);
-                if (lock->l_blocking_ast != NULL) {
-                        l_unlock(&ns->ns_lock);
-                        l_check_no_ns_lock(ns);
+                if (lock->l_blocking_ast != NULL)
                         lock->l_blocking_ast(lock, ld, lock->l_ast_data,
                                              LDLM_CB_BLOCKING);
-                        l_lock(&ns->ns_lock);
-                }
         } else {
                 LDLM_DEBUG(lock, "Lock still has references, will be"
                            " cancelled later");
         }
 
         LDLM_DEBUG(lock, "client blocking callback handler END");
-        l_unlock(&ns->ns_lock);
         LDLM_LOCK_PUT(lock);
         EXIT;
 }
@@ -1100,9 +1159,10 @@ static void ldlm_handle_cp_callback(struct ptlrpc_request *req,
         CFS_LIST_HEAD(ast_list);
         ENTRY;
 
-        l_lock(&ns->ns_lock);
         LDLM_DEBUG(lock, "client completion callback handler START");
 
+        lock_res_and_lock(lock);
+
         /* If we receive the completion AST before the actual enqueue returned,
          * then we might need to switch lock modes, resources, or extents. */
         if (dlm_req->lock_desc.l_granted_mode != lock->l_req_mode) {
@@ -1119,9 +1179,12 @@ static void ldlm_handle_cp_callback(struct ptlrpc_request *req,
         if (memcmp(&dlm_req->lock_desc.l_resource.lr_name,
                    &lock->l_resource->lr_name,
                    sizeof(lock->l_resource->lr_name)) != 0) {
+                unlock_res_and_lock(lock);
                 ldlm_lock_change_resource(ns, lock,
                                          dlm_req->lock_desc.l_resource.lr_name);
                 LDLM_DEBUG(lock, "completion AST, new resource");
+                CERROR("change resource!\n");
+                lock_res_and_lock(lock);
         }
 
         if (dlm_req->lock_flags & LDLM_FL_AST_SENT) {
@@ -1131,7 +1194,7 @@ static void ldlm_handle_cp_callback(struct ptlrpc_request *req,
 
         if (lock->l_lvb_len) {
                 void *lvb;
-                lvb = lustre_swab_reqbuf(req, 1, lock->l_lvb_len,
+                lvb = lustre_swab_reqbuf(req, DLM_REQ_REC_OFF, lock->l_lvb_len,
                                          lock->l_lvb_swabber);
                 if (lvb == NULL) {
                         LDLM_ERROR(lock, "completion AST did not contain "
@@ -1141,17 +1204,16 @@ static void ldlm_handle_cp_callback(struct ptlrpc_request *req,
                 }
         }
 
-        lock->l_resource->lr_tmp = &ast_list;
-        ldlm_grant_lock(lock, req, sizeof(*req), 1);
-        lock->l_resource->lr_tmp = NULL;
+        ldlm_grant_lock(lock, &ast_list);
+        unlock_res_and_lock(lock);
+
         LDLM_DEBUG(lock, "callback handler finished, about to run_ast_work");
-        l_unlock(&ns->ns_lock);
-        LDLM_LOCK_PUT(lock);
 
-        ldlm_run_ast_work(ns, &ast_list);
+        ldlm_run_cp_ast_work(&ast_list);
 
         LDLM_DEBUG_NOLOCK("client completion callback handler END (lock %p)",
                           lock);
+        LDLM_LOCK_PUT(lock);
         EXIT;
 }
 
@@ -1163,15 +1225,10 @@ static void ldlm_handle_gl_callback(struct ptlrpc_request *req,
         int rc = -ENOSYS;
         ENTRY;
 
-        l_lock(&ns->ns_lock);
         LDLM_DEBUG(lock, "client glimpse AST callback handler");
 
-        if (lock->l_glimpse_ast != NULL) {
-                l_unlock(&ns->ns_lock);
-                l_check_no_ns_lock(ns);
+        if (lock->l_glimpse_ast != NULL)
                 rc = lock->l_glimpse_ast(lock, req);
-                l_lock(&ns->ns_lock);
-        }
 
         if (req->rq_repmsg != NULL) {
                 ptlrpc_reply(req);
@@ -1180,17 +1237,19 @@ static void ldlm_handle_gl_callback(struct ptlrpc_request *req,
                 ptlrpc_error(req);
         }
 
-        l_unlock(&ns->ns_lock);
+        lock_res_and_lock(lock);
         if (lock->l_granted_mode == LCK_PW &&
             !lock->l_readers && !lock->l_writers &&
             cfs_time_after(cfs_time_current(),
                            cfs_time_add(lock->l_last_used, cfs_time_seconds(10)))) {
+                unlock_res_and_lock(lock);
                 if (ldlm_bl_to_thread(ns, NULL, lock))
                         ldlm_handle_bl_callback(ns, NULL, lock);
+
                 EXIT;
                 return;
         }
-
+        unlock_res_and_lock(lock);
         LDLM_LOCK_PUT(lock);
         EXIT;
 }
@@ -1199,7 +1258,7 @@ static int ldlm_callback_reply(struct ptlrpc_request *req, int rc)
 {
         req->rq_status = rc;
         if (req->rq_reply_state == NULL) {
-                rc = lustre_pack_reply(req, 0, NULL, NULL);
+                rc = lustre_pack_reply(req, 1, NULL, NULL);
                 if (rc)
                         return rc;
         }
@@ -1253,11 +1312,12 @@ static int ldlm_callback_handler(struct ptlrpc_request *req)
                 CDEBUG(D_RPCTRACE, "operation %d from %s with bad "
                        "export cookie "LPX64"; this is "
                        "normal if this node rebooted with a lock held\n",
-                       req->rq_reqmsg->opc,
+                       lustre_msg_get_opc(req->rq_reqmsg),
                        libcfs_id2str(req->rq_peer),
-                       req->rq_reqmsg->handle.cookie);
+                       lustre_msg_get_handle(req->rq_reqmsg)->cookie);
 
-                dlm_req = lustre_swab_reqbuf(req, 0, sizeof (*dlm_req),
+                dlm_req = lustre_swab_reqbuf(req, DLM_LOCKREQ_OFF,
+                                             sizeof(*dlm_req),
                                              lustre_swab_ldlm_request);
                 if (dlm_req != NULL)
                         CDEBUG(D_RPCTRACE, "--> lock cookie: "LPX64"\n",
@@ -1270,7 +1330,7 @@ static int ldlm_callback_handler(struct ptlrpc_request *req)
         LASSERT(req->rq_export != NULL);
         LASSERT(req->rq_export->exp_obd != NULL);
 
-        switch(req->rq_reqmsg->opc) {
+        switch (lustre_msg_get_opc(req->rq_reqmsg)) {
         case LDLM_BL_CALLBACK:
                 OBD_FAIL_RETURN(OBD_FAIL_LDLM_BL_CALLBACK, 0);
                 break;
@@ -1316,7 +1376,8 @@ static int ldlm_callback_handler(struct ptlrpc_request *req)
                 ldlm_callback_reply(req, rc);
                 RETURN(0);
         default:
-                CERROR("unknown opcode %u\n", req->rq_reqmsg->opc);
+                CERROR("unknown opcode %u\n",
+                       lustre_msg_get_opc(req->rq_reqmsg));
                 ldlm_callback_reply(req, -EPROTO);
                 RETURN(0);
         }
@@ -1324,11 +1385,11 @@ static int ldlm_callback_handler(struct ptlrpc_request *req)
         ns = req->rq_export->exp_obd->obd_namespace;
         LASSERT(ns != NULL);
 
-        dlm_req = lustre_swab_reqbuf (req, 0, sizeof (*dlm_req),
-                                      lustre_swab_ldlm_request);
+        dlm_req = lustre_swab_reqbuf(req, DLM_LOCKREQ_OFF, sizeof(*dlm_req),
+                                     lustre_swab_ldlm_request);
         if (dlm_req == NULL) {
                 CERROR ("can't unpack dlm_req\n");
-                ldlm_callback_reply (req, -EPROTO);
+                ldlm_callback_reply(req, -EPROTO);
                 RETURN (0);
         }
 
@@ -1341,7 +1402,9 @@ static int ldlm_callback_handler(struct ptlrpc_request *req)
         }
 
         /* Copy hints/flags (e.g. LDLM_FL_DISCARD_DATA) from AST. */
+        lock_res_and_lock(lock);
         lock->l_flags |= (dlm_req->lock_flags & LDLM_AST_FLAGS);
+        unlock_res_and_lock(lock);
 
         /* We want the ost thread to get this reply so that it can respond
          * to ost requests (write cache writeback) that might be triggered
@@ -1352,7 +1415,7 @@ static int ldlm_callback_handler(struct ptlrpc_request *req)
          * in the reply, so we might have to push the responsibility for sending
          * the reply down into the AST handlers, alas. */
 
-        switch (req->rq_reqmsg->opc) {
+        switch (lustre_msg_get_opc(req->rq_reqmsg)) {
         case LDLM_BL_CALLBACK:
                 CDEBUG(D_INODE, "blocking ast\n");
                 if (!(lock->l_flags & LDLM_FL_CANCEL_ON_BLOCK))
@@ -1390,10 +1453,12 @@ static int ldlm_cancel_handler(struct ptlrpc_request *req)
                 struct ldlm_request *dlm_req;
 
                 CERROR("operation %d from %s with bad export cookie "LPU64"\n",
-                       req->rq_reqmsg->opc, libcfs_id2str(req->rq_peer),
-                       req->rq_reqmsg->handle.cookie);
+                       lustre_msg_get_opc(req->rq_reqmsg),
+                       libcfs_id2str(req->rq_peer),
+                       lustre_msg_get_handle(req->rq_reqmsg)->cookie);
 
-                dlm_req = lustre_swab_reqbuf(req, 0, sizeof (*dlm_req),
+                dlm_req = lustre_swab_reqbuf(req, DLM_LOCKREQ_OFF,
+                                             sizeof(*dlm_req),
                                              lustre_swab_ldlm_request);
                 if (dlm_req != NULL)
                         ldlm_lock_dump_handle(D_ERROR, &dlm_req->lock_handle1);
@@ -1402,7 +1467,7 @@ static int ldlm_cancel_handler(struct ptlrpc_request *req)
                 RETURN(0);
         }
 
-        switch (req->rq_reqmsg->opc) {
+        switch (lustre_msg_get_opc(req->rq_reqmsg)) {
 
         /* XXX FIXME move this back to mds/handler.c, bug 249 */
         case LDLM_CANCEL:
@@ -1418,7 +1483,8 @@ static int ldlm_cancel_handler(struct ptlrpc_request *req)
                 ldlm_callback_reply(req, rc);
                 RETURN(0);
         default:
-                CERROR("invalid opcode %d\n", req->rq_reqmsg->opc);
+                CERROR("invalid opcode %d\n",
+                       lustre_msg_get_opc(req->rq_reqmsg));
                 ldlm_callback_reply(req, -EINVAL);
         }
 
@@ -1613,10 +1679,7 @@ static int ldlm_setup(void)
         spin_lock_init(&waiting_locks_spinlock);
         cfs_timer_init(&waiting_locks_timer, waiting_locks_callback, 0);
 
-        /* Using CLONE_FILES instead of CLONE_FS here causes failures in
-           conf-sanity test 21.  But using CLONE_FS can cause problems
-           if the daemonize happens between push/pop_ctxt... */
-        rc = cfs_kernel_thread(expired_lock_main, NULL, CLONE_VM | CLONE_FS);
+        rc = cfs_kernel_thread(expired_lock_main, NULL, CLONE_VM | CLONE_FILES);
         if (rc < 0) {
                 CERROR("Cannot start ldlm expired-lock thread: %d\n", rc);
                 GOTO(out_thread, rc);
@@ -1709,15 +1772,12 @@ int __init ldlm_init(void)
                 return -ENOMEM;
         }
 
-        l_lock_init(&ldlm_handle_lock);
-
         return 0;
 }
 
 void __exit ldlm_exit(void)
 {
         int rc;
-
         if (ldlm_refcount)
                 CERROR("ldlm_refcount is %d in ldlm_exit!\n", ldlm_refcount);
         rc = cfs_mem_cache_destroy(ldlm_resource_slab);
@@ -1760,6 +1820,8 @@ EXPORT_SYMBOL(ldlm_glimpse_ast);
 EXPORT_SYMBOL(ldlm_expired_completion_wait);
 EXPORT_SYMBOL(ldlm_cli_convert);
 EXPORT_SYMBOL(ldlm_cli_enqueue);
+EXPORT_SYMBOL(ldlm_cli_enqueue_fini);
+EXPORT_SYMBOL(ldlm_cli_enqueue_local);
 EXPORT_SYMBOL(ldlm_cli_cancel);
 EXPORT_SYMBOL(ldlm_cli_cancel_unused);
 EXPORT_SYMBOL(ldlm_cli_join_lru);
@@ -1767,7 +1829,7 @@ EXPORT_SYMBOL(ldlm_replay_locks);
 EXPORT_SYMBOL(ldlm_resource_foreach);
 EXPORT_SYMBOL(ldlm_namespace_foreach);
 EXPORT_SYMBOL(ldlm_namespace_foreach_res);
-EXPORT_SYMBOL(ldlm_change_cbdata);
+EXPORT_SYMBOL(ldlm_resource_iterate);
 
 /* ldlm_lockd.c */
 EXPORT_SYMBOL(ldlm_server_blocking_ast);
@@ -1781,6 +1843,7 @@ EXPORT_SYMBOL(ldlm_handle_convert0);
 EXPORT_SYMBOL(ldlm_del_waiting_lock);
 EXPORT_SYMBOL(ldlm_get_ref);
 EXPORT_SYMBOL(ldlm_put_ref);
+EXPORT_SYMBOL(ldlm_refresh_waiting_lock);
 
 /* ldlm_resource.c */
 EXPORT_SYMBOL(ldlm_namespace_new);
@@ -1790,10 +1853,7 @@ EXPORT_SYMBOL(ldlm_namespace_dump);
 EXPORT_SYMBOL(ldlm_dump_all_namespaces);
 EXPORT_SYMBOL(ldlm_resource_get);
 EXPORT_SYMBOL(ldlm_resource_putref);
-
-/* l_lock.c */
-EXPORT_SYMBOL(l_lock);
-EXPORT_SYMBOL(l_unlock);
+EXPORT_SYMBOL(ldlm_resource_unlink_lock);
 
 /* ldlm_lib.c */
 EXPORT_SYMBOL(client_import_add_conn);
@@ -1812,3 +1872,8 @@ EXPORT_SYMBOL(target_queue_recovery_request);
 EXPORT_SYMBOL(target_handle_ping);
 EXPORT_SYMBOL(target_handle_disconnect);
 EXPORT_SYMBOL(target_queue_final_reply);
+
+/* l_lock.c */
+EXPORT_SYMBOL(lock_res_and_lock);
+EXPORT_SYMBOL(unlock_res_and_lock);
+
index 38b0c40..69b1104 100644 (file)
@@ -38,7 +38,7 @@
 
 static inline int
 ldlm_plain_compat_queue(struct list_head *queue, struct ldlm_lock *req,
-                        int send_cbs)
+                        struct list_head *work_list)
 {
         struct list_head *tmp;
         struct ldlm_lock *lock;
@@ -57,12 +57,12 @@ ldlm_plain_compat_queue(struct list_head *queue, struct ldlm_lock *req,
                 if (lockmode_compat(lock->l_req_mode, req_mode))
                         continue;
 
-                if (!send_cbs)
+                if (!work_list)
                         RETURN(0);
 
                 compat = 0;
                 if (lock->l_blocking_ast)
-                        ldlm_add_ast_work_item(lock, req, NULL, 0);
+                        ldlm_add_ast_work_item(lock, req, work_list);
         }
 
         RETURN(compat);
@@ -78,7 +78,7 @@ ldlm_plain_compat_queue(struct list_head *queue, struct ldlm_lock *req,
  *   - the caller has NOT initialized req->lr_tmp, so we must
  *   - must call this function with the ns lock held once */
 int ldlm_process_plain_lock(struct ldlm_lock *lock, int *flags, int first_enq,
-                            ldlm_error_t *err)
+                            ldlm_error_t *err, struct list_head *work_list)
 {
         struct ldlm_resource *res = lock->l_resource;
         struct list_head rpc_list = CFS_LIST_HEAD_INIT(rpc_list);
@@ -88,25 +88,22 @@ int ldlm_process_plain_lock(struct ldlm_lock *lock, int *flags, int first_enq,
         LASSERT(list_empty(&res->lr_converting));
 
         if (!first_enq) {
-                LASSERT(res->lr_tmp != NULL);
-                rc = ldlm_plain_compat_queue(&res->lr_granted, lock, 0);
+                LASSERT(work_list != NULL);
+                rc = ldlm_plain_compat_queue(&res->lr_granted, lock, NULL);
                 if (!rc)
                         RETURN(LDLM_ITER_STOP);
-                rc = ldlm_plain_compat_queue(&res->lr_waiting, lock, 0);
+                rc = ldlm_plain_compat_queue(&res->lr_waiting, lock, NULL);
                 if (!rc)
                         RETURN(LDLM_ITER_STOP);
 
                 ldlm_resource_unlink_lock(lock);
-                ldlm_grant_lock(lock, NULL, 0, 1);
+                ldlm_grant_lock(lock, work_list);
                 RETURN(LDLM_ITER_CONTINUE);
         }
 
  restart:
-        LASSERT(res->lr_tmp == NULL);
-        res->lr_tmp = &rpc_list;
-        rc = ldlm_plain_compat_queue(&res->lr_granted, lock, 1);
-        rc += ldlm_plain_compat_queue(&res->lr_waiting, lock, 1);
-        res->lr_tmp = NULL;
+        rc = ldlm_plain_compat_queue(&res->lr_granted, lock, &rpc_list);
+        rc += ldlm_plain_compat_queue(&res->lr_waiting, lock, &rpc_list);
 
         if (rc != 2) {
                 /* If either of the compat_queue()s returned 0, then we
@@ -117,15 +114,15 @@ int ldlm_process_plain_lock(struct ldlm_lock *lock, int *flags, int first_enq,
                  * re-ordered!  Causes deadlock, because ASTs aren't sent! */
                 if (list_empty(&lock->l_res_link))
                         ldlm_resource_add_lock(res, &res->lr_waiting, lock);
-                l_unlock(&res->lr_namespace->ns_lock);
-                rc = ldlm_run_ast_work(res->lr_namespace, &rpc_list);
-                l_lock(&res->lr_namespace->ns_lock);
+                unlock_res(res);
+                rc = ldlm_run_bl_ast_work(&rpc_list);
+                lock_res(res);
                 if (rc == -ERESTART)
                         GOTO(restart, -ERESTART);
                 *flags |= LDLM_FL_BLOCK_GRANTED;
         } else {
                 ldlm_resource_unlink_lock(lock);
-                ldlm_grant_lock(lock, NULL, 0, 0);
+                ldlm_grant_lock(lock, NULL);
         }
         RETURN(0);
 }
index e28595e..25a319c 100644 (file)
@@ -54,9 +54,10 @@ int ldlm_expired_completion_wait(void *data)
         if (lock->l_conn_export == NULL) {
                 static cfs_time_t next_dump = 0, last_dump = 0;
 
-                LDLM_ERROR(lock, "lock timed out (enq %lus ago); not entering "
-                           "recovery in server code, just going back to sleep",
-                           lock->l_enqueued_time.tv_sec);
+                LDLM_ERROR(lock, "lock timed out (enqueued at %lu, %lus ago); "
+                           "not entering recovery in server code, just going "
+                           "back to sleep", lock->l_enqueued_time.tv_sec,
+                           CURRENT_SECONDS - lock->l_enqueued_time.tv_sec);
                 if (cfs_time_after(cfs_time_current(), next_dump)) {
                         last_dump = next_dump;
                         next_dump = cfs_time_shift(300);
@@ -71,8 +72,9 @@ int ldlm_expired_completion_wait(void *data)
         obd = lock->l_conn_export->exp_obd;
         imp = obd->u.cli.cl_import;
         ptlrpc_fail_import(imp, lwd->lwd_conn_cnt);
-        LDLM_ERROR(lock, "lock timed out (enqueued %lus ago), entering "
+        LDLM_ERROR(lock, "lock timed out (enqueued at %lu, %lus ago), entering "
                    "recovery for %s@%s", lock->l_enqueued_time.tv_sec,
+                   CURRENT_SECONDS - lock->l_enqueued_time.tv_sec,
                    obd2cli_tgt(obd), imp->imp_connection->c_remote_uuid.uuid);
 
         RETURN(0);
@@ -82,7 +84,6 @@ int ldlm_completion_ast(struct ldlm_lock *lock, int flags, void *data)
 {
         /* XXX ALLOCATE - 160 bytes */
         struct lock_wait_data lwd;
-        unsigned long irqflags;
         struct obd_device *obd;
         struct obd_import *imp = NULL;
         struct l_wait_info lwi;
@@ -115,7 +116,7 @@ noreproc:
 
         lwd.lwd_lock = lock;
 
-        if (unlikely(flags & LDLM_FL_NO_TIMEOUT)) {
+        if (lock->l_flags & LDLM_FL_NO_TIMEOUT) {
                 LDLM_DEBUG(lock, "waiting indefinitely because of NO_TIMEOUT");
                 lwi = LWI_INTR(interrupted_completion_wait, &lwd);
         } else {
@@ -125,9 +126,9 @@ noreproc:
         }
 
         if (imp != NULL) {
-                spin_lock_irqsave(&imp->imp_lock, irqflags);
+                spin_lock(&imp->imp_lock);
                 lwd.lwd_conn_cnt = imp->imp_conn_cnt;
-                spin_unlock_irqrestore(&imp->imp_lock, irqflags);
+                spin_unlock(&imp->imp_lock);
         }
 
         /* Go to sleep until the lock is granted or cancelled. */
@@ -164,20 +165,20 @@ int ldlm_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
                 RETURN(0);
         }
 
-        l_lock(&lock->l_resource->lr_namespace->ns_lock);
+        lock_res_and_lock(lock);
         /* Get this: if ldlm_blocking_ast is racing with intent_policy, such
          * that ldlm_blocking_ast is called just before intent_policy method
          * takes the ns_lock, then by the time we get the lock, we might not
          * be the correct blocking function anymore.  So check, and return
          * early, if so. */
         if (lock->l_blocking_ast != ldlm_blocking_ast) {
-                l_unlock(&lock->l_resource->lr_namespace->ns_lock);
+                unlock_res_and_lock(lock);
                 RETURN(0);
         }
 
         lock->l_flags |= LDLM_FL_CBPENDING;
         do_ast = (!lock->l_readers && !lock->l_writers);
-        l_unlock(&lock->l_resource->lr_namespace->ns_lock);
+        unlock_res_and_lock(lock);
 
         if (do_ast) {
                 struct lustre_handle lockh;
@@ -222,23 +223,20 @@ int ldlm_glimpse_ast(struct ldlm_lock *lock, void *reqp)
         return -ELDLM_NO_LOCK_DATA;
 }
 
-static int ldlm_cli_enqueue_local(struct ldlm_namespace *ns,
-                                  struct ldlm_res_id res_id,
-                                  __u32 type,
-                                  ldlm_policy_data_t *policy,
-                                  ldlm_mode_t mode,
-                                  int *flags,
-                                  ldlm_blocking_callback blocking,
-                                  ldlm_completion_callback completion,
-                                  ldlm_glimpse_callback glimpse,
-                                  void *data, __u32 lvb_len,
-                                  void *lvb_swabber,
-                                  struct lustre_handle *lockh)
+int ldlm_cli_enqueue_local(struct ldlm_namespace *ns, struct ldlm_res_id res_id,
+                           ldlm_type_t type, ldlm_policy_data_t *policy,
+                           ldlm_mode_t mode, int *flags,
+                           ldlm_blocking_callback blocking,
+                           ldlm_completion_callback completion,
+                           ldlm_glimpse_callback glimpse,
+                           void *data, __u32 lvb_len, void *lvb_swabber,
+                           struct lustre_handle *lockh)
 {
         struct ldlm_lock *lock;
         int err;
         ENTRY;
 
+        LASSERT(!(*flags & LDLM_FL_REPLAY));
         if (ns->ns_client) {
                 CERROR("Trying to enqueue local lock in a shadow namespace\n");
                 LBUG();
@@ -252,8 +250,12 @@ static int ldlm_cli_enqueue_local(struct ldlm_namespace *ns,
 
         ldlm_lock_addref_internal(lock, mode);
         ldlm_lock2handle(lock, lockh);
+        lock_res_and_lock(lock);
         lock->l_flags |= LDLM_FL_LOCAL;
+        if (*flags & LDLM_FL_ATOMIC_CB)
+                lock->l_flags |= LDLM_FL_ATOMIC_CB;
         lock->l_lvb_swabber = lvb_swabber;
+        unlock_res_and_lock(lock);
         if (policy != NULL)
                 lock->l_policy_data = *policy;
         if (type == LDLM_EXTENT)
@@ -287,10 +289,10 @@ static void failed_lock_cleanup(struct ldlm_namespace *ns,
                                 struct lustre_handle *lockh, int mode)
 {
         /* Set a flag to prevent us from sending a CANCEL (bug 407) */
-        l_lock(&ns->ns_lock);
+        lock_res_and_lock(lock);
         lock->l_flags |= LDLM_FL_LOCAL_ONLY;
+        unlock_res_and_lock(lock);
         LDLM_DEBUG(lock, "setting FL_LOCAL_ONLY");
-        l_unlock(&ns->ns_lock);
 
         ldlm_lock_decref_and_cancel(lockh, mode);
 
@@ -301,119 +303,29 @@ static void failed_lock_cleanup(struct ldlm_namespace *ns,
         }
 }
 
-int ldlm_cli_enqueue(struct obd_export *exp,
-                     struct ptlrpc_request *req,
-                     struct ldlm_namespace *ns,
-                     struct ldlm_res_id res_id,
-                     __u32 type,
-                     ldlm_policy_data_t *policy,
-                     ldlm_mode_t mode,
-                     int *flags,
-                     ldlm_blocking_callback blocking,
-                     ldlm_completion_callback completion,
-                     ldlm_glimpse_callback glimpse,
-                     void *data,
-                     void *lvb,
-                     __u32 lvb_len,
-                     void *lvb_swabber,
-                     struct lustre_handle *lockh)
+int ldlm_cli_enqueue_fini(struct obd_export *exp, struct ptlrpc_request *req,
+                          ldlm_type_t type, __u8 with_policy, ldlm_mode_t mode,
+                          int *flags, void *lvb, __u32 lvb_len,
+                          void *lvb_swabber, struct lustre_handle *lockh,int rc)
 {
+        struct ldlm_namespace *ns = exp->exp_obd->obd_namespace;
+        int is_replay = *flags & LDLM_FL_REPLAY;
         struct ldlm_lock *lock;
-        struct ldlm_request *body;
         struct ldlm_reply *reply;
-        int rc, size[] = {sizeof(*body), lvb_len}, req_passed_in = 1;
-        int is_replay = *flags & LDLM_FL_REPLAY;
-        int cleanup_phase = 0;
+        int cleanup_phase = 1;
         ENTRY;
 
-        if (exp == NULL) {
-                LASSERT(!is_replay);
-                rc = ldlm_cli_enqueue_local(ns, res_id, type, policy, mode,
-                                            flags, blocking, completion,
-                                            glimpse, data, lvb_len, lvb_swabber,
-                                            lockh);
-                RETURN(rc);
-        }
-
-        /* If we're replaying this lock, just check some invariants.
-         * If we're creating a new lock, get everything all setup nice. */
-        if (is_replay) {
-                lock = ldlm_handle2lock(lockh);
-                LDLM_DEBUG(lock, "client-side enqueue START");
-                LASSERT(exp == lock->l_conn_export);
-        } else {
-                lock = ldlm_lock_create(ns, NULL, res_id, type, mode, blocking,
-                                        completion, glimpse, data, lvb_len);
-                if (lock == NULL)
-                        RETURN(-ENOMEM);
-                /* for the local lock, add the reference */
-                ldlm_lock_addref_internal(lock, mode);
-                ldlm_lock2handle(lock, lockh);
-                lock->l_lvb_swabber = lvb_swabber;
-                if (policy != NULL) {
-                        /* INODEBITS_INTEROP: If the server does not support
-                         * inodebits, we will request a plain lock in the
-                         * descriptor (ldlm_lock2desc() below) but use an
-                         * inodebits lock internally with both bits set.
-                         */
-                        if (type == LDLM_IBITS && !(exp->exp_connect_flags &
-                                                    OBD_CONNECT_IBITS))
-                                lock->l_policy_data.l_inodebits.bits =
-                                        MDS_INODELOCK_LOOKUP |
-                                        MDS_INODELOCK_UPDATE;
-                        else
-                                lock->l_policy_data = *policy;
-                }
-
-                if (type == LDLM_EXTENT)
-                        lock->l_req_extent = policy->l_extent;
-                LDLM_DEBUG(lock, "client-side enqueue START");
-        }
-
-        /* lock not sent to server yet */
-        cleanup_phase = 2;
-
-        if (req == NULL) {
-                req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_DLM_VERSION,
-                                      LDLM_ENQUEUE, 1, size, NULL);
-                if (req == NULL)
-                        GOTO(cleanup, rc = -ENOMEM);
-                req_passed_in = 0;
-        } else {
-                LASSERTF(req->rq_reqmsg->buflens[MDS_REQ_INTENT_LOCKREQ_OFF] ==
-                         sizeof(*body), "buflen[%d] = %d, not %d\n",
-                         MDS_REQ_INTENT_LOCKREQ_OFF,
-                         req->rq_reqmsg->buflens[MDS_REQ_INTENT_LOCKREQ_OFF],
-                         (int)sizeof(*body));
-        }
-
-        lock->l_conn_export = exp;
-        lock->l_export = NULL;
-        lock->l_blocking_ast = blocking;
-
-        /* Dump lock data into the request buffer */
-        body = lustre_msg_buf(req->rq_reqmsg, MDS_REQ_INTENT_LOCKREQ_OFF,
-                              sizeof(*body));
-        ldlm_lock2desc(lock, &body->lock_desc);
-        body->lock_flags = *flags;
-
-        body->lock_handle1 = *lockh;
-
-        /* Continue as normal. */
-        if (!req_passed_in) {
-                size[0] = sizeof(*reply);
-                req->rq_replen = lustre_msg_size(1 + (lvb_len > 0), size);
-        }
-        LDLM_DEBUG(lock, "sending request");
-        rc = ptlrpc_queue_wait(req);
-
+        lock = ldlm_handle2lock(lockh);
+        /* ldlm_cli_enqueue is holding a reference on this lock. */
+        LASSERT(lock != NULL);
         if (rc != ELDLM_OK) {
                 LASSERT(!is_replay);
                 LDLM_DEBUG(lock, "client-side enqueue END (%s)",
                            rc == ELDLM_LOCK_ABORTED ? "ABORTED" : "FAILED");
                 if (rc == ELDLM_LOCK_ABORTED) {
                         /* Before we return, swab the reply */
-                        reply = lustre_swab_repbuf(req, 0, sizeof(*reply),
+                        reply = lustre_swab_repbuf(req, DLM_LOCKREPLY_OFF,
+                                                   sizeof(*reply),
                                                    lustre_swab_ldlm_reply);
                         if (reply == NULL) {
                                 CERROR("Can't unpack ldlm_reply\n");
@@ -421,7 +333,9 @@ int ldlm_cli_enqueue(struct obd_export *exp,
                         }
                         if (lvb_len) {
                                 void *tmplvb;
-                                tmplvb = lustre_swab_repbuf(req, 1, lvb_len,
+                                tmplvb = lustre_swab_repbuf(req,
+                                                            DLM_REPLY_REC_OFF,
+                                                            lvb_len,
                                                             lvb_swabber);
                                 if (tmplvb == NULL)
                                         GOTO(cleanup, rc = -EPROTO);
@@ -432,15 +346,7 @@ int ldlm_cli_enqueue(struct obd_export *exp,
                 GOTO(cleanup, rc);
         }
 
-        /*
-         * Liblustre client doesn't get extent locks, except for O_APPEND case
-         * where [0, OBD_OBJECT_EOF] lock is taken, or truncate, where
-         * [i_size, OBD_OBJECT_EOF] lock is taken.
-         */
-        LASSERT(ergo(LIBLUSTRE_CLIENT, type != LDLM_EXTENT ||
-                     policy->l_extent.end == OBD_OBJECT_EOF));
-
-        reply = lustre_swab_repbuf(req, 0, sizeof(*reply),
+        reply = lustre_swab_repbuf(req, DLM_LOCKREPLY_OFF, sizeof(*reply),
                                    lustre_swab_ldlm_reply);
         if (reply == NULL) {
                 CERROR("Can't unpack ldlm_reply\n");
@@ -448,13 +354,16 @@ int ldlm_cli_enqueue(struct obd_export *exp,
         }
 
         /* lock enqueued on the server */
-        cleanup_phase = 1;
+        cleanup_phase = 0;
 
-        l_lock(&ns->ns_lock);
+        lock_res_and_lock(lock);
         lock->l_remote_handle = reply->lock_handle;
         *flags = reply->lock_flags;
         lock->l_flags |= reply->lock_flags & LDLM_INHERIT_FLAGS;
-        l_unlock(&ns->ns_lock);
+        /* move NO_TIMEOUT flag to the lock to force ldlm_lock_match()
+         * to wait with no timeout as well */
+        lock->l_flags |= reply->lock_flags & LDLM_FL_NO_TIMEOUT;
+        unlock_res_and_lock(lock);
 
         CDEBUG(D_INFO, "local: %p, remote cookie: "LPX64", flags: 0x%x\n",
                lock, reply->lock_handle.cookie, *flags);
@@ -492,7 +401,7 @@ int ldlm_cli_enqueue(struct obd_export *exp,
                         }
                         LDLM_DEBUG(lock, "client-side enqueue, new resource");
                 }
-                if (policy != NULL)
+                if (with_policy)
                         if (!(type == LDLM_IBITS && !(exp->exp_connect_flags &
                                                     OBD_CONNECT_IBITS)))
                                 lock->l_policy_data =
@@ -506,9 +415,9 @@ int ldlm_cli_enqueue(struct obd_export *exp,
              * because it cannot handle asynchronous ASTs robustly (see
              * bug 7311). */
             (LIBLUSTRE_CLIENT && type == LDLM_EXTENT)) {
-                l_lock(&ns->ns_lock);
+                lock_res_and_lock(lock);
                 lock->l_flags |= LDLM_FL_CBPENDING;
-                l_unlock(&ns->ns_lock);
+                unlock_res_and_lock(lock);
                 LDLM_DEBUG(lock, "enqueue reply includes blocking AST");
         }
 
@@ -516,7 +425,8 @@ int ldlm_cli_enqueue(struct obd_export *exp,
          * clobber the LVB with an older one. */
         if (lvb_len && (lock->l_req_mode != lock->l_granted_mode)) {
                 void *tmplvb;
-                tmplvb = lustre_swab_repbuf(req, 1, lvb_len, lvb_swabber);
+                tmplvb = lustre_swab_repbuf(req, DLM_REPLY_REC_OFF, lvb_len,
+                                            lvb_swabber);
                 if (tmplvb == NULL)
                         GOTO(cleanup, rc = -EPROTO);
                 memcpy(lock->l_lvb_data, tmplvb, lvb_len);
@@ -528,8 +438,8 @@ int ldlm_cli_enqueue(struct obd_export *exp,
                         int err = lock->l_completion_ast(lock, *flags, NULL);
                         if (!rc)
                                 rc = err;
-                        if (rc)
-                                cleanup_phase = 2;
+                        if (rc && type != LDLM_FLOCK) /* bug 9425, bug 10250 */
+                                cleanup_phase = 1;
                 }
         }
 
@@ -542,17 +452,144 @@ int ldlm_cli_enqueue(struct obd_export *exp,
         LDLM_DEBUG(lock, "client-side enqueue END");
         EXIT;
 cleanup:
-        switch (cleanup_phase) {
-        case 2:
-                if (rc)
+        if (cleanup_phase == 1 && rc)
+                failed_lock_cleanup(ns, lock, lockh, mode);
+        /* Put lock 2 times, the second reference is held by ldlm_cli_enqueue */
+        LDLM_LOCK_PUT(lock);
+        LDLM_LOCK_PUT(lock);
+        return rc;
+}
+
+/* If a request has some specific initialisation it is passed in @reqp,
+ * otherwise it is created in ldlm_cli_enqueue.
+ *
+ * Supports sync and async requests, pass @async flag accordingly. If a
+ * request was created in ldlm_cli_enqueue and it is the async request,
+ * pass it to the caller in @reqp. */
+int ldlm_cli_enqueue(struct obd_export *exp, struct ptlrpc_request **reqp,
+                     struct ldlm_res_id res_id, 
+                     ldlm_type_t type, ldlm_policy_data_t *policy, 
+                     ldlm_mode_t mode, int *flags,
+                     ldlm_blocking_callback blocking,
+                     ldlm_completion_callback completion,
+                     ldlm_glimpse_callback glimpse,
+                     void *data, void *lvb, __u32 lvb_len, void *lvb_swabber,
+                     struct lustre_handle *lockh, int async)
+{
+        struct ldlm_namespace *ns = exp->exp_obd->obd_namespace;
+        struct ldlm_lock *lock;
+        struct ldlm_request *body;
+        struct ldlm_reply *reply;
+        int size[3] = { [MSG_PTLRPC_BODY_OFF] = sizeof(struct ptlrpc_body),
+                        [DLM_LOCKREQ_OFF]     = sizeof(*body),
+                        [DLM_REPLY_REC_OFF]   = lvb_len };
+        int is_replay = *flags & LDLM_FL_REPLAY;
+        int req_passed_in = 1, rc;
+        struct ptlrpc_request *req;
+        ENTRY;
+
+        LASSERT(exp != NULL);
+
+        /* If we're replaying this lock, just check some invariants.
+         * If we're creating a new lock, get everything all setup nice. */
+        if (is_replay) {
+                lock = ldlm_handle2lock(lockh);
+                LASSERT(lock != NULL);
+                LDLM_DEBUG(lock, "client-side enqueue START");
+                LASSERT(exp == lock->l_conn_export);
+        } else {
+                lock = ldlm_lock_create(ns, NULL, res_id, type, mode, blocking,
+                                        completion, glimpse, data, lvb_len);
+                if (lock == NULL)
+                        RETURN(-ENOMEM);
+                /* for the local lock, add the reference */
+                ldlm_lock_addref_internal(lock, mode);
+                ldlm_lock2handle(lock, lockh);
+                lock->l_lvb_swabber = lvb_swabber;
+                if (policy != NULL) {
+                        /* INODEBITS_INTEROP: If the server does not support
+                         * inodebits, we will request a plain lock in the
+                         * descriptor (ldlm_lock2desc() below) but use an
+                         * inodebits lock internally with both bits set.
+                         */
+                        if (type == LDLM_IBITS && !(exp->exp_connect_flags &
+                                                    OBD_CONNECT_IBITS))
+                                lock->l_policy_data.l_inodebits.bits =
+                                        MDS_INODELOCK_LOOKUP |
+                                        MDS_INODELOCK_UPDATE;
+                        else
+                                lock->l_policy_data = *policy;
+                }
+
+                if (type == LDLM_EXTENT)
+                        lock->l_req_extent = policy->l_extent;
+                LDLM_DEBUG(lock, "client-side enqueue START");
+        }
+
+        /* lock not sent to server yet */
+
+        if (reqp == NULL || *reqp == NULL) {
+                req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_DLM_VERSION,
+                                      LDLM_ENQUEUE, 2, size, NULL);
+                if (req == NULL) {
                         failed_lock_cleanup(ns, lock, lockh, mode);
-        case 1:
-                if (!req_passed_in && req != NULL)
-                        ptlrpc_req_finished(req);
+                        LDLM_LOCK_PUT(lock);
+                        RETURN(-ENOMEM);
+                }
+                req_passed_in = 0;
+                if (reqp)
+                        *reqp = req;
+        } else {
+                req = *reqp;
+                LASSERTF(lustre_msg_buflen(req->rq_reqmsg, DLM_LOCKREQ_OFF) ==
+                         sizeof(*body), "buflen[%d] = %d, not %d\n",
+                         DLM_LOCKREQ_OFF,
+                         lustre_msg_buflen(req->rq_reqmsg, DLM_LOCKREQ_OFF),
+                         sizeof(*body));
         }
 
-        LDLM_LOCK_PUT(lock);
-        return rc;
+        lock->l_conn_export = exp;
+        lock->l_export = NULL;
+        lock->l_blocking_ast = blocking;
+
+        /* Dump lock data into the request buffer */
+        body = lustre_msg_buf(req->rq_reqmsg, DLM_LOCKREQ_OFF, sizeof(*body));
+        ldlm_lock2desc(lock, &body->lock_desc);
+        body->lock_flags = *flags;
+        body->lock_handle1 = *lockh;
+
+        /* Continue as normal. */
+        if (!req_passed_in) {
+                size[DLM_LOCKREPLY_OFF] = sizeof(*reply);
+                ptlrpc_req_set_repsize(req, 2 + (lvb_len > 0), size);
+        }
+
+        /*
+         * Liblustre client doesn't get extent locks, except for O_APPEND case
+         * where [0, OBD_OBJECT_EOF] lock is taken, or truncate, where
+         * [i_size, OBD_OBJECT_EOF] lock is taken.
+         */
+        LASSERT(ergo(LIBLUSTRE_CLIENT, type != LDLM_EXTENT ||
+                     policy->l_extent.end == OBD_OBJECT_EOF));
+
+        if (async) {
+                LASSERT(reqp != NULL);
+                RETURN(0);
+        }
+
+        LDLM_DEBUG(lock, "sending request");
+        rc = ptlrpc_queue_wait(req);
+        rc = ldlm_cli_enqueue_fini(exp, req, type, policy ? 1 : 0,
+                                   mode, flags, lvb, lvb_len, lvb_swabber,
+                                   lockh, rc);
+
+        if (!req_passed_in && req != NULL) {
+                ptlrpc_req_finished(req);
+                if (reqp)
+                        *reqp = NULL;
+        }
+
+        RETURN(rc);
 }
 
 static int ldlm_cli_convert_local(struct ldlm_lock *lock, int new_mode,
@@ -590,7 +627,9 @@ int ldlm_cli_convert(struct lustre_handle *lockh, int new_mode, int *flags)
         struct ldlm_lock *lock;
         struct ldlm_resource *res;
         struct ptlrpc_request *req;
-        int rc, size = sizeof(*body);
+        int size[2] = { [MSG_PTLRPC_BODY_OFF] = sizeof(struct ptlrpc_body),
+                        [DLM_LOCKREQ_OFF]     = sizeof(*body) };
+        int rc;
         ENTRY;
 
         lock = ldlm_handle2lock(lockh);
@@ -606,24 +645,24 @@ int ldlm_cli_convert(struct lustre_handle *lockh, int new_mode, int *flags)
         LDLM_DEBUG(lock, "client-side convert");
 
         req = ptlrpc_prep_req(class_exp2cliimp(lock->l_conn_export),
-                              LUSTRE_DLM_VERSION, LDLM_CONVERT, 1, &size, NULL);
+                              LUSTRE_DLM_VERSION, LDLM_CONVERT, 2, size, NULL);
         if (!req)
                 GOTO(out, rc = -ENOMEM);
 
-        body = lustre_msg_buf(req->rq_reqmsg, 0, sizeof (*body));
+        body = lustre_msg_buf(req->rq_reqmsg, DLM_LOCKREQ_OFF, sizeof(*body));
         body->lock_handle1 = lock->l_remote_handle;
 
         body->lock_desc.l_req_mode = new_mode;
         body->lock_flags = *flags;
 
-        size = sizeof(*reply);
-        req->rq_replen = lustre_msg_size(1, &size);
+        size[DLM_LOCKREPLY_OFF] = sizeof(*reply);
+        ptlrpc_req_set_repsize(req, 2, size);
 
         rc = ptlrpc_queue_wait(req);
         if (rc != ELDLM_OK)
                 GOTO(out, rc);
 
-        reply = lustre_swab_repbuf(req, 0, sizeof (*reply),
+        reply = lustre_swab_repbuf(req, DLM_LOCKREPLY_OFF, sizeof(*reply),
                                    lustre_swab_ldlm_reply);
         if (reply == NULL) {
                 CERROR ("Can't unpack ldlm_reply\n");
@@ -659,7 +698,9 @@ int ldlm_cli_cancel(struct lustre_handle *lockh)
         struct ptlrpc_request *req;
         struct ldlm_lock *lock;
         struct ldlm_request *body;
-        int rc = 0, size = sizeof(*body);
+        int size[2] = { [MSG_PTLRPC_BODY_OFF] = sizeof(struct ptlrpc_body),
+                        [DLM_LOCKREQ_OFF]     = sizeof(*body) };
+        int rc = 0;
         ENTRY;
 
         /* concurrent cancels on the same handle can happen */
@@ -673,12 +714,12 @@ int ldlm_cli_cancel(struct lustre_handle *lockh)
 
                 LDLM_DEBUG(lock, "client-side cancel");
                 /* Set this flag to prevent others from getting new references*/
-                l_lock(&lock->l_resource->lr_namespace->ns_lock);
+                lock_res_and_lock(lock);
                 lock->l_flags |= LDLM_FL_CBPENDING;
                 local_only = (lock->l_flags &
                               (LDLM_FL_LOCAL_ONLY|LDLM_FL_CANCEL_ON_BLOCK));
-                l_unlock(&lock->l_resource->lr_namespace->ns_lock);
                 ldlm_cancel_callback(lock);
+                unlock_res_and_lock(lock);
 
                 if (local_only) {
                         CDEBUG(D_INFO, "not sending request (at caller's "
@@ -694,8 +735,8 @@ int ldlm_cli_cancel(struct lustre_handle *lockh)
                         goto local_cancel;
                 }
 
-                req = ptlrpc_prep_req(imp, LUSTRE_DLM_VERSION, LDLM_CANCEL,
-                                      1, &size, NULL);
+                req = ptlrpc_prep_req(imp, LUSTRE_DLM_VERSION, LDLM_CANCEL, 2,
+                                      size, NULL);
                 if (!req)
                         GOTO(out, rc = -ENOMEM);
                 req->rq_no_resend = 1;
@@ -704,11 +745,11 @@ int ldlm_cli_cancel(struct lustre_handle *lockh)
                 req->rq_request_portal = LDLM_CANCEL_REQUEST_PORTAL;
                 req->rq_reply_portal = LDLM_CANCEL_REPLY_PORTAL;
 
-                body = lustre_msg_buf(req->rq_reqmsg, 0, sizeof (*body));
+                body = lustre_msg_buf(req->rq_reqmsg, DLM_LOCKREQ_OFF,
+                                      sizeof(*body));
                 body->lock_handle1 = lock->l_remote_handle;
 
-                req->rq_replen = lustre_msg_size(0, NULL);
-
+                ptlrpc_req_set_repsize(req, 1, NULL);
                 rc = ptlrpc_queue_wait(req);
 
                 if (rc == ESTALE) {
@@ -767,17 +808,32 @@ int ldlm_cancel_lru(struct ldlm_namespace *ns, ldlm_sync_t sync)
         sync = LDLM_SYNC; /* force to be sync in user space */
 #endif
 
-        l_lock(&ns->ns_lock);
+        spin_lock(&ns->ns_unused_lock);
         count = ns->ns_nr_unused - ns->ns_max_unused;
 
         if (count <= 0) {
-                l_unlock(&ns->ns_lock);
+                spin_unlock(&ns->ns_unused_lock);
                 RETURN(0);
         }
 
-        list_for_each_entry_safe(lock, next, &ns->ns_unused_list, l_lru) {
+        while (!list_empty(&ns->ns_unused_list)) {
+                struct list_head *tmp = ns->ns_unused_list.next;
+                lock = list_entry(tmp, struct ldlm_lock, l_lru);
                 LASSERT(!lock->l_readers && !lock->l_writers);
 
+                LDLM_LOCK_GET(lock); /* dropped by bl thread */
+                spin_unlock(&ns->ns_unused_lock);
+
+                lock_res_and_lock(lock);
+                if (ldlm_lock_remove_from_lru(lock) == 0) {
+                        /* other thread is removing lock from lru */
+                        unlock_res_and_lock(lock);
+                        LDLM_LOCK_PUT(lock);
+                        spin_lock(&ns->ns_unused_lock);
+                        continue;
+
+                }
+
                 /* If we have chosen to canecl this lock voluntarily, we better
                    send cancel notification to server, so that it frees
                    appropriate state. This might lead to a race where while
@@ -792,32 +848,34 @@ int ldlm_cancel_lru(struct ldlm_namespace *ns, ldlm_sync_t sync)
                  * won't see this flag and call l_blocking_ast */
                 lock->l_flags |= LDLM_FL_CBPENDING;
 
-                LDLM_LOCK_GET(lock); /* dropped by bl thread */
-                ldlm_lock_remove_from_lru(lock);
-
                 /* We can't re-add to l_lru as it confuses the refcounting in
                  * ldlm_lock_remove_from_lru() if an AST arrives after we drop
-                 * ns_lock below.  Use l_export_chain as that is unused on
-                 * client, and lru is client-only (l_pending_chain is used by
-                 * ldlm_chain_lock_for_replay() on client).  bug 5666 */
-                if (sync != LDLM_ASYNC || ldlm_bl_to_thread(ns, NULL, lock)) {
-                        LASSERTF(list_empty(&lock->l_export_chain),
-                                 "lock %p next %p prev %p\n",
-                                 lock, &lock->l_export_chain.next,
-                                 &lock->l_export_chain.prev);
-                        __LDLM_DEBUG(D_INFO, lock, "adding to LRU clear list");
-                        list_add(&lock->l_export_chain, &cblist);
+                 * ns_lock below. We use l_tmp and can't use l_pending_chain as
+                 * it is used both on server and client nevertheles bug 5666
+                 * says it is used only on server. --umka */
+                list_add(&lock->l_tmp, &cblist);
+                unlock_res_and_lock(lock);
+
+                LDLM_LOCK_GET(lock); /* to hold lock after bl thread */
+                if (sync == LDLM_ASYNC && (ldlm_bl_to_thread(ns, NULL, lock) == 0)) {
+                        lock_res_and_lock(lock);
+                        list_del_init(&lock->l_tmp);
+                        unlock_res_and_lock(lock);
                 }
+                LDLM_LOCK_PUT(lock);
+
+                spin_lock(&ns->ns_unused_lock);
 
                 if (--count == 0)
                         break;
         }
-        l_unlock(&ns->ns_lock);
+        spin_unlock(&ns->ns_unused_lock);
 
-        list_for_each_entry_safe(lock, next, &cblist, l_export_chain) {
-                list_del_init(&lock->l_export_chain);
+        list_for_each_entry_safe(lock, next, &cblist, l_tmp) {
+                list_del_init(&lock->l_tmp);
                 ldlm_handle_bl_callback(ns, NULL, lock);
         }
+
         RETURN(rc);
 }
 
@@ -825,9 +883,9 @@ static int ldlm_cli_cancel_unused_resource(struct ldlm_namespace *ns,
                                            struct ldlm_res_id res_id, int flags,
                                            void *opaque)
 {
-        struct ldlm_resource *res;
         struct list_head *tmp, *next, list = CFS_LIST_HEAD_INIT(list);
-        struct ldlm_ast_work *w;
+        struct ldlm_resource *res;
+        struct ldlm_lock *lock;
         ENTRY;
 
         res = ldlm_resource_get(ns, NULL, res_id, 0, 0);
@@ -837,9 +895,8 @@ static int ldlm_cli_cancel_unused_resource(struct ldlm_namespace *ns,
                 RETURN(0);
         }
 
-        l_lock(&ns->ns_lock);
+        lock_res(res);
         list_for_each(tmp, &res->lr_granted) {
-                struct ldlm_lock *lock;
                 lock = list_entry(tmp, struct ldlm_lock, l_res_link);
 
                 if (opaque != NULL && lock->l_ast_data != opaque) {
@@ -860,31 +917,27 @@ static int ldlm_cli_cancel_unused_resource(struct ldlm_namespace *ns,
                 /* See CBPENDING comment in ldlm_cancel_lru */
                 lock->l_flags |= LDLM_FL_CBPENDING;
 
-                OBD_ALLOC(w, sizeof(*w));
-                LASSERT(w);
-
-                w->w_lock = LDLM_LOCK_GET(lock);
-
-                list_add(&w->w_list, &list);
+                LASSERT(list_empty(&lock->l_bl_ast));
+                list_add(&lock->l_bl_ast, &list);
+                LDLM_LOCK_GET(lock);
         }
-        l_unlock(&ns->ns_lock);
+        unlock_res(res);
 
         list_for_each_safe(tmp, next, &list) {
                 struct lustre_handle lockh;
                 int rc;
-                w = list_entry(tmp, struct ldlm_ast_work, w_list);
+                lock = list_entry(tmp, struct ldlm_lock, l_bl_ast);
 
                 if (flags & LDLM_FL_LOCAL_ONLY) {
-                        ldlm_lock_cancel(w->w_lock);
+                        ldlm_lock_cancel(lock);
                 } else {
-                        ldlm_lock2handle(w->w_lock, &lockh);
+                        ldlm_lock2handle(lock, &lockh);
                         rc = ldlm_cli_cancel(&lockh);
                         if (rc != ELDLM_OK)
                                 CERROR("ldlm_cli_cancel: %d\n", rc);
                 }
-                list_del(&w->w_list);
-                LDLM_LOCK_PUT(w->w_lock);
-                OBD_FREE(w, sizeof(*w));
+                list_del_init(&lock->l_bl_ast);
+                LDLM_LOCK_PUT(lock);
         }
 
         ldlm_resource_putref(res);
@@ -892,6 +945,18 @@ static int ldlm_cli_cancel_unused_resource(struct ldlm_namespace *ns,
         RETURN(0);
 }
 
+static inline int have_no_nsresource(struct ldlm_namespace *ns)
+{
+        int no_resource = 0;
+
+        spin_lock(&ns->ns_hash_lock);
+        if (ns->ns_resources == 0)
+                no_resource = 1;
+        spin_unlock(&ns->ns_hash_lock);
+
+        RETURN(no_resource);
+}
+
 /* Cancel all locks on a namespace (or a specific resource, if given)
  * that have 0 readers/writers.
  *
@@ -911,14 +976,17 @@ int ldlm_cli_cancel_unused(struct ldlm_namespace *ns,
                 RETURN(ldlm_cli_cancel_unused_resource(ns, *res_id, flags,
                                                        opaque));
 
-        l_lock(&ns->ns_lock);
+        spin_lock(&ns->ns_hash_lock);
         for (i = 0; i < RES_HASH_SIZE; i++) {
-                struct list_head *tmp, *pos;
-                list_for_each_safe(tmp, pos, &(ns->ns_hash[i])) {
-                        int rc;
+                struct list_head *tmp;
+                tmp = ns->ns_hash[i].next;
+                while (tmp != &(ns->ns_hash[i])) {
                         struct ldlm_resource *res;
+                        int rc;
+
                         res = list_entry(tmp, struct ldlm_resource, lr_hash);
                         ldlm_resource_getref(res);
+                        spin_unlock(&ns->ns_hash_lock);
 
                         rc = ldlm_cli_cancel_unused_resource(ns, res->lr_name,
                                                              flags, opaque);
@@ -926,10 +994,13 @@ int ldlm_cli_cancel_unused(struct ldlm_namespace *ns,
                         if (rc)
                                 CERROR("cancel_unused_res ("LPU64"): %d\n",
                                        res->lr_name.name[0], rc);
-                        ldlm_resource_putref(res);
+
+                        spin_lock(&ns->ns_hash_lock);
+                        tmp = tmp->next;
+                        ldlm_resource_putref_locked(res);
                 }
         }
-        l_unlock(&ns->ns_lock);
+        spin_unlock(&ns->ns_hash_lock);
 
         RETURN(ELDLM_OK);
 }
@@ -950,7 +1021,7 @@ int ldlm_cli_join_lru(struct ldlm_namespace *ns,
                 RETURN(count);
         LASSERT(res->lr_type == LDLM_EXTENT);
 
-        l_lock(&ns->ns_lock);
+        lock_res(res);
         if (!join)
                 goto split;
 
@@ -959,9 +1030,11 @@ int ldlm_cli_join_lru(struct ldlm_namespace *ns,
                     !lock->l_readers && !lock->l_writers &&
                     !(lock->l_flags & LDLM_FL_LOCAL) &&
                     !(lock->l_flags & LDLM_FL_CBPENDING)) {
+                        spin_lock(&ns->ns_unused_lock);
                         LASSERT(ns->ns_nr_unused >= 0);
                         list_add_tail(&lock->l_lru, &ns->ns_unused_list);
                         ns->ns_nr_unused++;
+                        spin_unlock(&ns->ns_unused_lock);
                         lock->l_flags &= ~LDLM_FL_NO_LRU;
                         LDLM_DEBUG(lock, "join lock to lru");
                         count++;
@@ -969,16 +1042,18 @@ int ldlm_cli_join_lru(struct ldlm_namespace *ns,
         }
         goto unlock;
 split:
+        spin_lock(&ns->ns_unused_lock);
         list_for_each_entry_safe (lock, n, &ns->ns_unused_list, l_lru) {
                 if (lock->l_resource == res) {
-                        ldlm_lock_remove_from_lru(lock);
+                        ldlm_lock_remove_from_lru_nolock(lock);
                         lock->l_flags |= LDLM_FL_NO_LRU;
                         LDLM_DEBUG(lock, "split lock from lru");
                         count++;
                 }
         }
+        spin_unlock(&ns->ns_unused_lock);
 unlock:
-        l_unlock(&ns->ns_lock);
+        unlock_res(res);
         ldlm_resource_putref(res);
         RETURN(count);
 }
@@ -991,15 +1066,13 @@ int ldlm_resource_foreach(struct ldlm_resource *res, ldlm_iterator_t iter,
         struct list_head *tmp, *next;
         struct ldlm_lock *lock;
         int rc = LDLM_ITER_CONTINUE;
-        struct ldlm_namespace *ns;
 
         ENTRY;
 
         if (!res)
                 RETURN(LDLM_ITER_CONTINUE);
 
-        ns = res->lr_namespace;
-        l_lock(&ns->ns_lock);
+        lock_res(res);
         list_for_each_safe(tmp, next, &res->lr_granted) {
                 lock = list_entry(tmp, struct ldlm_lock, l_res_link);
 
@@ -1021,7 +1094,7 @@ int ldlm_resource_foreach(struct ldlm_resource *res, ldlm_iterator_t iter,
                         GOTO(out, rc = LDLM_ITER_STOP);
         }
  out:
-        l_unlock(&ns->ns_lock);
+        unlock_res(res);
         RETURN(rc);
 }
 
@@ -1052,30 +1125,35 @@ int ldlm_namespace_foreach_res(struct ldlm_namespace *ns,
                                ldlm_res_iterator_t iter, void *closure)
 {
         int i, rc = LDLM_ITER_CONTINUE;
+        struct ldlm_resource *res;
+        struct list_head *tmp;
 
         ENTRY;
-        l_lock(&ns->ns_lock);
+        spin_lock(&ns->ns_hash_lock);
         for (i = 0; i < RES_HASH_SIZE; i++) {
-                struct list_head *tmp, *next;
-                list_for_each_safe(tmp, next, &(ns->ns_hash[i])) {
-                        struct ldlm_resource *res =
-                                list_entry(tmp, struct ldlm_resource, lr_hash);
-
+                tmp = ns->ns_hash[i].next;
+                while (tmp != &(ns->ns_hash[i])) {
+                        res = list_entry(tmp, struct ldlm_resource, lr_hash);
                         ldlm_resource_getref(res);
+                        spin_unlock(&ns->ns_hash_lock);
+
                         rc = iter(res, closure);
-                        ldlm_resource_putref(res);
+
+                        spin_lock(&ns->ns_hash_lock);
+                        tmp = tmp->next;
+                        ldlm_resource_putref_locked(res);
                         if (rc == LDLM_ITER_STOP)
                                 GOTO(out, rc);
                 }
         }
  out:
-        l_unlock(&ns->ns_lock);
+        spin_unlock(&ns->ns_hash_lock);
         RETURN(rc);
 }
 
 /* non-blocking function to manipulate a lock whose cb_data is being put away.*/
-void ldlm_change_cbdata(struct ldlm_namespace *ns, struct ldlm_res_id *res_id,
-                        ldlm_iterator_t iter, void *data)
+void ldlm_resource_iterate(struct ldlm_namespace *ns, struct ldlm_res_id *res_id,
+                           ldlm_iterator_t iter, void *data)
 {
         struct ldlm_resource *res;
         ENTRY;
@@ -1091,9 +1169,7 @@ void ldlm_change_cbdata(struct ldlm_namespace *ns, struct ldlm_res_id *res_id,
                 return;
         }
 
-        l_lock(&ns->ns_lock);
         ldlm_resource_foreach(res, iter, data);
-        l_unlock(&ns->ns_lock);
         ldlm_resource_putref(res);
         EXIT;
 }
@@ -1127,7 +1203,7 @@ static int replay_lock_interpret(struct ptlrpc_request *req,
         lock = req->rq_async_args.pointer_arg[0];
         LASSERT(lock != NULL);
 
-        reply = lustre_swab_repbuf(req, 0, sizeof (*reply),
+        reply = lustre_swab_repbuf(req, DLM_LOCKREPLY_OFF, sizeof(*reply),
                                    lustre_swab_ldlm_reply);
         if (reply == NULL) {
                 CERROR("Can't unpack ldlm_reply\n");
@@ -1150,8 +1226,8 @@ static int replay_one_lock(struct obd_import *imp, struct ldlm_lock *lock)
         struct ptlrpc_request *req;
         struct ldlm_request *body;
         struct ldlm_reply *reply;
-        int buffers = 1;
-        int size[2];
+        int buffers = 2;
+        int size[3] = { sizeof(struct ptlrpc_body) };
         int flags;
         ENTRY;
 
@@ -1186,26 +1262,26 @@ static int replay_one_lock(struct obd_import *imp, struct ldlm_lock *lock)
         else
                 flags = LDLM_FL_REPLAY;
 
-        size[0] = sizeof(*body);
-        req = ptlrpc_prep_req(imp, LUSTRE_DLM_VERSION, LDLM_ENQUEUE,
-                              1, size, NULL);
+        size[DLM_LOCKREQ_OFF] = sizeof(*body);
+        req = ptlrpc_prep_req(imp, LUSTRE_DLM_VERSION, LDLM_ENQUEUE, 2, size,
+                              NULL);
         if (!req)
                 RETURN(-ENOMEM);
 
         /* We're part of recovery, so don't wait for it. */
         req->rq_send_state = LUSTRE_IMP_REPLAY_LOCKS;
 
-        body = lustre_msg_buf(req->rq_reqmsg, 0, sizeof (*body));
+        body = lustre_msg_buf(req->rq_reqmsg, DLM_LOCKREQ_OFF, sizeof(*body));
         ldlm_lock2desc(lock, &body->lock_desc);
         body->lock_flags = flags;
 
         ldlm_lock2handle(lock, &body->lock_handle1);
-        size[0] = sizeof(*reply);
+        size[DLM_LOCKREPLY_OFF] = sizeof(*reply);
         if (lock->l_lvb_len != 0) {
-                buffers = 2;
-                size[1] = lock->l_lvb_len;
+                buffers = 3;
+                size[DLM_REPLY_REC_OFF] = lock->l_lvb_len;
         }
-        req->rq_replen = lustre_msg_size(buffers, size);
+        ptlrpc_req_set_repsize(req, buffers, size);
 
         LDLM_DEBUG(lock, "replaying lock:");
 
@@ -1232,7 +1308,6 @@ int ldlm_replay_locks(struct obd_import *imp)
         /* ensure this doesn't fall to 0 before all have been queued */
         atomic_inc(&imp->imp_replay_inflight);
 
-        l_lock(&ns->ns_lock);
         (void)ldlm_namespace_foreach(ns, ldlm_chain_lock_for_replay, &list);
 
         list_for_each_entry_safe(lock, next, &list, l_pending_chain) {
@@ -1241,7 +1316,6 @@ int ldlm_replay_locks(struct obd_import *imp)
                         continue; /* or try to do the rest? */
                 rc = replay_one_lock(imp, lock);
         }
-        l_unlock(&ns->ns_lock);
 
         atomic_dec(&imp->imp_replay_inflight);
 
index 809b87f..4d50aa8 100644 (file)
@@ -243,12 +243,12 @@ struct ldlm_namespace *ldlm_namespace_new(char *name, __u32 client)
         strcpy(ns->ns_name, name);
 
         CFS_INIT_LIST_HEAD(&ns->ns_root_list);
-        l_lock_init(&ns->ns_lock);
-        cfs_waitq_init(&ns->ns_refcount_waitq);
-        atomic_set(&ns->ns_refcount, 0);
+        ns->ns_refcount = 0;
         ns->ns_client = client;
-        spin_lock_init(&ns->ns_counter_lock);
-        ns->ns_locks = 0;
+        spin_lock_init(&ns->ns_hash_lock);
+        atomic_set(&ns->ns_locks, 0);
+        ns->ns_resources = 0;
+        cfs_waitq_init(&ns->ns_waitq);
 
         for (bucket = ns->ns_hash + RES_HASH_SIZE - 1; bucket >= ns->ns_hash;
              bucket--)
@@ -257,6 +257,7 @@ struct ldlm_namespace *ldlm_namespace_new(char *name, __u32 client)
         CFS_INIT_LIST_HEAD(&ns->ns_unused_list);
         ns->ns_nr_unused = 0;
         ns->ns_max_unused = LDLM_DEFAULT_LRU_SIZE;
+        spin_lock_init(&ns->ns_unused_lock);
 
         mutex_down(&ldlm_namespace_lock);
         list_add(&ns->ns_list_chain, &ldlm_namespace_list);
@@ -284,15 +285,33 @@ extern struct ldlm_lock *ldlm_lock_get(struct ldlm_lock *lock);
 static void cleanup_resource(struct ldlm_resource *res, struct list_head *q,
                              int flags)
 {
-        struct list_head *tmp, *pos;
+        struct list_head *tmp;
         int rc = 0, client = res->lr_namespace->ns_client;
         int local_only = (flags & LDLM_FL_LOCAL_ONLY);
         ENTRY;
 
-        list_for_each_safe(tmp, pos, q) {
-                struct ldlm_lock *lock;
-                lock = list_entry(tmp, struct ldlm_lock, l_res_link);
-                LDLM_LOCK_GET(lock);
+        
+        do {
+                struct ldlm_lock *lock = NULL;
+                /* first, we look for non-cleaned-yet lock
+                 * all cleaned locks are marked by CLEANED flag */
+                lock_res(res);
+                list_for_each(tmp, q) {
+                        lock = list_entry(tmp, struct ldlm_lock, l_res_link);
+                        if (lock->l_flags & LDLM_FL_CLEANED) {
+                                lock = NULL;
+                                continue;
+                        }
+                        LDLM_LOCK_GET(lock);
+                        lock->l_flags |= LDLM_FL_CLEANED;
+                        break;
+                }
+                
+                if (lock == NULL) {
+                        unlock_res(res);
+                        break;
+                }
 
                 /* Set CBPENDING so nothing in the cancellation path
                  * can match this lock */
@@ -307,6 +326,7 @@ static void cleanup_resource(struct ldlm_resource *res, struct list_head *q,
                          * will go away ... */
                         /* ... without sending a CANCEL message. */
                         lock->l_flags |= LDLM_FL_LOCAL_ONLY;
+                        unlock_res(res);
                         LDLM_DEBUG(lock, "setting FL_LOCAL_ONLY");
                         if (lock->l_completion_ast)
                                 lock->l_completion_ast(lock, 0, NULL);
@@ -316,6 +336,8 @@ static void cleanup_resource(struct ldlm_resource *res, struct list_head *q,
 
                 if (client) {
                         struct lustre_handle lockh;
+
+                        unlock_res(res);
                         ldlm_lock2handle(lock, &lockh);
                         if (!local_only) {
                                 rc = ldlm_cli_cancel(&lockh);
@@ -326,19 +348,21 @@ static void cleanup_resource(struct ldlm_resource *res, struct list_head *q,
                         if (local_only || rc != ELDLM_OK)
                                 ldlm_lock_cancel(lock);
                 } else {
+                        ldlm_resource_unlink_lock(lock);
+                        unlock_res(res);
                         LDLM_DEBUG(lock, "Freeing a lock still held by a "
                                    "client node");
-
-                        ldlm_resource_unlink_lock(lock);
                         ldlm_lock_destroy(lock);
                 }
                 LDLM_LOCK_PUT(lock);
-        }
+        } while (1);
+
         EXIT;
 }
 
 int ldlm_namespace_cleanup(struct ldlm_namespace *ns, int flags)
 {
+        struct list_head *tmp;
         int i;
 
         if (ns == NULL) {
@@ -346,27 +370,35 @@ int ldlm_namespace_cleanup(struct ldlm_namespace *ns, int flags)
                 return ELDLM_OK;
         }
 
-        l_lock(&ns->ns_lock);
         for (i = 0; i < RES_HASH_SIZE; i++) {
-                struct list_head *tmp, *pos;
-                list_for_each_safe(tmp, pos, &(ns->ns_hash[i])) {
+                spin_lock(&ns->ns_hash_lock);
+                tmp = ns->ns_hash[i].next;
+                while (tmp != &(ns->ns_hash[i])) {
                         struct ldlm_resource *res;
                         res = list_entry(tmp, struct ldlm_resource, lr_hash);
                         ldlm_resource_getref(res);
+                        spin_unlock(&ns->ns_hash_lock);
 
                         cleanup_resource(res, &res->lr_granted, flags);
                         cleanup_resource(res, &res->lr_converting, flags);
                         cleanup_resource(res, &res->lr_waiting, flags);
 
-                        if (!ldlm_resource_putref(res)) {
-                                CERROR("Namespace %s resource refcount %d "
-                                       "after lock cleanup; forcing cleanup.\n",
-                                       ns->ns_name,
-                                       atomic_read(&res->lr_refcount));
-                        }
+                        spin_lock(&ns->ns_hash_lock);
+                        tmp  = tmp->next;
+
+                        /* XXX: former stuff caused issues in case of race
+                         * between ldlm_namespace_cleanup() and lockd() when
+                         * client gets blocking ast when lock gets distracted by
+                         * server. This is 1_4 branch solution, let's see how
+                         * will it behave. */
+                        if (!ldlm_resource_putref_locked(res))
+                                CDEBUG(D_INFO,
+                                       "Namespace %s resource refcount nonzero "
+                                       "(%d) after lock cleanup; forcing cleanup.\n",
+                                       ns->ns_name, atomic_read(&res->lr_refcount));
                 }
+                spin_unlock(&ns->ns_hash_lock);
         }
-        l_unlock(&ns->ns_lock);
 
         return ELDLM_OK;
 }
@@ -398,22 +430,21 @@ int ldlm_namespace_free(struct ldlm_namespace *ns, int force)
         }
 #endif
 
-        if (atomic_read(&ns->ns_refcount) > 0) {
-                struct l_wait_info lwi = LWI_INTR(NULL, NULL);
+        if (ns->ns_refcount > 0) {
+                struct l_wait_info lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL);
                 int rc;
                 CDEBUG(D_DLMTRACE,
                        "dlm namespace %s free waiting on refcount %d\n",
-                       ns->ns_name, atomic_read(&ns->ns_refcount));
-                rc = l_wait_event(ns->ns_refcount_waitq,
-                                  atomic_read(&ns->ns_refcount) == 0, &lwi);
-                if (atomic_read(&ns->ns_refcount)) {
+                       ns->ns_name, ns->ns_refcount);
+                rc = l_wait_event(ns->ns_waitq,
+                                  ns->ns_refcount == 0, &lwi);
+                if (ns->ns_refcount)
                         LCONSOLE_ERROR("Lock manager: wait for %s namespace "
                                        "cleanup aborted with %d resources in "
                                        "use. (%d)\nI'm going to try to clean "
                                        "up anyway, but I might need a reboot "
                                        "of this node.\n", ns->ns_name,
-                                       atomic_read(&ns->ns_refcount), rc);
-                }
+                                       (int) ns->ns_refcount, rc);
                 CDEBUG(D_DLMTRACE,
                        "dlm namespace %s free done waiting\n", ns->ns_name);
         }
@@ -456,20 +487,43 @@ static struct ldlm_resource *ldlm_resource_new(void)
         CFS_INIT_LIST_HEAD(&res->lr_granted);
         CFS_INIT_LIST_HEAD(&res->lr_converting);
         CFS_INIT_LIST_HEAD(&res->lr_waiting);
-        sema_init(&res->lr_lvb_sem, 1);
         atomic_set(&res->lr_refcount, 1);
+        spin_lock_init(&res->lr_lock);
+
+        /* one who creates the resource must unlock
+         * the semaphore after lvb initialization */
+        init_MUTEX_LOCKED(&res->lr_lvb_sem);
 
         return res;
 }
 
+/* must be called with hash lock held */
+static struct ldlm_resource *
+ldlm_resource_find(struct ldlm_namespace *ns, struct ldlm_res_id name, __u32 hash)
+{
+        struct list_head *bucket, *tmp;
+        struct ldlm_resource *res;
+
+        LASSERT_SPIN_LOCKED(&ns->ns_hash_lock);
+        bucket = ns->ns_hash + hash;
+
+        list_for_each(tmp, bucket) {
+                res = list_entry(tmp, struct ldlm_resource, lr_hash);
+                if (memcmp(&res->lr_name, &name, sizeof(res->lr_name)) == 0)
+                        return res;
+        }
+
+        return NULL;
+}
+
 /* Args: locked namespace
  * Returns: newly-allocated, referenced, unlocked resource */
 static struct ldlm_resource *
 ldlm_resource_add(struct ldlm_namespace *ns, struct ldlm_resource *parent,
-                  struct ldlm_res_id name, ldlm_type_t type)
+                  struct ldlm_res_id name, __u32 hash, ldlm_type_t type)
 {
         struct list_head *bucket;
-        struct ldlm_resource *res;
+        struct ldlm_resource *res, *old_res;
         ENTRY;
 
         LASSERTF(type >= LDLM_MIN_TYPE && type < LDLM_MAX_TYPE,
@@ -479,16 +533,31 @@ ldlm_resource_add(struct ldlm_namespace *ns, struct ldlm_resource *parent,
         if (!res)
                 RETURN(NULL);
 
-        l_lock(&ns->ns_lock);
         res->lr_name = name;
         res->lr_namespace = ns;
-        atomic_inc(&ns->ns_refcount);
-
         res->lr_type = type;
         res->lr_most_restr = LCK_NL;
 
-        bucket = ns->ns_hash + ldlm_hash_fn(parent, name);
+        spin_lock(&ns->ns_hash_lock);
+        old_res = ldlm_resource_find(ns, name, hash);
+        if (old_res) {
+                /* someone won the race and added the resource before */
+                ldlm_resource_getref(old_res);
+                spin_unlock(&ns->ns_hash_lock);
+                OBD_SLAB_FREE(res, ldlm_resource_slab, sizeof *res);
+                /* synchronize WRT resource creation */
+                if (ns->ns_lvbo && ns->ns_lvbo->lvbo_init) {
+                        down(&old_res->lr_lvb_sem);
+                        up(&old_res->lr_lvb_sem);
+                }
+                RETURN(old_res);
+        }
+
+        /* we won! let's add the resource */
+        bucket = ns->ns_hash + hash;
         list_add(&res->lr_hash, bucket);
+        ns->ns_resources++;
+        ns->ns_refcount++;
 
         if (parent == NULL) {
                 list_add(&res->lr_childof, &ns->ns_root_list);
@@ -496,8 +565,19 @@ ldlm_resource_add(struct ldlm_namespace *ns, struct ldlm_resource *parent,
                 res->lr_parent = parent;
                 list_add(&res->lr_childof, &parent->lr_children);
         }
-        l_unlock(&ns->ns_lock);
+        spin_unlock(&ns->ns_hash_lock);
+
+        if (ns->ns_lvbo && ns->ns_lvbo->lvbo_init) {
+                int rc;
 
+                OBD_FAIL_TIMEOUT(OBD_FAIL_LDLM_CREATE_RESOURCE, 2);
+                rc = ns->ns_lvbo->lvbo_init(res);
+                if (rc)
+                        CERROR("lvbo_init failed for resource "
+                              LPU64": rc %d\n", name.name[0], rc);
+                /* we create resource with locked lr_lvb_sem */
+                up(&res->lr_lvb_sem);
+        }
 
         RETURN(res);
 }
@@ -509,7 +589,7 @@ struct ldlm_resource *
 ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent,
                   struct ldlm_res_id name, ldlm_type_t type, int create)
 {
-        struct list_head *bucket, *tmp;
+        __u32 hash = ldlm_hash_fn(parent, name);
         struct ldlm_resource *res = NULL;
         ENTRY;
 
@@ -517,47 +597,24 @@ ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent,
         LASSERT(ns->ns_hash != NULL);
         LASSERT(name.name[0] != 0);
 
-        l_lock(&ns->ns_lock);
-        bucket = ns->ns_hash + ldlm_hash_fn(parent, name);
-
-        list_for_each(tmp, bucket) {
-                res = list_entry(tmp, struct ldlm_resource, lr_hash);
-
-                if (memcmp(&res->lr_name, &name, sizeof(res->lr_name)) == 0) {
-                        ldlm_resource_getref(res);
-                        l_unlock(&ns->ns_lock);
-                        RETURN(res);
+        spin_lock(&ns->ns_hash_lock);
+        res = ldlm_resource_find(ns, name, hash);
+        if (res) {
+                ldlm_resource_getref(res);
+                spin_unlock(&ns->ns_hash_lock);
+                /* synchronize WRT resource creation */
+                if (ns->ns_lvbo && ns->ns_lvbo->lvbo_init) {
+                        down(&res->lr_lvb_sem);
+                        up(&res->lr_lvb_sem);
                 }
+                RETURN(res);
         }
+        spin_unlock(&ns->ns_hash_lock);
 
-        if (create) {
-                res = ldlm_resource_add(ns, parent, name, type);
-                if (res == NULL)
-                        GOTO(out, NULL);
-        } else {
-                res = NULL;
-        }
-
-        if (create && ns->ns_lvbo && ns->ns_lvbo->lvbo_init) {
-                int rc;
-
-                /* Although this is technically a lock inversion risk (lvb_sem
-                 * should be taken before DLM lock), this resource was just
-                 * created, so nobody else can take the lvb_sem yet. -p */
-                mutex_down(&res->lr_lvb_sem);
-                /* Drop the dlm lock, because lvbo_init can touch the disk */
-                l_unlock(&ns->ns_lock);
-                OBD_FAIL_TIMEOUT(OBD_FAIL_LDLM_CREATE_RESOURCE, 2);
-                rc = ns->ns_lvbo->lvbo_init(res);
-                mutex_up(&res->lr_lvb_sem);
-                if (rc)
-                        CERROR("lvbo_init failed for resource "LPU64"/"LPU64
-                               ": rc %d\n", name.name[0], name.name[1], rc);
-        } else {
-out:
-                l_unlock(&ns->ns_lock);
-        }
+        if (create == 0)
+                RETURN(NULL);
 
+        res = ldlm_resource_add(ns, parent, name, hash, type);
         RETURN(res);
 }
 
@@ -571,9 +628,45 @@ struct ldlm_resource *ldlm_resource_getref(struct ldlm_resource *res)
         return res;
 }
 
+void __ldlm_resource_putref_final(struct ldlm_resource *res)
+{
+        struct ldlm_namespace *ns = res->lr_namespace;
+
+        LASSERT_SPIN_LOCKED(&ns->ns_hash_lock);
+
+        if (!list_empty(&res->lr_granted)) {
+                ldlm_resource_dump(D_ERROR, res);
+                LBUG();
+        }
+
+        if (!list_empty(&res->lr_converting)) {
+                ldlm_resource_dump(D_ERROR, res);
+                LBUG();
+        }
+
+        if (!list_empty(&res->lr_waiting)) {
+                ldlm_resource_dump(D_ERROR, res);
+                LBUG();
+        }
+
+        if (!list_empty(&res->lr_children)) {
+                ldlm_resource_dump(D_ERROR, res);
+                LBUG();
+        }
+
+        ns->ns_refcount--;
+        list_del_init(&res->lr_hash);
+        list_del_init(&res->lr_childof);
+
+        ns->ns_resources--;
+        if (ns->ns_resources == 0)
+                wake_up(&ns->ns_waitq);
+}
+
 /* Returns 1 if the resource was freed, 0 if it remains. */
 int ldlm_resource_putref(struct ldlm_resource *res)
 {
+        struct ldlm_namespace *ns = res->lr_namespace;
         int rc = 0;
         ENTRY;
 
@@ -582,53 +675,37 @@ int ldlm_resource_putref(struct ldlm_resource *res)
         LASSERT(atomic_read(&res->lr_refcount) > 0);
         LASSERT(atomic_read(&res->lr_refcount) < LI_POISON);
 
-        if (atomic_dec_and_test(&res->lr_refcount)) {
-                struct ldlm_namespace *ns = res->lr_namespace;
-                ENTRY;
-
-                l_lock(&ns->ns_lock);
-
-                if (atomic_read(&res->lr_refcount) != 0) {
-                        /* We lost the race. */
-                        l_unlock(&ns->ns_lock);
-                        RETURN(rc);
-                }
-
-                if (!list_empty(&res->lr_granted)) {
-                        ldlm_resource_dump(D_ERROR, res);
-                        LBUG();
-                }
+        LASSERT(atomic_read(&res->lr_refcount) >= 0);
+        if (atomic_dec_and_lock(&res->lr_refcount, &ns->ns_hash_lock)) {
+                __ldlm_resource_putref_final(res);
+                spin_unlock(&ns->ns_hash_lock);
+                if (res->lr_lvb_data)
+                        OBD_FREE(res->lr_lvb_data, res->lr_lvb_len);
+                OBD_SLAB_FREE(res, ldlm_resource_slab, sizeof *res);
+                rc = 1;
+        }
 
-                if (!list_empty(&res->lr_converting)) {
-                        ldlm_resource_dump(D_ERROR, res);
-                        LBUG();
-                }
+        RETURN(rc);
+}
 
-                if (!list_empty(&res->lr_waiting)) {
-                        ldlm_resource_dump(D_ERROR, res);
-                        LBUG();
-                }
+/* Returns 1 if the resource was freed, 0 if it remains. */
+int ldlm_resource_putref_locked(struct ldlm_resource *res)
+{
+        int rc = 0;
+        ENTRY;
 
-                if (!list_empty(&res->lr_children)) {
-                        ldlm_resource_dump(D_ERROR, res);
-                        LBUG();
-                }
+        CDEBUG(D_INFO, "putref res: %p count: %d\n", res,
+               atomic_read(&res->lr_refcount) - 1);
+        LASSERT(atomic_read(&res->lr_refcount) > 0);
+        LASSERT(atomic_read(&res->lr_refcount) < LI_POISON);
 
-                list_del_init(&res->lr_hash);
-                list_del_init(&res->lr_childof);
+        LASSERT(atomic_read(&res->lr_refcount) >= 0);
+        if (atomic_dec_and_test(&res->lr_refcount)) {
+                __ldlm_resource_putref_final(res);
                 if (res->lr_lvb_data)
                         OBD_FREE(res->lr_lvb_data, res->lr_lvb_len);
-                l_unlock(&ns->ns_lock);
-
                 OBD_SLAB_FREE(res, ldlm_resource_slab, sizeof *res);
-
-                if (atomic_dec_and_test(&ns->ns_refcount)) {
-                        CDEBUG(D_DLMTRACE, "last ref on ns %s\n", ns->ns_name);
-                        cfs_waitq_signal(&ns->ns_refcount_waitq);
-                }
-
                 rc = 1;
-                EXIT;
         }
 
         RETURN(rc);
@@ -637,7 +714,7 @@ int ldlm_resource_putref(struct ldlm_resource *res)
 void ldlm_resource_add_lock(struct ldlm_resource *res, struct list_head *head,
                             struct ldlm_lock *lock)
 {
-        l_lock(&res->lr_namespace->ns_lock);
+        check_res_locked(res);
 
         ldlm_resource_dump(D_OTHER, res);
         CDEBUG(D_OTHER, "About to add this lock:\n");
@@ -645,14 +722,12 @@ void ldlm_resource_add_lock(struct ldlm_resource *res, struct list_head *head,
 
         if (lock->l_destroyed) {
                 CDEBUG(D_OTHER, "Lock destroyed, not adding to resource\n");
-                goto out;
+                return;
         }
 
         LASSERT(list_empty(&lock->l_res_link));
 
         list_add_tail(&lock->l_res_link, head);
- out:
-        l_unlock(&res->lr_namespace->ns_lock);
 }
 
 void ldlm_resource_insert_lock_after(struct ldlm_lock *original,
@@ -660,7 +735,7 @@ void ldlm_resource_insert_lock_after(struct ldlm_lock *original,
 {
         struct ldlm_resource *res = original->l_resource;
 
-        l_lock(&res->lr_namespace->ns_lock);
+        check_res_locked(res);
 
         ldlm_resource_dump(D_OTHER, res);
         CDEBUG(D_OTHER, "About to insert this lock after %p:\n", original);
@@ -674,17 +749,14 @@ void ldlm_resource_insert_lock_after(struct ldlm_lock *original,
         LASSERT(list_empty(&new->l_res_link));
 
         list_add(&new->l_res_link, &original->l_res_link);
- out:
-        l_unlock(&res->lr_namespace->ns_lock);
+ out:;
 }
 
 void ldlm_resource_unlink_lock(struct ldlm_lock *lock)
 {
-        l_lock(&lock->l_resource->lr_namespace->ns_lock);
+        check_res_locked(lock->l_resource);
         list_del_init(&lock->l_res_link);
-        l_unlock(&lock->l_resource->lr_namespace->ns_lock);
 }
-EXPORT_SYMBOL(ldlm_resource_unlink_lock);
 
 void ldlm_res2desc(struct ldlm_resource *res, struct ldlm_resource_desc *desc)
 {
@@ -711,22 +783,31 @@ void ldlm_namespace_dump(int level, struct ldlm_namespace *ns)
 {
         struct list_head *tmp;
 
-        CDEBUG_EX(level, "--- Namespace: %s (rc: %d, client: %d)\n", ns->ns_name,
-               atomic_read(&ns->ns_refcount), ns->ns_client);
+        CDEBUG(level, "--- Namespace: %s (rc: %d, client: %d)\n",
+                  ns->ns_name, ns->ns_refcount, ns->ns_client);
 
-        l_lock(&ns->ns_lock);
-        if (cfs_time_after(cfs_time_current(), ns->ns_next_dump)) {
-                list_for_each(tmp, &ns->ns_root_list) {
-                        struct ldlm_resource *res;
-                        res = list_entry(tmp, struct ldlm_resource, lr_childof);
+        if (cfs_time_before(cfs_time_current(), ns->ns_next_dump))
+                return;
 
-                        /* Once we have resources with children, this should
-                         * really dump them recursively. */
-                        ldlm_resource_dump(level, res);
-                }
-                ns->ns_next_dump = cfs_time_shift(10);
+        spin_lock(&ns->ns_hash_lock);
+        tmp = ns->ns_root_list.next;
+        while (tmp != &ns->ns_root_list) {
+                struct ldlm_resource *res;
+                res = list_entry(tmp, struct ldlm_resource, lr_childof);
+
+                ldlm_resource_getref(res);
+                spin_unlock(&ns->ns_hash_lock);
+
+                lock_res(res);
+                ldlm_resource_dump(level, res);
+                unlock_res(res);
+                
+                spin_lock(&ns->ns_hash_lock);
+                tmp = tmp->next;
+                ldlm_resource_putref_locked(res);
         }
-        l_unlock(&ns->ns_lock);
+        ns->ns_next_dump = cfs_time_shift(10);
+        spin_unlock(&ns->ns_hash_lock);
 }
 
 void ldlm_resource_dump(int level, struct ldlm_resource *res)
@@ -737,14 +818,14 @@ void ldlm_resource_dump(int level, struct ldlm_resource *res)
         if (RES_NAME_SIZE != 4)
                 LBUG();
 
-        CDEBUG_EX(level, "--- Resource: %p ("LPU64"/"LPU64"/"LPU64"/"LPU64
+        CDEBUG(level, "--- Resource: %p ("LPU64"/"LPU64"/"LPU64"/"LPU64
                ") (rc: %d)\n", res, res->lr_name.name[0], res->lr_name.name[1],
                res->lr_name.name[2], res->lr_name.name[3],
                atomic_read(&res->lr_refcount));
 
         if (!list_empty(&res->lr_granted)) {
                 pos = 0;
-                CDEBUG_EX(level, "Granted locks:\n");
+                CDEBUG(level, "Granted locks:\n");
                 list_for_each(tmp, &res->lr_granted) {
                         struct ldlm_lock *lock;
                         lock = list_entry(tmp, struct ldlm_lock, l_res_link);
@@ -753,7 +834,7 @@ void ldlm_resource_dump(int level, struct ldlm_resource *res)
         }
         if (!list_empty(&res->lr_converting)) {
                 pos = 0;
-                CDEBUG_EX(level, "Converting locks:\n");
+                CDEBUG(level, "Converting locks:\n");
                 list_for_each(tmp, &res->lr_converting) {
                         struct ldlm_lock *lock;
                         lock = list_entry(tmp, struct ldlm_lock, l_res_link);
@@ -762,7 +843,7 @@ void ldlm_resource_dump(int level, struct ldlm_resource *res)
         }
         if (!list_empty(&res->lr_waiting)) {
                 pos = 0;
-                CDEBUG_EX(level, "Waiting locks:\n");
+                CDEBUG(level, "Waiting locks:\n");
                 list_for_each(tmp, &res->lr_waiting) {
                         struct ldlm_lock *lock;
                         lock = list_entry(tmp, struct ldlm_lock, l_res_link);
index 5d91ff8..de73497 100644 (file)
@@ -15,7 +15,9 @@ LUSTRE_LIBS = libllite.a \
               $(top_builddir)/lustre/osc/libosc.a \
               $(top_builddir)/lustre/fid/libfid.a \
               $(top_builddir)/lustre/fld/libfld.a \
+              $(top_builddir)/lustre/lmv/liblmv.a \
               $(top_builddir)/lustre/mdc/libmdc.a \
+              $(top_builddir)/lustre/mgc/libmgc.a \
               $(top_builddir)/lustre/ptlrpc/libptlrpc.a \
               $(top_builddir)/lustre/obdclass/liblustreclass.a \
               $(top_builddir)/lustre/lvfs/liblvfs.a
@@ -28,7 +30,7 @@ LND_LIBS =
 if BUILD_USOCKLND
 LND_LIBS +=    $(top_builddir)/lnet/ulnds/socklnd/libsocklnd.a
 endif
-if BUILD_PTLLND
+if BUILD_UPTLLND
 LND_LIBS +=   $(top_builddir)/lnet/ulnds/ptllnd/libptllnd.a
 endif
 
index 8368c68..ca1f72e 100644 (file)
@@ -89,7 +89,7 @@ static int llu_dir_do_readpage(struct inode *inode, struct page *page)
 
                 rc = md_enqueue(sbi->ll_md_exp, LDLM_IBITS, &it, LCK_CR,
                                 &op_data, &lockh, NULL, 0,
-                                ldlm_completion_ast, llu_mdc_blocking_ast,
+                                ldlm_completion_ast, llu_md_blocking_ast,
                                 inode, LDLM_FL_CANCEL_ON_BLOCK);
                 request = (struct ptlrpc_request *)it.d.lustre.it_data;
                 if (request)
@@ -105,9 +105,11 @@ static int llu_dir_do_readpage(struct inode *inode, struct page *page)
         rc = md_readpage(sbi->ll_md_exp, &lli->lli_fid,
                          offset, page, &request);
         if (!rc) {
-                body = lustre_msg_buf(request->rq_repmsg, 0, sizeof (*body));
-                LASSERT (body != NULL);         /* checked by mdc_readpage() */
-                LASSERT_REPSWABBED (request, 0); /* swabbed by mdc_readpage() */
+                body = lustre_msg_buf(request->rq_repmsg, REPLY_REC_OFF,
+                                      sizeof(*body));
+                LASSERT(body != NULL);         /* checked by md_readpage() */
+                /* swabbed by md_readpage() */
+                LASSERT_REPSWABBED(request, REPLY_REC_OFF);
 
                 st->st_size = body->size;
         } else {
@@ -225,7 +227,7 @@ ssize_t llu_iop_filldirentries(struct inode *ino, _SYSIO_OFF_T *basep,
                 if (IS_ERR(page))
                         continue;
 
-                /* size might have been updated by mdc_readpage */
+                /* size might have been updated by md_readpage */
                 maxpages = (st->st_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
 
                 /* fill in buffer */
index 877dafc..34dbf74 100644 (file)
@@ -79,11 +79,16 @@ void llu_prepare_md_op_data(struct md_op_data *op_data,
                             int mode)
 {
         LASSERT(op_data);
-        LASSERT(i1);
+        LASSERT(i1 != NULL || i2 != NULL);
         memset(op_data, 0, sizeof(*op_data));
 
-        ll_i2gids(op_data->suppgids, i1, i2);
-        op_data->fid1 = *ll_inode2fid(i1);
+        if (i1) {
+                ll_i2gids(op_data->suppgids, i1, i2);
+                op_data->fid1 = *ll_inode2fid(i1);
+        }else {
+                ll_i2gids(op_data->suppgids, i2, i1);
+                op_data->fid1 = *ll_inode2fid(i2);
+        }
 
         if (i2)
                 op_data->fid2 = *ll_inode2fid(i2);
@@ -109,10 +114,16 @@ void obdo_refresh_inode(struct inode *dst,
 
         if (valid & OBD_MD_FLATIME && src->o_atime > LTIME_S(st->st_atime))
                 LTIME_S(st->st_atime) = src->o_atime;
-        if (valid & OBD_MD_FLMTIME && src->o_mtime > LTIME_S(st->st_mtime))
-                LTIME_S(st->st_mtime) = src->o_mtime;
-        if (valid & OBD_MD_FLCTIME && src->o_ctime > LTIME_S(st->st_ctime))
+        
+        /* mtime is always updated with ctime, but can be set in past.
+           As write and utime(2) may happen within 1 second, and utime's
+           mtime has a priority over write's one, leave mtime from mds 
+           for the same ctimes. */
+        if (valid & OBD_MD_FLCTIME && src->o_ctime > LTIME_S(st->st_ctime)) {
                 LTIME_S(st->st_ctime) = src->o_ctime;
+                if (valid & OBD_MD_FLMTIME)
+                        LTIME_S(st->st_mtime) = src->o_mtime;
+        }
         if (valid & OBD_MD_FLSIZE && src->o_size > st->st_size)
                 st->st_size = src->o_size;
         /* optimum IO size */
@@ -123,16 +134,16 @@ void obdo_refresh_inode(struct inode *dst,
                 st->st_blocks = src->o_blocks;
 }
 
-static int llu_local_open(struct llu_inode_info *lli, struct lookup_intent *it)
+int llu_local_open(struct llu_inode_info *lli, struct lookup_intent *it)
 {
         struct ptlrpc_request *req = it->d.lustre.it_data;
         struct ll_file_data *fd;
         struct mdt_body *body;
         ENTRY;
 
-        body = lustre_msg_buf (req->rq_repmsg, 1, sizeof (*body));
-        LASSERT (body != NULL);                 /* reply already checked out */
-        LASSERT_REPSWABBED (req, 1);            /* and swabbed down */
+        body = lustre_msg_buf(req->rq_repmsg, DLM_REPLY_REC_OFF, sizeof(*body));
+        LASSERT(body != NULL);                 /* reply already checked out */
+        LASSERT_REPSWABBED(req, DLM_REPLY_REC_OFF);       /* and swabbed down */
 
         /* already opened? */
         if (lli->lli_open_count++)
@@ -142,7 +153,7 @@ static int llu_local_open(struct llu_inode_info *lli, struct lookup_intent *it)
 
         OBD_ALLOC(fd, sizeof(*fd));
         /* We can't handle this well without reorganizing ll_file_open and
-         * ll_mdc_close, so don't even try right now. */
+         * ll_md_close, so don't even try right now. */
         LASSERT(fd != NULL);
 
         memcpy(&fd->fd_mds_och.och_fh, &body->handle, sizeof(body->handle));
@@ -239,7 +250,7 @@ int llu_objects_destroy(struct ptlrpc_request *request, struct inode *dir)
         ENTRY;
 
         /* req is swabbed so this is safe */
-        body = lustre_msg_buf(request->rq_repmsg, 0, sizeof(*body));
+        body = lustre_msg_buf(request->rq_repmsg, REPLY_REC_OFF, sizeof(*body));
 
         if (!(body->valid & OBD_MD_FLEASIZE))
                 RETURN(0);
@@ -253,7 +264,8 @@ int llu_objects_destroy(struct ptlrpc_request *request, struct inode *dir)
          * to this file. Use this EA to unlink the objects on the OST.
          * It's opaque so we don't swab here; we leave it to obd_unpackmd() to
          * check it is complete and sensible. */
-        eadata = lustre_swab_repbuf(request, 1, body->eadatasize, NULL);
+        eadata = lustre_swab_repbuf(request, REPLY_REC_OFF+1, body->eadatasize,
+                                    NULL);
         LASSERT(eadata != NULL);
         if (eadata == NULL) {
                 CERROR("Can't unpack MDS EA data\n");
@@ -278,7 +290,7 @@ int llu_objects_destroy(struct ptlrpc_request *request, struct inode *dir)
         if (body->valid & OBD_MD_FLCOOKIE) {
                 oa->o_valid |= OBD_MD_FLCOOKIE;
                 oti.oti_logcookies =
-                        lustre_msg_buf(request->rq_repmsg, 2,
+                        lustre_msg_buf(request->rq_repmsg, REPLY_REC_OFF + 2,
                                        sizeof(struct llog_cookie) *
                                        lsm->lsm_stripe_count);
                 if (oti.oti_logcookies == NULL) {
@@ -298,7 +310,7 @@ int llu_objects_destroy(struct ptlrpc_request *request, struct inode *dir)
         return rc;
 }
 
-int llu_mdc_close(struct obd_export *md_exp, struct inode *inode)
+int llu_md_close(struct obd_export *md_exp, struct inode *inode)
 {
         struct llu_inode_info *lli = llu_i2info(inode);
         struct ll_file_data *fd = lli->lli_file_data;
@@ -363,7 +375,7 @@ int llu_mdc_close(struct obd_export *md_exp, struct inode *inode)
         RETURN(rc);
 }
 
-static int llu_file_release(struct inode *inode)
+int llu_file_release(struct inode *inode)
 {
         struct ll_file_data *fd;
         struct llu_sb_info *sbi = llu_i2sbi(inode);
@@ -385,7 +397,7 @@ static int llu_file_release(struct inode *inode)
         if (!fd) /* no process opened the file after an mcreate */
                 RETURN(0);
 
-        rc2 = llu_mdc_close(sbi->ll_md_exp, inode);
+        rc2 = llu_md_close(sbi->ll_md_exp, inode);
         if (rc2 && !rc)
                 rc = rc2;
 
@@ -430,37 +442,40 @@ static void llu_truncate(struct inode *inode, obd_flag flags)
 {
         struct llu_inode_info *lli = llu_i2info(inode);
         struct intnl_stat *st = llu_i2stat(inode);
-        struct lov_stripe_md *lsm = lli->lli_smd;
-        struct obdo oa = {0};
+        struct obd_info oinfo = { { { 0 } } };
+        struct obdo oa = { 0 };
         int rc;
         ENTRY;
         CDEBUG(D_VFSTRACE, "VFS Op:inode=%llu/%lu(%p) to %llu\n",
                (long long)st->st_ino, lli->lli_st_generation, inode,
                (long long)st->st_size);
 
-        if (!lsm) {
+        if (!lli->lli_smd) {
                 CDEBUG(D_INODE, "truncate on inode %llu with no objects\n",
                        (long long)st->st_ino);
                 EXIT;
                 return;
         }
 
-        oa.o_id = lsm->lsm_object_id;
+        oinfo.oi_md = lli->lli_smd;
+        oinfo.oi_policy.l_extent.start = st->st_size;
+        oinfo.oi_policy.l_extent.end = OBD_OBJECT_EOF;
+        oinfo.oi_oa = &oa;
+        oa.o_id = lli->lli_smd->lsm_object_id;
         oa.o_valid = OBD_MD_FLID | OBD_MD_FLFLAGS;
         oa.o_flags = flags; /* We don't actually want to copy inode flags */
-
         obdo_from_inode(&oa, inode,
                         OBD_MD_FLTYPE | OBD_MD_FLMODE | OBD_MD_FLATIME |
                         OBD_MD_FLMTIME | OBD_MD_FLCTIME);
 
-        obd_adjust_kms(llu_i2obdexp(inode), lsm, st->st_size, 1);
+        obd_adjust_kms(llu_i2obdexp(inode), lli->lli_smd, st->st_size, 1);
 
         CDEBUG(D_INFO, "calling punch for "LPX64" (all bytes after %Lu)\n",
                oa.o_id, (long long)st->st_size);
 
         /* truncate == punch from new size to absolute end of file */
-        rc = obd_punch(llu_i2obdexp(inode), &oa, lsm, st->st_size,
-                       OBD_OBJECT_EOF, NULL);
+        rc = obd_punch_rqset(llu_i2obdexp(inode), &oinfo, NULL);
         if (rc)
                 CERROR("obd_truncate fails (%d) ino %llu\n",
                        rc, (long long)st->st_ino);
index 9d6f695..0599f98 100755 (executable)
@@ -62,9 +62,11 @@ build_obj_list . libllite.a
 build_obj_list ../lov liblov.a
 build_obj_list ../obdecho libobdecho.a
 build_obj_list ../osc libosc.a
+build_obj_list ../lmv liblmv.a
 build_obj_list ../mdc libmdc.a
 build_obj_list ../fid libfid.a
 build_obj_list ../fld libfld.a
+build_obj_list ../mgc libmgc.a
 build_obj_list ../ptlrpc libptlrpc.a
 build_obj_list ../obdclass liblustreclass.a
 build_obj_list ../lvfs liblvfs.a
index 36b46f3..8e31ba8 100644 (file)
@@ -55,27 +55,29 @@ static int lllib_init(void)
             init_lib_portals() ||
             init_obdclass() ||
             ptlrpc_init() ||
+            mgc_init() ||
+            lmv_init() ||
             mdc_init() ||
             lov_init() ||
             osc_init())
                 return -1;
 
-        return _sysio_fssw_register("llite", &llu_fssw_ops);
+        return _sysio_fssw_register("lustre", &llu_fssw_ops);
 }
 
 int liblustre_process_log(struct config_llog_instance *cfg,
-                          char *mdsnid, char *mdsname, char *profile,
+                          char *mgsnid, char *profile,
                           int allow_recov)
 {
         struct lustre_cfg_bufs bufs;
         struct lustre_cfg *lcfg;
-        char  *peer = "MDS_PEER_UUID";
+        char  *peer = "MGS_UUID";
         struct obd_device *obd;
-        struct lustre_handle mdc_conn = {0, };
+        struct lustre_handle mgc_conn = {0, };
         struct obd_export *exp;
-        char  *name = "mdc_dev";
+        char  *name = "mgc_dev";
         class_uuid_t uuid;
-        struct obd_uuid mdc_uuid;
+        struct obd_uuid mgc_uuid;
         struct llog_ctxt *ctxt;
         lnet_nid_t nid = 0;
         int err, rc = 0;
@@ -83,11 +85,11 @@ int liblustre_process_log(struct config_llog_instance *cfg,
         ENTRY;
 
         generate_random_uuid(uuid);
-        class_uuid_unparse(uuid, &mdc_uuid);
+        class_uuid_unparse(uuid, &mgc_uuid);
 
-        nid = libcfs_str2nid(mdsnid);
+        nid = libcfs_str2nid(mgsnid);
         if (nid == LNET_NID_ANY) {
-                CERROR("Can't parse NID %s\n", mdsnid);
+                CERROR("Can't parse NID %s\n", mgsnid);
                 RETURN(-EINVAL);
         }
 
@@ -101,8 +103,8 @@ int liblustre_process_log(struct config_llog_instance *cfg,
                 GOTO(out, rc);
 
         lustre_cfg_bufs_reset(&bufs, name);
-        lustre_cfg_bufs_set_string(&bufs, 1, LUSTRE_MDC_NAME);//FIXME connect to mgc
-        lustre_cfg_bufs_set_string(&bufs, 2, mdc_uuid.uuid);
+        lustre_cfg_bufs_set_string(&bufs, 1, LUSTRE_MGC_NAME);
+        lustre_cfg_bufs_set_string(&bufs, 2, mgc_uuid.uuid);
         lcfg = lustre_cfg_new(LCFG_ATTACH, &bufs);
         rc = class_process_config(lcfg);
         lustre_cfg_free(lcfg);
@@ -110,7 +112,7 @@ int liblustre_process_log(struct config_llog_instance *cfg,
                 GOTO(out_del_uuid, rc);
 
         lustre_cfg_bufs_reset(&bufs, name);
-        lustre_cfg_bufs_set_string(&bufs, 1, mdsname);
+        lustre_cfg_bufs_set_string(&bufs, 1, LUSTRE_MGS_OBDNAME);
         lustre_cfg_bufs_set_string(&bufs, 2, peer);
         lcfg = lustre_cfg_new(LCFG_SETUP, &bufs);
         rc = class_process_config(lcfg);
@@ -134,13 +136,14 @@ int liblustre_process_log(struct config_llog_instance *cfg,
                                 strlen(KEY_INIT_RECOV), KEY_INIT_RECOV,
                                 sizeof(allow_recov), &allow_recov, NULL);
 
-        rc = obd_connect(NULL, &mdc_conn, obd, &mdc_uuid, ocd);
+        rc = obd_connect(NULL, &mgc_conn, obd, &mgc_uuid, ocd);
         if (rc) {
-                CERROR("cannot connect to %s: rc = %d\n", mdsname, rc);
+                CERROR("cannot connect to %s at %s: rc = %d\n",
+                       LUSTRE_MGS_OBDNAME, mgsnid, rc);
                 GOTO(out_cleanup, rc);
         }
 
-        exp = class_conn2export(&mdc_conn);
+        exp = class_conn2export(&mgc_conn);
 
         ctxt = exp->exp_obd->obd_llog_ctxt[LLOG_CONFIG_REPL_CTXT];
         rc = class_config_parse_llog(ctxt, profile, cfg);
@@ -163,7 +166,7 @@ out_cleanup:
         err = class_process_config(lcfg);
         lustre_cfg_free(lcfg);
         if (err)
-                CERROR("mdc_cleanup failed: rc = %d\n", err);
+                CERROR("md_cleanup failed: rc = %d\n", err);
 
 out_detach:
         lustre_cfg_bufs_reset(&bufs, name);
@@ -171,7 +174,7 @@ out_detach:
         err = class_process_config(lcfg);
         lustre_cfg_free(lcfg);
         if (err)
-                CERROR("mdc_detach failed: rc = %d\n", err);
+                CERROR("md_detach failed: rc = %d\n", err);
 
 out_del_uuid:
         lustre_cfg_bufs_reset(&bufs, name);
@@ -186,9 +189,9 @@ out:
         RETURN(rc);
 }
 
-/* parse host:/mdsname/profile string */
-int ll_parse_mount_target(const char *target, char **mdsnid,
-                          char **mdsname, char **profile)
+/* parse host:/fsname string */
+int ll_parse_mount_target(const char *target, char **mgsnid,
+                          char **fsname)
 {
         static char buf[256];
         char *s;
@@ -197,17 +200,15 @@ int ll_parse_mount_target(const char *target, char **mdsnid,
         strncpy(buf, target, 255);
 
         if ((s = strchr(buf, ':'))) {
-                *mdsnid = buf;
+                *mgsnid = buf;
                 *s = '\0';
 
                 while (*++s == '/')
                         ;
-                *mdsname = s;
-                if ((s = strchr(*mdsname, '/'))) {
-                        *s = '\0';
-                        *profile = s + 1;
-                        return 0;
-                }
+                sprintf(s + strlen(s), "-client");
+                *fsname = s;
+
+                return 0;
         }
 
         return -1;
@@ -275,7 +276,7 @@ void __liblustre_setup_(void)
 {
         char *target = NULL;
         char *root_driver = "native";
-        char *lustre_driver = "llite";
+        char *lustre_driver = "lustre";
         char *root_path = "/";
         unsigned mntflgs = 0;
         int err;
index a9436e4..1bd631b 100644 (file)
@@ -8,7 +8,6 @@
 #include <liblustre.h>
 #include <obd.h>
 #include <obd_class.h>
-#include <lustre_mds.h>
 #include <lustre_mdc.h>
 #include <lustre_lite.h>
 #include <lustre_ver.h>
@@ -166,8 +165,8 @@ static inline __u64 ll_file_maxbytes(struct inode *inode)
 
 struct mount_option_s
 {
-        char *mdc_uuid;
-        char *osc_uuid;
+        char *md_uuid;
+        char *dt_uuid;
 };
 
 #define IS_BAD_PTR(ptr)         \
@@ -175,10 +174,10 @@ struct mount_option_s
 
 /* llite_lib.c */
 void generate_random_uuid(unsigned char uuid_out[16]);
-int liblustre_process_log(struct config_llog_instance *cfg, char *mdsnid,
-                          char *mdsname, char *profile, int allow_recov);
-int ll_parse_mount_target(const char *target, char **mdsnid,
-                          char **mdsname, char **profile);
+int liblustre_process_log(struct config_llog_instance *cfg, char *mgsnid,
+                          char *profile, int allow_recov);
+int ll_parse_mount_target(const char *target, char **mgsnid,
+                          char **fsname);
 
 extern struct mount_option_s mount_option;
 
@@ -202,8 +201,10 @@ void llu_prepare_md_op_data(struct md_op_data *op_data,
                             int namelen,
                             int mode);
 int llu_create(struct inode *dir, struct pnode_base *pnode, int mode);
+int llu_local_open(struct llu_inode_info *lli, struct lookup_intent *it);
 int llu_iop_open(struct pnode *pnode, int flags, mode_t mode);
-int llu_mdc_close(struct obd_export *md_exp, struct inode *inode);
+int llu_md_close(struct obd_export *md_exp, struct inode *inode);
+int llu_file_release(struct inode *inode);
 int llu_iop_close(struct inode *inode);
 _SYSIO_OFF_T llu_iop_pos(struct inode *ino, _SYSIO_OFF_T off);
 int llu_vmtruncate(struct inode * inode, loff_t offset, obd_flag obd_flags);
@@ -230,13 +231,13 @@ int llu_iop_lookup(struct pnode *pnode,
                    const char *path);
 void unhook_stale_inode(struct pnode *pno);
 struct inode *llu_inode_from_lock(struct ldlm_lock *lock);
-int llu_mdc_blocking_ast(struct ldlm_lock *lock,
-                         struct ldlm_lock_desc *desc,
-                         void *data, int flag);
+int llu_md_blocking_ast(struct ldlm_lock *lock,
+                        struct ldlm_lock_desc *desc,
+                        void *data, int flag);
 
 /* dir.c */
 ssize_t llu_iop_filldirentries(struct inode *ino, _SYSIO_OFF_T *basep, 
-                              char *buf, size_t nbytes);
+                               char *buf, size_t nbytes);
 
 /* liblustre/llite_fid.c*/
 int llu_fid_md_init(struct llu_sb_info *sbi);
index 8a50dbe..aea7407 100644 (file)
@@ -47,7 +47,7 @@
 
 #include "llite_lib.h"
 
-static void ll_intent_drop_lock(struct lookup_intent *it)
+void ll_intent_drop_lock(struct lookup_intent *it)
 {
         struct lustre_handle *handle;
 
@@ -63,7 +63,7 @@ static void ll_intent_drop_lock(struct lookup_intent *it)
         }
 }
 
-static void ll_intent_release(struct lookup_intent *it)
+void ll_intent_release(struct lookup_intent *it)
 {
         ENTRY;
 
@@ -130,9 +130,9 @@ static inline void llu_invalidate_inode_pages(struct inode * inode)
         /* do nothing */
 }
 
-int llu_mdc_blocking_ast(struct ldlm_lock *lock,
-                         struct ldlm_lock_desc *desc,
-                         void *data, int flag)
+int llu_md_blocking_ast(struct ldlm_lock *lock,
+                        struct ldlm_lock_desc *desc,
+                        void *data, int flag)
 {
         struct lustre_handle lockh;
         int rc;
@@ -276,9 +276,9 @@ static int llu_pb_revalidate(struct pnode *pnode, int flags,
                                 pb->pb_ino, pb->pb_name.name, pb->pb_name.len,0);
 
         rc = md_intent_lock(exp, &op_data, NULL, 0, it, flags,
-                            &req, llu_mdc_blocking_ast,
+                            &req, llu_md_blocking_ast,
                             LDLM_FL_CANCEL_ON_BLOCK);
-        /* If req is NULL, then mdc_intent_lock only tried to do a lock match;
+        /* If req is NULL, then md_intent_lock only tried to do a lock match;
          * if all was well, it will return 1 if it found locks, 0 otherwise. */
         if (req == NULL && rc >= 0)
                 GOTO(out, rc);
@@ -286,7 +286,7 @@ static int llu_pb_revalidate(struct pnode *pnode, int flags,
         if (rc < 0)
                 GOTO(out, rc = 0);
 
-        rc = pnode_revalidate_finish(req, 1, it, pnode);
+        rc = pnode_revalidate_finish(req, DLM_REPLY_REC_OFF, it, pnode);
         if (rc != 0) {
                 ll_intent_release(it);
                 GOTO(out, rc = 0);
@@ -333,7 +333,7 @@ static int lookup_it_finish(struct ptlrpc_request *request, int offset,
         if (it_disposition(it, DISP_OPEN_OPEN) &&
             it_open_error(DISP_OPEN_OPEN, it)) {
                 CDEBUG(D_INODE, "detect mds open error\n");
-                /* undo which did by mdc_intent_lock */
+                /* undo which did by md_intent_lock */
                 if (it_disposition(it, DISP_OPEN_CREATE) &&
                     !it_open_error(DISP_OPEN_CREATE, it)) {
                         LASSERT(request);
@@ -347,8 +347,7 @@ static int lookup_it_finish(struct ptlrpc_request *request, int offset,
         /* NB 1 request reference will be taken away by ll_intent_lock()
          * when I return
          */
-        if (!it_disposition(it, DISP_LOOKUP_NEG) ||
-            (it->it_op & IT_CREAT)) {
+        if (!it_disposition(it, DISP_LOOKUP_NEG) || (it->it_op & IT_CREAT)) {
                 struct lustre_md md;
                 struct llu_inode_info *lli;
                 struct intnl_stat *st;
@@ -409,7 +408,7 @@ static int lookup_it_finish(struct ptlrpc_request *request, int offset,
 struct inode *llu_inode_from_lock(struct ldlm_lock *lock)
 {
         struct inode *inode;
-        l_lock(&lock->l_resource->lr_namespace->ns_lock);
+        lock_res_and_lock(lock);
 
         if (lock->l_ast_data) {
                 inode = (struct inode *)lock->l_ast_data;
@@ -417,7 +416,7 @@ struct inode *llu_inode_from_lock(struct ldlm_lock *lock)
         } else
                 inode = NULL;
 
-        l_unlock(&lock->l_resource->lr_namespace->ns_lock);
+        unlock_res_and_lock(lock);
         return inode;
 }
 
@@ -460,12 +459,12 @@ static int llu_lookup_it(struct inode *parent, struct pnode *pnode,
                 }
         }
         rc = md_intent_lock(llu_i2mdcexp(parent), &op_data, NULL, 0, it,
-                            flags, &req, llu_mdc_blocking_ast,
+                            flags, &req, llu_md_blocking_ast,
                             LDLM_FL_CANCEL_ON_BLOCK);
         if (rc < 0)
                 GOTO(out, rc);
 
-        rc = lookup_it_finish(req, 1, it, &icbd);
+        rc = lookup_it_finish(req, DLM_REPLY_REC_OFF, it, &icbd);
         if (rc != 0) {
                 ll_intent_release(it);
                 GOTO(out, rc);
index 57ac68a..7ff2778 100644 (file)
@@ -154,10 +154,10 @@ static int llu_extent_lock_callback(struct ldlm_lock *lock,
                 lsm = lli->lli_smd;
 
                 stripe = llu_lock_to_stripe_offset(inode, lock);
-                l_lock(&lock->l_resource->lr_namespace->ns_lock);
+                lock_res_and_lock(lock);
                 kms = ldlm_extent_shift_kms(lock,
                                             lsm->lsm_oinfo[stripe].loi_kms);
-                l_unlock(&lock->l_resource->lr_namespace->ns_lock);
+                unlock_res_and_lock(lock);
                 if (lsm->lsm_oinfo[stripe].loi_kms != kms)
                         LDLM_DEBUG(lock, "updating kms from "LPU64" to "LPU64,
                                    lsm->lsm_oinfo[stripe].loi_kms, kms);
@@ -179,7 +179,8 @@ static int llu_glimpse_callback(struct ldlm_lock *lock, void *reqp)
         struct inode *inode = llu_inode_from_lock(lock);
         struct llu_inode_info *lli;
         struct ost_lvb *lvb;
-        int rc, size = sizeof(*lvb), stripe = 0;
+        int size[2] = { sizeof(struct ptlrpc_body), sizeof(*lvb) };
+        int rc, stripe = 0;
         ENTRY;
 
         if (inode == NULL)
@@ -194,13 +195,13 @@ static int llu_glimpse_callback(struct ldlm_lock *lock, void *reqp)
         if (lli->lli_smd->lsm_stripe_count > 1)
                 stripe = llu_lock_to_stripe_offset(inode, lock);
 
-        rc = lustre_pack_reply(req, 1, &size, NULL);
+        rc = lustre_pack_reply(req, 2, size, NULL);
         if (rc) {
                 CERROR("lustre_pack_reply: %d\n", rc);
                 GOTO(iput, rc);
         }
 
-        lvb = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*lvb));
+        lvb = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF, sizeof(*lvb));
         lvb->lvb_size = lli->lli_smd->lsm_oinfo[stripe].loi_kms;
 
         LDLM_DEBUG(lock, "i_size: %llu -> stripe number %u -> kms "LPU64,
@@ -211,7 +212,7 @@ static int llu_glimpse_callback(struct ldlm_lock *lock, void *reqp)
         /* These errors are normal races, so we don't want to fill the console
          * with messages by calling ptlrpc_error() */
         if (rc == -ELDLM_NO_LOCK_DATA)
-                lustre_pack_reply(req, 0, NULL, NULL);
+                lustre_pack_reply(req, 1, NULL, NULL);
 
         req->rq_status = rc;
         return rc;
@@ -224,18 +225,34 @@ int llu_glimpse_size(struct inode *inode)
         struct llu_inode_info *lli = llu_i2info(inode);
         struct intnl_stat *st = llu_i2stat(inode);
         struct llu_sb_info *sbi = llu_i2sbi(inode);
-        ldlm_policy_data_t policy = { .l_extent = { 0, OBD_OBJECT_EOF } };
         struct lustre_handle lockh = { 0 };
+        struct obd_enqueue_info einfo = { 0 };
+        struct obd_info oinfo = { { { 0 } } };
         struct ost_lvb lvb;
-        int rc, flags = LDLM_FL_HAS_INTENT;
+        int rc;
         ENTRY;
 
         CDEBUG(D_DLMTRACE, "Glimpsing inode %llu\n", (long long)st->st_ino);
 
-        rc = obd_enqueue(sbi->ll_dt_exp, lli->lli_smd, LDLM_EXTENT, &policy,
-                         LCK_PR, &flags, llu_extent_lock_callback,
-                         ldlm_completion_ast, llu_glimpse_callback, inode,
-                         sizeof(struct ost_lvb), lustre_swab_ost_lvb, &lockh);
+        if (!lli->lli_smd) {
+                CDEBUG(D_DLMTRACE, "No objects for inode %llu\n", 
+                       (long long)st->st_ino);
+                RETURN(0);
+        }
+
+        einfo.ei_type = LDLM_EXTENT;
+        einfo.ei_mode = LCK_PR;
+        einfo.ei_flags = LDLM_FL_HAS_INTENT;
+        einfo.ei_cb_bl = llu_extent_lock_callback;
+        einfo.ei_cb_cp = ldlm_completion_ast;
+        einfo.ei_cb_gl = llu_glimpse_callback;
+        einfo.ei_cbdata = inode;
+
+        oinfo.oi_policy.l_extent.end = OBD_OBJECT_EOF;
+        oinfo.oi_lockh = &lockh;
+        oinfo.oi_md = lli->lli_smd;
+
+        rc = obd_enqueue_rqset(sbi->ll_dt_exp, &oinfo, &einfo);
         if (rc) {
                 CERROR("obd_enqueue returned rc %d, returning -EIO\n", rc);
                 RETURN(rc > 0 ? -EIO : rc);
@@ -252,8 +269,6 @@ int llu_glimpse_size(struct inode *inode)
         CDEBUG(D_DLMTRACE, "glimpse: size: %llu, blocks: %llu\n",
                (long long)st->st_size, (long long)st->st_blocks);
 
-        obd_cancel(sbi->ll_dt_exp, lli->lli_smd, LCK_PR, &lockh);
-
         RETURN(rc);
 }
 
@@ -264,6 +279,8 @@ int llu_extent_lock(struct ll_file_data *fd, struct inode *inode,
 {
         struct llu_sb_info *sbi = llu_i2sbi(inode);
         struct intnl_stat *st = llu_i2stat(inode);
+        struct obd_enqueue_info einfo = { 0 };
+        struct obd_info oinfo = { { { 0 } } };
         struct ost_lvb lvb;
         int rc;
         ENTRY;
@@ -280,10 +297,20 @@ int llu_extent_lock(struct ll_file_data *fd, struct inode *inode,
                (long long)st->st_ino, policy->l_extent.start,
                policy->l_extent.end);
 
-        rc = obd_enqueue(sbi->ll_dt_exp, lsm, LDLM_EXTENT, policy, mode,
-                         &ast_flags, llu_extent_lock_callback,
-                         ldlm_completion_ast, llu_glimpse_callback, inode,
-                         sizeof(struct ost_lvb), lustre_swab_ost_lvb, lockh);
+        einfo.ei_type = LDLM_EXTENT;
+        einfo.ei_mode = mode;
+        einfo.ei_flags = ast_flags;
+        einfo.ei_cb_bl = llu_extent_lock_callback;
+        einfo.ei_cb_cp = ldlm_completion_ast;
+        einfo.ei_cb_gl = llu_glimpse_callback;
+        einfo.ei_cbdata = inode;
+
+        oinfo.oi_policy = *policy;
+        oinfo.oi_lockh = lockh;
+        oinfo.oi_md = lsm;
+
+        rc = obd_enqueue(sbi->ll_dt_exp, &oinfo, &einfo);
+        *policy = oinfo.oi_policy;
         if (rc > 0)
                 rc = -EIO;
 
@@ -348,14 +375,28 @@ static void llu_ap_fill_obdo(void *data, int cmd, struct obdo *oa)
         oa->o_valid = OBD_MD_FLID;
         valid_flags = OBD_MD_FLTYPE | OBD_MD_FLATIME;
         if (cmd & OBD_BRW_WRITE)
-                valid_flags |= OBD_MD_FLMTIME | OBD_MD_FLCTIME;
+                valid_flags |= OBD_MD_FLMTIME | OBD_MD_FLCTIME |
+                        OBD_MD_FLUID | OBD_MD_FLGID |
+                        OBD_MD_FLFID | OBD_MD_FLGENER;
 
         obdo_from_inode(oa, inode, valid_flags);
         EXIT;
 }
 
+static void llu_ap_update_obdo(void *data, int cmd, struct obdo *oa,
+                               obd_valid valid)
+{
+        struct ll_async_page *llap;
+        ENTRY;
+
+        llap = LLAP_FROM_COOKIE(data);
+        obdo_from_inode(oa, llap->llap_inode, valid);
+
+        EXIT;
+}
+
 /* called for each page in a completed rpc.*/
-static void llu_ap_completion(void *data, int cmd, struct obdo *oa, int rc)
+static int llu_ap_completion(void *data, int cmd, struct obdo *oa, int rc)
 {
         struct ll_async_page *llap;
         struct page *page;
@@ -370,13 +411,14 @@ static void llu_ap_completion(void *data, int cmd, struct obdo *oa, int rc)
                         CERROR("writeback error on page %p index %ld: %d\n",
                                page, page->index, rc);
         }
-        EXIT;
+        RETURN(0);
 }
 
 static struct obd_async_page_ops llu_async_page_ops = {
         .ap_make_ready =        NULL,
         .ap_refresh_count =     NULL,
         .ap_fill_obdo =         llu_ap_fill_obdo,
+        .ap_update_obdo =       llu_ap_update_obdo,
         .ap_completion =        llu_ap_completion,
 };
 
index ef5d57c..3676070 100644 (file)
@@ -152,9 +152,17 @@ void llu_update_inode(struct inode *inode, struct mdt_body *body,
         if (body->valid & OBD_MD_FLATIME &&
             body->atime > LTIME_S(st->st_atime))
                 LTIME_S(st->st_atime) = body->atime;
+        
+        /* mtime is always updated with ctime, but can be set in past.
+           As write and utime(2) may happen within 1 second, and utime's
+           mtime has a priority over write's one, so take mtime from mds 
+           for the same ctimes. */
         if (body->valid & OBD_MD_FLCTIME &&
-            body->ctime > LTIME_S(st->st_ctime))
+            body->ctime >= LTIME_S(st->st_ctime)) {
                 LTIME_S(st->st_ctime) = body->ctime;
+                if (body->valid & OBD_MD_FLMTIME)
+                        LTIME_S(st->st_mtime) = body->mtime;
+        }
         if (body->valid & OBD_MD_FLMODE)
                 st->st_mode = (st->st_mode & S_IFMT)|(body->mode & ~S_IFMT);
         if (body->valid & OBD_MD_FLTYPE)
@@ -294,7 +302,8 @@ int llu_inode_getattr(struct inode *inode, struct lov_stripe_md *lsm)
         struct llu_inode_info *lli = llu_i2info(inode);
         struct obd_export *exp = llu_i2obdexp(inode);
         struct ptlrpc_request_set *set;
-        struct obdo oa;
+        struct obd_info oinfo = { { { 0 } } };
+        struct obdo oa = { 0 };
         obd_flag refresh_valid;
         int rc;
         ENTRY;
@@ -302,7 +311,8 @@ int llu_inode_getattr(struct inode *inode, struct lov_stripe_md *lsm)
         LASSERT(lsm);
         LASSERT(lli);
 
-        memset(&oa, 0, sizeof oa);
+        oinfo.oi_md = lsm;
+        oinfo.oi_oa = &oa;
         oa.o_id = lsm->lsm_object_id;
         oa.o_mode = S_IFREG;
         oa.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLSIZE |
@@ -314,7 +324,7 @@ int llu_inode_getattr(struct inode *inode, struct lov_stripe_md *lsm)
                 CERROR ("ENOMEM allocing request set\n");
                 rc = -ENOMEM;
         } else {
-                rc = obd_getattr_async(exp, &oa, lsm, set);
+                rc = obd_getattr_async(exp, &oinfo, set);
                 if (rc == 0)
                         rc = ptlrpc_set_wait(set);
                 ptlrpc_set_destroy(set);
@@ -443,7 +453,7 @@ static int llu_inode_revalidate(struct inode *inode)
                                (long long)llu_i2stat(inode)->st_ino);
                         RETURN(-abs(rc));
                 }
-                rc = md_get_lustre_md(sbi->ll_md_exp, req, 0,
+                rc = md_get_lustre_md(sbi->ll_md_exp, req, REPLY_REC_OFF,
                                       sbi->ll_dt_exp, &md);
 
                 /* XXX Too paranoid? */
@@ -654,6 +664,16 @@ int llu_setattr_raw(struct inode *inode, struct iattr *attr)
                 attr->ia_mtime = CURRENT_TIME;
                 attr->ia_valid |= ATTR_MTIME_SET;
         }
+        if ((attr->ia_valid & ATTR_CTIME) && !(attr->ia_valid & ATTR_MTIME)) {
+                /* To avoid stale mtime on mds, obtain it from ost and send 
+                   to mds. */
+                rc = llu_glimpse_size(inode);
+                if (rc) 
+                        RETURN(rc);
+                
+                attr->ia_valid |= ATTR_MTIME_SET | ATTR_MTIME;
+                attr->ia_mtime = inode->i_stbuf.st_mtime;
+        }
 
         if (attr->ia_valid & (ATTR_MTIME | ATTR_CTIME))
                 CDEBUG(D_INODE, "setting mtime %lu, ctime %lu, now = %lu\n",
@@ -676,11 +696,11 @@ int llu_setattr_raw(struct inode *inode, struct iattr *attr)
                 if (rc) {
                         ptlrpc_req_finished(request);
                         if (rc != -EPERM && rc != -EACCES)
-                                CERROR("mdc_setattr fails: rc = %d\n", rc);
+                                CERROR("md_setattr fails: rc = %d\n", rc);
                         RETURN(rc);
                 }
 
-                rc = md_get_lustre_md(sbi->ll_md_exp, request, 0,
+                rc = md_get_lustre_md(sbi->ll_md_exp, request, REPLY_REC_OFF,
                                       sbi->ll_dt_exp, &md);
                 if (rc) {
                         ptlrpc_req_finished(request);
@@ -773,17 +793,23 @@ int llu_setattr_raw(struct inode *inode, struct iattr *attr)
                                 rc = err;
                 }
         } else if (ia_valid & (ATTR_MTIME | ATTR_MTIME_SET)) {
+                struct obd_info oinfo = { { { 0 } } };
                 struct obdo oa;
 
                 CDEBUG(D_INODE, "set mtime on OST inode %llu to %lu\n",
                        (long long)st->st_ino, LTIME_S(attr->ia_mtime));
                 oa.o_id = lsm->lsm_object_id;
                 oa.o_valid = OBD_MD_FLID;
+
                 obdo_from_inode(&oa, inode, OBD_MD_FLTYPE | OBD_MD_FLATIME |
                                             OBD_MD_FLMTIME | OBD_MD_FLCTIME);
-                rc = obd_setattr(sbi->ll_dt_exp, &oa, lsm, NULL);
+
+                oinfo.oi_oa = &oa;
+                oinfo.oi_md = lsm;
+
+                rc = obd_setattr_rqset(sbi->ll_dt_exp, &oinfo, NULL);
                 if (rc)
-                        CERROR("obd_setattr fails: rc=%d\n", rc);
+                        CERROR("obd_setattr_async fails: rc=%d\n", rc);
         }
         RETURN(rc);
 }
@@ -906,9 +932,10 @@ static int llu_readlink_internal(struct inode *inode,
                 RETURN(rc);
         }
 
-        body = lustre_msg_buf ((*request)->rq_repmsg, 0, sizeof (*body));
-        LASSERT (body != NULL);
-        LASSERT_REPSWABBED (*request, 0);
+        body = lustre_msg_buf((*request)->rq_repmsg, REPLY_REC_OFF,
+                              sizeof(*body));
+        LASSERT(body != NULL);
+        LASSERT_REPSWABBED(*request, REPLY_REC_OFF);
 
         if ((body->valid & OBD_MD_LINKNAME) == 0) {
                 CERROR ("OBD_MD_LINKNAME not set on reply\n");
@@ -922,7 +949,8 @@ static int llu_readlink_internal(struct inode *inode,
                 GOTO(failed, rc = -EPROTO);
         }
 
-        *symname = lustre_msg_buf ((*request)->rq_repmsg, 1, symlen);
+        *symname = lustre_msg_buf((*request)->rq_repmsg, REPLY_REC_OFF + 1,
+                                   symlen);
         if (*symname == NULL ||
             strnlen(*symname, symlen) != symlen - 1) {
                 /* not full/NULL terminated */
@@ -1108,8 +1136,7 @@ static int llu_iop_rename_raw(struct pnode *old, struct pnode *new)
 
 #ifdef _HAVE_STATVFS
 static int llu_statfs_internal(struct llu_sb_info *sbi,
-                               struct obd_statfs *osfs,
-                               unsigned long max_age)
+                               struct obd_statfs *osfs, __u64 max_age)
 {
         struct obd_statfs obd_osfs;
         int rc;
@@ -1117,14 +1144,15 @@ static int llu_statfs_internal(struct llu_sb_info *sbi,
 
         rc = obd_statfs(class_exp2obd(sbi->ll_md_exp), osfs, max_age);
         if (rc) {
-                CERROR("mdc_statfs fails: rc = %d\n", rc);
+                CERROR("md_statfs fails: rc = %d\n", rc);
                 RETURN(rc);
         }
 
         CDEBUG(D_SUPER, "MDC blocks "LPU64"/"LPU64" objects "LPU64"/"LPU64"\n",
                osfs->os_bavail, osfs->os_blocks, osfs->os_ffree,osfs->os_files);
 
-        rc = obd_statfs(class_exp2obd(sbi->ll_dt_exp), &obd_osfs, max_age);
+        rc = obd_statfs_rqset(class_exp2obd(sbi->ll_dt_exp),
+                              &obd_statfs, max_age);
         if (rc) {
                 CERROR("obd_statfs fails: rc = %d\n", rc);
                 RETURN(rc);
@@ -1161,7 +1189,7 @@ static int llu_statfs(struct llu_sb_info *sbi, struct statfs *sfs)
         /* For now we will always get up-to-date statfs values, but in the
          * future we may allow some amount of caching on the client (e.g.
          * from QOS or lprocfs updates). */
-        rc = llu_statfs_internal(sbi, &osfs, jiffies - 1);
+        rc = llu_statfs_internal(sbi, &osfs, cfs_time_current_64() - HZ);
         if (rc)
                 return rc;
 
@@ -1296,7 +1324,6 @@ static int llu_file_flock(struct inode *ino,
                           int cmd,
                           struct file_lock *file_lock)
 {
-        struct obd_device *obddev;
         struct llu_inode_info *lli = llu_i2info(ino);
         struct intnl_stat *st = llu_i2stat(ino);
         struct ldlm_res_id res_id =
@@ -1367,11 +1394,10 @@ static int llu_file_flock(struct inode *ino,
                "start="LPU64", end="LPU64"\n", st->st_ino, flock.l_flock.pid,
                flags, mode, flock.l_flock.start, flock.l_flock.end);
 
-        obddev = llu_i2mdcexp(ino)->exp_obd;
-        rc = ldlm_cli_enqueue(llu_i2mdcexp(ino), NULL, obddev->obd_namespace,
-                              res_id, LDLM_FLOCK, &flock, mode, &flags,
-                              NULL, ldlm_flock_completion_ast, NULL, file_lock,
-                              NULL, 0, NULL, &lockh);
+        rc = ldlm_cli_enqueue(llu_i2mdcexp(ino), NULL, res_id, 
+                              LDLM_FLOCK, &flock, mode, &flags, NULL, 
+                              ldlm_flock_completion_ast, NULL, 
+                              file_lock, NULL, 0, NULL, &lockh, 0);
         RETURN(rc);
 }
 
@@ -1610,6 +1636,166 @@ static int llu_put_grouplock(struct inode *inode, unsigned long arg)
         RETURN(0);
 }
 
+static int llu_lov_dir_setstripe(struct inode *ino, unsigned long arg)
+{
+        struct llu_sb_info *sbi = llu_i2sbi(ino); 
+        struct ptlrpc_request *request = NULL;
+        struct md_op_data op_data;
+        struct iattr attr = { 0 };
+        struct lov_user_md lum, *lump = (struct lov_user_md *)arg;
+        int rc = 0;
+
+        llu_prepare_md_op_data(&op_data, ino, NULL, NULL, 0, 0);
+
+        LASSERT(sizeof(lum) == sizeof(*lump));
+        LASSERT(sizeof(lum.lmm_objects[0]) ==
+                sizeof(lump->lmm_objects[0]));
+        rc = copy_from_user(&lum, lump, sizeof(lum));
+        if (rc)
+                return(-EFAULT);
+
+        if (lum.lmm_magic != LOV_USER_MAGIC)
+                RETURN(-EINVAL);
+
+        if (lum.lmm_magic != cpu_to_le32(LOV_USER_MAGIC))
+                lustre_swab_lov_user_md(&lum);
+
+        /* swabbing is done in lov_setstripe() on server side */
+        rc = md_setattr(sbi->ll_md_exp, &op_data,
+                        &attr, &lum, sizeof(lum), NULL, 0, &request);
+        if (rc) {
+                ptlrpc_req_finished(request);
+                if (rc != -EPERM && rc != -EACCES)
+                        CERROR("md_setattr fails: rc = %d\n", rc);
+                return rc;
+        }
+        ptlrpc_req_finished(request);
+
+        return rc;
+}
+
+static int llu_lov_setstripe_ea_info(struct inode *ino, int flags,
+                                     struct lov_user_md *lum, int lum_size)
+{
+        struct llu_sb_info *sbi = llu_i2sbi(ino); 
+        struct llu_inode_info *lli = llu_i2info(ino);
+        struct llu_inode_info *lli2 = NULL;
+        struct lov_stripe_md *lsm;
+        struct lookup_intent oit = {.it_op = IT_OPEN, .it_flags = flags};
+        struct ptlrpc_request *req = NULL;
+        struct lustre_md md;
+        struct md_op_data data;
+        struct lustre_handle lockh;
+        int rc = 0;
+        ENTRY;
+
+        lsm = lli->lli_smd;
+        if (lsm) {
+                CDEBUG(D_IOCTL, "stripe already exists for ino "DFID"\n",
+                       PFID(&lli->lli_fid));
+                return -EEXIST;
+        }
+
+        OBD_ALLOC(lli2, sizeof(struct llu_inode_info));
+        if (!lli2)
+                return -ENOMEM;
+        
+        memcpy(lli2, lli, sizeof(struct llu_inode_info));
+        lli2->lli_open_count = 0;
+        lli2->lli_it = NULL;
+        lli2->lli_file_data = NULL;
+        lli2->lli_smd = NULL;
+        lli2->lli_symlink_name = NULL;
+        ino->i_private = lli2;
+
+        llu_prepare_md_op_data(&data, NULL, ino, NULL, 0, O_RDWR);
+
+        rc = md_enqueue(sbi->ll_md_exp, LDLM_IBITS, &oit, LCK_CR, &data,
+                        &lockh, lum, lum_size, ldlm_completion_ast,
+                        llu_md_blocking_ast, NULL, LDLM_FL_INTENT_ONLY);
+        if (rc)
+                GOTO(out, rc);
+        
+        req = oit.d.lustre.it_data;
+        rc = it_open_error(DISP_IT_EXECD, &oit);
+        if (rc) {
+                req->rq_replay = 0;
+                GOTO(out, rc);
+        }
+        
+        rc = it_open_error(DISP_OPEN_OPEN, &oit);
+        if (rc) {
+                req->rq_replay = 0;
+                GOTO(out, rc);
+        }
+        
+        rc = md_get_lustre_md(sbi->ll_md_exp, req,
+                              1, sbi->ll_dt_exp, &md);
+        if (rc)
+                GOTO(out, rc);
+        
+        llu_update_inode(ino, md.body, md.lsm);
+        lli->lli_smd = lli2->lli_smd;
+        lli2->lli_smd = NULL;
+
+        llu_local_open(lli2, &oit);
+       
+        /* release intent */
+        if (lustre_handle_is_used(&lockh))
+                ldlm_lock_decref(&lockh, LCK_CR);
+
+        ptlrpc_req_finished(req);
+        req = NULL;
+        
+        rc = llu_file_release(ino);
+ out:
+        ino->i_private = lli;
+        if (lli2)
+                OBD_FREE(lli2, sizeof(struct llu_inode_info));
+        if (req != NULL)
+                ptlrpc_req_finished(req);
+        RETURN(rc);
+}
+
+static int llu_lov_file_setstripe(struct inode *ino, unsigned long arg)
+{
+        struct lov_user_md lum, *lump = (struct lov_user_md *)arg;
+        int rc;
+        int flags = FMODE_WRITE;
+        ENTRY;
+
+        LASSERT(sizeof(lum) == sizeof(*lump));
+        LASSERT(sizeof(lum.lmm_objects[0]) == sizeof(lump->lmm_objects[0]));
+        rc = copy_from_user(&lum, lump, sizeof(lum));
+        if (rc)
+                RETURN(-EFAULT);
+
+        rc = llu_lov_setstripe_ea_info(ino, flags, &lum, sizeof(lum));
+        RETURN(rc);
+}
+
+static int llu_lov_setstripe(struct inode *ino, unsigned long arg)
+{
+        struct intnl_stat *st = llu_i2stat(ino);
+        if (S_ISREG(st->st_mode))
+                return llu_lov_file_setstripe(ino, arg);
+        if (S_ISDIR(st->st_mode))
+                return llu_lov_dir_setstripe(ino, arg);
+        
+        return -EINVAL; 
+}
+
+static int llu_lov_getstripe(struct inode *ino, unsigned long arg)
+{
+        struct lov_stripe_md *lsm = llu_i2info(ino)->lli_smd;
+
+        if (!lsm)
+                RETURN(-ENODATA);
+
+        return obd_iocontrol(LL_IOC_LOV_GETSTRIPE, llu_i2obdexp(ino), 0, lsm,
+                            (void *)arg);
+}
+
 static int llu_iop_ioctl(struct inode *ino, unsigned long int request,
                          va_list ap)
 {
@@ -1627,6 +1813,14 @@ static int llu_iop_ioctl(struct inode *ino, unsigned long int request,
                 arg = va_arg(ap, unsigned long);
                 rc = llu_put_grouplock(ino, arg);
                 break;
+        case LL_IOC_LOV_SETSTRIPE:
+                arg = va_arg(ap, unsigned long);
+                rc = llu_lov_setstripe(ino, arg);
+                break;
+        case LL_IOC_LOV_GETSTRIPE:
+                arg = va_arg(ap, unsigned long);
+                rc = llu_lov_getstripe(ino, arg);
+                break;
         default:
                 CERROR("did not support ioctl cmd %lx\n", request);
                 rc = -ENOSYS;
@@ -1740,14 +1934,14 @@ llu_fsswop_mount(const char *source,
         struct obd_statfs osfs;
         static struct qstr noname = { NULL, 0, 0 };
         struct ptlrpc_request *request = NULL;
-        struct lustre_handle mdc_conn = {0, };
-        struct lustre_handle osc_conn = {0, };
+        struct lustre_handle md_conn = {0, };
+        struct lustre_handle dt_conn = {0, };
         struct lustre_md md;
         class_uuid_t uuid;
         struct config_llog_instance cfg;
         char ll_instance[sizeof(sbi) * 2 + 1];
         struct lustre_profile *lprof;
-        char *zconf_mdsnid, *zconf_mdsname, *zconf_profile;
+        char *zconf_mgsnid, *zconf_profile;
         char *osc = NULL, *mdc = NULL;
         int async = 1, err = -EINVAL;
         struct obd_connect_data ocd = {0,};
@@ -1755,13 +1949,12 @@ llu_fsswop_mount(const char *source,
         ENTRY;
 
         if (ll_parse_mount_target(source,
-                                  &zconf_mdsnid,
-                                  &zconf_mdsname,
+                                  &zconf_mgsnid,
                                   &zconf_profile)) {
                 CERROR("mal-formed target %s\n", source);
                 RETURN(err);
         }
-        if (!zconf_mdsnid || !zconf_mdsname || !zconf_profile) {
+        if (!zconf_mgsnid || !zconf_profile) {
                 printf("Liblustre: invalid target %s\n", source);
                 RETURN(err);
         }
@@ -1781,8 +1974,8 @@ llu_fsswop_mount(const char *source,
         /* retrive & parse config log */
         cfg.cfg_instance = ll_instance;
         cfg.cfg_uuid = sbi->ll_sb_uuid;
-        err = liblustre_process_log(&cfg, zconf_mdsnid, zconf_mdsname,
-                                    zconf_profile, 1);
+        cfg.cfg_last_idx = 0;
+        err = liblustre_process_log(&cfg, zconf_mgsnid, zconf_profile, 1);
         if (err < 0) {
                 CERROR("Unable to process log: %s\n", zconf_profile);
                 GOTO(out_free, err);
@@ -1793,11 +1986,11 @@ llu_fsswop_mount(const char *source,
                 CERROR("No profile found: %s\n", zconf_profile);
                 GOTO(out_free, err = -EINVAL);
         }
-        OBD_ALLOC(osc, strlen(lprof->lp_osc) + strlen(ll_instance) + 2);
-        sprintf(osc, "%s-%s", lprof->lp_osc, ll_instance);
+        OBD_ALLOC(osc, strlen(lprof->lp_dt) + strlen(ll_instance) + 2);
+        sprintf(osc, "%s-%s", lprof->lp_dt, ll_instance);
 
-        OBD_ALLOC(mdc, strlen(lprof->lp_mdc) + strlen(ll_instance) + 2);
-        sprintf(mdc, "%s-%s", lprof->lp_mdc, ll_instance);
+        OBD_ALLOC(mdc, strlen(lprof->lp_md) + strlen(ll_instance) + 2);
+        sprintf(mdc, "%s-%s", lprof->lp_md, ll_instance);
 
         if (!osc) {
                 CERROR("no osc\n");
@@ -1822,17 +2015,17 @@ llu_fsswop_mount(const char *source,
         obd_set_info_async(obd->obd_self_export, strlen("async"), "async",
                            sizeof(async), &async, NULL);
 
-        ocd.ocd_connect_flags = OBD_CONNECT_IBITS|OBD_CONNECT_VERSION;
+        ocd.ocd_connect_flags = OBD_CONNECT_IBITS | OBD_CONNECT_VERSION;
         ocd.ocd_ibits_known = MDS_INODELOCK_FULL;
         ocd.ocd_version = LUSTRE_VERSION_CODE;
 
         /* setup mdc */
-        err = obd_connect(NULL, &mdc_conn, obd, &sbi->ll_sb_uuid, &ocd);
+        err = obd_connect(NULL, &md_conn, obd, &sbi->ll_sb_uuid, &ocd);
         if (err) {
                 CERROR("cannot connect to %s: rc = %d\n", mdc, err);
                 GOTO(out_free, err);
         }
-        sbi->ll_md_exp = class_conn2export(&mdc_conn);
+        sbi->ll_md_exp = class_conn2export(&md_conn);
 
         err = obd_statfs(obd, &osfs, 100000000);
         if (err)
@@ -1858,15 +2051,15 @@ llu_fsswop_mount(const char *source,
         obd->obd_upcall.onu_owner = &sbi->ll_lco;
         obd->obd_upcall.onu_upcall = ll_ocd_update;
 
-        ocd.ocd_connect_flags = OBD_CONNECT_SRVLOCK|OBD_CONNECT_REQPORTAL|
-                                OBD_CONNECT_VERSION|OBD_CONNECT_TRUNCLOCK;
+        ocd.ocd_connect_flags = OBD_CONNECT_SRVLOCK | OBD_CONNECT_REQPORTAL |
+                                OBD_CONNECT_VERSION | OBD_CONNECT_TRUNCLOCK;
         ocd.ocd_version = LUSTRE_VERSION_CODE;
-        err = obd_connect(NULL, &osc_conn, obd, &sbi->ll_sb_uuid, &ocd);
+        err = obd_connect(NULL, &dt_conn, obd, &sbi->ll_sb_uuid, &ocd);
         if (err) {
                 CERROR("cannot connect to %s: rc = %d\n", osc, err);
                 GOTO(out_mdc, err);
         }
-        sbi->ll_dt_exp = class_conn2export(&osc_conn);
+        sbi->ll_dt_exp = class_conn2export(&dt_conn);
         sbi->ll_lco.lco_flags = ocd.ocd_connect_flags;
 
         err = llu_fid_dt_init(sbi);
@@ -1887,11 +2080,11 @@ llu_fsswop_mount(const char *source,
         err = md_getattr(sbi->ll_md_exp, &rootfid,
                          OBD_MD_FLGETATTR | OBD_MD_FLBLOCKS, 0, &request);
         if (err) {
-                CERROR("mdc_getattr failed for root: rc = %d\n", err);
+                CERROR("md_getattr failed for root: rc = %d\n", err);
                 GOTO(out_osc, err);
         }
 
-        err = md_get_lustre_md(sbi->ll_md_exp, request, 0,
+        err = md_get_lustre_md(sbi->ll_md_exp, request, REPLY_REC_OFF,
                                sbi->ll_dt_exp, &md);
         if (err) {
                 CERROR("failed to understand root inode md: rc = %d\n",err);
index 650cd96..9ed59aa 100644 (file)
@@ -4,7 +4,7 @@ AM_CPPFLAGS = -I$(SYSIO)/include -I/opt/lam/include $(LLCPPFLAGS) -I$(top_srcdir
 AM_CFLAGS = $(LLCFLAGS)
 AM_LIBS = $(LIBEFENCE) $(LIBREADLINE)
 
-LLIB_EXEC= $(top_builddir)/lustre/liblustre/liblustre.a $(CAP_LIBS) $(PTHREAD_LIBS)
+LLIB_EXEC = $(top_builddir)/lustre/utils/liblustreapi.a $(top_builddir)/lustre/liblustre/liblustre.a $(CAP_LIBS) $(PTHREAD_LIBS)
 
 if LIBLUSTRE
 noinst_LIBRARIES = libtestcommon.a
index c47f052..91028f0 100644 (file)
@@ -277,6 +277,7 @@ int main(int argc, char **argv)
        if (liblustre_init_current(argv[0]) ||
            init_obdclass() || init_lib_portals() ||
            ptlrpc_init() ||
+           lmv_init() ||
            mdc_init() ||
            lov_init() ||
            osc_init() ||
index ccab0c3..9cc6806 100644 (file)
@@ -40,6 +40,8 @@
 #include <sys/time.h>
 
 #include "test_common.h"
+#include <ioctl.h>
+#include <lustre/lustre_user.h>
 
 #ifndef PAGE_SIZE
 #define PAGE_SIZE getpagesize()
@@ -224,10 +226,18 @@ int t8(char *name)
         ENTRY("chmod");
         snprintf(path, MAX_PATH_LENGTH, "%s/test_t8", lustre_path);
 
+        /* Check file. */
         t_touch(path);
         t_chmod_raw(path, 0700);
         t_check_stat(path, NULL);
         t_unlink(path);
+
+        /* Check dir. */
+        t_mkdir(path);
+        t_chmod_raw(path, 0700);
+        t_check_stat(path, NULL);
+        t_rmdir(path);
+
         LEAVE();
 }
 
@@ -766,8 +776,6 @@ int t23(char *name)
 {
         char path[MAX_PATH_LENGTH];
         int fd;
-        char *str = "1234567890";
-        char buf[100];
         long long ret;
         loff_t off;
 
@@ -974,7 +982,7 @@ int t50b(char *name)
 {
         loff_t off_array[] = {1, 17, 255, 258, 4095, 4097, 8191,
                               1024*1024*1024*1024ULL};
-        int np = 1, i;
+        int i;
         loff_t offset;
 
         ENTRY("4k un-aligned i/o sanity");
@@ -1001,7 +1009,6 @@ int t51(char *name)
 {
         char file[MAX_PATH_LENGTH] = "";
         int fd;
-        struct stat statbuf;
         off_t size;
         int result;
 
@@ -1159,6 +1166,170 @@ int t54(char *name)
         LEAVE();
 }
 
+/* for O_DIRECTORY */
+#define _GNU_SOURCE
+
+#define STRIPE_SIZE       (2048 * 2048)
+#define STRIPE_OFFSET           0
+#define STRIPE_COUNT            1
+int t55(char *name)
+{
+        char path[MAX_PATH_LENGTH] = "";
+        char file[MAX_PATH_LENGTH] = "";
+        struct lov_user_md *lum = NULL;
+        struct lov_user_ost_data *lo = NULL;
+        int index, fd, buflen, rc;
+
+        ENTRY("setstripe/getstripe");
+        snprintf(path, MAX_PATH_LENGTH, "%s/test_t55", lustre_path);
+        snprintf(file, MAX_PATH_LENGTH, "%s/test_t55/file_t55", lustre_path);
+      
+        buflen = sizeof(struct lov_user_md);
+        buflen += STRIPE_COUNT * sizeof(struct lov_user_ost_data);
+        lum = (struct lov_user_md *)malloc(buflen);
+        if (!lum) {
+                printf("out of memory!\n");
+                return -1;
+        }
+        memset(lum, 0, buflen);
+
+        t_mkdir(path);
+        rc = llapi_file_create(path, STRIPE_SIZE, STRIPE_OFFSET,
+                               STRIPE_COUNT, LOV_PATTERN_RAID0);
+        if (rc) {
+                printf("llapi_file_create failed: rc = %d (%s) \n",
+                       rc, strerror(-rc));
+                t_rmdir(path);
+                free(lum);
+                return -1;
+        }
+
+        fd = open(file, O_CREAT | O_RDWR, 0644);
+        if (fd < 0) {
+                printf("open file(%s) failed: rc = %d (%s) \n)",
+                       file, fd, strerror(errno));
+                t_rmdir(path);
+                free(lum);
+                return -1;
+        }
+        
+        lum->lmm_magic = LOV_USER_MAGIC;
+        lum->lmm_stripe_count = STRIPE_COUNT;
+        rc = ioctl(fd, LL_IOC_LOV_GETSTRIPE, lum);
+        if (rc) {
+                printf("dir:ioctl(LL_IOC_LOV_GETSTRIPE) failed: rc = %d(%s)\n",
+                       rc, strerror(errno));
+                close(fd);
+                t_unlink(file);
+                t_rmdir(path);
+                free(lum);
+                return -1;
+        }
+
+        close(fd);
+
+        if (opt_verbose) {
+                printf("lmm_magic:          0x%08X\n",  lum->lmm_magic);
+                printf("lmm_object_id:      "LPX64"\n", lum->lmm_object_id);
+                printf("lmm_object_gr:      "LPX64"\n", lum->lmm_object_gr);
+                printf("lmm_stripe_count:   %u\n", (int)lum->lmm_stripe_count);
+                printf("lmm_stripe_size:    %u\n",      lum->lmm_stripe_size);
+                printf("lmm_stripe_pattern: %x\n",      lum->lmm_pattern);
+        
+                for (index = 0; index < lum->lmm_stripe_count; index++) {
+                        lo = lum->lmm_objects + index;
+                        printf("object %d:\n", index);
+                        printf("\tobject_gr:    "LPX64"\n", lo->l_object_gr);
+                        printf("\tobject_id:    "LPX64"\n", lo->l_object_id);
+                        printf("\tost_gen:      "LPX64"\n", lo->l_ost_gen);
+                        printf("\tost_idx:      %u\n", lo->l_ost_idx);
+                }
+        }
+
+        if (lum->lmm_magic != LOV_USER_MAGIC ||
+            lum->lmm_pattern != LOV_PATTERN_RAID0 ||
+            lum->lmm_stripe_size != STRIPE_SIZE ||
+            lum->lmm_objects[0].l_ost_idx != STRIPE_OFFSET ||
+            lum->lmm_stripe_count != STRIPE_COUNT) {
+                printf("incorrect striping information!\n");
+                t_unlink(file);
+                t_rmdir(path);
+                free(lum);
+                return -1;
+        }
+        t_unlink(file);
+
+        /* setstripe on regular file */
+        rc = llapi_file_create(file, STRIPE_SIZE, STRIPE_OFFSET,
+                               STRIPE_COUNT, LOV_PATTERN_RAID0);
+        if (rc) {
+                printf("llapi_file_create failed: rc = %d (%s) \n",
+                       rc, strerror(-rc));
+                t_unlink(file);
+                t_rmdir(path);
+                free(lum);
+                return -1;
+        }
+        fd = open(file, O_RDWR, 0644);
+        if (fd < 0) {
+                printf("failed to open(%s): rc = %d (%s)\n", 
+                       file, fd, strerror(errno));
+                t_unlink(file);
+                t_rmdir(path);
+                free(lum);
+                return -1;
+        }
+
+        lum->lmm_magic = LOV_USER_MAGIC;
+        lum->lmm_stripe_count = STRIPE_COUNT;
+        rc = ioctl(fd, LL_IOC_LOV_GETSTRIPE, lum);
+        if (rc) {
+                printf("file:ioctl(LL_IOC_LOV_GETSTRIPE) failed: rc = %d(%s)\n",
+                       rc, strerror(errno));
+                close(fd);
+                t_unlink(file);
+                t_rmdir(path);
+                free(lum);
+                return -1;
+        }
+        close(fd);
+
+        if (opt_verbose) {
+                printf("lmm_magic:          0x%08X\n",  lum->lmm_magic);
+                printf("lmm_object_id:      "LPX64"\n", lum->lmm_object_id);
+                printf("lmm_object_gr:      "LPX64"\n", lum->lmm_object_gr);
+                printf("lmm_stripe_count:   %u\n", (int)lum->lmm_stripe_count);
+                printf("lmm_stripe_size:    %u\n",      lum->lmm_stripe_size);
+                printf("lmm_stripe_pattern: %x\n",      lum->lmm_pattern);
+        
+                for (index = 0; index < lum->lmm_stripe_count; index++) {
+                        lo = lum->lmm_objects + index;
+                        printf("object %d:\n", index);
+                        printf("\tobject_gr:    "LPX64"\n", lo->l_object_gr);
+                        printf("\tobject_id:    "LPX64"\n", lo->l_object_id);
+                        printf("\tost_gen:      "LPX64"\n", lo->l_ost_gen);
+                        printf("\tost_idx:      %u\n", lo->l_ost_idx);
+                }
+        }
+
+        if (lum->lmm_magic != LOV_USER_MAGIC ||
+            lum->lmm_pattern != LOV_PATTERN_RAID0 ||
+            lum->lmm_stripe_size != STRIPE_SIZE ||
+            lum->lmm_objects[0].l_ost_idx != STRIPE_OFFSET ||
+            lum->lmm_stripe_count != STRIPE_COUNT) {
+                printf("incorrect striping information!\n");
+                t_unlink(file);
+                t_rmdir(path);
+                free(lum);
+                return -1;
+        }
+
+        t_unlink(file);
+        t_rmdir(path);
+        free(lum);
+        LEAVE();
+}
+
 extern void __liblustre_setup_(void);
 extern void __liblustre_cleanup_(void);
 
@@ -1166,7 +1337,7 @@ extern void __liblustre_cleanup_(void);
 void usage(char *cmd)
 {
         printf("\n"
-               "usage: %s [--only {test}] --target mdsnid:/mdsname/profile\n",
+               "usage: %s [--only {test}] --target mgsnid:/fsname\n",
                cmd);
         printf("       %s --dumpfile dumpfile\n", cmd);
         exit(-1);
@@ -1205,6 +1376,7 @@ struct testlist {
         { t51, "51" },
         { t53, "53" },
         { t54, "54" },
+        { t55, "55" },
         { NULL, NULL }
 };
 
index 5059937..d67f148 100644 (file)
@@ -1,10 +1,10 @@
-MODULES := llite
-llite-objs := dcache.o dir.o file.o llite_close.o llite_lib.o llite_nfs.o llite_fid.o rw.o lproc_llite.o namei.o symlink.o llite_mmap.o xattr.o
+MODULES := lustre
+lustre-objs := dcache.o dir.o file.o llite_close.o llite_lib.o llite_nfs.o llite_fid.o rw.o lproc_llite.o namei.o symlink.o llite_mmap.o xattr.o
 
 ifeq ($(PATCHLEVEL),4)
-llite-objs += rw24.o super.o
+lustre-objs += rw24.o super.o
 else
-llite-objs += rw26.o super25.o
+lustre-objs += rw26.o super25.o
 endif
 
 @INCLUDE_RULES@
index c389b31..102674f 100644 (file)
@@ -4,8 +4,8 @@
 # See the file COPYING in this distribution
 
 if MODULES
-modulefs_DATA = llite$(KMODEXT)
+modulefs_DATA = lustre$(KMODEXT)
 endif
 
-DIST_SOURCES := $(llite-objs:.o=.c) llite_internal.h rw24.c super.c rw26.c super25.c
+DIST_SOURCES := $(lustre-objs:.o=.c) llite_internal.h rw24.c super.c rw26.c super25.c
 MOSTLYCLEANFILES := @MOSTLYCLEANFILES@ 
index bf59310..43c6e27 100644 (file)
@@ -46,6 +46,12 @@ static void ll_release(struct dentry *de)
                 EXIT;
                 return;
         }
+#ifndef LUSTRE_KERNEL_VERSION
+        if (lld->lld_it) {
+                ll_intent_release(lld->lld_it);
+                OBD_FREE(lld->lld_it, sizeof(*lld->lld_it));
+        }
+#endif
         LASSERT(lld->lld_cwd_count == 0);
         LASSERT(lld->lld_mnt_count == 0);
         OBD_FREE(de->d_fsdata, sizeof(*lld));
@@ -53,6 +59,7 @@ static void ll_release(struct dentry *de)
         EXIT;
 }
 
+#ifdef LUSTRE_KERNEL_VERSION
 /* Compare if two dentries are the same.  Don't match if the existing dentry
  * is marked DCACHE_LUSTRE_INVALID.  Returns 1 if different, 0 if the same.
  *
@@ -81,17 +88,26 @@ int ll_dcompare(struct dentry *parent, struct qstr *d_name, struct qstr *name)
 
         RETURN(0);
 }
+#endif
 
 /* should NOT be called with the dcache lock, see fs/dcache.c */
 static int ll_ddelete(struct dentry *de)
 {
         ENTRY;
         LASSERT(de);
+#ifndef DCACHE_LUSTRE_INVALID
+#define DCACHE_LUSTRE_INVALID 0
+#endif
+
         CDEBUG(D_DENTRY, "%s dentry %.*s (%p, parent %p, inode %p) %s%s\n",
                (de->d_flags & DCACHE_LUSTRE_INVALID ? "deleting" : "keeping"),
                de->d_name.len, de->d_name.name, de, de->d_parent, de->d_inode,
                d_unhashed(de) ? "" : "hashed,",
                list_empty(&de->d_subdirs) ? "" : "subdirs");
+#if DCACHE_LUSTRE_INVALID == 0
+#undef DCACHE_LUSTRE_INVALID
+#endif
+
         RETURN(0);
 }
 
@@ -134,8 +150,19 @@ void ll_intent_release(struct lookup_intent *it)
 
         CDEBUG(D_INFO, "intent %p released\n", it);
         ll_intent_drop_lock(it);
+#ifdef LUSTRE_KERNEL_VERSION
         it->it_magic = 0;
         it->it_op_release = 0;
+#endif
+        /* We are still holding extra reference on a request, need to free it */
+        if (it_disposition(it, DISP_ENQ_OPEN_REF)) /* open req for llfile_open*/
+                ptlrpc_req_finished(it->d.lustre.it_data);
+        if (it_disposition(it, DISP_ENQ_CREATE_REF)) /* create rec */
+                ptlrpc_req_finished(it->d.lustre.it_data);
+        if (it_disposition(it, DISP_ENQ_COMPLETE)) /* saved req from revalidate
+                                                    * to lookup */
+                ptlrpc_req_finished(it->d.lustre.it_data);
+
         it->d.lustre.it_disposition = 0;
         it->d.lustre.it_data = NULL;
         EXIT;
@@ -147,11 +174,6 @@ void ll_intent_release(struct lookup_intent *it)
 int ll_drop_dentry(struct dentry *dentry)
 {
         lock_dentry(dentry);
-                CDEBUG(D_DENTRY, "dentry in drop %.*s (%p) parent %p "
-                       "inode %p flags %d\n", dentry->d_name.len,
-                       dentry->d_name.name, dentry, dentry->d_parent,
-                       dentry->d_inode, dentry->d_flags);
-
         if (atomic_read(&dentry->d_count) == 0) {
                 CDEBUG(D_DENTRY, "deleting dentry %.*s (%p) parent %p "
                        "inode %p\n", dentry->d_name.len,
@@ -260,17 +282,17 @@ int ll_revalidate_it_finish(struct ptlrpc_request *request,
                 RETURN(0);
 
         if (it_disposition(it, DISP_LOOKUP_NEG)) {
-                /*Sometimes, revalidate_it might also create node in MDS,
-                 *So we need check whether it is really created, if not,
-                 *just return the -ENOENT, if it is, return -ESTALE anyway.
-                 *which is original done in mdc_intent_lock, 
-                 *but no chance for new fid allocation in client. 
+                /* Sometimes, revalidate_it might also create node in MDS,
+                 * So we need check whether it is really created, if not,
+                 * just return the -ENOENT, if it is, return -ESTALE anyway.
+                 * which is original done in md_intent_lock, 
+                 * but no chance for new fid allocation in client. 
                  */
                 if (it_disposition(it, DISP_OPEN_CREATE) && 
                     !it_open_error(DISP_OPEN_CREATE, it)) {
-                         /*These 2 req finished is for balancing 2 add ref
-                          *in mdc_intent_lock, since there are no create_node
-                          *and file_open following revalidate_it*/
+                         /* These 2 req finished is for balancing 2 add ref
+                          * in md_intent_lock, since there are no create_node
+                          * and file_open following revalidate_it*/
                          it_set_disposition(it, DISP_ENQ_COMPLETE);
                          if (it_disposition(it, DISP_OPEN_CREATE) &&
                             !it_open_error(DISP_OPEN_CREATE, it))
@@ -306,7 +328,7 @@ void ll_lookup_finish_locks(struct lookup_intent *it, struct dentry *dentry)
         }
 
         /* drop lookup or getattr locks immediately */
-        if (it->it_op & (IT_LOOKUP | IT_GETATTR)) {
+        if (it->it_op == IT_LOOKUP || it->it_op == IT_GETATTR) {
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
                 /* on 2.6 there are situation when several lookups and
                  * revalidations may be requested during single operation.
@@ -321,7 +343,7 @@ void ll_lookup_finish_locks(struct lookup_intent *it, struct dentry *dentry)
 void ll_frob_intent(struct lookup_intent **itp, struct lookup_intent *deft)
 {
         struct lookup_intent *it = *itp;
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+#if defined(LUSTRE_KERNEL_VERSION)&&(LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
         if (it) {
                 LASSERTF(it->it_magic == INTENT_MAGIC, 
                          "%p has bad intent magic: %x\n",
@@ -332,14 +354,15 @@ void ll_frob_intent(struct lookup_intent **itp, struct lookup_intent *deft)
         if (!it || it->it_op == IT_GETXATTR)
                 it = *itp = deft;
 
+#ifdef LUSTRE_KERNEL_VERSION
         it->it_op_release = ll_intent_release;
+#endif
 }
 
 int ll_revalidate_it(struct dentry *de, int lookup_flags,
                      struct lookup_intent *it)
 {
         int rc;
-        struct it_cb_data icbd;
         struct md_op_data *op_data;
         struct ptlrpc_request *req = NULL;
         struct lookup_intent lookup_it = { .it_op = IT_LOOKUP };
@@ -350,19 +373,38 @@ int ll_revalidate_it(struct dentry *de, int lookup_flags,
         CDEBUG(D_VFSTRACE, "VFS Op:name=%s,intent=%s\n", de->d_name.name,
                LL_IT2STR(it));
 
-        /* Cached negative dentries are unsafe for now - look them up again */
-        if (de->d_inode == NULL)
-                RETURN(0);
+        if (de->d_inode == NULL) {
+                /* We can only use negative dentries if this is stat or lookup,
+                   for opens and stuff we do need to query server. */
+                /* If there is IT_CREAT in intent op set, then we must throw
+                   away this negative dentry and actually do the request to
+                   kernel to create whatever needs to be created (if possible)*/
+                if (it && (it->it_op & IT_CREAT))
+                        RETURN(0);
+
+#ifdef LUSTRE_KERNEL_VERSION
+                if (de->d_flags & DCACHE_LUSTRE_INVALID)
+                        RETURN(0);
+#endif
+
+                rc = ll_have_md_lock(de->d_parent->d_inode, 
+                                     MDS_INODELOCK_UPDATE);
+        
+                RETURN(rc);
+        }
 
         exp = ll_i2mdexp(de->d_inode);
-        icbd.icbd_parent = de->d_parent->d_inode;
-        icbd.icbd_childp = &de;
 
         /* Never execute intents for mount points.
          * Attributes will be fixed up in ll_inode_revalidate_it */
         if (d_mountpoint(de))
                 RETURN(1);
 
+        /* Root of the lustre tree. Always valid.
+         * Attributes will be fixed up in ll_inode_revalidate_it */
+        if (de->d_name.name[0] == '/' && de->d_name.len == 1)
+                RETURN(1);
+
         OBD_FAIL_TIMEOUT(OBD_FAIL_MDC_REVALIDATE_PAUSE, 5);
         ll_frob_intent(&it, &lookup_it);
         LASSERT(it);
@@ -375,9 +417,9 @@ int ll_revalidate_it(struct dentry *de, int lookup_flags,
         
         if (it->it_op & IT_CREAT) {
                 struct lu_placement_hint hint = { .ph_pname = NULL,
-                                          .ph_pfid = ll_inode2fid(parent),
-                                          .ph_cname = &de->d_name,
-                                          .ph_opc = LUSTRE_OPC_CREATE };
+                                                  .ph_pfid = ll_inode2fid(parent),
+                                                  .ph_cname = &de->d_name,
+                                                  .ph_opc = LUSTRE_OPC_CREATE };
 
                 ll_prepare_md_op_data(op_data, parent, NULL,
                                       de->d_name.name, de->d_name.len, 0);
@@ -392,13 +434,61 @@ int ll_revalidate_it(struct dentry *de, int lookup_flags,
                                       de->d_name.name, de->d_name.len, 0);
         }
 
+        if ((it->it_op == IT_OPEN) && de->d_inode) {
+                struct inode *inode = de->d_inode;
+                struct ll_inode_info *lli = ll_i2info(inode);
+                struct obd_client_handle **och_p;
+                __u64 *och_usecount;
+                /* We used to check for MDS_INODELOCK_OPEN here, but in fact
+                 * just having LOOKUP lock is enough to justify inode is the
+                 * same. And if inode is the same and we have suitable
+                 * openhandle, then there is no point in doing another OPEN RPC
+                 * just to throw away newly received openhandle.
+                 * There are no security implications too, if file owner or
+                 * access mode is change, LOOKUP lock is revoked */
+
+                it->it_create_mode &= ~current->fs->umask;
+
+                if (it->it_flags & FMODE_WRITE) {
+                        och_p = &lli->lli_mds_write_och;
+                        och_usecount = &lli->lli_open_fd_write_count;
+                } else if (it->it_flags & FMODE_EXEC) {
+                        och_p = &lli->lli_mds_exec_och;
+                        och_usecount = &lli->lli_open_fd_exec_count;
+                } else {
+                        och_p = &lli->lli_mds_read_och;
+                        och_usecount = &lli->lli_open_fd_read_count;
+                }
+                /* Check for the proper lock. */
+                if (!ll_have_md_lock(inode, MDS_INODELOCK_LOOKUP))
+                        goto do_lock;
+                down(&lli->lli_och_sem);
+                if (*och_p) { /* Everything is open already, do nothing */
+                        /*(*och_usecount)++;  Do not let them steal our open
+                          handle from under us */
+                        /* XXX The code above was my original idea, but in case
+                           we have the handle, but we cannot use it due to later
+                           checks (e.g. O_CREAT|O_EXCL flags set), nobody
+                           would decrement counter increased here. So we just
+                           hope the lock won't be invalidated in between. But
+                           if it would be, we'll reopen the open request to
+                           MDS later during file open path */
+                        up(&lli->lli_och_sem);
+                        RETURN(1);
+                } else {
+                        up(&lli->lli_och_sem);
+                }
+        }
+
+do_lock:
         rc = md_intent_lock(exp, op_data, NULL, 0, it, lookup_flags,
                             &req, ll_md_blocking_ast, 0);
-
         OBD_FREE_PTR(op_data);
         /* If req is NULL, then md_intent_lock only tried to do a lock match;
          * if all was well, it will return 1 if it found locks, 0 otherwise. */
         if (req == NULL && rc >= 0) {
+                if (!rc)
+                        goto do_lookup;
                 GOTO(out, rc);
         }
 
@@ -410,7 +500,8 @@ int ll_revalidate_it(struct dentry *de, int lookup_flags,
                 GOTO(out, rc = 0);
         }
 
-        rc = ll_revalidate_it_finish(req, 1, it, de);
+revalidate_finish:
+        rc = ll_revalidate_it_finish(req, DLM_REPLY_REC_OFF, it, de);
         if (rc != 0) {
                 if (rc != -ESTALE && rc != -ENOENT)
                         ll_intent_release(it);
@@ -432,28 +523,76 @@ int ll_revalidate_it(struct dentry *de, int lookup_flags,
         __d_rehash(de, 0);
         spin_unlock(&dcache_lock);
 
- out:
+out:
         /* We do not free request as it may be reused during following lookup
-          (see comment in mdc/mdc_locks.c::mdc_intent_lock()), request will
-           be freed in ll_lookup_it or in ll_intent_release. But if
-           request was not completed, we need to free it. (bug 5154) */
+         * (see comment in mdc/mdc_locks.c::mdc_intent_lock()), request will
+         * be freed in ll_lookup_it or in ll_intent_release. But if
+         * request was not completed, we need to free it. (bug 5154, 9903) */
         if (req != NULL && !it_disposition(it, DISP_ENQ_COMPLETE))
                 ptlrpc_req_finished(req);
         if (rc == 0) {
+#ifdef LUSTRE_KERNEL_VERSION
                 ll_unhash_aliases(de->d_inode);
                 /* done in ll_unhash_aliases()
-                dentry->d_flags |= DCACHE_LUSTRE_INVALID; */
+                   dentry->d_flags |= DCACHE_LUSTRE_INVALID; */
+#else
+                /* We do not want d_invalidate to kill all child dentries too */
+                d_drop(de);
+#endif
         } else {
                 CDEBUG(D_DENTRY, "revalidated dentry %.*s (%p) parent %p "
-                               "inode %p refc %d\n", de->d_name.len,
-                               de->d_name.name, de, de->d_parent, de->d_inode,
-                               atomic_read(&de->d_count));
+                       "inode %p refc %d\n", de->d_name.len,
+                       de->d_name.name, de, de->d_parent, de->d_inode,
+                       atomic_read(&de->d_count));
                 ll_lookup_finish_locks(it, de);
+#ifdef LUSTRE_KERNEL_VERSION
                 lock_dentry(de);
                 de->d_flags &= ~DCACHE_LUSTRE_INVALID;
                 unlock_dentry(de);
+#endif
         }
         RETURN(rc);
+        
+        /* This part is here to combat evil-evil race in real_lookup on 2.6
+         * kernels.  The race details are: We enter do_lookup() looking for some
+         * name, there is nothing in dcache for this name yet and d_lookup()
+         * returns NULL.  We proceed to real_lookup(), and while we do this,
+         * another process does open on the same file we looking up (most simple
+         * reproducer), open succeeds and the dentry is added. Now back to
+         * us. In real_lookup() we do d_lookup() again and suddenly find the
+         * dentry, so we call d_revalidate on it, but there is no lock, so
+         * without this code we would return 0, but unpatched real_lookup just
+         * returns -ENOENT in such a case instead of retrying the lookup. Once
+         * this is dealt with in real_lookup(), all of this ugly mess can go and
+         * we can just check locks in ->d_revalidate without doing any RPCs
+         * ever. */
+do_lookup:
+        if (it != &lookup_it) {
+                ll_lookup_finish_locks(it, de);
+                it = &lookup_it;
+        }
+        
+        OBD_ALLOC_PTR(op_data);
+        if (op_data == NULL)
+                RETURN(-ENOMEM);
+
+        /* do real lookup here */
+        ll_prepare_md_op_data(op_data, de->d_parent->d_inode, NULL,
+                              de->d_name.name, de->d_name.len, 0);
+        rc = md_intent_lock(exp, op_data, NULL, 0,  it, 0, &req,
+                            ll_md_blocking_ast, 0);
+        if (rc >= 0) {
+                struct mdt_body *mdt_body = lustre_msg_buf(req->rq_repmsg,
+                                                           DLM_REPLY_REC_OFF,
+                                                           sizeof(*mdt_body));
+                /* see if we got same inode, if not - return error */
+                if(!memcmp(&op_data->fid2, &mdt_body->fid1,
+                           sizeof(op_data->fid2)))
+                        goto revalidate_finish;
+                ll_intent_release(it);
+        }
+        OBD_FREE_PTR(op_data);
+        GOTO(out, rc = 0);
 }
 
 /*static*/ void ll_pin(struct dentry *de, struct vfsmount *mnt, int flag)
@@ -541,6 +680,7 @@ int ll_revalidate_it(struct dentry *de, int lookup_flags,
 }
 
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+#ifdef LUSTRE_KERNEL_VERSION
 static int ll_revalidate_nd(struct dentry *dentry, struct nameidata *nd)
 {
         int rc;
@@ -553,6 +693,76 @@ static int ll_revalidate_nd(struct dentry *dentry, struct nameidata *nd)
 
         RETURN(rc);
 }
+#else
+int ll_revalidate_nd(struct dentry *dentry, struct nameidata *nd)
+{
+        int rc;
+        ENTRY;
+
+        if (nd && !(nd->flags & (LOOKUP_CONTINUE|LOOKUP_PARENT))) {
+                struct lookup_intent *it;
+                it = ll_convert_intent(&nd->intent.open, nd->flags);
+                if (IS_ERR(it))
+                        RETURN(0);
+                if (it->it_op == (IT_OPEN|IT_CREAT))
+                        if (nd->intent.open.flags & O_EXCL) {
+                                CDEBUG(D_VFSTRACE, "create O_EXCL, returning 0\n");
+                                rc = 0;
+                                goto out_it;
+                        }
+
+                rc = ll_revalidate_it(dentry, nd->flags, it);
+
+                if (rc && (nd->flags & LOOKUP_OPEN) &&
+                    it_disposition(it, DISP_OPEN_OPEN)) {/*Open*/
+#ifdef HAVE_FILE_IN_STRUCT_INTENT
+// XXX Code duplication with ll_lookup_nd
+                        if (S_ISFIFO(dentry->d_inode->i_mode)) {
+                                // We cannot call open here as it would
+                                // deadlock.
+                                ptlrpc_req_finished(
+                                               (struct ptlrpc_request *)
+                                                  it->d.lustre.it_data);
+                        } else {
+                                struct file *filp;
+
+                                nd->intent.open.file->private_data = it;
+                                filp = lookup_instantiate_filp(nd, dentry,NULL);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17))
+/* 2.6.1[456] have a bug in open_namei() that forgets to check
+ * nd->intent.open.file for error, so we need to return it as lookup's result
+ * instead */
+                                if (IS_ERR(filp))
+                                        rc = 0;
+#endif
+                        }
+#else
+                        ll_release_openhandle(dentry, it);
+#endif /* HAVE_FILE_IN_STRUCT_INTENT */
+                }
+                if (!rc && (nd->flags & LOOKUP_CREATE) &&
+                    it_disposition(it, DISP_OPEN_CREATE)) {
+                        /* We created something but we may only return
+                         * negative dentry here, so save request in dentry,
+                         * if lookup will be called later on, it will
+                         * pick the request, otherwise it would be freed
+                         * with dentry */
+                        ll_d2d(dentry)->lld_it = it;
+                        it = NULL; /* avoid freeing */
+                }
+                        
+out_it:
+                if (it) {
+                        ll_intent_release(it);
+                        OBD_FREE(it, sizeof(*it));
+                }
+        } else {
+                rc = ll_revalidate_it(dentry, 0, NULL);
+        }
+
+        RETURN(rc);
+}
+#endif
 #endif
 
 struct dentry_operations ll_d_ops = {
@@ -563,7 +773,9 @@ struct dentry_operations ll_d_ops = {
 #endif
         .d_release = ll_release,
         .d_delete = ll_ddelete,
+#ifdef LUSTRE_KERNEL_VERSION
         .d_compare = ll_dcompare,
+#endif
 #if 0
         .d_pin = ll_pin,
         .d_unpin = ll_unpin,
index 02d1bf7..30f5a1a 100644 (file)
@@ -152,9 +152,11 @@ static int ll_dir_readpage(struct file *file, struct page *page)
         rc = md_readpage(ll_i2sbi(inode)->ll_md_exp, ll_inode2fid(inode),
                          hash, page, &request);
         if (!rc) {
-                body = lustre_msg_buf(request->rq_repmsg, 0, sizeof (*body));
-                LASSERT (body != NULL);         /* checked by md_readpage() */
-                LASSERT_REPSWABBED (request, 0); /* swabbed by md_readpage() */
+                body = lustre_msg_buf(request->rq_repmsg, REPLY_REC_OFF,
+                                      sizeof(*body));
+                LASSERT(body != NULL); /* checked by md_readpage() */
+                /* swabbed by md_readpage() */
+                LASSERT_REPSWABBED(request, REPLY_REC_OFF);
 
                 if (body->valid & OBD_MD_FLSIZE)
                         inode->i_size = body->size;
@@ -655,98 +657,71 @@ static int ll_dir_ioctl(struct inode *inode, struct file *file,
                 ptlrpc_req_finished(request);
                 RETURN(rc);
         }
-        case LL_IOC_LOV_GETSTRIPE: {
-                struct ptlrpc_request *request = NULL;
-                struct lov_user_md *lump = (struct lov_user_md *)arg;
-                struct lov_mds_md *lmm;
-                struct mdt_body *body;
-                int rc, lmmsize;
-
-                rc = ll_get_max_mdsize(sbi, &lmmsize);
-                if (rc)
-                        RETURN(rc);
-
-                rc = md_getattr(sbi->ll_md_exp, ll_inode2fid(inode),
-                                OBD_MD_FLDIREA, lmmsize, &request);
-                if (rc < 0) {
-                        CDEBUG(D_INFO, "md_getattr failed: rc = %d\n", rc);
-                        RETURN(rc);
-                }
-
-                body = lustre_msg_buf(request->rq_repmsg, 0, sizeof(*body));
-                LASSERT(body != NULL);         /* checked by md_getattr_name */
-                LASSERT_REPSWABBED(request, 0);/* swabbed by md_getattr_name */
-
-                lmmsize = body->eadatasize;
-                if (lmmsize == 0)
-                        GOTO(out_get, rc = -ENODATA);
-
-                lmm = lustre_msg_buf(request->rq_repmsg, 1, lmmsize);
-                LASSERT(lmm != NULL);
-                LASSERT_REPSWABBED(request, 1);
-
-                /*
-                 * This is coming from the MDS, so is probably in
-                 * little endian.  We convert it to host endian before
-                 * passing it to userspace.
-                 */
-                if (lmm->lmm_magic == __swab32(LOV_MAGIC)) {
-                        lustre_swab_lov_user_md((struct lov_user_md *)lmm);
-                        lustre_swab_lov_user_md_objects((struct lov_user_md *)lmm);
-                }
-
-                rc = copy_to_user(lump, lmm, lmmsize);
-                if (rc)
-                        GOTO(out_get, rc = -EFAULT);
-
-                EXIT;
-        out_get:
-                ptlrpc_req_finished(request);
-                return rc;
-        }
         case LL_IOC_OBD_STATFS:
                 RETURN(ll_obd_statfs(inode, (void *)arg));
+        case LL_IOC_LOV_GETSTRIPE:
+        case LL_IOC_MDC_GETINFO:
         case IOC_MDC_GETFILEINFO:
-        case IOC_MDC_GETSTRIPE: {
+        case IOC_MDC_GETFILESTRIPE: {
                 struct ptlrpc_request *request = NULL;
                 struct lov_user_md *lump;
-                struct lov_mds_md *lmm;
+                struct lov_mds_md *lmm = NULL;
                 struct mdt_body *body;
-                char *filename;
+                char *filename = NULL;
                 int rc, lmmsize;
 
-                filename = getname((const char *)arg);
-                if (IS_ERR(filename))
-                        RETURN(PTR_ERR(filename));
-
                 rc = ll_get_max_mdsize(sbi, &lmmsize);
                 if (rc)
                         RETURN(rc);
 
-                rc = md_getattr_name(sbi->ll_md_exp, ll_inode2fid(inode),
-                                     filename, strlen(filename) + 1,
-                                     OBD_MD_FLEASIZE, lmmsize, &request);
-                if (rc < 0) {
-                        CDEBUG(D_INFO, "md_getattr_name failed on %s: rc %d\n",
-                               filename, rc);
-                        GOTO(out_name, rc);
+                if (cmd == IOC_MDC_GETFILEINFO ||
+                    cmd == IOC_MDC_GETFILESTRIPE) {
+                        filename = getname((const char *)arg);
+                        if (IS_ERR(filename))
+                                RETURN(PTR_ERR(filename));
+
+                        rc = md_getattr_name(sbi->ll_md_exp, ll_inode2fid(inode),
+                                             filename, strlen(filename) + 1,
+                                             OBD_MD_FLEASIZE | OBD_MD_FLDIREA, 
+                                             lmmsize, &request);
+                        if (rc < 0) {
+                                CDEBUG(D_INFO, "md_getattr_name failed "
+                                       "on %s: rc %d\n", filename, rc);
+                                GOTO(out_name, rc);
+                        }
+                } else {
+                        rc = md_getattr(sbi->ll_md_exp, ll_inode2fid(inode),
+                                        OBD_MD_FLEASIZE | OBD_MD_FLDIREA,
+                                        lmmsize, &request);
+                        if (rc < 0) {
+                                CDEBUG(D_INFO, "md_getattr failed on inode "
+                                       "%lu/%u: rc %d\n", inode->i_ino,
+                                       inode->i_generation, rc);
+                                GOTO(out_name, rc);
+                         }
                 }
 
-                body = lustre_msg_buf(request->rq_repmsg, 0, sizeof (*body));
-                LASSERT(body != NULL);         /* checked by md_getattr_name */
-                LASSERT_REPSWABBED(request, 0);/* swabbed by md_getattr_name */
+                body = lustre_msg_buf(request->rq_repmsg, REPLY_REC_OFF,
+                                      sizeof(*body));
+                LASSERT(body != NULL); /* checked by md_getattr_name */
+                /* swabbed by md_getattr_name */
+                LASSERT_REPSWABBED(request, REPLY_REC_OFF);
 
                 lmmsize = body->eadatasize;
 
-                if (!(body->valid & OBD_MD_FLEASIZE) || lmmsize == 0)
-                        GOTO(out_req, rc = -ENODATA);
-
-                if (lmmsize > 4096)
-                        GOTO(out_req, rc = -EFBIG);
+                if (!(body->valid & (OBD_MD_FLEASIZE | OBD_MD_FLDIREA)) ||
+                    lmmsize == 0) {
+                        if (cmd == LL_IOC_LOV_GETSTRIPE ||
+                            cmd == IOC_MDC_GETFILESTRIPE)
+                                GOTO(out_req, rc = -ENODATA);
+                        else
+                                GOTO(skip_lmm, rc = 0);
+                }
 
-                lmm = lustre_msg_buf(request->rq_repmsg, 1, lmmsize);
+                lmm = lustre_msg_buf(request->rq_repmsg, REPLY_REC_OFF + 1,
+                                     lmmsize);
                 LASSERT(lmm != NULL);
-                LASSERT_REPSWABBED(request, 1);
+                LASSERT_REPSWABBED(request, REPLY_REC_OFF + 1);
 
                 /*
                  * This is coming from the MDS, so is probably in
@@ -780,25 +755,22 @@ static int ll_dir_ioctl(struct inode *inode, struct file *file,
 
                         memcpy(lmj, lmm, sizeof(struct lov_user_md_join));
                         for (i = 0; i < lsm->lsm_stripe_count; i++) {
-                                struct lov_array_info *lai = lsm->lsm_array;
-                                if ((lai->lai_ext_array[aindex].le_loi_idx +
-                                     lai->lai_ext_array[aindex].le_stripe_count)<=i){
+                                struct lov_extent *lex =
+                                        &lsm->lsm_array->lai_ext_array[aindex];
+
+                                if (lex->le_loi_idx + lex->le_stripe_count <= i)
                                         aindex ++;
-                                }
-                                CDEBUG(D_INFO, "aindex %d i %d l_extent_start"
-                                       LPU64"len %d \n", aindex, i,
-                                       lai->lai_ext_array[aindex].le_start,
-                                       (int)lai->lai_ext_array[aindex].le_len);
+                                CDEBUG(D_INFO, "aindex %d i %d l_extent_start "
+                                       LPU64" len %d\n", aindex, i,
+                                       lex->le_start, (int)lex->le_len);
                                 lmj->lmm_objects[i].l_extent_start =
-                                        lai->lai_ext_array[aindex].le_start;
+                                        lex->le_start;
 
-                                if ((int)lai->lai_ext_array[aindex].le_len == -1) {
+                                if ((int)lex->le_len == -1)
                                         lmj->lmm_objects[i].l_extent_end = -1;
-                                } else {
+                                else
                                         lmj->lmm_objects[i].l_extent_end =
-                                          lai->lai_ext_array[aindex].le_start +
-                                          lai->lai_ext_array[aindex].le_len;
-                                }
+                                                lex->le_start + lex->le_len;
                                 lmj->lmm_objects[i].l_object_id =
                                         lsm->lsm_oinfo[i].loi_id;
                                 lmj->lmm_objects[i].l_object_gr =
@@ -810,16 +782,28 @@ static int ll_dir_ioctl(struct inode *inode, struct file *file,
                         }
                         lmm = (struct lov_mds_md *)lmj;
                         lmmsize = lmj_size;
-out_free_memmd:
+                out_free_memmd:
                         obd_free_memmd(sbi->ll_dt_exp, &lsm);
                         if (rc)
                                 GOTO(out_req, rc);
                 }
-                if (cmd == IOC_MDC_GETFILEINFO) {
+                if (cmd == IOC_MDC_GETFILESTRIPE ||
+                    cmd == LL_IOC_LOV_GETSTRIPE) {
+                        lump = (struct lov_user_md *)arg;
+                } else {
+                        struct lov_user_mds_data *lmdp;
+                        lmdp = (struct lov_user_mds_data *)arg;
+                        lump = &lmdp->lmd_lmm;
+                }
+                rc = copy_to_user(lump, lmm, lmmsize);
+                if (rc)
+                        GOTO(out_lmm, rc = -EFAULT);
+        skip_lmm:
+                if (cmd == IOC_MDC_GETFILEINFO || cmd == LL_IOC_MDC_GETINFO) {
                         struct lov_user_mds_data *lmdp;
                         lstat_t st = { 0 };
 
-                        st.st_dev     = 0;
+                        st.st_dev     = inode->i_sb->s_dev;
                         st.st_mode    = body->mode;
                         st.st_nlink   = body->nlink;
                         st.st_uid     = body->uid;
@@ -836,31 +820,74 @@ out_free_memmd:
                         lmdp = (struct lov_user_mds_data *)arg;
                         rc = copy_to_user(&lmdp->lmd_st, &st, sizeof(st));
                         if (rc)
-                                GOTO(out_req, rc = -EFAULT);
-                        lump = &lmdp->lmd_lmm;
-                } else {
-                        lump = (struct lov_user_md *)arg;
+                                GOTO(out_lmm, rc = -EFAULT);
                 }
 
-                rc = copy_to_user(lump, lmm, lmmsize);
-                if (lmm->lmm_magic == LOV_MAGIC_JOIN)
-                        OBD_FREE(lmm, lmmsize);
-                if (rc)
-                        GOTO(out_req, rc = -EFAULT);
-
                 EXIT;
+        out_lmm:
+                if (lmm && lmm->lmm_magic == LOV_MAGIC_JOIN)
+                        OBD_FREE(lmm, lmmsize);
         out_req:
                 ptlrpc_req_finished(request);
         out_name:
-                putname(filename);
+                if (filename)
+                        putname(filename);
+                return rc;
+        }
+        case IOC_LOV_GETINFO: {
+                struct lov_user_mds_data *lumd;
+                struct lov_stripe_md *lsm;
+                struct lov_user_md *lum;
+                struct lov_mds_md *lmm;
+                int lmmsize;
+                lstat_t st;
+                int rc;
+
+                lumd = (struct lov_user_mds_data *)arg;
+                lum = &lumd->lmd_lmm;
+
+                rc = ll_get_max_mdsize(sbi, &lmmsize);
+                if (rc)
+                        RETURN(rc);
+
+                OBD_ALLOC(lmm, lmmsize);
+                rc = copy_from_user(lmm, lum, lmmsize);
+                if (rc)
+                        GOTO(free_lmm, rc = -EFAULT);
+
+                rc = obd_unpackmd(sbi->ll_dt_exp, &lsm, lmm, lmmsize);
+                if (rc < 0)
+                        GOTO(free_lmm, rc = -ENOMEM);
+
+                rc = obd_checkmd(sbi->ll_dt_exp, sbi->ll_md_exp, lsm);
+                if (rc)
+                        GOTO(free_lsm, rc);
+
+                /* Perform glimpse_size operation. */
+                memset(&st, 0, sizeof(st));
+
+                rc = ll_glimpse_ioctl(sbi, lsm, &st);
+                if (rc)
+                        GOTO(free_lsm, rc);
+
+                rc = copy_to_user(&lumd->lmd_st, &st, sizeof(st));
+                if (rc)
+                        GOTO(free_lsm, rc = -EFAULT);
+
+                EXIT;
+        free_lsm:
+                obd_free_memmd(sbi->ll_dt_exp, &lsm);
+        free_lmm:
+                OBD_FREE(lmm, lmmsize);
                 return rc;
         }
         case OBD_IOC_LLOG_CATINFO: {
                 struct ptlrpc_request *req = NULL;
                 char *buf = NULL;
                 int rc, len = 0;
-                char *bufs[2], *str;
-                int lens[2], size;
+                char *bufs[3] = { NULL }, *str;
+                int lens[3] = { sizeof(struct ptlrpc_body) };
+                int size[2] = { sizeof(struct ptlrpc_body) };
 
                 rc = obd_ioctl_getdata(&buf, &len, (void *)arg);
                 if (rc)
@@ -872,28 +899,30 @@ out_free_memmd:
                         RETURN(-EINVAL);
                 }
 
-                lens[0] = data->ioc_inllen1;
-                bufs[0] = data->ioc_inlbuf1;
+                lens[REQ_REC_OFF] = data->ioc_inllen1;
+                bufs[REQ_REC_OFF] = data->ioc_inlbuf1;
                 if (data->ioc_inllen2) {
-                        lens[1] = data->ioc_inllen2;
-                        bufs[1] = data->ioc_inlbuf2;
+                        lens[REQ_REC_OFF + 1] = data->ioc_inllen2;
+                        bufs[REQ_REC_OFF + 1] = data->ioc_inlbuf2;
                 } else {
-                        lens[1] = 0;
-                        bufs[1] = NULL;
+                        lens[REQ_REC_OFF + 1] = 0;
+                        bufs[REQ_REC_OFF + 1] = NULL;
                 }
-                size = data->ioc_plen1;
+
                 req = ptlrpc_prep_req(sbi2mdc(sbi)->cl_import,
-                                      LUSTRE_LOG_VERSION, LLOG_CATINFO,
-                                      2, lens, bufs);
+                                      LUSTRE_LOG_VERSION, LLOG_CATINFO, 3, lens,
+                                      bufs);
                 if (!req)
                         GOTO(out_catinfo, rc = -ENOMEM);
-                req->rq_replen = lustre_msg_size(1, &size);
+
+                size[REPLY_REC_OFF] = data->ioc_plen1;
+                ptlrpc_req_set_repsize(req, 2, size);
 
                 rc = ptlrpc_queue_wait(req);
-                str = lustre_msg_string(req->rq_repmsg, 0, data->ioc_plen1);
+                str = lustre_msg_string(req->rq_repmsg, REPLY_REC_OFF,
+                                        data->ioc_plen1);
                 if (!rc)
-                        rc = copy_to_user(data->ioc_pbuf1, str,
-                                          data->ioc_plen1);
+                        rc = copy_to_user(data->ioc_pbuf1, str,data->ioc_plen1);
                 ptlrpc_req_finished(req);
         out_catinfo:
                 obd_ioctl_freedata(buf, len);
@@ -1031,11 +1060,10 @@ out_free_memmd:
                                                             exp_obd->u.lov;
 
                                 for (i = 0; i < lov->desc.ld_tgt_count; i++) {
-                                        exp = lov->tgts[i].ltd_exp;
-
-                                        if (!lov->tgts[i].active)
+                                        if (!lov->lov_tgts[i] ||
+                                            !lov->lov_tgts[i]->ltd_active)
                                                 continue;
-
+                                        exp = lov->lov_tgts[i]->ltd_exp;
                                         if (exp->exp_obd == obd) {
                                                 rc = obd_quotactl(exp, oqctl);
                                                 break;
index f9a306c..86423b0 100644 (file)
@@ -54,9 +54,29 @@ static int ll_close_inode_openhandle(struct obd_export *md_exp,
 {
         struct md_op_data *op_data;
         struct ptlrpc_request *req = NULL;
+        struct obd_device *obd;
         int rc;
         ENTRY;
 
+        obd = class_exp2obd(ll_i2mdexp(inode));
+        if (obd == NULL) {
+                /* 
+                 * XXX: in case of LMV, is this correct to access 
+                 * ->exp_handle? 
+                 */
+                CERROR("Invalid MDC connection handle "LPX64"\n",
+                       ll_i2mdexp(inode)->exp_handle.h_cookie);
+                GOTO(out, rc = 0);
+        }
+
+        /*
+         * here we check if this is forced umount. If so this is called on
+         * canceling "open lock" and we do not call md_close() in this case, as
+         * it will not be successful, as import is already deactivated.
+         */
+        if (obd->obd_no_recov)
+                GOTO(out, rc = 0);
+
         OBD_ALLOC_PTR(op_data);
         if (op_data == NULL)
                 RETURN(-ENOMEM);
@@ -98,15 +118,59 @@ static int ll_close_inode_openhandle(struct obd_export *md_exp,
                                inode->i_ino, rc);
         }
 
-        md_clear_open_replay_data(md_exp, och);
         ptlrpc_req_finished(req); /* This is close request */
+        EXIT;
+out:
+        md_clear_open_replay_data(md_exp, och);
+        return rc;
+}
+
+int ll_md_real_close(struct inode *inode, int flags)
+{
+        struct ll_inode_info *lli = ll_i2info(inode);
+        int rc = 0;
+        struct obd_client_handle **och_p;
+        struct obd_client_handle *och;
+        __u64 *och_usecount;
+
+        ENTRY;
+
+        if (flags & FMODE_WRITE) {
+                och_p = &lli->lli_mds_write_och;
+                och_usecount = &lli->lli_open_fd_write_count;
+        } else if (flags & FMODE_EXEC) {
+                och_p = &lli->lli_mds_exec_och;
+                och_usecount = &lli->lli_open_fd_exec_count;
+         } else {
+                LASSERT(flags & FMODE_READ);
+                och_p = &lli->lli_mds_read_och;
+                och_usecount = &lli->lli_open_fd_read_count;
+        }
+
+        down(&lli->lli_och_sem);
+        if (*och_usecount) { /* There are still users of this handle, so
+                                skip freeing it. */
+                up(&lli->lli_och_sem);
+                RETURN(0);
+        }
+        och=*och_p;
+        *och_p = NULL;
+        up(&lli->lli_och_sem);
+
+        if (och) { /* There might be a race and somebody have freed this och
+                      already */
+                rc = ll_close_inode_openhandle(ll_i2sbi(inode)->ll_md_exp, 
+                                               inode, och);
+                och->och_fh.cookie = DEAD_HANDLE_MAGIC;
+                OBD_FREE(och, sizeof *och);
+        }
 
         RETURN(rc);
 }
 
 /* just for debugging by huanghua@clusterfs.com, will be removed later */
 #include <lustre_lib.h>
-struct mdc_open_data {
+struct md_open_data {
         struct obd_client_handle *mod_och;
         struct ptlrpc_request    *mod_open_req;
         struct ptlrpc_request    *mod_close_req;
@@ -117,8 +181,8 @@ int ll_md_close(struct obd_export *md_exp, struct inode *inode,
                 struct file *file)
 {
         struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
-        struct obd_client_handle *och = &fd->fd_mds_och;
-        int rc;
+        struct ll_inode_info *lli = ll_i2info(inode);
+        int rc = 0;
         ENTRY;
 
         /* clear group lock, if present */
@@ -128,16 +192,43 @@ int ll_md_close(struct obd_export *md_exp, struct inode *inode,
                 rc = ll_extent_unlock(fd, inode, lsm, LCK_GROUP,
                                       &fd->fd_cwlockh);
         }
-        CDEBUG(D_INFO, "closing ino = %lu file = %p has open req = %p, type = %x, "
-                       "transno = "LPU64", handle = "LPX64"\n",
-                       inode->i_ino, file,
-                       och->och_mod->mod_open_req,
-                       och->och_mod->mod_open_req->rq_type,
-                       och->och_mod->mod_open_req->rq_transno,
-                       och->och_fh.cookie);
 
-        rc = ll_close_inode_openhandle(md_exp, inode, och);
-        och->och_fh.cookie = DEAD_HANDLE_MAGIC;
+        /* Let's see if we have good enough OPEN lock on the file and if
+           we can skip talking to MDS */
+        if (file->f_dentry->d_inode) { /* Can this ever be false? */
+                int lockmode;
+                int flags = LDLM_FL_BLOCK_GRANTED | LDLM_FL_TEST_LOCK;
+                struct lustre_handle lockh;
+                struct inode *inode = file->f_dentry->d_inode;
+                ldlm_policy_data_t policy = {.l_inodebits={MDS_INODELOCK_OPEN}};
+
+                down(&lli->lli_och_sem);
+                if (fd->fd_omode & FMODE_WRITE) {
+                        lockmode = LCK_CW;
+                        LASSERT(lli->lli_open_fd_write_count);
+                        lli->lli_open_fd_write_count--;
+                } else if (fd->fd_omode & FMODE_EXEC) {
+                        lockmode = LCK_PR;
+                        LASSERT(lli->lli_open_fd_exec_count);
+                        lli->lli_open_fd_exec_count--;
+                } else {
+                        lockmode = LCK_CR;
+                        LASSERT(lli->lli_open_fd_read_count);
+                        lli->lli_open_fd_read_count--;
+                }
+                up(&lli->lli_och_sem);
+
+                if (!md_lock_match(md_exp, flags, ll_inode2fid(inode),
+                                   LDLM_IBITS, &policy, lockmode,
+                                   &lockh)) {
+                        rc = ll_md_real_close(file->f_dentry->d_inode,
+                                              fd->fd_omode);
+                }
+        } else {
+                CERROR("Releasing a file %p with negative dentry %p. Name %s",
+                       file, file->f_dentry, file->f_dentry->d_name.name);
+        }
+        
         LUSTRE_FPRIVATE(file) = NULL;
         ll_file_data_put(fd);
 
@@ -200,6 +291,18 @@ static int ll_intent_file_open(struct file *file, void *lmm,
         if (op_data == NULL)
                 RETURN(-ENOMEM);
 
+        /* Usually we come here only for NFSD, and we want open lock.
+           But we can also get here with pre 2.6.15 patchless kernels, and in
+           that case that lock is also ok */
+        /* We can also get here if there was cached open handle in revalidate_it
+         * but it disappeared while we were getting from there to ll_file_open.
+         * But this means this file was closed and immediatelly opened which
+         * makes a good candidate for using OPEN lock */
+        /* If lmmsize & lmm are not 0, we are just setting stripe info
+         * parameters. No need for the open lock */
+        if (!lmm && !lmmsize)
+                itp->it_flags |= MDS_OPEN_LOCK;
+        
         ll_prepare_md_op_data(op_data, parent->d_inode, NULL,
                               name, len, O_RDWR);
 
@@ -212,9 +315,14 @@ static int ll_intent_file_open(struct file *file, void *lmm,
                 RETURN(rc);
         }
 
+        if (itp->d.lustre.it_lock_mode) { /* If we got lock - release it right
+                                           * away */
+                ldlm_lock_decref(&lockh, itp->d.lustre.it_lock_mode);
+                itp->d.lustre.it_lock_mode = 0;
+        }
         rc = ll_prep_inode(&file->f_dentry->d_inode,
                            (struct ptlrpc_request *)itp->d.lustre.it_data,
-                           1, NULL);
+                           DLM_REPLY_REC_OFF, NULL);
         RETURN(rc);
 }
 
@@ -226,9 +334,9 @@ static void ll_och_fill(struct obd_export *md_exp, struct ll_inode_info *lli,
 
         LASSERT(och);
 
-        body = lustre_msg_buf(req->rq_repmsg, 1, sizeof(*body));
+        body = lustre_msg_buf(req->rq_repmsg, DLM_REPLY_REC_OFF, sizeof(*body));
         LASSERT(body != NULL);                  /* reply already checked out */
-        LASSERT_REPSWABBED(req, 1);             /* and swabbed in md_enqueue */
+        LASSERT_REPSWABBED(req, DLM_REPLY_REC_OFF); /* and swabbed in md_enqueue */
 
         memcpy(&och->och_fh, &body->handle, sizeof(body->handle));
         och->och_magic = OBD_CLIENT_HANDLE_MAGIC;
@@ -238,7 +346,7 @@ static void ll_och_fill(struct obd_export *md_exp, struct ll_inode_info *lli,
 }
 
 int ll_local_open(struct file *file, struct lookup_intent *it,
-                  struct ll_file_data *fd)
+                  struct ll_file_data *fd, struct obd_client_handle *och)
 {
         struct inode *inode = file->f_dentry->d_inode;
         ENTRY;
@@ -247,12 +355,13 @@ int ll_local_open(struct file *file, struct lookup_intent *it,
 
         LASSERT(fd != NULL);
 
-        ll_och_fill(ll_i2sbi(inode)->ll_md_exp,
-                    ll_i2info(inode), it, &fd->fd_mds_och);
+        if (och)
+                ll_och_fill(ll_i2sbi(inode)->ll_md_exp,
+                            ll_i2info(inode), it, och);
 
         LUSTRE_FPRIVATE(file) = fd;
         ll_readahead_init(inode, &fd->fd_ras);
-
+        fd->fd_omode = it->it_flags;
         RETURN(0);
 }
 
@@ -277,7 +386,9 @@ int ll_file_open(struct inode *inode, struct file *file)
         struct lookup_intent *it, oit = { .it_op = IT_OPEN,
                                           .it_flags = file->f_flags };
         struct lov_stripe_md *lsm;
-        struct ptlrpc_request *req;
+        struct ptlrpc_request *req = NULL;
+        struct obd_client_handle **och_p;
+        __u64 *och_usecount;
         struct ll_file_data *fd;
         int rc = 0;
         ENTRY;
@@ -285,7 +396,12 @@ int ll_file_open(struct inode *inode, struct file *file)
         CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), flags %o\n", inode->i_ino,
                inode->i_generation, inode, file->f_flags);
 
+#ifdef LUSTRE_KERNEL_VERSION
         it = file->f_it;
+#else
+        it = file->private_data; /* XXX: compat macro */
+        file->private_data = NULL; /* prevent ll_local_open assertion */
+#endif
 
         fd = ll_file_data_get();
         if (fd == NULL)
@@ -298,8 +414,6 @@ int ll_file_open(struct inode *inode, struct file *file)
         }
 
         if (!it || !it->d.lustre.it_disposition) {
-                struct ll_sb_info *sbi = ll_i2sbi(inode);
-
                 /* Convert f_flags into access mode. We cannot use file->f_mode,
                  * because everything but O_ACCMODE mask was stripped from
                  * there */
@@ -311,38 +425,92 @@ int ll_file_open(struct inode *inode, struct file *file)
                 if (oit.it_flags & O_CREAT)
                         oit.it_flags |= MDS_OPEN_OWNEROVERRIDE;
 
+                /* NFS hack - some strange NFS clients create files with zero
+                 * permission bits, and then expect to be able to open such
+                 * files. We are relying on real VFS client to do ll_permission
+                 * first before coming here, so if we got here, we either came
+                 * from NFS or all access checks ar eok, so it is safe to set
+                 * this flag in any case (XXX - race with chmod?)
+                 */ 
+                oit.it_flags |= MDS_OPEN_OWNEROVERRIDE;
+
                 /* We do not want O_EXCL here, presumably we opened the file
                  * already? XXX - NFS implications? */
                 oit.it_flags &= ~O_EXCL;
 
                 it = &oit;
-                rc = ll_intent_file_open(file, NULL, 0, it);
-                if (rc) {
+        }
+
+        /* Let's see if we have file open on MDS already. */
+        if (it->it_flags & FMODE_WRITE) {
+                och_p = &lli->lli_mds_write_och;
+                och_usecount = &lli->lli_open_fd_write_count;
+        } else if (it->it_flags & FMODE_EXEC) {
+                och_p = &lli->lli_mds_exec_och;
+                och_usecount = &lli->lli_open_fd_exec_count;
+         } else {
+                och_p = &lli->lli_mds_read_och;
+                och_usecount = &lli->lli_open_fd_read_count;
+        }
+        down(&lli->lli_och_sem);
+        if (*och_p) { /* Open handle is present */
+                if (it_disposition(it, DISP_LOOKUP_POS) && /* Positive lookup */
+                    it_disposition(it, DISP_OPEN_OPEN)) { /* & OPEN happened */
+                        /* Well, there's extra open request that we do not need,
+                           let's close it somehow. This will decref request. */
+                        ll_release_openhandle(file->f_dentry, it);
+                }
+                (*och_usecount)++;
+
+                rc = ll_local_open(file, it, fd, NULL);
+
+                LASSERTF(rc == 0, "rc = %d\n", rc);
+        } else {
+                LASSERT(*och_usecount == 0);
+                OBD_ALLOC(*och_p, sizeof (struct obd_client_handle));
+                if (!*och_p) {
                         ll_file_data_put(fd);
-                        GOTO(out, rc);
+                        GOTO(out_och_free, rc = -ENOMEM);
                 }
+                (*och_usecount)++;
+                if (!it->d.lustre.it_disposition) {
+                        rc = ll_intent_file_open(file, NULL, 0, it);
+                        if (rc) {
+                                ll_file_data_put(fd);
+                                GOTO(out_och_free, rc);
+                        }
 
-                md_set_lock_data(sbi->ll_md_exp, &it->d.lustre.it_lock_handle,
-                                 file->f_dentry->d_inode);
-        }
+                        /* Got some error? Release the request */
+                        if (it->d.lustre.it_status < 0) {
+                                req = it->d.lustre.it_data;
+                                ptlrpc_req_finished(req);
+                        }
+                        md_set_lock_data(ll_i2sbi(inode)->ll_md_exp,
+                                         &it->d.lustre.it_lock_handle,
+                                         file->f_dentry->d_inode);
+                }
+                req = it->d.lustre.it_data;
+
+                /* md_intent_lock() didn't get a request ref if there was an
+                 * open error, so don't do cleanup on the request here 
+                 * (bug 3430) */
+                /* XXX (green): Should not we bail out on any error here, not
+                 * just open error? */
+                rc = it_open_error(DISP_OPEN_OPEN, it);
+                if (rc) {
+                        ll_file_data_put(fd);
+                        GOTO(out_och_free, rc);
+                }
 
-        lprocfs_counter_incr(ll_i2sbi(inode)->ll_stats, LPROC_LL_OPEN);
-        rc = it_open_error(DISP_OPEN_OPEN, it);
-        /* md_intent_lock() didn't get a request ref if there was an open
-         * error, so don't do cleanup on the request here (bug 3430) */
-        if (rc) {
-                ll_file_data_put(fd);
-                RETURN(rc);
+                lprocfs_counter_incr(ll_i2sbi(inode)->ll_stats, LPROC_LL_OPEN);
+                rc = ll_local_open(file, it, fd, *och_p);
+                LASSERTF(rc == 0, "rc = %d\n", rc);
         }
+        up(&lli->lli_och_sem);
 
-        rc = ll_local_open(file, it, fd);
-        req = it->d.lustre.it_data;
-        LASSERTF(rc == 0, "rc = %d\n", rc);
-        CDEBUG(D_INFO, "opening ino = %lu file = %p has open req = %p, type = %x, "
-                       "transno = "LPU64", handle = "LPX64"\n",
-                       inode->i_ino, file, req, req->rq_type,
-                       req->rq_transno, fd->fd_mds_och.och_fh.cookie);
-
+        /* Must do this outside lli_och_sem lock to prevent deadlock where
+           different kind of OPEN lock for this same inode gets cancelled
+           by ldlm_cancel_lru */
         if (!S_ISREG(inode->i_mode))
                 GOTO(out, rc);
 
@@ -357,10 +525,21 @@ int ll_file_open(struct inode *inode, struct file *file)
         file->f_flags &= ~O_LOV_DELAY_CREATE;
         GOTO(out, rc);
  out:
-        req = it->d.lustre.it_data;
         ptlrpc_req_finished(req);
-        if (rc == 0)
+        if (req)
+                it_clear_disposition(it, DISP_ENQ_OPEN_REF);
+        if (rc == 0) {
                 ll_open_complete(inode);
+        } else {
+out_och_free:
+                if (*och_p) {
+                        OBD_FREE(*och_p, sizeof (struct obd_client_handle));
+                        *och_p = NULL; /* OBD_FREE writes some magic there */
+                        (*och_usecount)--;
+                }
+                up(&lli->lli_och_sem);
+        }
+
         return rc;
 }
 
@@ -369,12 +548,15 @@ int ll_lsm_getattr(struct obd_export *exp, struct lov_stripe_md *lsm,
                    struct obdo *oa)
 {
         struct ptlrpc_request_set *set;
+        struct obd_info oinfo = { { { 0 } } };
         int rc;
         ENTRY;
 
         LASSERT(lsm != NULL);
 
         memset(oa, 0, sizeof *oa);
+        oinfo.oi_md = lsm;
+        oinfo.oi_oa = oa;
         oa->o_id = lsm->lsm_object_id;
         oa->o_mode = S_IFREG;
         oa->o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLSIZE |
@@ -385,7 +567,7 @@ int ll_lsm_getattr(struct obd_export *exp, struct lov_stripe_md *lsm,
         if (set == NULL) {
                 rc = -ENOMEM;
         } else {
-                rc = obd_getattr_async(exp, oa, lsm, set);
+                rc = obd_getattr_async(exp, &oinfo, set);
                 if (rc == 0)
                         rc = ptlrpc_set_wait(set);
                 ptlrpc_set_destroy(set);
@@ -476,6 +658,9 @@ void ll_pgcache_remove_extent(struct inode *inode, struct lov_stripe_md *lsm,
 
         /* our locks are page granular thanks to osc_enqueue, we invalidate the
          * whole page. */
+        if ((tmpex.l_extent.start & ~PAGE_CACHE_MASK) != 0 ||
+            ((tmpex.l_extent.end + 1) & ~PAGE_CACHE_MASK) != 0)
+                LDLM_ERROR(lock, "lock not aligned on PAGE_SIZE %lu",PAGE_SIZE);
         LASSERT((tmpex.l_extent.start & ~PAGE_CACHE_MASK) == 0);
         LASSERT(((tmpex.l_extent.end + 1) & ~PAGE_CACHE_MASK) == 0);
 
@@ -523,6 +708,7 @@ void ll_pgcache_remove_extent(struct inode *inode, struct lov_stripe_md *lsm,
          * batching writeback under the lock explicitly. */
         for (i = start, j = start % count; i <= end;
              j++, i++, tmpex.l_extent.start += PAGE_CACHE_SIZE) {
+                int l_flags;
                 if (j == count) {
                         CDEBUG(D_PAGE, "skip index %lu to %lu\n", i, i + skip);
                         i += skip;
@@ -560,14 +746,17 @@ void ll_pgcache_remove_extent(struct inode *inode, struct lov_stripe_md *lsm,
                         lock_page(page);
                 }
 
+                l_flags = LDLM_FL_BLOCK_GRANTED|LDLM_FL_CBPENDING |
+                          LDLM_FL_TEST_LOCK;
+
                 tmpex.l_extent.end = tmpex.l_extent.start + PAGE_CACHE_SIZE - 1;
                 /* check to see if another DLM lock covers this page */
-                rc2 = ldlm_lock_match(lock->l_resource->lr_namespace,
-                                      LDLM_FL_BLOCK_GRANTED|LDLM_FL_CBPENDING |
-                                      LDLM_FL_TEST_LOCK,
-                                      &lock->l_resource->lr_name, LDLM_EXTENT,
-                                      &tmpex, LCK_PR | LCK_PW, &lockh);
-                if (rc2 == 0 && page->mapping != NULL) {
+                rc2 = obd_match(ll_s2dtexp(inode->i_sb), lsm, LDLM_EXTENT,
+                                &tmpex, LCK_PR | LCK_PW, &l_flags, inode,
+                                &lockh);
+                /* rc2 < 0 means some error occured, e.g. export was down.
+                 * rc2 == 0 means nothing was matched */
+                if (rc2 <= 0 && page->mapping != NULL) {
                         struct ll_async_page *llap = llap_cast_private(page);
                         // checking again to account for writeback's lock_page()
                         LL_CDEBUG_PAGE(D_PAGE, page, "truncating\n");
@@ -634,8 +823,8 @@ static int ll_extent_lock_callback(struct ldlm_lock *lock,
 
                 ll_pgcache_remove_extent(inode, lsm, lock, stripe);
 
-                l_lock(&lock->l_resource->lr_namespace->ns_lock);
                 lov_stripe_lock(lsm);
+                lock_res_and_lock(lock);
                 kms = ldlm_extent_shift_kms(lock,
                                             lsm->lsm_oinfo[stripe].loi_kms);
 
@@ -643,8 +832,8 @@ static int ll_extent_lock_callback(struct ldlm_lock *lock,
                         LDLM_DEBUG(lock, "updating kms from "LPU64" to "LPU64,
                                    lsm->lsm_oinfo[stripe].loi_kms, kms);
                 lsm->lsm_oinfo[stripe].loi_kms = kms;
+                unlock_res_and_lock(lock);
                 lov_stripe_unlock(lsm);
-                l_unlock(&lock->l_resource->lr_namespace->ns_lock);
                 //ll_try_done_writing(inode);
         iput:
                 iput(inode);
@@ -690,16 +879,16 @@ int ll_async_completion_ast(struct ldlm_lock *lock, int flags, void *data)
                 lvb = lock->l_lvb_data;
                 lsm->lsm_oinfo[stripe].loi_rss = lvb->lvb_size;
 
-                l_lock(&lock->l_resource->lr_namespace->ns_lock);
                 LOCK_INODE_MUTEX(inode);
+                lock_res_and_lock(lock);
                 kms = MAX(lsm->lsm_oinfo[stripe].loi_kms, lvb->lvb_size);
                 kms = ldlm_extent_shift_kms(NULL, kms);
                 if (lsm->lsm_oinfo[stripe].loi_kms != kms)
                         LDLM_DEBUG(lock, "updating kms from "LPU64" to "LPU64,
                                    lsm->lsm_oinfo[stripe].loi_kms, kms);
                 lsm->lsm_oinfo[stripe].loi_kms = kms;
+                unlock_res_and_lock(lock);
                 UNLOCK_INODE_MUTEX(inode);
-                l_unlock(&lock->l_resource->lr_namespace->ns_lock);
         }
 
 iput:
@@ -719,7 +908,8 @@ static int ll_glimpse_callback(struct ldlm_lock *lock, void *reqp)
         struct ll_inode_info *lli;
         struct lov_stripe_md *lsm;
         struct ost_lvb *lvb;
-        int rc, size = sizeof(*lvb), stripe;
+        int rc, stripe;
+        int size[2] = { sizeof(struct ptlrpc_body), sizeof(*lvb) };
         ENTRY;
 
         if (inode == NULL)
@@ -736,13 +926,13 @@ static int ll_glimpse_callback(struct ldlm_lock *lock, void *reqp)
         if (stripe < 0)
                 GOTO(iput, rc = -ELDLM_NO_LOCK_DATA);
 
-        rc = lustre_pack_reply(req, 1, &size, NULL);
+        rc = lustre_pack_reply(req, 2, size, NULL);
         if (rc) {
                 CERROR("lustre_pack_reply: %d\n", rc);
                 GOTO(iput, rc);
         }
 
-        lvb = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*lvb));
+        lvb = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF, sizeof(*lvb));
         lvb->lvb_size = lli->lli_smd->lsm_oinfo[stripe].loi_kms;
         lvb->lvb_mtime = LTIME_S(inode->i_mtime);
         lvb->lvb_atime = LTIME_S(inode->i_atime);
@@ -752,7 +942,6 @@ static int ll_glimpse_callback(struct ldlm_lock *lock, void *reqp)
                    " atime "LPU64", mtime "LPU64", ctime "LPU64,
                    inode->i_size, stripe, lvb->lvb_size, lvb->lvb_mtime,
                    lvb->lvb_atime, lvb->lvb_ctime);
-        GOTO(iput, 0);
  iput:
         iput(inode);
 
@@ -760,27 +949,76 @@ static int ll_glimpse_callback(struct ldlm_lock *lock, void *reqp)
         /* These errors are normal races, so we don't want to fill the console
          * with messages by calling ptlrpc_error() */
         if (rc == -ELDLM_NO_LOCK_DATA)
-                lustre_pack_reply(req, 0, NULL, NULL);
+                lustre_pack_reply(req, 1, NULL, NULL);
 
         req->rq_status = rc;
         return rc;
 }
 
+int ll_glimpse_ioctl(struct ll_sb_info *sbi, struct lov_stripe_md *lsm,
+                     lstat_t *st)
+{
+        struct lustre_handle lockh = { 0 };
+        struct obd_enqueue_info einfo = { 0 };
+        struct obd_info oinfo = { { { 0 } } };
+        struct ost_lvb lvb;
+        int rc;
+        
+        ENTRY;
+        
+        einfo.ei_type = LDLM_EXTENT;
+        einfo.ei_mode = LCK_PR;
+        einfo.ei_flags = LDLM_FL_HAS_INTENT;
+        einfo.ei_cb_bl = ll_extent_lock_callback;
+        einfo.ei_cb_cp = ldlm_completion_ast;
+        einfo.ei_cb_gl = ll_glimpse_callback;
+        einfo.ei_cbdata = NULL;
+
+        oinfo.oi_policy.l_extent.end = OBD_OBJECT_EOF;
+        oinfo.oi_lockh = &lockh;
+        oinfo.oi_md = lsm;
+
+        rc = obd_enqueue_rqset(sbi->ll_dt_exp, &oinfo, &einfo);
+        if (rc == -ENOENT)
+                RETURN(rc);
+        if (rc != 0) {
+                CERROR("obd_enqueue returned rc %d, "
+                       "returning -EIO\n", rc);
+                RETURN(rc > 0 ? -EIO : rc);
+        }
+        
+        lov_stripe_lock(lsm);
+        memset(&lvb, 0, sizeof(lvb));
+        obd_merge_lvb(sbi->ll_dt_exp, lsm, &lvb, 0);
+        st->st_size = lvb.lvb_size;
+        st->st_blocks = lvb.lvb_blocks;
+        st->st_mtime = lvb.lvb_mtime;
+        st->st_atime = lvb.lvb_atime;
+        st->st_ctime = lvb.lvb_ctime;
+        lov_stripe_unlock(lsm);
+        
+        RETURN(rc);
+}
+
 /* NB: obd_merge_lvb will prefer locally cached writes if they extend the
  * file (because it prefers KMS over RSS when larger) */
 int ll_glimpse_size(struct inode *inode, int ast_flags)
 {
         struct ll_inode_info *lli = ll_i2info(inode);
         struct ll_sb_info *sbi = ll_i2sbi(inode);
-        ldlm_policy_data_t policy = { .l_extent = { 0, OBD_OBJECT_EOF } };
         struct lustre_handle lockh = { 0 };
+        struct obd_enqueue_info einfo = { 0 };
+        struct obd_info oinfo = { { { 0 } } };
         struct ost_lvb lvb;
         int rc;
         ENTRY;
 
         CDEBUG(D_DLMTRACE, "Glimpsing inode %lu\n", inode->i_ino);
 
-        ast_flags |= LDLM_FL_HAS_INTENT;
+        if (!lli->lli_smd) {
+                CDEBUG(D_DLMTRACE, "No objects for inode %lu\n", inode->i_ino);
+                RETURN(0);
+        }
 
         /* NOTE: this looks like DLM lock request, but it may not be one. Due
          *       to LDLM_FL_HAS_INTENT flag, this is glimpse request, that
@@ -789,10 +1027,19 @@ int ll_glimpse_size(struct inode *inode, int ast_flags)
          *       holding a DLM lock against this file, and resulting size
          *       will be returned for each stripe. DLM lock on [0, EOF] is
          *       acquired only if there were no conflicting locks. */
-        rc = obd_enqueue(sbi->ll_dt_exp, lli->lli_smd, LDLM_EXTENT, &policy,
-                         LCK_PR, &ast_flags, ll_extent_lock_callback,
-                         ldlm_completion_ast, ll_glimpse_callback, inode,
-                         sizeof(struct ost_lvb), lustre_swab_ost_lvb, &lockh);
+        einfo.ei_type = LDLM_EXTENT;
+        einfo.ei_mode = LCK_PR;
+        einfo.ei_flags = ast_flags | LDLM_FL_HAS_INTENT;
+        einfo.ei_cb_bl = ll_extent_lock_callback;
+        einfo.ei_cb_cp = ldlm_completion_ast;
+        einfo.ei_cb_gl = ll_glimpse_callback;
+        einfo.ei_cbdata = inode;
+
+        oinfo.oi_policy.l_extent.end = OBD_OBJECT_EOF;
+        oinfo.oi_lockh = &lockh;
+        oinfo.oi_md = lli->lli_smd;
+
+        rc = obd_enqueue_rqset(sbi->ll_dt_exp, &oinfo, &einfo);
         if (rc == -ENOENT)
                 RETURN(rc);
         if (rc != 0) {
@@ -813,8 +1060,6 @@ int ll_glimpse_size(struct inode *inode, int ast_flags)
         CDEBUG(D_DLMTRACE, "glimpse: size: %llu, blocks: %lu\n",
                inode->i_size, inode->i_blocks);
 
-        obd_cancel(sbi->ll_dt_exp, lli->lli_smd, LCK_PR, &lockh);
-
         RETURN(rc);
 }
 
@@ -825,6 +1070,8 @@ int ll_extent_lock(struct ll_file_data *fd, struct inode *inode,
 {
         struct ll_sb_info *sbi = ll_i2sbi(inode);
         struct ost_lvb lvb;
+        struct obd_enqueue_info einfo = { 0 };
+        struct obd_info oinfo = { { { 0 } } };
         int rc;
         ENTRY;
 
@@ -843,10 +1090,20 @@ int ll_extent_lock(struct ll_file_data *fd, struct inode *inode,
         CDEBUG(D_DLMTRACE, "Locking inode %lu, start "LPU64" end "LPU64"\n",
                inode->i_ino, policy->l_extent.start, policy->l_extent.end);
 
-        rc = obd_enqueue(sbi->ll_dt_exp, lsm, LDLM_EXTENT, policy, mode,
-                         &ast_flags, ll_extent_lock_callback,
-                         ldlm_completion_ast, ll_glimpse_callback, inode,
-                         sizeof(struct ost_lvb), lustre_swab_ost_lvb, lockh);
+        einfo.ei_type = LDLM_EXTENT;
+        einfo.ei_mode = mode;
+        einfo.ei_flags = ast_flags;
+        einfo.ei_cb_bl = ll_extent_lock_callback;
+        einfo.ei_cb_cp = ldlm_completion_ast;
+        einfo.ei_cb_gl = ll_glimpse_callback;
+        einfo.ei_cbdata = inode;
+
+        oinfo.oi_policy = *policy;
+        oinfo.oi_lockh = lockh;
+        oinfo.oi_md = lsm;
+
+        rc = obd_enqueue(sbi->ll_dt_exp, &oinfo, &einfo);
+        *policy = oinfo.oi_policy;
         if (rc > 0)
                 rc = -EIO;
 
@@ -903,12 +1160,15 @@ static ssize_t ll_file_read(struct file *file, char *buf, size_t count,
         struct inode *inode = file->f_dentry->d_inode;
         struct ll_inode_info *lli = ll_i2info(inode);
         struct lov_stripe_md *lsm = lli->lli_smd;
+        struct ll_sb_info *sbi = ll_i2sbi(inode);
         struct ll_lock_tree tree;
         struct ll_lock_tree_node *node;
         struct ost_lvb lvb;
         struct ll_ra_read bead;
-        int rc;
-        ssize_t retval;
+        int rc, ra = 0;
+        loff_t end;
+        ssize_t retval, chunk, sum = 0;
+
         __u64 kms;
         ENTRY;
         CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p),size="LPSZ",offset=%Ld\n",
@@ -948,12 +1208,29 @@ static ssize_t ll_file_read(struct file *file, char *buf, size_t count,
                 RETURN(count);
         }
 
-        node = ll_node_from_inode(inode, *ppos, *ppos + count - 1, LCK_PR);
+repeat:
+        if (sbi->ll_max_rw_chunk != 0) {
+                /* first, let's know the end of the current stripe */
+                end = *ppos;
+                obd_extent_calc(sbi->ll_dt_exp, lsm, OBD_CALC_STRIPE_END, &end);
+
+                /* correct, the end is beyond the request */
+                if (end > *ppos + count - 1)
+                        end = *ppos + count - 1;
+
+                /* and chunk shouldn't be too large even if striping is wide */
+                if (end - *ppos > sbi->ll_max_rw_chunk)
+                        end = *ppos + sbi->ll_max_rw_chunk - 1;
+        } else {
+                end = *ppos + count - 1;
+        }
+       
+        node = ll_node_from_inode(inode, *ppos, end, LCK_PR);
         tree.lt_fd = LUSTRE_FPRIVATE(file);
         rc = ll_tree_lock(&tree, node, buf, count,
                           file->f_flags & O_NONBLOCK ? LDLM_FL_BLOCK_NOWAIT :0);
         if (rc != 0)
-                RETURN(rc);
+                GOTO(out, retval = rc);
 
         ll_inode_size_lock(inode, 1);
         /*
@@ -991,8 +1268,9 @@ static ssize_t ll_file_read(struct file *file, char *buf, size_t count,
                 ll_inode_size_unlock(inode, 1);
         }
 
+        chunk = end - *ppos + 1;
         CDEBUG(D_INFO, "Read ino %lu, "LPSZ" bytes, offset %lld, i_size %llu\n",
-               inode->i_ino, count, *ppos, inode->i_size);
+               inode->i_ino, chunk, *ppos, inode->i_size);
 
         /* turn off the kernel's read-ahead */
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
@@ -1000,16 +1278,32 @@ static ssize_t ll_file_read(struct file *file, char *buf, size_t count,
 #else
         file->f_ra.ra_pages = 0;
 #endif
-        bead.lrr_start = *ppos >> CFS_PAGE_SHIFT;
-        bead.lrr_count = (count + CFS_PAGE_SIZE - 1) >> CFS_PAGE_SHIFT;
-        ll_ra_read_in(file, &bead);
+        /* initialize read-ahead window once per syscall */
+        if (ra == 0) {
+                ra = 1;
+                bead.lrr_start = *ppos >> CFS_PAGE_SHIFT;
+                bead.lrr_count = (count + CFS_PAGE_SIZE - 1) >> CFS_PAGE_SHIFT;
+                ll_ra_read_in(file, &bead);
+        }
+
         /* BUG: 5972 */
         file_accessed(file);
-        retval = generic_file_read(file, buf, count, ppos);
-        ll_ra_read_ex(file, &bead);
+        retval = generic_file_read(file, buf, chunk, ppos);
 
- out:
         ll_tree_unlock(&tree);
+
+        if (retval > 0) {
+                buf += retval;
+                count -= retval;
+                sum += retval;
+                if (retval == chunk && count > 0)
+                        goto repeat;
+        }
+
+ out:
+        if (ra != 0)
+                ll_ra_read_ex(file, &bead);
+        retval = (sum > 0) ? sum : retval;
         RETURN(retval);
 }
 
@@ -1020,10 +1314,13 @@ static ssize_t ll_file_write(struct file *file, const char *buf, size_t count,
                              loff_t *ppos)
 {
         struct inode *inode = file->f_dentry->d_inode;
+        struct ll_sb_info *sbi = ll_i2sbi(inode);
+        struct lov_stripe_md *lsm = ll_i2info(inode)->lli_smd;
         struct ll_lock_tree tree;
         struct ll_lock_tree_node *node;
         loff_t maxbytes = ll_file_maxbytes(inode);
-        ssize_t retval;
+        loff_t lock_start, lock_end, end;
+        ssize_t retval, chunk, sum = 0;
         int rc;
         ENTRY;
         CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p),size="LPSZ",offset=%Ld\n",
@@ -1043,43 +1340,78 @@ static ssize_t ll_file_write(struct file *file, const char *buf, size_t count,
 
         LASSERT(ll_i2info(inode)->lli_smd != NULL);
 
-        if (file->f_flags & O_APPEND)
-                node = ll_node_from_inode(inode, 0, OBD_OBJECT_EOF, LCK_PW);
-        else
-                node = ll_node_from_inode(inode, *ppos, *ppos  + count - 1,
-                                          LCK_PW);
+        down(&ll_i2info(inode)->lli_write_sem);
+
+repeat:
+        chunk = 0; /* just to fix gcc's warning */
+        end = *ppos + count - 1;
+
+        if (file->f_flags & O_APPEND) {
+                lock_start = 0;
+                lock_end = OBD_OBJECT_EOF;
+        } else if (sbi->ll_max_rw_chunk != 0) {
+                /* first, let's know the end of the current stripe */
+                end = *ppos;
+                obd_extent_calc(sbi->ll_dt_exp, lsm, OBD_CALC_STRIPE_END, &end);
+
+                /* correct, the end is beyond the request */
+                if (end > *ppos + count - 1)
+                        end = *ppos + count - 1;
+
+                /* and chunk shouldn't be too large even if striping is wide */
+                if (end - *ppos > sbi->ll_max_rw_chunk)
+                        end = *ppos + sbi->ll_max_rw_chunk - 1;
+                lock_start = *ppos;
+                lock_end = end;
+        } else {
+                lock_start = *ppos;
+                lock_end = *ppos + count - 1;
+        }
+        node = ll_node_from_inode(inode, lock_start, lock_end, LCK_PW);
 
         if (IS_ERR(node))
-                RETURN(PTR_ERR(node));
+                GOTO(out, retval = PTR_ERR(node));
 
         tree.lt_fd = LUSTRE_FPRIVATE(file);
         rc = ll_tree_lock(&tree, node, buf, count,
                           file->f_flags & O_NONBLOCK ? LDLM_FL_BLOCK_NOWAIT :0);
         if (rc != 0)
-                RETURN(rc);
+                GOTO(out, retval = rc);
 
         /* this is ok, g_f_w will overwrite this under i_mutex if it races
          * with a local truncate, it just makes our maxbyte checking easier */
-        if (file->f_flags & O_APPEND)
+        if (file->f_flags & O_APPEND) {
                 *ppos = inode->i_size;
+                end = *ppos + count - 1;
+        }
 
         if (*ppos >= maxbytes) {
-                if (count || *ppos > maxbytes) {
-                        send_sig(SIGXFSZ, current, 0);
-                        GOTO(out, retval = -EFBIG);
-                }
+                send_sig(SIGXFSZ, current, 0);
+                GOTO(out, retval = -EFBIG);
         }
         if (*ppos + count > maxbytes)
                 count = maxbytes - *ppos;
 
-        CDEBUG(D_INFO, "Writing inode %lu, "LPSZ" bytes, offset %Lu\n",
-               inode->i_ino, count, *ppos);
-
         /* generic_file_write handles O_APPEND after getting i_mutex */
-        retval = generic_file_write(file, buf, count, ppos);
+        chunk = end - *ppos + 1;
+        CDEBUG(D_INFO, "Writing inode %lu, "LPSZ" bytes, offset %Lu\n",
+               inode->i_ino, chunk, *ppos);
+        retval = generic_file_write(file, buf, chunk, ppos);
 
 out:
         ll_tree_unlock(&tree);
+
+        if (retval > 0) {
+                buf += retval;
+                count -= retval;
+                sum += retval;
+                if (retval == chunk && count > 0)
+                        goto repeat;
+        }
+
+        up(&ll_i2info(inode)->lli_write_sem);
+
+        retval = (sum > 0) ? sum : retval;
         lprocfs_counter_add(ll_i2sbi(inode)->ll_stats, LPROC_LL_WRITE_BYTES,
                             retval > 0 ? retval : 0);
         RETURN(retval);
@@ -1241,15 +1573,9 @@ static int ll_lov_setstripe_ea_info(struct inode *inode, struct file *file,
                                     int lum_size)
 {
         struct ll_inode_info *lli = ll_i2info(inode);
-        struct file *f = NULL;
-        struct obd_export *dt_exp = ll_i2dtexp(inode);
-        struct obd_export *md_exp = ll_i2mdexp(inode);
         struct lov_stripe_md *lsm;
         struct lookup_intent oit = {.it_op = IT_OPEN, .it_flags = flags};
-        struct ptlrpc_request *req = NULL;
-        struct ll_file_data *fd;
         int rc = 0;
-        struct lustre_md md;
         ENTRY;
 
         down(&lli->lli_open_sem);
@@ -1261,49 +1587,24 @@ static int ll_lov_setstripe_ea_info(struct inode *inode, struct file *file,
                 RETURN(-EEXIST);
         }
 
-        fd = ll_file_data_get();
-        if (fd == NULL)
-                GOTO(out, -ENOMEM);
-
-        f = get_empty_filp();
-        if (!f)
-                GOTO(out, -ENOMEM);
-
-        f->f_dentry = dget(file->f_dentry);
-        f->f_vfsmnt = mntget(file->f_vfsmnt);
-
-        rc = ll_intent_file_open(f, lum, lum_size, &oit);
+        rc = ll_intent_file_open(file, lum, lum_size, &oit);
         if (rc)
                 GOTO(out, rc);
         if (it_disposition(&oit, DISP_LOOKUP_NEG))
-                GOTO(out, -ENOENT);
-        req = oit.d.lustre.it_data;
+                GOTO(out_req_free, rc = -ENOENT);
         rc = oit.d.lustre.it_status;
-
         if (rc < 0)
-                GOTO(out, rc);
-
-        rc = md_get_lustre_md(md_exp, req, 1, dt_exp, &md);
-        if (rc)
-                GOTO(out, rc);
-        ll_update_inode(f->f_dentry->d_inode, &md);
-
-        rc = ll_local_open(f, &oit, fd);
-        if (rc)
-                GOTO(out, rc);
-        fd = NULL;
-        ll_intent_release(&oit);
+                GOTO(out_req_free, rc);
 
-        rc = ll_file_release(f->f_dentry->d_inode, f);
+        ll_release_openhandle(file->f_dentry, &oit);
 
  out:
-        if (f)
-                fput(f);
-        ll_file_data_put(fd);
         up(&lli->lli_open_sem);
-        if (req != NULL)
-                ptlrpc_req_finished(req);
+        ll_intent_release(&oit);
         RETURN(rc);
+out_req_free:
+        ptlrpc_req_finished((struct ptlrpc_request *) oit.d.lustre.it_data);
+        goto out;
 }
 
 static int ll_lov_setea(struct inode *inode, struct file *file,
@@ -1447,8 +1748,7 @@ static int join_sanity_check(struct inode *head, struct inode *tail)
                 RETURN(-EINVAL);
         }
         if (head->i_size % JOIN_FILE_ALIGN) {
-                CERROR("hsize" LPU64 " must be times of 64K\n",
-                        head->i_size);
+                CERROR("hsize %llu must be times of 64K\n", head->i_size);
                 RETURN(-EINVAL);
         }
         RETURN(0);
@@ -1461,13 +1761,10 @@ static int join_file(struct inode *head_inode, struct file *head_filp,
         struct dentry *tail_dentry = tail_filp->f_dentry;
         struct lookup_intent oit = {.it_op = IT_OPEN,
                                    .it_flags = head_filp->f_flags|O_JOIN_FILE};
-        struct ptlrpc_request *req = NULL;
-        struct ll_file_data *fd;
         struct lustre_handle lockh;
         struct md_op_data *op_data;
         __u32  hsize = head_inode->i_size >> 32;
         __u32  tsize = head_inode->i_size;
-        struct file *f;
         int    rc;
         ENTRY;
 
@@ -1475,23 +1772,11 @@ static int join_file(struct inode *head_inode, struct file *head_filp,
         tail_inode = tail_dentry->d_inode;
         tail_parent = tail_dentry->d_parent->d_inode;
 
-        fd = ll_file_data_get();
-        if (fd == NULL)
-                RETURN(-ENOMEM);
-
         OBD_ALLOC_PTR(op_data);
         if (op_data == NULL) {
-                ll_file_data_put(fd);
                 RETURN(-ENOMEM);
         }
 
-        f = get_empty_filp();
-        if (f == NULL)
-                GOTO(out, rc = -ENOMEM);
-
-        f->f_dentry = dget(head_filp->f_dentry);
-        f->f_vfsmnt = mntget(head_filp->f_vfsmnt);
-
         ll_prepare_md_op_data(op_data, head_inode, tail_parent,
                               tail_dentry->d_name.name,
                               tail_dentry->d_name.len, 0);
@@ -1503,26 +1788,24 @@ static int join_file(struct inode *head_inode, struct file *head_filp,
         if (rc < 0)
                 GOTO(out, rc);
 
-        req = oit.d.lustre.it_data;
         rc = oit.d.lustre.it_status;
 
-        if (rc < 0)
+        if (rc < 0) {
+                ptlrpc_req_finished((struct ptlrpc_request *)
+                                                          oit.d.lustre.it_data);
                 GOTO(out, rc);
+        }
 
-        rc = ll_local_open(f, &oit, fd);
-        LASSERTF(rc == 0, "rc = %d\n", rc);
-
-        fd = NULL;
-        ll_intent_release(&oit);
-
-        rc = ll_file_release(f->f_dentry->d_inode, f);
+        if (oit.d.lustre.it_lock_mode) { /* If we got lock - release it right
+                                           * away */
+                ldlm_lock_decref(&lockh, oit.d.lustre.it_lock_mode);
+                oit.d.lustre.it_lock_mode = 0;
+        }
+        ll_release_openhandle(head_filp->f_dentry, &oit);
 out:
         if (op_data)
                 OBD_FREE_PTR(op_data);
-        if (f)
-                fput(f);
-        ll_file_data_put(fd);
-        ptlrpc_req_finished(req);
+        ll_intent_release(&oit);
         RETURN(rc);
 }
 
@@ -1650,6 +1933,7 @@ int ll_release_openhandle(struct dentry *dentry, struct lookup_intent *it)
  out:
         /* this one is in place of ll_file_open */
         ptlrpc_req_finished(it->d.lustre.it_data);
+        it_clear_disposition(it, DISP_ENQ_OPEN_REF);
         RETURN(rc);
 }
 
@@ -1723,7 +2007,7 @@ int ll_file_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                 RETURN(ll_get_grouplock(inode, file, arg));
         case LL_IOC_GROUP_UNLOCK:
                 RETURN(ll_put_grouplock(inode, file, arg));
-        case LL_IOC_OBD_STATFS:
+        case IOC_OBD_STATFS:
                 RETURN(ll_obd_statfs(inode, (void *)arg));
 
         /* We need to special case any other ioctls we want to handle,
@@ -1847,7 +2131,6 @@ int ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock)
 {
         struct inode *inode = file->f_dentry->d_inode;
         struct ll_sb_info *sbi = ll_i2sbi(inode);
-        struct obd_device *obddev;
         struct ldlm_res_id res_id =
                 { .name = { fid_seq(ll_inode2fid(inode)),
                             fid_oid(ll_inode2fid(inode)),
@@ -1921,11 +2204,10 @@ int ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock)
                "start="LPU64", end="LPU64"\n", inode->i_ino, flock.l_flock.pid,
                flags, mode, flock.l_flock.start, flock.l_flock.end);
 
-        obddev = sbi->ll_md_exp->exp_obd;
-        rc = ldlm_cli_enqueue(sbi->ll_md_exp, NULL, obddev->obd_namespace,
-                              res_id, LDLM_FLOCK, &flock, mode, &flags,
-                              NULL, ldlm_flock_completion_ast, NULL, file_lock,
-                              NULL, 0, NULL, &lockh);
+        rc = ldlm_cli_enqueue(sbi->ll_md_exp, NULL, res_id, 
+                              LDLM_FLOCK, &flock, mode, &flags, NULL, 
+                              ldlm_flock_completion_ast, NULL, file_lock,
+                              NULL, 0, NULL, &lockh, 0);
         RETURN(rc);
 }
 
@@ -1945,21 +2227,41 @@ int ll_have_md_lock(struct inode *inode, __u64 bits)
 
         flags = LDLM_FL_BLOCK_GRANTED | LDLM_FL_CBPENDING | LDLM_FL_TEST_LOCK;
         if (md_lock_match(ll_i2mdexp(inode), flags, fid, LDLM_IBITS, &policy, 
-                                LCK_CR|LCK_CW|LCK_PR, &lockh)) {
+                          LCK_CR|LCK_CW|LCK_PR, &lockh)) {
                 RETURN(1);
         }
 
         RETURN(0);
 }
 
+static int ll_inode_revalidate_fini(struct inode *inode, int rc) {
+        if (rc == -ENOENT) { /* Already unlinked. Just update nlink
+                              * and return success */
+                inode->i_nlink = 0;
+                /* This path cannot be hit for regular files unless in
+                 * case of obscure races, so no need to to validate
+                 * size. */
+                if (!S_ISREG(inode->i_mode) &&
+                    !S_ISDIR(inode->i_mode))
+                        return 0;
+        }
+
+        if (rc) {
+                CERROR("failure %d inode %lu\n", rc, inode->i_ino);
+                return -abs(rc);
+
+        }
+
+        return 0;
+}
+
 int ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it)
 {
-        struct lookup_intent oit = { .it_op = IT_GETATTR };
         struct inode *inode = dentry->d_inode;
         struct ptlrpc_request *req = NULL;
-        struct md_op_data *op_data;
         struct ll_inode_info *lli;
         struct ll_sb_info *sbi;
+        struct obd_export *exp;
         int rc;
         ENTRY;
 
@@ -1976,42 +2278,82 @@ int ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it)
         lprocfs_counter_incr(ll_i2sbi(inode)->ll_stats, LPROC_LL_REVALIDATE);
 #endif
 
-        OBD_ALLOC_PTR(op_data);
-        if (op_data == NULL)
-                RETURN(-ENOMEM);
+        exp = ll_i2mdexp(inode);
 
-        ll_prepare_md_op_data(op_data, inode, inode, NULL, 0, 0);
+        if (exp->exp_connect_flags & OBD_CONNECT_ATTRFID) {
+                struct lookup_intent oit = { .it_op = IT_GETATTR };
+                struct md_op_data *op_data;
 
-        rc = md_intent_lock(sbi->ll_md_exp, op_data, NULL, 0, &oit, 0,
-                            &req, ll_md_blocking_ast, 0);
-        OBD_FREE_PTR(op_data);
+                OBD_ALLOC_PTR(op_data);
+                if (op_data == NULL)
+                        RETURN(-ENOMEM);
 
-        if (rc < 0)
-                GOTO(out, rc);
+                /* Call getattr by fid, so do not provide name at all. */
+                ll_prepare_md_op_data(op_data, dentry->d_parent->d_inode,
+                                      dentry->d_inode, NULL, 0, 0);
+                rc = md_intent_lock(exp, op_data, NULL, 0,
+                                    /* we are not interested in name
+                                       based lookup */
+                                    &oit, 0, &req,
+                                    ll_md_blocking_ast, 0);
+                OBD_FREE_PTR(op_data);
+                if (rc < 0) {
+                        rc = ll_inode_revalidate_fini(inode, rc);
+                        GOTO (out, rc);
+                }
+                
+                rc = ll_revalidate_it_finish(req, DLM_REPLY_REC_OFF, &oit, dentry);
+                if (rc != 0) {
+                        ll_intent_release(&oit);
+                        GOTO(out, rc);
+                }
 
-        rc = ll_revalidate_it_finish(req, 1, &oit, dentry);
-        if (rc)
-                GOTO(out, rc);
-        
-        if (!dentry->d_inode->i_nlink) {
-                spin_lock(&dcache_lock);
-                ll_drop_dentry(dentry);
-                spin_unlock(&dcache_lock);
+                /* Unlinked? Unhash dentry, so it is not picked up later by
+                   do_lookup() -> ll_revalidate_it(). We cannot use d_drop
+                   here to preserve get_cwd functionality on 2.6.
+                   Bug 10503 */
+                if (!dentry->d_inode->i_nlink) {
+                        spin_lock(&dcache_lock);
+                        ll_drop_dentry(dentry);
+                        spin_unlock(&dcache_lock);
+                }
+
+                ll_lookup_finish_locks(&oit, dentry);
+        } else if (!ll_have_md_lock(dentry->d_inode,
+                                    MDS_INODELOCK_UPDATE|MDS_INODELOCK_LOOKUP)) {
+                struct ll_sb_info *sbi = ll_i2sbi(dentry->d_inode);
+                obd_valid valid = OBD_MD_FLGETATTR;
+                int ealen = 0;
+
+                if (S_ISREG(inode->i_mode)) {
+                        rc = ll_get_max_mdsize(sbi, &ealen);
+                        if (rc) 
+                                RETURN(rc); 
+                        valid |= OBD_MD_FLEASIZE | OBD_MD_FLMODEASIZE;
+                }
+                rc = md_getattr(sbi->ll_md_exp, ll_inode2fid(inode), valid, ealen, &req);
+                if (rc) {
+                        rc = ll_inode_revalidate_fini(inode, rc);
+                        RETURN(rc);
+                }
+
+                rc = ll_prep_inode(&inode, req, REPLY_REC_OFF,
+                                   NULL);
+                if (rc)
+                        GOTO(out, rc);
         }
         
-        ll_lookup_finish_locks(&oit, dentry);
+        /* if object not yet allocated, don't validate size */
+        if (ll_i2info(inode)->lli_smd == NULL) 
+                GOTO(out, rc = 0);
+
+        /* ll_glimpse_size will prefer locally cached writes if they extend
+         * the file */
+        rc = ll_glimpse_size(inode, 0);
 
-        /* object is allocated, validate size */
-        if (lli->lli_smd) {
-                /* ll_glimpse_size will prefer locally cached writes if they
-                 * extend the file */
-                rc = ll_glimpse_size(inode, 0);
-        }
-        EXIT;
 out:
-        if (req)
-                ptlrpc_req_finished(req);
-        return rc;
+        ptlrpc_req_finished(req);
+        RETURN(rc);
 }
 
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
@@ -2168,11 +2510,13 @@ struct file_operations ll_file_operations_flock = {
 
 
 struct inode_operations ll_file_inode_operations = {
+#ifdef LUSTRE_KERNEL_VERSION
         .setattr_raw    = ll_setattr_raw,
+#endif
         .setattr        = ll_setattr,
         .truncate       = ll_truncate,
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
-        .getattr_it     = ll_getattr_it,
+        .getattr        = ll_getattr,
 #else
         .revalidate_it  = ll_inode_revalidate_it,
 #endif
index 92a1927..49f4cd4 100644 (file)
@@ -5,25 +5,39 @@
 #ifndef LLITE_INTERNAL_H
 #define LLITE_INTERNAL_H
 
+# include <linux/lustre_acl.h>
+
 #ifdef CONFIG_FS_POSIX_ACL
 # include <linux/fs.h>
+#ifdef HAVE_XATTR_ACL
 # include <linux/xattr_acl.h>
 #endif
-#include <linux/lustre_version.h>
+#ifdef HAVE_LINUX_POSIX_ACL_XATTR_H
+# include <linux/posix_acl_xattr.h>
+#endif
+#endif
 
 #include <lustre_debug.h>
 #include <lustre_ver.h>
 #include <lustre_disk.h>  /* for s2sbi */
 
-#define LL_IT2STR(it) ((it) ? ldlm_it2str((it)->it_op) : "0")
+/* If there is no FMODE_EXEC defined, make it to match nothing */
+#ifndef FMODE_EXEC
+#define FMODE_EXEC 0
+#endif
 
+#define LL_IT2STR(it) ((it) ? ldlm_it2str((it)->it_op) : "0")
+#if !defined(LUSTRE_KERNEL_VERSION) || (LUSTRE_KERNEL_VERSION < 46)
+#define LUSTRE_FPRIVATE(file) ((file)->private_data)
+#else
 #if (LUSTRE_KERNEL_VERSION < 46)
 #define LUSTRE_FPRIVATE(file) ((file)->private_data)
 #else
 #define LUSTRE_FPRIVATE(file) ((file)->fs_private)
 #endif
+#endif
 
-
+#ifdef LUSTRE_KERNEL_VERSION
 static inline struct lookup_intent *ll_nd2it(struct nameidata *nd)
 {
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
@@ -32,12 +46,16 @@ static inline struct lookup_intent *ll_nd2it(struct nameidata *nd)
         return nd->intent;
 #endif
 }
+#endif
 
 struct ll_dentry_data {
         int                      lld_cwd_count;
         int                      lld_mnt_count;
         struct obd_client_handle lld_cwd_och;
         struct obd_client_handle lld_mnt_och;
+#ifndef LUSTRE_KERNEL_VERSION
+        struct lookup_intent     *lld_it;
+#endif
 };
 
 #define ll_d2d(de) ((struct ll_dentry_data*) de->d_fsdata)
@@ -54,6 +72,7 @@ struct ll_inode_info {
         struct semaphore        lli_size_sem;
         void                   *lli_size_sem_owner;
         struct semaphore        lli_open_sem;
+        struct semaphore        lli_write_sem;
         char                   *lli_symlink_name;
         __u64                   lli_maxbytes;
         __u64                   lli_io_epoch;
@@ -74,11 +93,22 @@ struct ll_inode_info {
 
         struct list_head        lli_dead_list;
 
+        struct semaphore        lli_och_sem; /* Protects access to och pointers
+                                                and their usage counters */
+        /* We need all three because every inode may be opened in different
+           modes */
+        struct obd_client_handle *lli_mds_read_och;
+        __u64                   lli_open_fd_read_count;
+        struct obd_client_handle *lli_mds_write_och;
+        __u64                   lli_open_fd_write_count;
+        struct obd_client_handle *lli_mds_exec_och;
+        __u64                   lli_open_fd_exec_count;
+
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
         struct inode            lli_vfs_inode;
 #endif
 
-        /* indexing fields for both metadata and data stacks. */
+        /* identifying fields for both metadata and data stacks. */
         struct lu_fid           lli_fid;
         struct lov_stripe_md   *lli_smd;
 };
@@ -174,8 +204,13 @@ struct ll_sb_info {
 
         struct list_head          ll_deathrow; /* inodes to be destroyed (b1443) */
         spinlock_t                ll_deathrow_lock;
+        /* =0 - hold lock over whole read/write
+         * >0 - max. chunk to be read/written w/o lock re-acquiring */
+        unsigned long             ll_max_rw_chunk;
 };
 
+#define LL_DEFAULT_MAX_RW_CHUNK         (32 * 1024 * 1024)
+
 struct ll_ra_read {
         pgoff_t             lrr_start;
         pgoff_t             lrr_count;
@@ -256,12 +291,12 @@ struct ll_file_dir {
 extern kmem_cache_t *ll_file_data_slab;
 struct lustre_handle;
 struct ll_file_data {
-        struct obd_client_handle fd_mds_och;
         struct ll_readahead_state fd_ras;
-        __u32 fd_flags;
+        int fd_omode;
         struct lustre_handle fd_cwlockh;
         unsigned long fd_gid;
         struct ll_file_dir fd_dir;
+        __u32 fd_flags;
 };
 
 struct lov_stripe_md;
@@ -360,13 +395,19 @@ int ll_md_blocking_ast(struct ldlm_lock *, struct ldlm_lock_desc *,
 void ll_prepare_md_op_data(struct md_op_data *op_data, struct inode *i1,
                            struct inode *i2, const char *name, int namelen,
                            int mode);
+int ll_md_cancel_unused(struct lustre_handle *, struct inode *, int flags,
+                        void *opaque);
+#ifndef LUSTRE_KERNEL_VERSION
+struct lookup_intent *ll_convert_intent(struct open_intent *oit,
+                                        int lookup_flags);
+#endif
 
 /* llite/rw.c */
 int ll_prepare_write(struct file *, struct page *, unsigned from, unsigned to);
 int ll_commit_write(struct file *, struct page *, unsigned from, unsigned to);
 int ll_writepage(struct page *page);
 void ll_inode_fill_obdo(struct inode *inode, int cmd, struct obdo *oa);
-void ll_ap_completion(void *data, int cmd, struct obdo *oa, int rc);
+int ll_ap_completion(void *data, int cmd, struct obdo *oa, int rc);
 int llap_shrink_cache(struct ll_sb_info *sbi, int shrink_fraction);
 extern struct cache_definition ll_cache_definition;
 void ll_removepage(struct page *page);
@@ -391,12 +432,16 @@ int ll_extent_unlock(struct ll_file_data *, struct inode *,
 int ll_file_open(struct inode *inode, struct file *file);
 int ll_file_release(struct inode *inode, struct file *file);
 int ll_lsm_getattr(struct obd_export *, struct lov_stripe_md *, struct obdo *);
+int ll_glimpse_ioctl(struct ll_sb_info *sbi, 
+                     struct lov_stripe_md *lsm, lstat_t *st);
 int ll_glimpse_size(struct inode *inode, int ast_flags);
 int ll_local_open(struct file *file,
-                  struct lookup_intent *it, struct ll_file_data *fd);
+                  struct lookup_intent *it, struct ll_file_data *fd,
+                  struct obd_client_handle *och);
 int ll_release_openhandle(struct dentry *, struct lookup_intent *);
 int ll_md_close(struct obd_export *md_exp, struct inode *inode,
                 struct file *file);
+int ll_md_real_close(struct inode *inode, int flags);
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
 int ll_getattr_it(struct vfsmount *mnt, struct dentry *de,
                struct lookup_intent *it, struct kstat *stat);
@@ -414,6 +459,7 @@ void ll_intent_drop_lock(struct lookup_intent *);
 void ll_intent_release(struct lookup_intent *);
 int ll_drop_dentry(struct dentry *dentry);
 extern void ll_set_dd(struct dentry *de);
+int ll_drop_dentry(struct dentry *dentry);
 void ll_unhash_aliases(struct inode *);
 void ll_frob_intent(struct lookup_intent **itp, struct lookup_intent *deft);
 void ll_lookup_finish_locks(struct lookup_intent *it, struct dentry *dentry);
@@ -422,11 +468,9 @@ int ll_revalidate_it_finish(struct ptlrpc_request *request, int offset,
                             struct lookup_intent *it, struct dentry *de);
 
 /* llite/llite_lib.c */
-
 extern struct super_operations lustre_super_operations;
 
 char *ll_read_opt(const char *opt, char *data);
-void ll_options(char *options, int *flags);
 void ll_lli_init(struct ll_inode_info *lli);
 int ll_fill_super(struct super_block *sb);
 void ll_put_super(struct super_block *sb);
@@ -436,7 +480,7 @@ int ll_setattr_raw(struct inode *inode, struct iattr *attr);
 int ll_setattr(struct dentry *de, struct iattr *attr);
 int ll_statfs(struct super_block *sb, struct kstatfs *sfs);
 int ll_statfs_internal(struct super_block *sb, struct obd_statfs *osfs,
-                       unsigned long maxage);
+                       __u64 max_age);
 void ll_update_inode(struct inode *inode, struct lustre_md *md);
 void ll_read_inode2(struct inode *inode, void *opaque);
 void ll_delete_inode(struct inode *inode);
@@ -452,6 +496,7 @@ struct ll_async_page *llite_pglist_next_llap(struct ll_sb_info *sbi,
                                              struct list_head *list);
 int ll_obd_statfs(struct inode *inode, void *arg);
 int ll_get_max_mdsize(struct ll_sb_info *sbi, int *max_mdsize);
+int ll_process_config(struct lustre_cfg *lcfg);
 
 /* llite/llite_nfs.c */
 extern struct export_operations lustre_export_operations;
index 275c3e0..c1768f3 100644 (file)
@@ -33,6 +33,8 @@
 #include <lustre_dlm.h>
 #include <lprocfs_status.h>
 #include <lustre_disk.h>
+#include <lustre_param.h>
+#include <lustre_log.h>
 #include "llite_internal.h"
 
 kmem_cache_t *ll_file_data_slab;
@@ -48,7 +50,7 @@ extern struct address_space_operations ll_dir_aops;
 #endif
 
 
-struct ll_sb_info *ll_init_sbi(void)
+static struct ll_sb_info *ll_init_sbi(void)
 {
         struct ll_sb_info *sbi = NULL;
         class_uuid_t uuid;
@@ -102,7 +104,9 @@ void ll_free_sbi(struct super_block *sb)
 }
 
 static struct dentry_operations ll_d_root_ops = {
+#ifdef LUSTRE_KERNEL_VERSION
         .d_compare = ll_dcompare,
+#endif
 };
 
 /* Initialize the default and maximum LOV EA and cookie sizes.  This allows
@@ -171,24 +175,22 @@ int client_common_fill_super(struct super_block *sb, char *mdc, char *osc)
                         CERROR("could not register mount in /proc/lustre");
         }
 
-        /* indicate that inodebits locking is supported by this client */
-        data->ocd_connect_flags |= OBD_CONNECT_IBITS | OBD_CONNECT_NODEVOH;
+        /* indicate the features supported by this client */
+        data->ocd_connect_flags = OBD_CONNECT_IBITS | OBD_CONNECT_NODEVOH |
+                                  OBD_CONNECT_ACL | OBD_CONNECT_JOIN |
+                                  OBD_CONNECT_ATTRFID | OBD_CONNECT_VERSION;
         data->ocd_ibits_known = MDS_INODELOCK_FULL;
+        data->ocd_version = LUSTRE_VERSION_CODE;
 
         if (sb->s_flags & MS_RDONLY)
                 data->ocd_connect_flags |= OBD_CONNECT_RDONLY;
         if (sbi->ll_flags & LL_SBI_USER_XATTR)
                 data->ocd_connect_flags |= OBD_CONNECT_XATTR;
-        data->ocd_connect_flags |= OBD_CONNECT_ACL | OBD_CONNECT_JOIN;
 
-        if (sbi->ll_flags & LL_SBI_FLOCK) {
+        if (sbi->ll_flags & LL_SBI_FLOCK)
                 sbi->ll_fop = &ll_file_operations_flock;
-        } else {
+        else
                 sbi->ll_fop = &ll_file_operations;
-        }
-
-        data->ocd_connect_flags |= OBD_CONNECT_VERSION;
-        data->ocd_version = LUSTRE_VERSION_CODE;
 
         /* real client */
         data->ocd_connect_flags |= OBD_CONNECT_REAL;
@@ -205,7 +207,7 @@ int client_common_fill_super(struct super_block *sb, char *mdc, char *osc)
         }
         sbi->ll_md_exp = class_conn2export(&md_conn);
 
-        err = obd_statfs(obd, &osfs, jiffies - HZ);
+        err = obd_statfs(obd, &osfs, cfs_time_current_64() - HZ);
         if (err)
                 GOTO(out_mdc, err);
 
@@ -215,6 +217,7 @@ int client_common_fill_super(struct super_block *sb, char *mdc, char *osc)
         sb->s_magic = LL_SUPER_MAGIC;
         sb->s_maxbytes = PAGE_CACHE_MAXBYTES;
         sbi->ll_namelen = osfs.os_namelen;
+        sbi->ll_max_rw_chunk = LL_DEFAULT_MAX_RW_CHUNK;
 
         if ((sbi->ll_flags & LL_SBI_USER_XATTR) &&
             !(data->ocd_connect_flags & OBD_CONNECT_XATTR)) {
@@ -257,8 +260,8 @@ int client_common_fill_super(struct super_block *sb, char *mdc, char *osc)
                 GOTO(out_md_fid, err = -ENODEV);
         }
 
-        data->ocd_connect_flags =
-                OBD_CONNECT_GRANT | OBD_CONNECT_VERSION | OBD_CONNECT_REQPORTAL;
+        data->ocd_connect_flags = OBD_CONNECT_GRANT | OBD_CONNECT_VERSION |
+                                  OBD_CONNECT_REQPORTAL | OBD_CONNECT_BRW_SIZE;
 
         CDEBUG(D_RPCTRACE, "ocd_connect_flags: "LPX64" ocd_version: %d "
                "ocd_grant: %d\n", data->ocd_connect_flags,
@@ -266,6 +269,8 @@ int client_common_fill_super(struct super_block *sb, char *mdc, char *osc)
 
         obd->obd_upcall.onu_owner = &sbi->ll_lco;
         obd->obd_upcall.onu_upcall = ll_ocd_update;
+        data->ocd_brw_size = PTLRPC_MAX_BRW_PAGES << PAGE_SHIFT;
+
 
         err = obd_connect(NULL, &osc_conn, obd, &sbi->ll_sb_uuid, data);
         if (err == -EBUSY) {
@@ -336,7 +341,8 @@ int client_common_fill_super(struct super_block *sb, char *mdc, char *osc)
                 GOTO(out_osc, err);
         }
 
-        err = md_get_lustre_md(sbi->ll_md_exp, request, 0, sbi->ll_dt_exp, &md);
+        err = md_get_lustre_md(sbi->ll_md_exp, request, 
+                               REPLY_REC_OFF, sbi->ll_dt_exp, &md);
         if (err) {
                 CERROR("failed to understand root inode md: rc = %d\n", err);
                 ptlrpc_req_finished (request);
@@ -381,10 +387,12 @@ out_dt_fid:
         obd_fid_fini(sbi->ll_dt_exp);
 out_osc:
         obd_disconnect(sbi->ll_dt_exp);
+        sbi->ll_dt_exp = NULL;
 out_md_fid:
         obd_fid_fini(sbi->ll_md_exp);
 out_mdc:
         obd_disconnect(sbi->ll_md_exp);
+        sbi->ll_md_exp = NULL;
 out:
         if (data != NULL)
                 OBD_FREE_PTR(data);
@@ -470,43 +478,97 @@ void lustre_throw_orphan_dentries(struct super_block *sb)
 #define lustre_throw_orphan_dentries(sb)
 #endif
 
-static void prune_deathrow(struct ll_sb_info *sbi, int try)
+static void prune_dir_dentries(struct inode *inode)
 {
-        LIST_HEAD(throw_away);
-        int locked = 0;
-        ENTRY;
-
-        if (try) {
-                locked = spin_trylock(&sbi->ll_deathrow_lock);
-        } else {
-                spin_lock(&sbi->ll_deathrow_lock);
-                locked = 1;
+        struct dentry *dentry, *prev = NULL;
+
+        /* due to lustre specific logic, a directory
+         * can have few dentries - a bug from VFS POV */
+restart:
+        spin_lock(&dcache_lock);
+        if (!list_empty(&inode->i_dentry)) {
+                dentry = list_entry(inode->i_dentry.prev,
+                                    struct dentry, d_alias);
+                /* in order to prevent infinite loops we
+                 * break if previous dentry is busy */
+                if (dentry != prev) {
+                        prev = dentry;
+                        dget_locked(dentry);
+                        spin_unlock(&dcache_lock);
+
+                        /* try to kill all child dentries */
+                        lock_dentry(dentry);
+                        shrink_dcache_parent(dentry);
+                        unlock_dentry(dentry);
+                        dput(dentry);
+
+                        /* now try to get rid of current dentry */
+                        d_prune_aliases(inode);
+                        goto restart;
+                }
         }
+        spin_unlock(&dcache_lock);
+}
 
-        if (!locked) {
-                EXIT;
-                return;
-        }
+static void prune_deathrow_one(struct ll_inode_info *lli)
+{
+        struct inode *inode = ll_info2i(lli);
 
-        list_splice_init(&sbi->ll_deathrow, &throw_away);
-        spin_unlock(&sbi->ll_deathrow_lock);
+        /* first, try to drop any dentries - they hold a ref on the inode */
+        if (S_ISDIR(inode->i_mode))
+                prune_dir_dentries(inode);
+        else
+                d_prune_aliases(inode);
 
-        while (!list_empty(&throw_away)) {
-                struct ll_inode_info *lli;
-                struct inode *inode;
 
-                lli = list_entry(throw_away.next, struct ll_inode_info,
-                                 lli_dead_list);
-                list_del_init(&lli->lli_dead_list);
+        /* if somebody still uses it, leave it */
+        LASSERT(atomic_read(&inode->i_count) > 0);
+        if (atomic_read(&inode->i_count) > 1)
+                goto out;
 
-                inode = ll_info2i(lli);
-                d_prune_aliases(inode);
+        CDEBUG(D_INODE, "inode %lu/%u(%d) looks a good candidate for prune\n",
+               inode->i_ino,inode->i_generation, atomic_read(&inode->i_count));
 
-                CDEBUG(D_INODE, "prune duplicate inode %p inum %lu count %u\n",
-                       inode, inode->i_ino, atomic_read(&inode->i_count));
-                iput(inode);
-        }
-        EXIT;
+        /* seems nobody uses it anymore */
+        inode->i_nlink = 0;
+
+out:
+        iput(inode);
+        return;
+}
+
+static void prune_deathrow(struct ll_sb_info *sbi, int try)
+{
+        struct ll_inode_info *lli;
+        int empty;
+
+        do {
+                if (need_resched() && try)
+                        break;
+
+                if (try) {
+                        if (!spin_trylock(&sbi->ll_deathrow_lock))
+                                break;
+                } else {
+                        spin_lock(&sbi->ll_deathrow_lock);
+                }
+
+                empty = 1;
+                lli = NULL;
+                if (!list_empty(&sbi->ll_deathrow)) {
+                        lli = list_entry(sbi->ll_deathrow.next,
+                                         struct ll_inode_info,
+                                         lli_dead_list);
+                        list_del_init(&lli->lli_dead_list);
+                        if (!list_empty(&sbi->ll_deathrow))
+                                empty = 0;
+                }
+                spin_unlock(&sbi->ll_deathrow_lock);
+
+                if (lli)
+                        prune_deathrow_one(lli);
+
+        } while (empty == 0);
 }
 
 void client_common_put_super(struct super_block *sb)
@@ -522,15 +584,13 @@ void client_common_put_super(struct super_block *sb)
         list_del(&sbi->ll_conn_chain);
         ll_fid_dt_fini(sbi);
         obd_disconnect(sbi->ll_dt_exp);
+        sbi->ll_dt_exp = NULL;
 
         lprocfs_unregister_mountpoint(sbi);
-        if (sbi->ll_proc_root) {
-                lprocfs_remove(sbi->ll_proc_root);
-                sbi->ll_proc_root = NULL;
-        }
 
         ll_fid_md_fini(sbi);
         obd_disconnect(sbi->ll_md_exp);
+        sbi->ll_md_exp = NULL;
 
         lustre_throw_orphan_dentries(sb);
         EXIT;
@@ -569,16 +629,14 @@ static inline int ll_set_opt(const char *opt, char *data, int fl)
 }
 
 /* non-client-specific mount options are parsed in lmd_parse */
-void ll_options(char *options, int *flags)
+static int ll_options(char *options, int *flags)
 {
         int tmp;
         char *s1 = options, *s2;
         ENTRY;
 
-        if (!options) {
-                EXIT;
-                return;
-        }
+        if (!options) 
+                RETURN(0);
 
         CDEBUG(D_CONFIG, "Parsing opts %s\n", options);
 
@@ -621,6 +679,9 @@ void ll_options(char *options, int *flags)
                         goto next;
                 }
 
+                LCONSOLE_ERROR("Unknown option '%s', won't mount.\n", s1);
+                RETURN(-EINVAL);
+
 next:
                 /* Find next opt */
                 s2 = strchr(s1, ',');
@@ -628,28 +689,209 @@ next:
                         break;
                 s1 = s2 + 1;
         }
-        EXIT;
+        RETURN(0);
 }
 
 void ll_lli_init(struct ll_inode_info *lli)
 {
         sema_init(&lli->lli_open_sem, 1);
         sema_init(&lli->lli_size_sem, 1);
+        sema_init(&lli->lli_write_sem, 1);
         lli->lli_flags = 0;
         lli->lli_maxbytes = PAGE_CACHE_MAXBYTES;
         spin_lock_init(&lli->lli_lock);
         INIT_LIST_HEAD(&lli->lli_pending_write_llaps);
         lli->lli_inode_magic = LLI_INODE_MAGIC;
+        sema_init(&lli->lli_och_sem, 1);
+        lli->lli_mds_read_och = lli->lli_mds_write_och = NULL;
+        lli->lli_mds_exec_och = NULL;
+        lli->lli_open_fd_read_count = lli->lli_open_fd_write_count = 0;
+        lli->lli_open_fd_exec_count = 0;
         INIT_LIST_HEAD(&lli->lli_dead_list);
 }
 
+/* COMPAT_146 */
+#define MDCDEV "mdc_dev"
+static int old_lustre_process_log(struct super_block *sb, char *newprofile,
+                                  struct config_llog_instance *cfg)
+{
+        struct lustre_sb_info *lsi = s2lsi(sb);
+        struct obd_device *obd;
+        struct lustre_handle mdc_conn = {0, };
+        struct obd_export *exp;
+        char *ptr, *mdt, *profile;
+        char niduuid[10] = "mdtnid0";
+        class_uuid_t uuid;
+        struct obd_uuid mdc_uuid;
+        struct llog_ctxt *ctxt;
+        struct obd_connect_data ocd = { 0 };
+        lnet_nid_t nid;
+        int i, rc = 0, recov_bk = 1, failnodes = 0;
+        ENTRY;
+
+        class_generate_random_uuid(uuid);
+        class_uuid_unparse(uuid, &mdc_uuid);
+        CDEBUG(D_HA, "generated uuid: %s\n", mdc_uuid.uuid);
+        
+        /* Figure out the old mdt and profile name from new-style profile
+           ("lustre" from "mds/lustre-client") */
+        mdt = newprofile;
+        profile = strchr(mdt, '/');
+        if (profile == NULL) {
+                CDEBUG(D_CONFIG, "Can't find MDT name in %s\n", newprofile);
+                GOTO(out, rc = -EINVAL);
+        }
+        *profile = '\0';
+        profile++;
+        ptr = strrchr(profile, '-');
+        if (ptr == NULL) {
+                CDEBUG(D_CONFIG, "Can't find client name in %s\n", newprofile);
+                GOTO(out, rc = -EINVAL);
+        }
+        *ptr = '\0';
+
+        LCONSOLE_WARN("This looks like an old mount command; I will try to "
+                      "contact MDT '%s' for profile '%s'\n", mdt, profile);
+
+        /* Use nids from mount line: uml1,1@elan:uml2,2@elan:/lustre */
+        i = 0;
+        ptr = lsi->lsi_lmd->lmd_dev;
+        while (class_parse_nid(ptr, &nid, &ptr) == 0) {
+                rc = do_lcfg(MDCDEV, nid, LCFG_ADD_UUID, niduuid, 0,0,0);
+                i++;
+                /* Stop at the first failover nid */
+                if (*ptr == ':') 
+                        break;
+        }
+        if (i == 0) {
+                CERROR("No valid MDT nids found.\n");
+                GOTO(out, rc = -EINVAL);
+        }
+        failnodes++;
+
+        rc = do_lcfg(MDCDEV, 0, LCFG_ATTACH, LUSTRE_MDC_NAME, mdc_uuid.uuid, 0, 0);
+        if (rc < 0)
+                GOTO(out_del_uuid, rc);
+
+        rc = do_lcfg(MDCDEV, 0, LCFG_SETUP, mdt, niduuid, 0, 0);
+        if (rc < 0) {
+                LCONSOLE_ERROR("I couldn't establish a connection with the MDT."
+                               " Check that the MDT host NID is correct and the"
+                               " networks are up.\n");
+                GOTO(out_detach, rc);
+        }
+
+        obd = class_name2obd(MDCDEV);
+        if (obd == NULL)
+                GOTO(out_cleanup, rc = -EINVAL);
+
+        /* Add any failover nids */
+        while (*ptr == ':') {
+                /* New failover node */
+                sprintf(niduuid, "mdtnid%d", failnodes);
+                i = 0;
+                while (class_parse_nid(ptr, &nid, &ptr) == 0) {
+                        i++;
+                        rc = do_lcfg(MDCDEV, nid, LCFG_ADD_UUID, niduuid,0,0,0);
+                        if (rc)
+                                CERROR("Add uuid for %s failed %d\n", 
+                                       libcfs_nid2str(nid), rc);
+                        if (*ptr == ':') 
+                                break;
+                }
+                if (i > 0) {
+                        rc = do_lcfg(MDCDEV, 0, LCFG_ADD_CONN, niduuid, 0, 0,0);
+                        if (rc) 
+                                CERROR("Add conn for %s failed %d\n", 
+                                       libcfs_nid2str(nid), rc);
+                        failnodes++;
+                } else {
+                        /* at ":/fsname" */
+                        break;
+                }
+        }
+
+        /* Try all connections, but only once. */
+        rc = obd_set_info_async(obd->obd_self_export,
+                                strlen("init_recov_bk"), "init_recov_bk",
+                                sizeof(recov_bk), &recov_bk, NULL);
+        if (rc)
+                GOTO(out_cleanup, rc);
+
+        /* If we don't have this then an ACL MDS will refuse the connection */
+        ocd.ocd_connect_flags = OBD_CONNECT_ACL;
+
+        rc = obd_connect(NULL, &mdc_conn, obd, &mdc_uuid, &ocd);
+        if (rc) {
+                CERROR("cannot connect to %s: rc = %d\n", mdt, rc);
+                GOTO(out_cleanup, rc);
+        }
+
+        exp = class_conn2export(&mdc_conn);
+
+        ctxt = llog_get_context(exp->exp_obd, LLOG_CONFIG_REPL_CTXT);
+        
+        cfg->cfg_flags |= CFG_F_COMPAT146;
+
+#if 1
+        rc = class_config_parse_llog(ctxt, profile, cfg);
+#else
+        /*
+         * For debugging, it's useful to just dump the log
+         */
+        rc = class_config_dump_llog(ctxt, profile, cfg);
+#endif
+        switch (rc) {
+        case 0: {
+                /* Set the caller's profile name to the old-style */
+                memcpy(newprofile, profile, strlen(profile) + 1);
+                break;
+        }
+        case -EINVAL:
+                LCONSOLE_ERROR("%s: The configuration '%s' could not be read "
+                               "from the MDT '%s'.  Make sure this client and "
+                               "the MDT are running compatible versions of "
+                               "Lustre.\n",
+                               obd->obd_name, profile, mdt);
+                /* fall through */
+        default:
+                LCONSOLE_ERROR("%s: The configuration '%s' could not be read "
+                               "from the MDT '%s'.  This may be the result of "
+                               "communication errors between the client and "
+                               "the MDT, or if the MDT is not running.\n",
+                               obd->obd_name, profile, mdt);
+                break;
+        }
+
+        /* We don't so much care about errors in cleaning up the config llog
+         * connection, as we have already read the config by this point. */
+        obd_disconnect(exp);
+
+out_cleanup:
+        do_lcfg(MDCDEV, 0, LCFG_CLEANUP, 0, 0, 0, 0);
+
+out_detach:
+        do_lcfg(MDCDEV, 0, LCFG_DETACH, 0, 0, 0, 0);
+
+out_del_uuid:
+        /* class_add_uuid adds a nid even if the same uuid exists; we might
+           delete any copy here.  So they all better match. */
+        for (i = 0; i < failnodes; i++) {
+                sprintf(niduuid, "mdtnid%d", i);
+                do_lcfg(MDCDEV, 0, LCFG_DEL_UUID, niduuid, 0, 0, 0);
+        }
+        /* class_import_put will get rid of the additional connections */
+out:
+        RETURN(rc);
+}
+/* end COMPAT_146 */
+
 int ll_fill_super(struct super_block *sb)
 {
         struct lustre_profile *lprof;
         struct lustre_sb_info *lsi = s2lsi(sb);
         struct ll_sb_info *sbi;
-        char  *osc = NULL;
-        char  *mdc = NULL;
+        char  *dt = NULL, *md = NULL;
         char  *profilenm = get_profile_name(sb);
         struct config_llog_instance cfg;
         char   ll_instance[sizeof(sb) * 2 + 1];
@@ -663,7 +905,9 @@ int ll_fill_super(struct super_block *sb)
         if (!sbi)
                 RETURN(-ENOMEM);
 
-        ll_options(lsi->lsi_lmd->lmd_opts, &sbi->ll_flags);
+        err = ll_options(lsi->lsi_lmd->lmd_opts, &sbi->ll_flags);
+        if (err) 
+                GOTO(out_free, err);
 
         /* Generate a string unique to this super, in case some joker tries
            to mount the same fs at two mount points.
@@ -675,6 +919,36 @@ int ll_fill_super(struct super_block *sb)
 
         /* set up client obds */
         err = lustre_process_log(sb, profilenm, &cfg);
+        /* COMPAT_146 */
+        if (err < 0) {
+                char *oldname;
+                int rc, oldnamelen;
+                oldnamelen = strlen(profilenm) + 1;
+                /* Temp storage for 1.4.6 profile name */
+                OBD_ALLOC(oldname, oldnamelen);
+                if (oldname) {
+                        memcpy(oldname, profilenm, oldnamelen); 
+                        rc = old_lustre_process_log(sb, oldname, &cfg);
+                        if (rc >= 0) {
+                                /* That worked - update the profile name 
+                                   permanently */
+                                err = rc;
+                                OBD_FREE(lsi->lsi_lmd->lmd_profile, 
+                                         strlen(lsi->lsi_lmd->lmd_profile) + 1);
+                                OBD_ALLOC(lsi->lsi_lmd->lmd_profile, 
+                                         strlen(oldname) + 1);
+                                if (!lsi->lsi_lmd->lmd_profile) {
+                                        OBD_FREE(oldname, oldnamelen);
+                                        GOTO(out_free, err = -ENOMEM);
+                                }
+                                memcpy(lsi->lsi_lmd->lmd_profile, oldname,
+                                       strlen(oldname) + 1); 
+                                profilenm = get_profile_name(sb);
+                        }
+                        OBD_FREE(oldname, oldnamelen);
+                }
+        }
+        /* end COMPAT_146 */
         if (err < 0) {
                 CERROR("Unable to process log: %d\n", err);
                 GOTO(out_free, err);
@@ -682,46 +956,36 @@ int ll_fill_super(struct super_block *sb)
 
         lprof = class_get_profile(profilenm);
         if (lprof == NULL) {
-                CERROR("No profile found: %s\n", profilenm);
+                LCONSOLE_ERROR("The client profile '%s' could not be read "
+                               "from the MGS.  Does that filesystem exist?\n",
+                               profilenm);
                 GOTO(out_free, err = -EINVAL);
         }
         CDEBUG(D_CONFIG, "Found profile %s: mdc=%s osc=%s\n", profilenm,
-               lprof->lp_mdc, lprof->lp_osc);
+               lprof->lp_md, lprof->lp_dt);
 
-        OBD_ALLOC(osc, strlen(lprof->lp_osc) +
+        OBD_ALLOC(dt, strlen(lprof->lp_dt) +
                   strlen(ll_instance) + 2);
-        if (!osc)
+        if (!dt)
                 GOTO(out_free, err = -ENOMEM);
-        sprintf(osc, "%s-%s", lprof->lp_osc, ll_instance);
+        sprintf(dt, "%s-%s", lprof->lp_dt, ll_instance);
 
-        OBD_ALLOC(mdc, strlen(lprof->lp_mdc) +
+        OBD_ALLOC(md, strlen(lprof->lp_md) +
                   strlen(ll_instance) + 2);
-        if (!mdc)
+        if (!md)
                 GOTO(out_free, err = -ENOMEM);
-        sprintf(mdc, "%s-%s", lprof->lp_mdc, ll_instance);
+        sprintf(md, "%s-%s", lprof->lp_md, ll_instance);
 
         /* connections, registrations, sb setup */
-        err = client_common_fill_super(sb, mdc, osc);
+        err = client_common_fill_super(sb, md, dt);
 
 out_free:
-        if (mdc)
-                OBD_FREE(mdc, strlen(mdc) + 1);
-        if (osc)
-                OBD_FREE(osc, strlen(osc) + 1);
-        if (err) {
-                struct obd_device *obd;
-                int next = 0;
-                /* like ll_put_super below */
-                lustre_end_log(sb, NULL, &cfg);
-                while ((obd = class_devices_in_group(&sbi->ll_sb_uuid, &next))
-                       != NULL) {
-                        class_manual_cleanup(obd);
-                }
-                class_del_profile(profilenm);
-                ll_free_sbi(sb);
-                lsi->lsi_llsbi = NULL;
-                lustre_common_put_super(sb);
-        }
+        if (md)
+                OBD_FREE(md, strlen(md) + 1);
+        if (dt)
+                OBD_FREE(dt, strlen(dt) + 1);
+        if (err) 
+                ll_put_super(sb);
         RETURN(err);
 } /* ll_fill_super */
 
@@ -734,7 +998,7 @@ void ll_put_super(struct super_block *sb)
         struct lustre_sb_info *lsi = s2lsi(sb);
         struct ll_sb_info *sbi = ll_s2sbi(sb);
         char *profilenm = get_profile_name(sb);
-        int next;
+        int force = 1, next;
         ENTRY;
 
         CDEBUG(D_VFSTRACE, "VFS Op: sb %p - %s\n", sb, profilenm);
@@ -742,21 +1006,27 @@ void ll_put_super(struct super_block *sb)
         sprintf(ll_instance, "%p", sb);
         cfg.cfg_instance = ll_instance;
         lustre_end_log(sb, NULL, &cfg);
-
-        obd = class_exp2obd(sbi->ll_md_exp);
-        if (obd) {
-                int force = obd->obd_no_recov;
-                /* We need to set force before the lov_disconnect in
-                lustre_common_put_super, since l_d cleans up osc's as well. */
+        
+        if (sbi->ll_md_exp) {
+                obd = class_exp2obd(sbi->ll_md_exp);
+                if (obd) 
+                        force = obd->obd_no_recov;
+        }
+        
+        /* We need to set force before the lov_disconnect in 
+           lustre_common_put_super, since l_d cleans up osc's as well. */
+        if (force) {
                 next = 0;
-                while ((obd = class_devices_in_group(&sbi->ll_sb_uuid, &next))
-                       != NULL) {
+                while ((obd = class_devices_in_group(&sbi->ll_sb_uuid,
+                                                     &next)) != NULL) {
                         obd->obd_force = force;
                 }
-        }
-
-        client_common_put_super(sb);
+        }                       
 
+        if (sbi->ll_lcq) {
+                /* Only if client_common_fill_super succeeded */
+                client_common_put_super(sb);
+        }
         next = 0;
         while ((obd = class_devices_in_group(&sbi->ll_sb_uuid, &next)) !=NULL) {
                 class_manual_cleanup(obd);
@@ -770,7 +1040,7 @@ void ll_put_super(struct super_block *sb)
 
         lustre_common_put_super(sb);
 
-        LCONSOLE_WARN("client umount complete\n");
+        LCONSOLE_WARN("client %s umount complete\n", ll_instance);
         EXIT;
 } /* client_put_super */
 
@@ -803,7 +1073,8 @@ struct cache_definition ll_cache_definition = {
 struct inode *ll_inode_from_lock(struct ldlm_lock *lock)
 {
         struct inode *inode = NULL;
-        l_lock(&lock->l_resource->lr_namespace->ns_lock);
+        /* NOTE: we depend on atomic igrab() -bzzz */
+        lock_res_and_lock(lock);
         if (lock->l_ast_data) {
                 struct ll_inode_info *lli = ll_i2info(lock->l_ast_data);
                 if (lli->lli_inode_magic == LLI_INODE_MAGIC) {
@@ -822,7 +1093,7 @@ struct inode *ll_inode_from_lock(struct ldlm_lock *lock)
                         inode = NULL;
                 }
         }
-        l_unlock(&lock->l_resource->lr_namespace->ns_lock);
+        unlock_res_and_lock(lock);
         return inode;
 }
 
@@ -851,6 +1122,21 @@ void ll_clear_inode(struct inode *inode)
         md_change_cbdata(sbi->ll_md_exp, ll_inode2fid(inode),
                          null_if_equal, inode);
 
+        LASSERT(!lli->lli_open_fd_write_count);
+        LASSERT(!lli->lli_open_fd_read_count);
+        LASSERT(!lli->lli_open_fd_exec_count);
+
+        if (lli->lli_mds_write_och)
+                ll_md_real_close(inode, FMODE_WRITE);
+        if (lli->lli_mds_exec_och) {
+                if (!FMODE_EXEC)
+                        CERROR("No FMODE exec, bug exec och is present for "
+                               "inode %ld\n", inode->i_ino);
+                ll_md_real_close(inode, FMODE_EXEC);
+        }
+        if (lli->lli_mds_read_och)
+                ll_md_real_close(inode, FMODE_READ);
+
         if (lli->lli_smd) {
                 obd_change_cbdata(sbi->ll_dt_exp, lli->lli_smd,
                                   null_if_equal, inode);
@@ -939,6 +1225,16 @@ int ll_setattr_raw(struct inode *inode, struct iattr *attr)
                 attr->ia_mtime = CURRENT_TIME;
                 attr->ia_valid |= ATTR_MTIME_SET;
         }
+        if ((attr->ia_valid & ATTR_CTIME) && !(attr->ia_valid & ATTR_MTIME)) {
+                /* To avoid stale mtime on mds, obtain it from ost and send 
+                   to mds. */
+                rc = ll_glimpse_size(inode, 0);
+                if (rc) 
+                        RETURN(rc);
+                
+                attr->ia_valid |= ATTR_MTIME_SET | ATTR_MTIME;
+                attr->ia_mtime = inode->i_mtime;
+        }
 
         if (attr->ia_valid & (ATTR_MTIME | ATTR_CTIME))
                 CDEBUG(D_INODE, "setting mtime %lu, ctime %lu, now = %lu\n",
@@ -982,7 +1278,8 @@ int ll_setattr_raw(struct inode *inode, struct iattr *attr)
                         RETURN(rc);
                 }
 
-                rc = md_get_lustre_md(sbi->ll_md_exp, request, 0, sbi->ll_dt_exp, &md);
+                rc = md_get_lustre_md(sbi->ll_md_exp, request, 
+                                      REPLY_REC_OFF, sbi->ll_dt_exp, &md);
                 if (rc) {
                         ptlrpc_req_finished(request);
                         RETURN(rc);
@@ -1075,33 +1372,47 @@ int ll_setattr_raw(struct inode *inode, struct iattr *attr)
                 }
         } else if (ia_valid & (ATTR_MTIME | ATTR_MTIME_SET)) {
                 obd_flag flags;
-                struct obdo oa;
+                struct obd_info oinfo = { { { 0 } } };
+                struct obdo *oa = obdo_alloc();
 
                 CDEBUG(D_INODE, "set mtime on OST inode %lu to %lu\n",
                        inode->i_ino, LTIME_S(attr->ia_mtime));
 
-                oa.o_id = lsm->lsm_object_id;
-                oa.o_valid = OBD_MD_FLID;
+                if (oa) {
+                        oa->o_id = lsm->lsm_object_id;
+                        oa->o_valid = OBD_MD_FLID;
+
+                        flags = OBD_MD_FLTYPE | OBD_MD_FLATIME |
+                                OBD_MD_FLMTIME | OBD_MD_FLCTIME |
+                                OBD_MD_FLFID | OBD_MD_FLGENER;
+
+                        obdo_from_inode(oa, inode, flags);
 
-                flags = OBD_MD_FLTYPE | OBD_MD_FLATIME |
-                        OBD_MD_FLMTIME | OBD_MD_FLCTIME |
-                        OBD_MD_FLFID | OBD_MD_FLGENER;
+                        oinfo.oi_oa = oa;
+                        oinfo.oi_md = lsm;
 
-                obdo_from_inode(&oa, inode, flags);
-                rc = obd_setattr(sbi->ll_dt_exp, &oa, lsm, NULL);
-                if (rc)
-                        CERROR("obd_setattr fails: rc=%d\n", rc);
+                        rc = obd_setattr_rqset(sbi->ll_dt_exp, &oinfo, NULL);
+                        if (rc)
+                                CERROR("obd_setattr_async fails: rc=%d\n", rc);
+                        obdo_free(oa);
+                } else {
+                        rc = -ENOMEM;
+                }
         }
         RETURN(rc);
 }
 
 int ll_setattr(struct dentry *de, struct iattr *attr)
 {
+        if ((attr->ia_valid & (ATTR_CTIME|ATTR_SIZE|ATTR_MODE)) ==
+            (ATTR_CTIME|ATTR_SIZE|ATTR_MODE))
+                attr->ia_valid |= MDS_OPEN_OWNEROVERRIDE;
+
         return ll_setattr_raw(de->d_inode, attr);
 }
 
 int ll_statfs_internal(struct super_block *sb, struct obd_statfs *osfs,
-                       unsigned long max_age)
+                       __u64 max_age)
 {
         struct ll_sb_info *sbi = ll_s2sbi(sb);
         struct obd_statfs obd_osfs;
@@ -1119,7 +1430,8 @@ int ll_statfs_internal(struct super_block *sb, struct obd_statfs *osfs,
         CDEBUG(D_SUPER, "MDC blocks "LPU64"/"LPU64" objects "LPU64"/"LPU64"\n",
                osfs->os_bavail, osfs->os_blocks, osfs->os_ffree,osfs->os_files);
 
-        rc = obd_statfs(class_exp2obd(sbi->ll_dt_exp), &obd_osfs, max_age);
+        rc = obd_statfs_rqset(class_exp2obd(sbi->ll_dt_exp),
+                              &obd_osfs, max_age);
         if (rc) {
                 CERROR("obd_statfs fails: rc = %d\n", rc);
                 RETURN(rc);
@@ -1157,14 +1469,18 @@ int ll_statfs(struct super_block *sb, struct kstatfs *sfs)
         /* For now we will always get up-to-date statfs values, but in the
          * future we may allow some amount of caching on the client (e.g.
          * from QOS or lprocfs updates). */
-        rc = ll_statfs_internal(sb, &osfs, jiffies - 1);
+        rc = ll_statfs_internal(sb, &osfs, cfs_time_current_64() - 1);
         if (rc)
                 return rc;
 
         statfs_unpack(sfs, &osfs);
 
-        if (sizeof(sfs->f_blocks) == 4) {
-                while (osfs.os_blocks > ~0UL) {
+        /* We need to downshift for all 32-bit kernels, because we can't
+         * tell if the kernel is being called via sys_statfs64() or not.
+         * Stop before overflowing f_bsize - in which case it is better
+         * to just risk EOVERFLOW if caller is using old sys_statfs(). */
+        if (sizeof(long) < 8) {
+                while (osfs.os_blocks > ~0UL && sfs->f_bsize < 0x40000000) {
                         sfs->f_bsize <<= 1;
 
                         osfs.os_blocks >>= 1;
@@ -1269,14 +1585,8 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md)
                         } else
                                 ll_replace_lsm(inode, lsm);
                 }
-                /* bug 2844 - limit i_blksize for broken user-space apps */
-                LASSERTF(lsm->lsm_xfersize != 0, "%lu\n", lsm->lsm_xfersize);
-                inode->i_blksize = min(lsm->lsm_xfersize, LL_MAX_BLKSIZE);
                 if (lli->lli_smd != lsm)
                         obd_free_memmd(ll_i2dtexp(inode), &lsm);
-        } else {
-                inode->i_blksize = max(inode->i_blksize,
-                                       inode->i_sb->s_blocksize);
         }
 
 #ifdef CONFIG_FS_POSIX_ACL
@@ -1293,25 +1603,35 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md)
         if (body->valid & OBD_MD_FLATIME &&
             body->atime > LTIME_S(inode->i_atime))
                 LTIME_S(inode->i_atime) = body->atime;
-        if (body->valid & OBD_MD_FLMTIME &&
-            body->mtime > LTIME_S(inode->i_mtime)) {
-                CDEBUG(D_INODE, "setting ino %lu mtime from %lu to "LPU64"\n",
-                       inode->i_ino, LTIME_S(inode->i_mtime), body->mtime);
-                LTIME_S(inode->i_mtime) = body->mtime;
-        }
+        
+        /* mtime is always updated with ctime, but can be set in past.
+           As write and utime(2) may happen within 1 second, and utime's
+           mtime has a priority over write's one, so take mtime from mds 
+           for the same ctimes. */
         if (body->valid & OBD_MD_FLCTIME &&
-            body->ctime > LTIME_S(inode->i_ctime))
+            body->ctime >= LTIME_S(inode->i_ctime)) {
                 LTIME_S(inode->i_ctime) = body->ctime;
+                if (body->valid & OBD_MD_FLMTIME) {
+                        CDEBUG(D_INODE, "setting ino %lu mtime "
+                               "from %lu to "LPU64"\n", inode->i_ino, 
+                               LTIME_S(inode->i_mtime), body->mtime);
+                        LTIME_S(inode->i_mtime) = body->mtime;
+                }
+        }
         if (body->valid & OBD_MD_FLMODE)
                 inode->i_mode = (inode->i_mode & S_IFMT)|(body->mode & ~S_IFMT);
         if (body->valid & OBD_MD_FLTYPE)
                 inode->i_mode = (inode->i_mode & ~S_IFMT)|(body->mode & S_IFMT);
+        if (S_ISREG(inode->i_mode))
+                inode->i_blksize = min(2UL*PTLRPC_MAX_BRW_SIZE, LL_MAX_BLKSIZE);
+        else
+                inode->i_blksize = inode->i_sb->s_blocksize;
         if (body->valid & OBD_MD_FLUID)
                 inode->i_uid = body->uid;
         if (body->valid & OBD_MD_FLGID)
                 inode->i_gid = body->gid;
         if (body->valid & OBD_MD_FLFLAGS)
-                inode->i_flags = body->flags;
+                inode->i_flags = ll_ext_to_inode_flags(body->flags);
         if (body->valid & OBD_MD_FLNLINK)
                 inode->i_nlink = body->nlink;
         if (body->valid & OBD_MD_FLRDEV)
@@ -1434,26 +1754,29 @@ int ll_iocontrol(struct inode *inode, struct file *file,
                         RETURN(-abs(rc));
                 }
 
-                body = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*body));
-                
+                body = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
+                                      sizeof(*body));
+
                 /*Now the ext3 will be packed directly back to client,
                  *no need convert here*/
                 flags = body->flags;
+
                 ptlrpc_req_finished (req);
 
                 RETURN(put_user(flags, (int *)arg));
         }
         case EXT3_IOC_SETFLAGS: {
                 struct lov_stripe_md *lsm = ll_i2info(inode)->lli_smd;
-                struct ll_iattr_struct attr;
+                struct ll_iattr_struct attr = { 0 };
+                struct obd_info oinfo = { { { 0 } } };
                 struct md_op_data *op_data;
-                struct obdo *oa;
 
                 if (get_user(flags, (int *)arg))
                         RETURN(-EFAULT);
 
-                oa = obdo_alloc();
-                if (!oa)
+                oinfo.oi_md = lsm;
+                oinfo.oi_oa = obdo_alloc();
+                if (!oinfo.oi_oa)
                         RETURN(-ENOMEM);
 
                 OBD_ALLOC_PTR(op_data);
@@ -1462,46 +1785,34 @@ int ll_iocontrol(struct inode *inode, struct file *file,
                 
                 ll_prepare_md_op_data(op_data, inode, NULL, NULL, 0, 0);
 
-                memset(&attr, 0x0, sizeof(attr));
                 attr.ia_attr_flags = flags;
                 ((struct iattr *)&attr)->ia_valid |= ATTR_ATTR_FLAG;
 
                 rc = md_setattr(sbi->ll_md_exp, op_data,
                                 (struct iattr *)&attr, NULL, 0, NULL, 0, &req);
                 OBD_FREE_PTR(op_data);
+                ptlrpc_req_finished(req);
                 if (rc || lsm == NULL) {
-                        ptlrpc_req_finished(req);
-                        obdo_free(oa);
+                        obdo_free(oinfo.oi_oa);
                         RETURN(rc);
                 }
-                ptlrpc_req_finished(req);
 
-                oa->o_id = lsm->lsm_object_id;
-                oa->o_flags = flags;
-                oa->o_valid = OBD_MD_FLID | OBD_MD_FLFLAGS;
+                oinfo.oi_oa->o_id = lsm->lsm_object_id;
+                oinfo.oi_oa->o_flags = flags;
+                oinfo.oi_oa->o_valid = OBD_MD_FLID | OBD_MD_FLFLAGS;
 
-                obdo_from_inode(oa, inode, OBD_MD_FLFID | OBD_MD_FLGENER);
-                rc = obd_setattr(sbi->ll_dt_exp, oa, lsm, NULL);
-                obdo_free(oa);
+                obdo_from_inode(oinfo.oi_oa, inode,
+                                OBD_MD_FLFID | OBD_MD_FLGENER);
+                rc = obd_setattr_rqset(sbi->ll_dt_exp, &oinfo, NULL);
+                obdo_free(oinfo.oi_oa);
                 if (rc) {
                         if (rc != -EPERM && rc != -EACCES)
-                                CERROR("md_setattr fails: rc = %d\n", rc);
+                                CERROR("md_setattr_async fails: rc = %d\n", rc);
                         RETURN(rc);
                 }
 
-                if (flags & EXT3_APPEND_FL)
-                        inode->i_flags |= S_APPEND;
-                else
-                        inode->i_flags &= ~S_APPEND;
-                if (flags & EXT3_IMMUTABLE_FL)
-                        inode->i_flags |= S_IMMUTABLE;
-                else
-                        inode->i_flags &= ~S_IMMUTABLE;
-                if (flags & EXT3_NOATIME_FL)
-                        inode->i_flags |= S_NOATIME;
-                else
-                        inode->i_flags &= ~S_NOATIME;
-
+                inode->i_flags = ll_ext_to_inode_flags(flags |
+                                                       MDS_BFLAG_EXT_FLAGS);
                 RETURN(0);
         }
         default:
@@ -1685,18 +1996,19 @@ int ll_obd_statfs(struct inode *inode, void *arg)
                 lov_obd = class_exp2obd(sbi->ll_dt_exp);
                 lov = &lov_obd->u.lov;
 
-                if (index >= lov->desc.ld_tgt_count)
+                if ((index >= lov->desc.ld_tgt_count) ||
+                    !lov->lov_tgts[index])
                         GOTO(out_statfs, rc = -ENODEV);
 
-                client_obd = class_exp2obd(lov->tgts[index].ltd_exp);
-                if (!lov->tgts[index].active)
+                client_obd = class_exp2obd(lov->lov_tgts[index]->ltd_exp);
+                if (!lov->lov_tgts[index]->ltd_active)
                         GOTO(out_uuid, rc = -ENODATA);
         }
 
         if (!client_obd)
                 GOTO(out_statfs, rc = -EINVAL);
 
-        rc = obd_statfs(client_obd, &stat_buf, jiffies - 1);
+        rc = obd_statfs(client_obd, &stat_buf, cfs_time_current_64() - 1);
         if (rc)
                 GOTO(out_statfs, rc);
 
@@ -1713,3 +2025,31 @@ out_statfs:
                 obd_ioctl_freedata(buf, len);
         return rc;
 }
+
+int ll_process_config(struct lustre_cfg *lcfg)
+{
+        char *ptr;
+        void *sb;
+        struct lprocfs_static_vars lvars;
+        unsigned long x; 
+        int rc = 0;
+
+        lprocfs_init_vars(llite, &lvars);
+
+        /* The instance name contains the sb: lustre-client-aacfe000 */
+        ptr = strrchr(lustre_cfg_string(lcfg, 0), '-');
+        if (!ptr || !*(++ptr)) 
+                return -EINVAL;
+        if (sscanf(ptr, "%lx", &x) != 1)
+                return -EINVAL;
+        sb = (void *)x;
+        /* This better be a real Lustre superblock! */
+        LASSERT(s2lsi((struct super_block *)sb)->lsi_lmd->lmd_magic == LMD_MAGIC);
+
+        /* Note we have not called client_common_fill_super yet, so 
+           proc fns must be able to handle that! */
+        rc = class_process_proc_param(PARAM_LLITE, lvars.obd_vars,
+                                      lcfg, sb);
+        return(rc);
+}
+
index f0de698..417b6e3 100644 (file)
@@ -460,6 +460,9 @@ static void ll_vm_open(struct vm_area_struct * vma)
                 int count;
 
                 spin_unlock(&lli->lli_lock);
+
+                if (!lsm)
+                        return;
                 count = obd_join_lru(sbi->ll_dt_exp, lsm, 0);
                 VMA_DEBUG(vma, "split %d unused locks from lru\n", count);
         } else {
@@ -486,6 +489,9 @@ static void ll_vm_close(struct vm_area_struct *vma)
                 int count;
 
                 spin_unlock(&lli->lli_lock);
+
+                if (!lsm)
+                        return;
                 count = obd_join_lru(sbi->ll_dt_exp, lsm, 1);
                 VMA_DEBUG(vma, "join %d unused locks to lru\n", count);
         } else {
index bb21e49..80ab9d8 100644 (file)
@@ -86,7 +86,7 @@ static struct inode *search_inode_for_lustre(struct super_block *sb,
                 return ERR_PTR(rc);
         }
 
-        rc = ll_prep_inode(&inode, req, 0, sb);
+        rc = ll_prep_inode(&inode, req, REPLY_REC_OFF, sb);
         if (rc) {
                 ptlrpc_req_finished(req);
                 return ERR_PTR(rc);
@@ -264,7 +264,7 @@ struct dentry *ll_get_parent(struct dentry *dchild)
         struct inode *dir = dchild->d_inode;
         struct ll_sb_info *sbi;
         struct dentry *result = NULL;
-        struct mds_body *body;
+        struct mdt_body *body;
         char dotdot[] = "..";
         int  rc = 0;
         ENTRY;
@@ -280,7 +280,7 @@ struct dentry *ll_get_parent(struct dentry *dchild)
                 CERROR("failure %d inode %lu get parent\n", rc, dir->i_ino);
                 return ERR_PTR(rc);
         }
-        body = lustre_msg_buf(req->rq_repmsg, 0, sizeof (*body)); 
+        body = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF, sizeof (*body)); 
        
         LASSERT((body->valid & OBD_MD_FLGENER) && (body->valid & OBD_MD_FLID));
         
index e08a466..4cc1777 100644 (file)
@@ -36,8 +36,6 @@ struct proc_dir_entry *proc_lustre_fs_root;
 struct file_operations llite_dump_pgcache_fops;
 struct file_operations ll_ra_stats_fops;
 
-long long mnt_instance;
-
 static int ll_rd_blksize(char *page, char **start, off_t off, int count,
                          int *eof, void *data)
 {
@@ -46,7 +44,7 @@ static int ll_rd_blksize(char *page, char **start, off_t off, int count,
         int rc;
 
         LASSERT(sb != NULL);
-        rc = ll_statfs_internal(sb, &osfs, jiffies - HZ);
+        rc = ll_statfs_internal(sb, &osfs, cfs_time_current_64() - HZ);
         if (!rc) {
               *eof = 1;
               rc = snprintf(page, count, "%u\n", osfs.os_bsize);
@@ -63,7 +61,7 @@ static int ll_rd_kbytestotal(char *page, char **start, off_t off, int count,
         int rc;
 
         LASSERT(sb != NULL);
-        rc = ll_statfs_internal(sb, &osfs, jiffies - HZ);
+        rc = ll_statfs_internal(sb, &osfs, cfs_time_current_64() - HZ);
         if (!rc) {
                 __u32 blk_size = osfs.os_bsize >> 10;
                 __u64 result = osfs.os_blocks;
@@ -86,7 +84,7 @@ static int ll_rd_kbytesfree(char *page, char **start, off_t off, int count,
         int rc;
 
         LASSERT(sb != NULL);
-        rc = ll_statfs_internal(sb, &osfs, jiffies - HZ);
+        rc = ll_statfs_internal(sb, &osfs, cfs_time_current_64() - HZ);
         if (!rc) {
                 __u32 blk_size = osfs.os_bsize >> 10;
                 __u64 result = osfs.os_bfree;
@@ -108,7 +106,7 @@ static int ll_rd_kbytesavail(char *page, char **start, off_t off, int count,
         int rc;
 
         LASSERT(sb != NULL);
-        rc = ll_statfs_internal(sb, &osfs, jiffies - HZ);
+        rc = ll_statfs_internal(sb, &osfs, cfs_time_current_64() - HZ);
         if (!rc) {
                 __u32 blk_size = osfs.os_bsize >> 10;
                 __u64 result = osfs.os_bavail;
@@ -130,7 +128,7 @@ static int ll_rd_filestotal(char *page, char **start, off_t off, int count,
         int rc;
 
         LASSERT(sb != NULL);
-        rc = ll_statfs_internal(sb, &osfs, jiffies - HZ);
+        rc = ll_statfs_internal(sb, &osfs, cfs_time_current_64() - HZ);
         if (!rc) {
                  *eof = 1;
                  rc = snprintf(page, count, LPU64"\n", osfs.os_files);
@@ -146,7 +144,7 @@ static int ll_rd_filesfree(char *page, char **start, off_t off, int count,
         int rc;
 
         LASSERT(sb != NULL);
-        rc = ll_statfs_internal(sb, &osfs, jiffies - HZ);
+        rc = ll_statfs_internal(sb, &osfs, cfs_time_current_64() - HZ);
         if (!rc) {
                  *eof = 1;
                  rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
@@ -180,13 +178,15 @@ static int ll_rd_max_readahead_mb(char *page, char **start, off_t off,
 {
         struct super_block *sb = data;
         struct ll_sb_info *sbi = ll_s2sbi(sb);
-        unsigned val;
+        long pages_number;
+        int mult;
 
         spin_lock(&sbi->ll_lock);
-        val = sbi->ll_ra_info.ra_max_pages >> (20 - PAGE_CACHE_SHIFT);
+        pages_number = sbi->ll_ra_info.ra_max_pages;
         spin_unlock(&sbi->ll_lock);
 
-        return snprintf(page, count, "%u\n", val);
+        mult = 1 << (20 - PAGE_CACHE_SHIFT);
+        return lprocfs_read_frac_helper(page, count, pages_number, mult);
 }
 
 static int ll_wr_max_readahead_mb(struct file *file, const char *buffer,
@@ -194,20 +194,21 @@ static int ll_wr_max_readahead_mb(struct file *file, const char *buffer,
 {
         struct super_block *sb = data;
         struct ll_sb_info *sbi = ll_s2sbi(sb);
-        int val, rc;
+        int mult, rc, pages_number;
 
-        rc = lprocfs_write_helper(buffer, count, &val);
+        mult = 1 << (20 - PAGE_CACHE_SHIFT);
+        rc = lprocfs_write_frac_helper(buffer, count, &pages_number, mult);
         if (rc)
                 return rc;
 
-        if (val < 0 || val > (num_physpages >> (20 - PAGE_CACHE_SHIFT - 1))) {
+        if (pages_number < 0 || pages_number > num_physpages / 2) {
                 CERROR("can't set file readahead more than %lu MB\n",
-                        num_physpages >> (20 - PAGE_CACHE_SHIFT - 1));
+                        num_physpages >> (20 - PAGE_CACHE_SHIFT + 1)); /*1/2 of RAM*/
                 return -ERANGE;
         }
 
         spin_lock(&sbi->ll_lock);
-        sbi->ll_ra_info.ra_max_pages = val << (20 - PAGE_CACHE_SHIFT);
+        sbi->ll_ra_info.ra_max_pages = pages_number;
         spin_unlock(&sbi->ll_lock);
 
         return count;
@@ -218,14 +219,15 @@ static int ll_rd_max_read_ahead_whole_mb(char *page, char **start, off_t off,
 {
         struct super_block *sb = data;
         struct ll_sb_info *sbi = ll_s2sbi(sb);
-        unsigned val;
+        long pages_number;
+        int mult;
 
         spin_lock(&sbi->ll_lock);
-        val = sbi->ll_ra_info.ra_max_read_ahead_whole_pages >>
-              (20 - PAGE_CACHE_SHIFT);
+        pages_number = sbi->ll_ra_info.ra_max_read_ahead_whole_pages;
         spin_unlock(&sbi->ll_lock);
 
-        return snprintf(page, count, "%u\n", val);
+        mult = 1 << (20 - PAGE_CACHE_SHIFT);
+        return lprocfs_read_frac_helper(page, count, pages_number, mult);
 }
 
 static int ll_wr_max_read_ahead_whole_mb(struct file *file, const char *buffer,
@@ -233,16 +235,16 @@ static int ll_wr_max_read_ahead_whole_mb(struct file *file, const char *buffer,
 {
         struct super_block *sb = data;
         struct ll_sb_info *sbi = ll_s2sbi(sb);
-        int val, rc;
+        int mult, rc, pages_number;
 
-        rc = lprocfs_write_helper(buffer, count, &val);
+        mult = 1 << (20 - PAGE_CACHE_SHIFT);
+        rc = lprocfs_write_frac_helper(buffer, count, &pages_number, mult);
         if (rc)
                 return rc;
 
         /* Cap this at the current max readahead window size, the readahead
          * algorithm does this anyway so it's pointless to set it larger. */
-        if (val < 0 ||
-            val > (sbi->ll_ra_info.ra_max_pages >> (20 - PAGE_CACHE_SHIFT))) {
+        if (pages_number < 0 || pages_number > sbi->ll_ra_info.ra_max_pages) {
                 CERROR("can't set max_read_ahead_whole_mb more than "
                        "max_read_ahead_mb: %lu\n",
                        sbi->ll_ra_info.ra_max_pages >> (20 - PAGE_CACHE_SHIFT));
@@ -250,8 +252,7 @@ static int ll_wr_max_read_ahead_whole_mb(struct file *file, const char *buffer,
         }
 
         spin_lock(&sbi->ll_lock);
-        sbi->ll_ra_info.ra_max_read_ahead_whole_pages =
-                val << (20 - PAGE_CACHE_SHIFT);
+        sbi->ll_ra_info.ra_max_read_ahead_whole_pages = pages_number;
         spin_unlock(&sbi->ll_lock);
 
         return count;
@@ -262,13 +263,15 @@ static int ll_rd_max_cached_mb(char *page, char **start, off_t off,
 {
         struct super_block *sb = data;
         struct ll_sb_info *sbi = ll_s2sbi(sb);
-        unsigned val;
+        long pages_number;
+        int mult;
 
         spin_lock(&sbi->ll_lock);
-        val = sbi->ll_async_page_max >> (20 - PAGE_CACHE_SHIFT);
+        pages_number = sbi->ll_async_page_max;
         spin_unlock(&sbi->ll_lock);
 
-        return snprintf(page, count, "%u\n", val);
+        mult = 1 << (20 - PAGE_CACHE_SHIFT);
+        return lprocfs_read_frac_helper(page, count, pages_number, mult);;
 }
 
 static int ll_wr_max_cached_mb(struct file *file, const char *buffer,
@@ -276,21 +279,26 @@ static int ll_wr_max_cached_mb(struct file *file, const char *buffer,
 {
         struct super_block *sb = data;
         struct ll_sb_info *sbi = ll_s2sbi(sb);
-        int val, rc;
+        int mult, rc, pages_number;
 
-        rc = lprocfs_write_helper(buffer, count, &val);
+        mult = 1 << (20 - PAGE_CACHE_SHIFT);
+        rc = lprocfs_write_frac_helper(buffer, count, &pages_number, mult);
         if (rc)
                 return rc;
 
-        if (val < 0 || val > (num_physpages >> (20 - PAGE_CACHE_SHIFT))) {
+        if (pages_number < 0 || pages_number > num_physpages) {
                 CERROR("can't set max cache more than %lu MB\n",
                         num_physpages >> (20 - PAGE_CACHE_SHIFT));
                 return -ERANGE;
         }
 
         spin_lock(&sbi->ll_lock);
-        sbi->ll_async_page_max = val << (20 - PAGE_CACHE_SHIFT);
+        sbi->ll_async_page_max = pages_number ;
         spin_unlock(&sbi->ll_lock);
+        
+        if (!sbi->ll_dt_exp)
+                /* Not set up yet, don't call llap_shrink_cache */
+                return count;
 
         if (sbi->ll_async_page_count >= sbi->ll_async_page_max)
                 llap_shrink_cache(sbi, 0);
@@ -315,10 +323,13 @@ static int ll_wr_checksum(struct file *file, const char *buffer,
         struct ll_sb_info *sbi = ll_s2sbi(sb);
         int val, rc;
 
+        if (!sbi->ll_dt_exp)
+                /* Not set up yet */
+                return -EAGAIN;
+
         rc = lprocfs_write_helper(buffer, count, &val);
         if (rc)
                 return rc;
-
         if (val)
                 sbi->ll_flags |= LL_SBI_CHECKSUM;
         else
@@ -332,6 +343,27 @@ static int ll_wr_checksum(struct file *file, const char *buffer,
         return count;
 }
 
+static int ll_rd_max_rw_chunk(char *page, char **start, off_t off,
+                          int count, int *eof, void *data)
+{
+        struct super_block *sb = data;
+
+        return snprintf(page, count, "%lu\n", ll_s2sbi(sb)->ll_max_rw_chunk);
+}
+
+static int ll_wr_max_rw_chunk(struct file *file, const char *buffer,
+                          unsigned long count, void *data)
+{
+        struct super_block *sb = data;
+        int rc, val;
+
+        rc = lprocfs_write_helper(buffer, count, &val);
+        if (rc)
+                return rc;
+        ll_s2sbi(sb)->ll_max_rw_chunk = val;
+        return count;
+}
+
 static struct lprocfs_vars lprocfs_obd_vars[] = {
         { "uuid",         ll_rd_sb_uuid,          0, 0 },
         //{ "mntpt_path",   ll_rd_path,             0, 0 },
@@ -349,6 +381,7 @@ static struct lprocfs_vars lprocfs_obd_vars[] = {
                                      ll_wr_max_read_ahead_whole_mb, 0 },
         { "max_cached_mb", ll_rd_max_cached_mb, ll_wr_max_cached_mb, 0 },
         { "checksum_pages", ll_rd_checksum, ll_wr_checksum, 0 },
+        { "max_rw_chunk", ll_rd_max_rw_chunk, ll_wr_max_rw_chunk, 0 },
         { 0 }
 };
 
@@ -409,10 +442,11 @@ int lprocfs_register_mountpoint(struct proc_dir_entry *parent,
                                 struct super_block *sb, char *osc, char *mdc)
 {
         struct lprocfs_vars lvars[2];
+        struct lustre_sb_info *lsi = s2lsi(sb);
         struct ll_sb_info *sbi = ll_s2sbi(sb);
         struct obd_device *obd;
-        char name[MAX_STRING_SIZE + 1];
-        int err, id;
+        char name[MAX_STRING_SIZE + 1], *ptr;
+        int err, id, len;
         struct lprocfs_stats *svc_stats = NULL;
         struct proc_dir_entry *entry;
         ENTRY;
@@ -426,10 +460,16 @@ int lprocfs_register_mountpoint(struct proc_dir_entry *parent,
         LASSERT(mdc != NULL);
         LASSERT(osc != NULL);
 
+        /* Get fsname */
+        len = strlen(lsi->lsi_lmd->lmd_profile);
+        ptr = strrchr(lsi->lsi_lmd->lmd_profile, '-');
+        if (ptr && (strcmp(ptr, "-client") == 0))
+                len -= 7; 
+        
         /* Mount info */
-        snprintf(name, MAX_STRING_SIZE, "fs%llu", mnt_instance);
-
-        mnt_instance++;
+        snprintf(name, MAX_STRING_SIZE, "%.*s-%p", len,
+                 lsi->lsi_lmd->lmd_profile, sb);
+        
         sbi->ll_proc_root = lprocfs_register(name, parent, NULL, NULL);
         if (IS_ERR(sbi->ll_proc_root)) {
                 err = PTR_ERR(sbi->ll_proc_root);
@@ -488,7 +528,7 @@ int lprocfs_register_mountpoint(struct proc_dir_entry *parent,
         obd = class_name2obd(mdc);
 
         LASSERT(obd != NULL);
-        LASSERT(obd->obd_type != NULL);
+        LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
         LASSERT(obd->obd_type->typ_name != NULL);
 
         snprintf(name, MAX_STRING_SIZE, "%s/common_name",
@@ -508,7 +548,7 @@ int lprocfs_register_mountpoint(struct proc_dir_entry *parent,
         obd = class_name2obd(osc);
 
         LASSERT(obd != NULL);
-        LASSERT(obd->obd_type != NULL);
+        LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
         LASSERT(obd->obd_type->typ_name != NULL);
 
         snprintf(name, MAX_STRING_SIZE, "%s/common_name",
@@ -527,6 +567,7 @@ out:
                         lprocfs_free_stats(svc_stats);
                 if (sbi->ll_proc_root)
                         lprocfs_remove(sbi->ll_proc_root);
+                sbi->ll_proc_root = NULL;
         }
         RETURN(err);
 }
@@ -536,11 +577,10 @@ void lprocfs_unregister_mountpoint(struct ll_sb_info *sbi)
         if (sbi->ll_proc_root) {
                 struct proc_dir_entry *file_stats =
                         lprocfs_srch(sbi->ll_proc_root, "stats");
-
-                if (file_stats) {
+                if (file_stats) 
                         lprocfs_free_stats(sbi->ll_stats);
-                        lprocfs_remove(file_stats);
-                }
+                lprocfs_remove(sbi->ll_proc_root);
+                sbi->ll_proc_root = NULL;
         }
 }
 #undef MAX_STRING_SIZE
@@ -601,7 +641,9 @@ static int llite_dump_pgcache_seq_show(struct seq_file *seq, void *v)
                 seq_page_flag(seq, page, referenced, has_flags);
                 seq_page_flag(seq, page, uptodate, has_flags);
                 seq_page_flag(seq, page, dirty, has_flags);
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,12))
                 seq_page_flag(seq, page, highmem, has_flags);
+#endif
                 if (!has_flags)
                         seq_puts(seq, "-]\n");
                 else 
@@ -817,4 +859,5 @@ struct file_operations ll_ra_stats_fops = {
         .release = seq_release,
 };
 
+LPROCFS_INIT_VARS(llite, NULL, lprocfs_obd_vars)
 #endif /* LPROCFS */
index d730418..10fff69 100644 (file)
@@ -131,16 +131,77 @@ int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
                                    PFID(ll_inode2fid(inode)), inode);
                 }
 
+                if (bits & MDS_INODELOCK_OPEN) {
+                        int flags = 0;
+                        switch (lock->l_req_mode) {
+                        case LCK_CW:
+                                flags = FMODE_WRITE;
+                                break;
+                        case LCK_PR:
+                                flags = FMODE_EXEC;
+                                if (!FMODE_EXEC)
+                                        CERROR("open PR lock without FMODE_EXEC\n");
+                                break;
+                        case LCK_CR:
+                                flags = FMODE_READ;
+                                break;
+                        default:
+                                CERROR("Unexpected lock mode for OPEN lock "
+                                       "%d, inode %ld\n", lock->l_req_mode,
+                                       inode->i_ino);
+                        }
+                        ll_md_real_close(inode, flags);
+                }
+
                 if (bits & MDS_INODELOCK_UPDATE)
                         clear_bit(LLI_F_HAVE_MDS_SIZE_LOCK,
                                   &(ll_i2info(inode)->lli_flags));
 
-
                 if (S_ISDIR(inode->i_mode) &&
-                     (bits & MDS_INODELOCK_UPDATE))  {
+                     (bits & MDS_INODELOCK_UPDATE)) {
+                        struct dentry *dentry, *tmp, *dir;
+                        struct list_head *list;
+                        
                         CDEBUG(D_INODE, "invalidating inode %lu\n",
                                inode->i_ino);
                         truncate_inode_pages(inode->i_mapping, 0);
+
+                        
+                        /* Drop possible cached negative dentries */
+                        list = &inode->i_dentry;
+                        dir = NULL;
+                        spin_lock(&dcache_lock);
+                        
+                        /* It is possible to have several dentries (with 
+                           racer?) */
+                        while ((list = list->next) != &inode->i_dentry) {
+                                dir = list_entry(list, struct dentry, d_alias);
+#ifdef LUSTRE_KERNEL_VERSION
+                                if (!(dir->d_flags & DCACHE_LUSTRE_INVALID))
+#else
+                                if (!d_unhashed(dir))
+#endif
+                                        break;
+
+                                dir = NULL;
+                        }
+                        
+                        if (dir) {
+restart:
+                                list_for_each_entry_safe(dentry, tmp, 
+                                                         &dir->d_subdirs, 
+                                                         d_child)
+                                {
+                                        /* XXX Print some debug here? */
+                                        if (!dentry->d_inode) 
+                                                /* Negative dentry. If we were 
+                                                   dropping dcache lock, go 
+                                                   throught the list again */
+                                                if (ll_drop_dentry(dentry))
+                                                        goto restart;
+                                }
+                        }
+                        spin_unlock(&dcache_lock);
                 }
 
                 if (inode->i_sb->s_root &&
@@ -285,7 +346,9 @@ struct dentry *ll_find_alias(struct inode *inode, struct dentry *de)
                 dget_locked(dentry);
                 lock_dentry(dentry);
                 __d_drop(dentry);
+#ifdef LUSTRE_KERNEL_VERSION
                 dentry->d_flags &= ~DCACHE_LUSTRE_INVALID;
+#endif
                 unlock_dentry(dentry);
                 __d_rehash(dentry, 0); /* avoid taking dcache_lock inside */
                 spin_unlock(&dcache_lock);
@@ -308,11 +371,13 @@ struct dentry *ll_find_alias(struct inode *inode, struct dentry *de)
         struct dentry *dentry;
 
         dentry = d_add_unique(de, inode);
+#ifdef LUSTRE_KERNEL_VERSION
         if (dentry) {
                 lock_dentry(dentry);
                 dentry->d_flags &= ~DCACHE_LUSTRE_INVALID;
                 unlock_dentry(dentry);
         }
+#endif
 
         return dentry?dentry:de;
 }
@@ -356,14 +421,15 @@ static int lookup_it_finish(struct ptlrpc_request *request, int offset,
         } else {
                 ENTRY;
                 /* Check that parent has UPDATE lock. If there is none, we
-                 * cannot afford to hash this dentry (done by ll_d_add) as it
-                 * might get picked up later when UPDATE lock will appear */
+                   cannot afford to hash this dentry (done by ll_d_add) as it
+                   might get picked up later when UPDATE lock will appear */
                 if (ll_have_md_lock(parent, MDS_INODELOCK_UPDATE)) {
                         spin_lock(&dcache_lock);
                         ll_d_add(*de, inode);
                         spin_unlock(&dcache_lock);
-                } else
-                        (*de)->d_inode = NULL;
+                } else {
+                        (*de)->d_inode = NULL; 
+                }
         }
 
         ll_set_dd(*de);
@@ -430,7 +496,7 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
         if (rc < 0)
                 GOTO(out, retval = ERR_PTR(rc));
 
-        rc = lookup_it_finish(req, 1, it, &icbd);
+        rc = lookup_it_finish(req, DLM_REPLY_REC_OFF, it, &icbd);
         if (rc != 0) {
                 ll_intent_release(it);
                 GOTO(out, retval = ERR_PTR(rc));
@@ -454,6 +520,7 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
 }
 
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+#ifdef LUSTRE_KERNEL_VERSION
 static struct dentry *ll_lookup_nd(struct inode *parent, struct dentry *dentry,
                                    struct nameidata *nd)
 {
@@ -467,6 +534,120 @@ static struct dentry *ll_lookup_nd(struct inode *parent, struct dentry *dentry,
 
         RETURN(de);
 }
+#else
+struct lookup_intent *ll_convert_intent(struct open_intent *oit,
+                                        int lookup_flags)
+{
+        struct lookup_intent *it;
+
+        OBD_ALLOC(it, sizeof(*it));
+        if (!it)
+                return ERR_PTR(-ENOMEM);
+
+        if (lookup_flags & LOOKUP_OPEN) {
+                it->it_op = IT_OPEN;
+                if (lookup_flags & LOOKUP_CREATE)
+                        it->it_op |= IT_CREAT;
+                it->it_create_mode = oit->create_mode;
+                it->it_flags = oit->flags;
+        } else {
+                it->it_op = IT_GETATTR;
+        }
+
+#ifndef HAVE_FILE_IN_STRUCT_INTENT
+                /* Since there is no way to pass our intent to ll_file_open,
+                 * just check the file is there. Actual open will be done
+                 * in ll_file_open */
+                if (it->it_op & IT_OPEN)
+                        it->it_op = IT_LOOKUP;
+#endif
+
+        return it;
+}
+
+static struct dentry *ll_lookup_nd(struct inode *parent, struct dentry *dentry,
+                                   struct nameidata *nd)
+{
+        struct dentry *de;
+        ENTRY;
+
+        if (nd && !(nd->flags & (LOOKUP_CONTINUE|LOOKUP_PARENT))) {
+                struct lookup_intent *it;
+
+#if defined(HAVE_FILE_IN_STRUCT_INTENT) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17))
+                /* Did we came here from failed revalidate just to propagate
+                 * its error? */
+                if (nd->flags & LOOKUP_OPEN)
+                        if (IS_ERR(nd->intent.open.file))
+                                RETURN((struct dentry *)nd->intent.open.file);
+#endif
+
+                if (ll_d2d(dentry) && ll_d2d(dentry)->lld_it) {
+                        it = ll_d2d(dentry)->lld_it;
+                        ll_d2d(dentry)->lld_it = NULL;
+                } else {
+                        it = ll_convert_intent(&nd->intent.open, nd->flags);
+                        if (IS_ERR(it))
+                                RETURN((struct dentry *)it);
+                }
+
+                de = ll_lookup_it(parent, dentry, it, nd->flags);
+                if (de)
+                        dentry = de;
+                if ((nd->flags & LOOKUP_OPEN) && !IS_ERR(dentry)) { /* Open */
+                        if (dentry->d_inode && 
+                            it_disposition(it, DISP_OPEN_OPEN)) { /* nocreate */
+#ifdef HAVE_FILE_IN_STRUCT_INTENT
+                                if (S_ISFIFO(dentry->d_inode->i_mode)) {
+                                        // We cannot call open here as it would
+                                        // deadlock.
+                                        ptlrpc_req_finished(
+                                                       (struct ptlrpc_request *)
+                                                          it->d.lustre.it_data);
+                                } else {
+                                        struct file *filp;
+                                        nd->intent.open.file->private_data = it;
+                                        filp =lookup_instantiate_filp(nd,dentry,
+                                                                      NULL);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17))
+/* 2.6.1[456] have a bug in open_namei() that forgets to check
+ * nd->intent.open.file for error, so we need to return it as lookup's result
+ * instead */
+                                        if (IS_ERR(filp)) {
+                                                if (de)
+                                                        dput(de);
+                                                de = (struct dentry *) filp;
+                                        }
+#endif
+                                                
+                                }
+#else /* HAVE_FILE_IN_STRUCT_INTENT */
+                                /* Release open handle as we have no way to
+                                 * pass it to ll_file_open */
+                                ll_release_openhandle(dentry, it);
+#endif /* HAVE_FILE_IN_STRUCT_INTENT */
+                        } else if (it_disposition(it, DISP_OPEN_CREATE)) {
+                                // XXX This can only reliably work on assumption
+                                // that there are NO hashed negative dentries.
+                                ll_d2d(dentry)->lld_it = it;
+                                it = NULL; /* Will be freed in ll_create_nd */
+                                /* We absolutely depend on ll_create_nd to be
+                                 * called to not leak this intent and possible
+                                 * data attached to it */
+                        }
+                }
+
+                if (it) {
+                        ll_intent_release(it);
+                        OBD_FREE(it, sizeof(*it));
+                }
+        } else {
+                de = ll_lookup_it(parent, dentry, NULL, 0);
+        }
+
+        RETURN(de);
+}
+#endif
 #endif
 
 /* We depend on "mode" being set with the proper file type/umask by now */
@@ -483,8 +664,10 @@ static struct inode *ll_create_node(struct inode *dir, const char *name,
 
         LASSERT(it && it->d.lustre.it_disposition);
 
+        LASSERT(it_disposition(it, DISP_ENQ_CREATE_REF));
         request = it->d.lustre.it_data;
-        rc = ll_prep_inode(&inode, request, 1, dir->i_sb);
+        it_clear_disposition(it, DISP_ENQ_CREATE_REF);
+        rc = ll_prep_inode(&inode, request, DLM_REPLY_REC_OFF, dir->i_sb);
         if (rc)
                 GOTO(out, inode = ERR_PTR(rc));
 
@@ -549,15 +732,21 @@ static void ll_update_times(struct ptlrpc_request *request, int offset,
                                                sizeof(*body));
         LASSERT(body);
 
-        if (body->valid & OBD_MD_FLMTIME &&
-            body->mtime > LTIME_S(inode->i_mtime)) {
-                CDEBUG(D_INODE, "setting ino %lu mtime from %lu to "LPU64"\n",
-                       inode->i_ino, LTIME_S(inode->i_mtime), body->mtime);
-                LTIME_S(inode->i_mtime) = body->mtime;
-        }
+        /* mtime is always updated with ctime, but can be set in past.
+           As write and utime(2) may happen within 1 second, and utime's
+           mtime has a priority over write's one, so take mtime from mds 
+           for the same ctimes. */
         if (body->valid & OBD_MD_FLCTIME &&
-            body->ctime > LTIME_S(inode->i_ctime))
+            body->ctime >= LTIME_S(inode->i_ctime)) {
                 LTIME_S(inode->i_ctime) = body->ctime;
+
+                if (body->valid & OBD_MD_FLMTIME) {
+                        CDEBUG(D_INODE, "setting ino %lu mtime from %lu "
+                               "to "LPU64"\n", inode->i_ino, 
+                               LTIME_S(inode->i_mtime), body->mtime);
+                        LTIME_S(inode->i_mtime) = body->mtime;
+                }
+        }
 }
 
 static int ll_mknod_generic(struct inode *dir, struct qstr *name, int mode,
@@ -604,10 +793,10 @@ static int ll_mknod_generic(struct inode *dir, struct qstr *name, int mode,
                 OBD_FREE_PTR(op_data);
                 if (err)
                         break;
-                ll_update_times(request, 0, dir);
+                ll_update_times(request, REPLY_REC_OFF, dir);
 
                 if (dchild) {
-                        err = ll_prep_inode(&inode, request, 0,
+                        err = ll_prep_inode(&inode, request, REPLY_REC_OFF,
                                             dchild->d_sb);
                         if (err)
                                 break;
@@ -626,16 +815,50 @@ static int ll_mknod_generic(struct inode *dir, struct qstr *name, int mode,
 }
 
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+#ifndef LUSTRE_KERNEL_VERSION
 static int ll_create_nd(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
 {
-        if (!nd || !nd->intent.d.lustre.it_disposition) {
-                /* No saved request? Just mknod the file */
+        struct lookup_intent *it = ll_d2d(dentry)->lld_it;
+        int rc;
+        
+        if (!it)
                 return ll_mknod_generic(dir, &dentry->d_name, mode, 0, dentry);
+                
+        ll_d2d(dentry)->lld_it = NULL;
+        
+        /* Was there an error? Propagate it! */
+        if (it->d.lustre.it_status) {
+                rc = it->d.lustre.it_status;
+                goto out;
+        }       
+        
+        rc = ll_create_it(dir, dentry, mode, it);
+#ifdef HAVE_FILE_IN_STRUCT_INTENT
+        if (nd && (nd->flags & LOOKUP_OPEN) && dentry->d_inode) { /* Open */
+                nd->intent.open.file->private_data = it;
+                lookup_instantiate_filp(nd, dentry, NULL);
         }
+#else
+        ll_release_openhandle(dentry,it);
+#endif
+
+out:
+        ll_intent_release(it);
+        OBD_FREE(it, sizeof(*it));
+
+        return rc;
+}
+#else
+static int ll_create_nd(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
+{
+        if (!nd || !nd->intent.d.lustre.it_disposition)
+                /* No saved request? Just mknod the file */
+                return ll_mknod_generic(dir, &dentry->d_name, mode, 0, dentry);
 
         return ll_create_it(dir, dentry, mode, &nd->intent);
 }
 #endif
+#endif
 
 static int ll_symlink_generic(struct inode *dir, struct dentry *dchild,
                               const char *tgt)
@@ -677,10 +900,10 @@ static int ll_symlink_generic(struct inode *dir, struct dentry *dchild,
                         0, &request);
         OBD_FREE_PTR(op_data);
         if (err == 0) {
-                ll_update_times(request, 0, dir);
+                ll_update_times(request, REPLY_REC_OFF, dir);
 
                 if (dchild) {
-                        err = ll_prep_inode(&inode, request, 0,
+                        err = ll_prep_inode(&inode, request, REPLY_REC_OFF,
                                             dchild->d_sb);
                         if (err == 0)
                                 d_instantiate(dchild, inode);
@@ -713,7 +936,7 @@ static int ll_link_generic(struct inode *src,  struct inode *dir,
         err = md_link(sbi->ll_md_exp, op_data, &request);
         OBD_FREE_PTR(op_data);
         if (err == 0)
-                ll_update_times(request, 0, dir);
+                ll_update_times(request, REPLY_REC_OFF, dir);
 
         ptlrpc_req_finished(request);
         RETURN(err);
@@ -755,9 +978,9 @@ static int ll_mkdir_generic(struct inode *dir, struct qstr *name,
                         current->fsuid, current->fsgid,
                         current->cap_effective, 0, &request);
         OBD_FREE_PTR(op_data);
-        ll_update_times(request, 0, dir);
+        ll_update_times(request, REPLY_REC_OFF, dir);
         if (!err && dchild) {
-                err = ll_prep_inode(&inode, request, 0,
+                err = ll_prep_inode(&inode, request, REPLY_REC_OFF,
                                     dchild->d_sb);
                 if (err)
                         GOTO(out, err);
@@ -801,7 +1024,7 @@ static int ll_rmdir_generic(struct inode *dir, struct dentry *dparent,
         rc = md_unlink(ll_i2sbi(dir)->ll_md_exp, op_data, &request);
         OBD_FREE_PTR(op_data);
         if (rc == 0)
-                ll_update_times(request, 0, dir);
+                ll_update_times(request, REPLY_REC_OFF, dir);
         ptlrpc_req_finished(request);
         RETURN(rc);
 }
@@ -817,7 +1040,7 @@ int ll_objects_destroy(struct ptlrpc_request *request, struct inode *dir)
         ENTRY;
 
         /* req is swabbed so this is safe */
-        body = lustre_msg_buf(request->rq_repmsg, 0, sizeof(*body));
+        body = lustre_msg_buf(request->rq_repmsg, REPLY_REC_OFF, sizeof(*body));
 
         if (!(body->valid & OBD_MD_FLEASIZE))
                 RETURN(0);
@@ -831,7 +1054,8 @@ int ll_objects_destroy(struct ptlrpc_request *request, struct inode *dir)
          * to this file. Use this EA to unlink the objects on the OST.
          * It's opaque so we don't swab here; we leave it to obd_unpackmd() to
          * check it is complete and sensible. */
-        eadata = lustre_swab_repbuf(request, 1, body->eadatasize, NULL);
+        eadata = lustre_swab_repbuf(request, REPLY_REC_OFF + 1,
+                                    body->eadatasize, NULL);
         LASSERT(eadata != NULL);
         if (eadata == NULL) {
                 CERROR("Can't unpack MDS EA data\n");
@@ -860,7 +1084,7 @@ int ll_objects_destroy(struct ptlrpc_request *request, struct inode *dir)
         if (body->valid & OBD_MD_FLCOOKIE) {
                 oa->o_valid |= OBD_MD_FLCOOKIE;
                 oti.oti_logcookies =
-                        lustre_msg_buf(request->rq_repmsg, 2,
+                        lustre_msg_buf(request->rq_repmsg, REPLY_REC_OFF + 2,
                                        sizeof(struct llog_cookie) *
                                        lsm->lsm_stripe_count);
                 if (oti.oti_logcookies == NULL) {
@@ -900,7 +1124,7 @@ static int ll_unlink_generic(struct inode * dir, struct qstr *name)
         if (rc)
                 GOTO(out, rc);
 
-        ll_update_times(request, 0, dir);
+        ll_update_times(request, REPLY_REC_OFF, dir);
 
         rc = ll_objects_destroy(request, dir);
  out:
@@ -931,8 +1155,8 @@ static int ll_rename_generic(struct inode *src, struct qstr *src_name,
                         tgt_name->name, tgt_name->len, &request);
         OBD_FREE_PTR(op_data);
         if (!err) {
-                ll_update_times(request, 0, src);
-                ll_update_times(request, 0, tgt);
+                ll_update_times(request, REPLY_REC_OFF, src);
+                ll_update_times(request, REPLY_REC_OFF, tgt);
                 err = ll_objects_destroy(request, src);
         }
 
@@ -941,6 +1165,7 @@ static int ll_rename_generic(struct inode *src, struct qstr *src_name,
         RETURN(err);
 }
 
+#ifdef LUSTRE_KERNEL_VERSION
 static int ll_mknod_raw(struct nameidata *nd, int mode, dev_t rdev)
 {
         return ll_mknod_generic(nd->dentry->d_inode, &nd->last, mode,rdev,NULL);
@@ -971,6 +1196,7 @@ static int ll_unlink_raw(struct nameidata *nd)
 {
         return ll_unlink_generic(nd->dentry->d_inode, &nd->last);
 }
+#endif
 
 static int ll_mknod(struct inode *dir, struct dentry *dchild, int mode,
                     ll_dev_t rdev)
@@ -1011,16 +1237,18 @@ static int ll_rename(struct inode *old_dir, struct dentry *old_dentry,
 #endif
 
 struct inode_operations ll_dir_inode_operations = {
+#ifdef LUSTRE_KERNEL_VERSION
         .link_raw           = ll_link_raw,
         .unlink_raw         = ll_unlink_raw,
         .symlink_raw        = ll_symlink_raw,
         .mkdir_raw          = ll_mkdir_raw,
         .rmdir_raw          = ll_rmdir_raw,
         .mknod_raw          = ll_mknod_raw,
-        .mknod              = ll_mknod,
         .rename_raw         = ll_rename_raw,
         .setattr            = ll_setattr,
         .setattr_raw        = ll_setattr_raw,
+#endif
+        .mknod              = ll_mknod,
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
         .create_it          = ll_create_it,
         .lookup_it          = ll_lookup_it,
@@ -1028,7 +1256,6 @@ struct inode_operations ll_dir_inode_operations = {
 #else
         .lookup             = ll_lookup_nd,
         .create             = ll_create_nd,
-        .getattr_it         = ll_getattr_it,
         /* We need all these non-raw things for NFSD, to not patch it. */
         .unlink             = ll_unlink,
         .mkdir              = ll_mkdir,
@@ -1047,11 +1274,13 @@ struct inode_operations ll_dir_inode_operations = {
 };
 
 struct inode_operations ll_special_inode_operations = {
+#ifdef LUSTRE_KERNEL_VERSION
         .setattr_raw    = ll_setattr_raw,
+#endif
         .setattr        = ll_setattr,
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
-        .getattr_it     = ll_getattr_it,
-#else
+        .getattr        = ll_getattr,
+#else   
         .revalidate_it  = ll_inode_revalidate_it,
 #endif
         .permission     = ll_inode_permission,
index 8c0a8d2..57c8a45 100644 (file)
@@ -63,6 +63,7 @@ static int ll_brw(int cmd, struct inode *inode, struct obdo *oa,
 {
         struct ll_inode_info *lli = ll_i2info(inode);
         struct lov_stripe_md *lsm = lli->lli_smd;
+        struct obd_info oinfo = { { { 0 } } };
         struct brw_page pg;
         int rc;
         ENTRY;
@@ -93,7 +94,9 @@ static int ll_brw(int cmd, struct inode *inode, struct obdo *oa,
         else
                 lprocfs_counter_add(ll_i2sbi(inode)->ll_stats,
                                     LPROC_LL_BRW_READ, pg.count);
-        rc = obd_brw(cmd, ll_i2dtexp(inode), oa, lsm, 1, &pg, NULL);
+        oinfo.oi_oa = oa;
+        oinfo.oi_md = lsm;
+        rc = obd_brw(cmd, ll_i2dtexp(inode), &oinfo, 1, &pg, NULL);
         if (rc == 0)
                 obdo_to_inode(inode, oa, OBD_MD_FLBLOCKS);
         else if (rc != -EIO)
@@ -110,7 +113,7 @@ static int ll_brw(int cmd, struct inode *inode, struct obdo *oa,
 void ll_truncate(struct inode *inode)
 {
         struct ll_inode_info *lli = ll_i2info(inode);
-        struct lov_stripe_md *lsm = lli->lli_smd;
+        struct obd_info oinfo = { { { 0 } } };
         struct ost_lvb lvb;
         struct obdo oa;
         int rc;
@@ -123,7 +126,7 @@ void ll_truncate(struct inode *inode)
                 return;
         }
 
-        if (!lsm) {
+        if (!lli->lli_smd) {
                 CDEBUG(D_INODE, "truncate on inode %lu with no objects\n",
                        inode->i_ino);
                 GOTO(out_unlock, 0);
@@ -133,18 +136,18 @@ void ll_truncate(struct inode *inode)
 
         /* XXX I'm pretty sure this is a hack to paper over a more fundamental
          * race condition. */
-        lov_stripe_lock(lsm);
+        lov_stripe_lock(lli->lli_smd);
         inode_init_lvb(inode, &lvb);
-        obd_merge_lvb(ll_i2dtexp(inode), lsm, &lvb, 0);
+        obd_merge_lvb(ll_i2dtexp(inode), lli->lli_smd, &lvb, 0);
         if (lvb.lvb_size == inode->i_size) {
                 CDEBUG(D_VFSTRACE, "skipping punch for obj "LPX64", %Lu=%#Lx\n",
-                       lsm->lsm_object_id, inode->i_size, inode->i_size);
-                lov_stripe_unlock(lsm);
+                       lli->lli_smd->lsm_object_id, inode->i_size, inode->i_size);
+                lov_stripe_unlock(lli->lli_smd);
                 GOTO(out_unlock, 0);
         }
 
-        obd_adjust_kms(ll_i2dtexp(inode), lsm, inode->i_size, 1);
-        lov_stripe_unlock(lsm);
+        obd_adjust_kms(ll_i2dtexp(inode), lli->lli_smd, inode->i_size, 1);
+        lov_stripe_unlock(lli->lli_smd);
 
         if (unlikely((ll_i2sbi(inode)->ll_flags & LL_SBI_CHECKSUM) &&
                      (inode->i_size & ~PAGE_MASK))) {
@@ -164,9 +167,13 @@ void ll_truncate(struct inode *inode)
         }
 
         CDEBUG(D_INFO, "calling punch for "LPX64" (new size %Lu=%#Lx)\n",
-               lsm->lsm_object_id, inode->i_size, inode->i_size);
+               lli->lli_smd->lsm_object_id, inode->i_size, inode->i_size);
 
-        oa.o_id = lsm->lsm_object_id;
+        oinfo.oi_md = lli->lli_smd;
+        oinfo.oi_policy.l_extent.start = inode->i_size;
+        oinfo.oi_policy.l_extent.end = OBD_OBJECT_EOF;
+        oinfo.oi_oa = &oa;
+        oa.o_id = lli->lli_smd->lsm_object_id;
         oa.o_valid = OBD_MD_FLID;
 
         obdo_from_inode(&oa, inode, OBD_MD_FLTYPE | OBD_MD_FLMODE |
@@ -175,8 +182,7 @@ void ll_truncate(struct inode *inode)
 
         ll_inode_size_unlock(inode, 0);
 
-        rc = obd_punch(ll_i2dtexp(inode), &oa, lsm, inode->i_size,
-                       OBD_OBJECT_EOF, NULL);
+        rc = obd_punch_rqset(ll_i2dtexp(inode), &oinfo, NULL);
         if (rc)
                 CERROR("obd_truncate fails (%d) ino %lu\n", rc, inode->i_ino);
         else
@@ -196,6 +202,7 @@ int ll_prepare_write(struct file *file, struct page *page, unsigned from,
         struct ll_inode_info *lli = ll_i2info(inode);
         struct lov_stripe_md *lsm = lli->lli_smd;
         obd_off offset = ((obd_off)page->index) << PAGE_SHIFT;
+        struct obd_info oinfo = { { { 0 } } };
         struct brw_page pga;
         struct obdo oa;
         struct ost_lvb lvb;
@@ -216,8 +223,9 @@ int ll_prepare_write(struct file *file, struct page *page, unsigned from,
         oa.o_valid = OBD_MD_FLID | OBD_MD_FLMODE | OBD_MD_FLTYPE;
         obdo_from_inode(&oa, inode, OBD_MD_FLFID | OBD_MD_FLGENER);
 
-        rc = obd_brw(OBD_BRW_CHECK, ll_i2dtexp(inode), &oa, lsm,
-                     1, &pga, NULL);
+        oinfo.oi_oa = &oa;
+        oinfo.oi_md = lsm;
+        rc = obd_brw(OBD_BRW_CHECK, ll_i2dtexp(inode), &oinfo, 1, &pga, NULL);
         if (rc)
                 RETURN(rc);
 
@@ -360,8 +368,6 @@ void ll_inode_fill_obdo(struct inode *inode, int cmd, struct obdo *oa)
         if (cmd & OBD_BRW_WRITE) {
                 oa->o_valid |= OBD_MD_FLEPOCH;
                 oa->o_easize = ll_i2info(inode)->lli_io_epoch;
-                oa->o_uid = inode->i_uid;
-                oa->o_gid = inode->i_gid;
 
                 valid_flags |= OBD_MD_FLMTIME | OBD_MD_FLCTIME |
                         OBD_MD_FLUID | OBD_MD_FLGID |
@@ -382,10 +388,23 @@ static void ll_ap_fill_obdo(void *data, int cmd, struct obdo *oa)
         EXIT;
 }
 
+static void ll_ap_update_obdo(void *data, int cmd, struct obdo *oa,
+                              obd_valid valid)
+{
+        struct ll_async_page *llap;
+        ENTRY;
+
+        llap = LLAP_FROM_COOKIE(data);
+        obdo_from_inode(oa, llap->llap_page->mapping->host, valid);
+
+        EXIT;
+}
+
 static struct obd_async_page_ops ll_async_page_ops = {
         .ap_make_ready =        ll_ap_make_ready,
         .ap_refresh_count =     ll_ap_refresh_count,
         .ap_fill_obdo =         ll_ap_fill_obdo,
+        .ap_update_obdo =       ll_ap_update_obdo,
         .ap_completion =        ll_ap_completion,
 };
 
@@ -814,10 +833,11 @@ static void ll_ra_count_put(struct ll_sb_info *sbi, unsigned long len)
 }
 
 /* called for each page in a completed rpc.*/
-void ll_ap_completion(void *data, int cmd, struct obdo *oa, int rc)
+int ll_ap_completion(void *data, int cmd, struct obdo *oa, int rc)
 {
         struct ll_async_page *llap;
         struct page *page;
+        int ret = 0;
         ENTRY;
 
         llap = LLAP_FROM_COOKIE(data);
@@ -842,6 +862,7 @@ void ll_ap_completion(void *data, int cmd, struct obdo *oa, int rc)
                         llap->llap_defer_uptodate = 0;
                 } else {
                         ll_redirty_page(page);
+                        ret = 1;
                 }
                 SetPageError(page);
         }
@@ -857,7 +878,8 @@ void ll_ap_completion(void *data, int cmd, struct obdo *oa, int rc)
                 end_page_writeback(page);
         }
         page_cache_release(page);
-        EXIT;
+
+        RETURN(ret);
 }
 
 /* the kernel calls us here when a page is unhashed from the page cache.
@@ -1211,7 +1233,7 @@ static int ll_readahead(struct ll_readahead_state *ras,
 
 static void ras_set_start(struct ll_readahead_state *ras, unsigned long index)
 {
-        ras->ras_window_start = index & (~(PTLRPC_MAX_BRW_PAGES - 1));
+        ras->ras_window_start = index & (~((1024 * 1024 >> PAGE_SHIFT) - 1));
 }
 
 /* called with the ras_lock held or from places where it doesn't matter */
@@ -1275,7 +1297,7 @@ static void ras_update(struct ll_sb_info *sbi, struct inode *inode,
 
                 kms_pages = (inode->i_size + PAGE_SIZE - 1) >> PAGE_CACHE_SHIFT;
 
-                CDEBUG(D_READA, "kmsp %llu mwp %lu mp %lu\n", kms_pages,
+                CDEBUG(D_READA, "kmsp "LPU64" mwp %lu mp %lu\n", kms_pages,
                        ra->ra_max_read_ahead_whole_pages, ra->ra_max_pages);
 
                 if (kms_pages &&
@@ -1303,7 +1325,7 @@ static void ras_update(struct ll_sb_info *sbi, struct inode *inode,
         /* Trigger RA in the mmap case where ras_consecutive_requests
          * is not incremented and thus can't be used to trigger RA */
         if (!ras->ras_window_len && ras->ras_consecutive_pages == 3) {
-                ras->ras_window_len = PTLRPC_MAX_BRW_PAGES;
+                ras->ras_window_len = 1024 * 1024 >> PAGE_SHIFT;
                 GOTO(out_unlock, 0);
         }
 
@@ -1312,7 +1334,7 @@ static void ras_update(struct ll_sb_info *sbi, struct inode *inode,
          * only increased once per consecutive request received. */
         if (ras->ras_consecutive_requests > 1 && !ras->ras_request_index) {
                 ras->ras_window_len = min(ras->ras_window_len +
-                                          PTLRPC_MAX_BRW_PAGES,
+                                          (1024 * 1024 >> PAGE_SHIFT),
                                           ra->ra_max_pages);
         }
 
@@ -1402,7 +1424,6 @@ int ll_readpage(struct file *filp, struct page *page)
                 ll_truncate_complete_page(page);
                 clear_page(page);
                 SetPageUptodate(page);
-                unlock_page(page);
                 RETURN(0);
         }
 
index 98c4a4c..5d2bd2f 100644 (file)
@@ -64,7 +64,6 @@ static int ll_direct_IO_24(int rw,
         struct ll_inode_info *lli = ll_i2info(inode);
         struct lov_stripe_md *lsm = lli->lli_smd;
         struct brw_page *pga;
-        struct ptlrpc_request_set *set;
         struct obdo oa;
         int length, i, flags, rc = 0;
         loff_t offset;
@@ -78,15 +77,9 @@ static int ll_direct_IO_24(int rw,
             (iobuf->length & (PAGE_SIZE - 1)))
                 RETURN(-EINVAL);
 
-        set = ptlrpc_prep_set();
-        if (set == NULL)
-                RETURN(-ENOMEM);
-
         OBD_ALLOC(pga, sizeof(*pga) * iobuf->nr_pages);
-        if (!pga) {
-                ptlrpc_set_destroy(set);
+        if (!pga)
                 RETURN(-ENOMEM);
-        }
 
         flags = 0 /* | OBD_BRW_DIRECTIO */;
         offset = ((obd_off)blocknr << inode->i_blkbits);
@@ -113,17 +106,8 @@ static int ll_direct_IO_24(int rw,
         else
                 lprocfs_counter_add(ll_i2sbi(inode)->ll_stats,
                                     LPROC_LL_DIRECT_READ, iobuf->length);
-        rc = obd_brw_async(rw, ll_i2dtexp(inode), &oa, lsm, iobuf->nr_pages,
-                           pga, set, NULL);
-        if (rc) {
-                CDEBUG(rc == -ENOSPC ? D_INODE : D_ERROR,
-                       "error from obd_brw_async: rc = %d\n", rc);
-        } else {
-                rc = ptlrpc_set_wait(set);
-                if (rc)
-                        CERROR("error from callback: rc = %d\n", rc);
-        }
-        ptlrpc_set_destroy(set);
+        rc = obd_brw_rqset(rw, ll_i2dtexp(inode), &oa, lsm, iobuf->nr_pages,
+                           pga, NULL);
         if (rc == 0) {
                 rc = iobuf->length;
                 if (rw == OBD_BRW_WRITE) {
index 598c130..349eab7 100644 (file)
@@ -75,10 +75,160 @@ static int ll_releasepage(struct page *page, gfp_t gfp_mask)
         return 1;
 }
 
+#define MAX_DIRECTIO_SIZE 2*1024*1024*1024UL
+
+static inline int ll_get_user_pages(int rw, unsigned long user_addr,
+                                    size_t size, struct page ***pages)
+{
+        int result = -ENOMEM;
+        unsigned long page_count;
+
+        /* set an arbitrary limit to prevent arithmetic overflow */
+        if (size > MAX_DIRECTIO_SIZE) {
+                *pages = NULL;
+                return -EFBIG;
+        }
+
+        page_count = (user_addr + size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+        page_count -= user_addr >> PAGE_SHIFT;
+
+        OBD_ALLOC_GFP(*pages, page_count * sizeof(**pages), GFP_KERNEL);
+        if (*pages) {
+                down_read(&current->mm->mmap_sem);
+                result = get_user_pages(current, current->mm, user_addr,
+                                        page_count, (rw == READ), 0, *pages,
+                                        NULL);
+                up_read(&current->mm->mmap_sem);
+        }
+
+        return result;
+}
+
+/*  ll_free_user_pages - tear down page struct array
+ *  @pages: array of page struct pointers underlying target buffer */
+static void ll_free_user_pages(struct page **pages, int npages, int do_dirty)
+{
+        int i;
+
+        for (i = 0; i < npages; i++) {
+                if (do_dirty)
+                        set_page_dirty_lock(pages[i]);
+                page_cache_release(pages[i]);
+        }
+
+        OBD_FREE(pages, npages * sizeof(*pages));
+}
+
+static ssize_t ll_direct_IO_26_seg(int rw, struct file *file,
+                                   struct address_space *mapping,
+                                   struct inode *inode,
+                                   struct lov_stripe_md *lsm,
+                                   unsigned long user_addr, size_t size,
+                                   loff_t file_offset, struct page **pages,
+                                   int page_count)
+{
+        struct brw_page *pga;
+        struct obdo oa;
+        int i, rc = 0;
+        size_t length;
+        ENTRY;
+
+        OBD_ALLOC(pga, sizeof(*pga) * page_count);
+        if (!pga)
+                RETURN(-ENOMEM);
+
+        for (i = 0, length = size; length > 0;
+             length -=pga[i].count, file_offset +=pga[i].count,i++) {/*i last!*/
+                pga[i].pg = pages[i];
+                pga[i].off = file_offset;
+                /* To the end of the page, or the length, whatever is less */
+                pga[i].count = min_t(int, PAGE_SIZE -(file_offset & ~PAGE_MASK),
+                                     length);
+                pga[i].flag = 0;
+                if (rw == READ)
+                        POISON_PAGE(pages[i], 0x0d);
+        }
+
+        ll_inode_fill_obdo(inode, rw, &oa);
+
+        if (rw == WRITE)
+                lprocfs_counter_add(ll_i2sbi(inode)->ll_stats,
+                                    LPROC_LL_DIRECT_WRITE, size);
+        else
+                lprocfs_counter_add(ll_i2sbi(inode)->ll_stats,
+                                    LPROC_LL_DIRECT_READ, size);
+        rc = obd_brw_rqset(rw == WRITE ? OBD_BRW_WRITE : OBD_BRW_READ,
+                           ll_i2dtexp(inode), &oa, lsm, page_count, pga, NULL);
+        if (rc == 0) {
+                rc = size;
+                if (rw == WRITE) {
+                        lov_stripe_lock(lsm);
+                        obd_adjust_kms(ll_i2dtexp(inode), lsm, file_offset, 0);
+                        lov_stripe_unlock(lsm);
+                }
+        }
+
+        OBD_FREE(pga, sizeof(*pga) * page_count);
+        RETURN(rc);
+}
+
+static ssize_t ll_direct_IO_26(int rw, struct kiocb *iocb,
+                               const struct iovec *iov, loff_t file_offset,
+                               unsigned long nr_segs)
+{
+        struct file *file = iocb->ki_filp;
+        ssize_t count = iov_length(iov, nr_segs), tot_bytes = 0;
+        struct ll_inode_info *lli = ll_i2info(file->f_mapping->host);
+        unsigned long seg = 0;
+        ENTRY;
+
+        if (!lli->lli_smd || !lli->lli_smd->lsm_object_id)
+                RETURN(-EBADF);
+
+        /* FIXME: io smaller than PAGE_SIZE is broken on ia64 ??? */
+        if ((file_offset & (PAGE_SIZE - 1)) || (count & (PAGE_SIZE - 1)))
+                RETURN(-EINVAL);
+
+        while ((seg < nr_segs) && (tot_bytes >= 0)) {
+                const struct iovec *vec = &iov[seg++];
+                unsigned long user_addr = (unsigned long)vec->iov_base;
+                size_t size = vec->iov_len;
+                struct page **pages;
+                int page_count;
+                ssize_t result;
+
+                page_count = ll_get_user_pages(rw, user_addr, size, &pages);
+                if (page_count < 0) {
+                        ll_free_user_pages(pages, 0, 0);
+                        if (tot_bytes > 0)
+                                break;
+                        return page_count;
+                }
+
+                result = ll_direct_IO_26_seg(rw, file, file->f_mapping,
+                                             file->f_mapping->host,
+                                             lli->lli_smd, user_addr, size,
+                                             file_offset, pages, page_count);
+                ll_free_user_pages(pages, page_count, rw == READ);
+
+                if (result <= 0) {
+                        if (tot_bytes > 0)
+                                break;
+                        return result;
+                }
+
+                tot_bytes += result;
+                file_offset += result;
+                if (result < size)
+                        break;
+        }
+        return tot_bytes;
+}
+
 struct address_space_operations ll_aops = {
         .readpage       = ll_readpage,
 //        .readpages      = ll_readpages,
-//        .direct_IO      = ll_direct_IO_26,
+        .direct_IO      = ll_direct_IO_26,
         .writepage      = ll_writepage_26,
         .writepages     = generic_writepages,
         .set_page_dirty = __set_page_dirty_nobuffers,
index eb16296..a5ca4b2 100644 (file)
@@ -56,6 +56,9 @@ struct super_operations lustre_super_operations =
         .remount_fs     = ll_remount_fs,
 };
 
+
+void lustre_register_client_process_config(int (*cpc)(struct lustre_cfg *lcfg));
+
 static int __init init_lustre_lite(void)
 {
         int rc, seed[2];
@@ -74,6 +77,7 @@ static int __init init_lustre_lite(void)
         ll_register_cache(&ll_cache_definition);
 
         lustre_register_client_fill_super(ll_fill_super);
+        lustre_register_client_process_config(ll_process_config);
 
         get_random_bytes(seed, sizeof(seed));
         ll_srand(seed[0], seed[1]);
@@ -84,8 +88,10 @@ static int __init init_lustre_lite(void)
 static void __exit exit_lustre_lite(void)
 {
         int rc;
+        int rc;
 
         lustre_register_client_fill_super(NULL);
+        lustre_register_client_process_config(NULL);
         
         ll_unregister_cache(&ll_cache_definition);
 
index 976fcca..2dd87ad 100644 (file)
@@ -80,7 +80,6 @@ int ll_init_inodecache(void)
 void ll_destroy_inodecache(void)
 {
         int rc;
-
         rc = kmem_cache_destroy(ll_inode_cachep);
         LASSERTF(rc == 0, "ll_inode_cache: not all structures were freed\n");
 }
@@ -99,6 +98,8 @@ struct super_operations lustre_super_operations =
 };
 
 
+void lustre_register_client_process_config(int (*cpc)(struct lustre_cfg *lcfg));
+
 static int __init init_lustre_lite(void)
 {
         int rc, seed[2];
@@ -121,6 +122,7 @@ static int __init init_lustre_lite(void)
         ll_register_cache(&ll_cache_definition);
         
         lustre_register_client_fill_super(ll_fill_super);
+        lustre_register_client_process_config(ll_process_config);
         
         get_random_bytes(seed, sizeof(seed));
         ll_srand(seed[0], seed[1]);
@@ -133,10 +135,12 @@ static void __exit exit_lustre_lite(void)
         int rc;
 
         lustre_register_client_fill_super(NULL);
+        lustre_register_client_process_config(NULL);
 
         ll_unregister_cache(&ll_cache_definition);
 
         ll_destroy_inodecache();
+
         rc = kmem_cache_destroy(ll_file_data_slab);
         LASSERTF(rc == 0, "couldn't destroy ll_file_data slab\n");
         if (ll_async_page_slab) {
index 990a9c1..0765586 100644 (file)
@@ -54,29 +54,31 @@ static int ll_readlink_internal(struct inode *inode,
                 GOTO (failed, rc);
         }
 
-        body = lustre_msg_buf ((*request)->rq_repmsg, 0, sizeof (*body));
-        LASSERT (body != NULL);
-        LASSERT_REPSWABBED (*request, 0);
+        body = lustre_msg_buf((*request)->rq_repmsg, REPLY_REC_OFF,
+                              sizeof(*body));
+        LASSERT(body != NULL);
+        LASSERT_REPSWABBED(*request, REPLY_REC_OFF);
 
         if ((body->valid & OBD_MD_LINKNAME) == 0) {
-                CERROR ("OBD_MD_LINKNAME not set on reply\n");
-                GOTO (failed, rc = -EPROTO);
+                CERROR("OBD_MD_LINKNAME not set on reply\n");
+                GOTO(failed, rc = -EPROTO);
         }
         
-        LASSERT (symlen != 0);
+        LASSERT(symlen != 0);
         if (body->eadatasize != symlen) {
-                CERROR ("inode %lu: symlink length %d not expected %d\n",
+                CERROR("inode %lu: symlink length %d not expected %d\n",
                         inode->i_ino, body->eadatasize - 1, symlen - 1);
-                GOTO (failed, rc = -EPROTO);
+                GOTO(failed, rc = -EPROTO);
         }
 
-        *symname = lustre_msg_buf ((*request)->rq_repmsg, 1, symlen);
+        *symname = lustre_msg_buf((*request)->rq_repmsg, REPLY_REC_OFF + 1,
+                                  symlen);
         if (*symname == NULL ||
             strnlen (*symname, symlen) != symlen - 1) {
                 /* not full/NULL terminated */
-                CERROR ("inode %lu: symlink not NULL terminated string"
+                CERROR("inode %lu: symlink not NULL terminated string"
                         "of length %d\n", inode->i_ino, symlen - 1);
-                GOTO (failed, rc = -EPROTO);
+                GOTO(failed, rc = -EPROTO);
         }
 
         OBD_ALLOC(lli->lli_symlink_name, symlen);
@@ -118,12 +120,23 @@ static int ll_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
         struct inode *inode = dentry->d_inode;
         struct ll_inode_info *lli = ll_i2info(inode);
+#ifdef LUSTRE_KERNEL_VERSION
         struct lookup_intent *it = ll_nd2it(nd);
+#endif
         struct ptlrpc_request *request;
         int rc;
         char *symname;
         ENTRY;
 
+#ifdef CONFIG_4KSTACKS
+        if (current->link_count >= 5) {
+                path_release(nd); /* Kernel assumes that ->follow_link()
+                                     releases nameidata on error */
+                GOTO(out, rc = -ELOOP);
+        }
+#endif  
+
+#ifdef LUSTRE_KERNEL_VERSION
         if (it != NULL) {
                 int op = it->it_op;
                 int mode = it->it_create_mode;
@@ -132,6 +145,7 @@ static int ll_follow_link(struct dentry *dentry, struct nameidata *nd)
                 it->it_op = op;
                 it->it_create_mode = mode;
         }
+#endif
 
         CDEBUG(D_VFSTRACE, "VFS Op\n");
         down(&lli->lli_open_sem);
@@ -152,12 +166,14 @@ static int ll_follow_link(struct dentry *dentry, struct nameidata *nd)
 struct inode_operations ll_fast_symlink_inode_operations = {
         .readlink       = ll_readlink,
         .setattr        = ll_setattr,
+#ifdef LUSTRE_KERNEL_VERSION
         .setattr_raw    = ll_setattr_raw,
+#endif
         .follow_link    = ll_follow_link,
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
         .revalidate_it  = ll_inode_revalidate_it,
 #else 
-        .getattr_it     = ll_getattr_it,
+        .getattr        = ll_getattr,
 #endif
         .permission     = ll_inode_permission,
         .setxattr       = ll_setxattr,
index cbfc0da..63fe107 100644 (file)
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp_lock.h>
-#ifdef HAVE_LINUX_XATTR_ACL_H
-#include <linux/xattr_acl.h>
-#else
-#define XATTR_NAME_ACL_ACCESS   "system.posix_acl_access"
-#define XATTR_NAME_ACL_DEFAULT  "system.posix_acl_default"
-#endif
 
 #define DEBUG_SUBSYSTEM S_LLITE
 
 #include <lustre_dlm.h>
 #include <lustre_ver.h>
 #include <lustre_mdc.h>
+#include <linux/lustre_acl.h>
+
+#if 0
+#ifndef POSIX_ACL_XATTR_ACCESS
+#ifndef XATTR_NAME_ACL_ACCESS
+#define XATTR_NAME_ACL_ACCESS   "system.posix_acl_access"
+#endif
+#define POSIX_ACL_XATTR_ACCESS XATTR_NAME_ACL_ACCESS
+#endif
+#ifndef POSIX_ACL_XATTR_DEFAULT
+#ifndef XATTR_NAME_ACL_DEFAULT
+#define XATTR_NAME_ACL_DEFAULT  "system.posix_acl_default"
+#endif
+#define POSIX_ACL_XATTR_DEFAULT XATTR_NAME_ACL_DEFAULT
+#endif
+#endif
 
 #include "llite_internal.h"
 
 static
 int get_xattr_type(const char *name)
 {
-        if (!strcmp(name, XATTR_NAME_ACL_ACCESS))
+        if (!strcmp(name, POSIX_ACL_XATTR_ACCESS))
                 return XATTR_ACL_ACCESS_T;
 
-        if (!strcmp(name, XATTR_NAME_ACL_DEFAULT))
+        if (!strcmp(name, POSIX_ACL_XATTR_DEFAULT))
                 return XATTR_ACL_DEFAULT_T;
 
         if (!strncmp(name, XATTR_USER_PREFIX,
@@ -188,6 +198,7 @@ int ll_getxattr_common(struct inode *inode, const char *name,
          * we just have path resolution to the target inode, so we have great
          * chance that cached ACL is uptodate.
          */
+#ifdef CONFIG_FS_POSIX_ACL
         if (xattr_type == XATTR_ACL_ACCESS_T) {
                 struct ll_inode_info *lli = ll_i2info(inode);
                 struct posix_acl *acl;
@@ -203,6 +214,7 @@ int ll_getxattr_common(struct inode *inode, const char *name,
                 posix_acl_release(acl);
                 RETURN(rc);
         }
+#endif
 
 do_getxattr:
         rc = md_getxattr(sbi->ll_md_exp, ll_inode2fid(inode), valid,
@@ -216,9 +228,9 @@ do_getxattr:
                 RETURN(rc);
         }
 
-        body = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*body));
+        body = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF, sizeof(*body));
         LASSERT(body);
-        LASSERT_REPSWABBED(req, 0);
+        LASSERT_REPSWABBED(req, REPLY_REC_OFF);
 
         /* only detect the xattr size */
         if (size == 0)
@@ -230,17 +242,19 @@ do_getxattr:
                 GOTO(out, rc = -ERANGE);
         }
 
-        if (req->rq_repmsg->bufcount < 2) {
-                CERROR("reply bufcount %u\n", req->rq_repmsg->bufcount);
+        if (lustre_msg_bufcount(req->rq_repmsg) < 3) {
+                CERROR("reply bufcount %u\n",
+                       lustre_msg_bufcount(req->rq_repmsg));
                 GOTO(out, rc = -EFAULT);
         }
 
         /* do not need swab xattr data */
-        LASSERT_REPSWAB(req, 1);
-        xdata = lustre_msg_buf(req->rq_repmsg, 1, body->eadatasize);
+        LASSERT_REPSWAB(req, REPLY_REC_OFF + 1);
+        xdata = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF + 1,
+                               body->eadatasize);
         if (!xdata) {
                 CERROR("can't extract: %u : %u\n", body->eadatasize,
-                       lustre_msg_buflen(req->rq_repmsg, 1));
+                       lustre_msg_buflen(req->rq_repmsg, REPLY_REC_OFF + 1));
                 GOTO(out, rc = -EFAULT);
         }
 
index 760e545..ce0e3a8 100644 (file)
@@ -41,7 +41,6 @@
 #include <lustre_lib.h>
 #include <lustre_net.h>
 #include <lustre_dlm.h>
-#include <lustre_mds.h>
 #include <obd_class.h>
 #include <lprocfs_status.h>
 #include "lmv_internal.h"
@@ -69,7 +68,7 @@ int lmv_intent_remote(struct obd_export *exp, void *lmm,
         int pmode, i, rc = 0;
         ENTRY;
 
-        body = lustre_msg_buf((*reqp)->rq_repmsg, 1, sizeof(*body));
+        body = lustre_msg_buf((*reqp)->rq_repmsg, DLM_REPLY_REC_OFF, sizeof(*body));
         LASSERT(body != NULL);
 
         if (!(body->valid & OBD_MD_MDS))
@@ -233,7 +232,7 @@ repeat:
 
         /* caller may use attrs MDS returns on IT_OPEN lock request so, we have
          * to update them for splitted dir */
-        body = lustre_msg_buf((*reqp)->rq_repmsg, 1, sizeof(*body));
+        body = lustre_msg_buf((*reqp)->rq_repmsg, DLM_REPLY_REC_OFF, sizeof(*body));
         LASSERT(body != NULL);
 
         /* could not find object, FID is not present in response. */
@@ -242,7 +241,7 @@ repeat:
 
         cid = &body->fid1;
         obj = lmv_obj_grab(obd, cid);
-        if (!obj && (mea = lmv_get_mea(*reqp, 1))) {
+        if (!obj && (mea = lmv_get_mea(*reqp, DLM_REPLY_REC_OFF))) {
                 /* wow! this is splitted dir, we'd like to handle it */
                 obj = lmv_obj_create(exp, &body->fid1, mea);
                 if (IS_ERR(obj))
@@ -382,7 +381,7 @@ int lmv_intent_getattr(struct obd_export *exp, struct lu_fid *pid,
         if (it->d.lustre.it_disposition & DISP_LOOKUP_NEG)
                 GOTO(out_free_op_data, rc = 0);
 
-        body = lustre_msg_buf((*reqp)->rq_repmsg, 1, sizeof(*body));
+        body = lustre_msg_buf((*reqp)->rq_repmsg, DLM_REPLY_REC_OFF, sizeof(*body));
         LASSERT(body != NULL);
 
         /* could not find object, FID is not present in response. */
@@ -392,9 +391,9 @@ int lmv_intent_getattr(struct obd_export *exp, struct lu_fid *pid,
         cid = &body->fid1;
         obj2 = lmv_obj_grab(obd, cid);
 
-        if (!obj2 && (mea = lmv_get_mea(*reqp, 1))) {
+        if (!obj2 && (mea = lmv_get_mea(*reqp, DLM_REPLY_REC_OFF))) {
                 /* wow! this is splitted dir, we'd like to handle it. */
-                body = lustre_msg_buf((*reqp)->rq_repmsg, 1, sizeof(*body));
+                body = lustre_msg_buf((*reqp)->rq_repmsg, DLM_REPLY_REC_OFF, sizeof(*body));
                 LASSERT(body != NULL);
 
                 obj2 = lmv_obj_create(exp, &body->fid1, mea);
@@ -451,7 +450,7 @@ int lmv_lookup_slaves(struct obd_export *exp, struct ptlrpc_request **reqp)
          * last case possible only if all the objs (master and all slaves aren't
          * valid */
 
-        body = lustre_msg_buf((*reqp)->rq_repmsg, 1, sizeof(*body));
+        body = lustre_msg_buf((*reqp)->rq_repmsg, DLM_REPLY_REC_OFF, sizeof(*body));
         LASSERT(body != NULL);
         LASSERT((body->valid & OBD_MD_FLID) != 0);
 
@@ -511,7 +510,7 @@ int lmv_lookup_slaves(struct obd_export *exp, struct ptlrpc_request **reqp)
 
                 lock->l_ast_data = lmv_obj_get(obj);
 
-                body2 = lustre_msg_buf(req->rq_repmsg, 1, sizeof(*body2));
+                body2 = lustre_msg_buf(req->rq_repmsg, DLM_REPLY_REC_OFF, sizeof(*body2));
                 LASSERT(body2);
 
                 obj->lo_inodes[i].li_size = body2->size;
@@ -665,9 +664,9 @@ repeat:
         rc = lmv_intent_remote(exp, lmm, lmmsize, it, flags, reqp,
                                cb_blocking, extra_lock_flags);
 
-        if (rc == 0 && (mea = lmv_get_mea(*reqp, 1))) {
+        if (rc == 0 && (mea = lmv_get_mea(*reqp, DLM_REPLY_REC_OFF))) {
                 /* wow! this is splitted dir, we'd like to handle it */
-                body = lustre_msg_buf((*reqp)->rq_repmsg, 1, sizeof(*body));
+                body = lustre_msg_buf((*reqp)->rq_repmsg, DLM_REPLY_REC_OFF, sizeof(*body));
                 LASSERT(body != NULL);
                 LASSERT((body->valid & OBD_MD_FLID) != 0);
 
@@ -790,7 +789,8 @@ int lmv_revalidate_slaves(struct obd_export *exp, struct ptlrpc_request **reqp,
                                         /* it even got the reply refresh attrs
                                          * from that reply */
                                         body = lustre_msg_buf(mreq->rq_repmsg,
-                                                              1, sizeof(*body));
+                                                              DLM_REPLY_REC_OFF, 
+                                                              sizeof(*body));
                                         LASSERT(body != NULL);
                                         goto update;
                                 }
@@ -848,7 +848,7 @@ int lmv_revalidate_slaves(struct obd_export *exp, struct ptlrpc_request **reqp,
 
                 }
 
-                body = lustre_msg_buf(req->rq_repmsg, 1, sizeof(*body));
+                body = lustre_msg_buf(req->rq_repmsg, DLM_REPLY_REC_OFF, sizeof(*body));
                 LASSERT(body);
 
 update:
@@ -872,7 +872,8 @@ release_lock:
                 CDEBUG(D_OTHER, "return refreshed attrs: size = %lu\n",
                        (unsigned long)size);
 
-                body = lustre_msg_buf((*reqp)->rq_repmsg, 1, sizeof(*body));
+                body = lustre_msg_buf((*reqp)->rq_repmsg, 
+                                      DLM_REPLY_REC_OFF, sizeof(*body));
                 LASSERT(body);
 
                 /* FIXME: what about other attributes? */
index 3b5a389..637c4a6 100644 (file)
 #include <linux/namei.h>
 #else
 #include <liblustre.h>
-#include <lustre_log.h>
 #endif
 #include <linux/ext2_fs.h>
 
 #include <lustre/lustre_idl.h>
+#include <lustre_log.h>
 #include <obd_support.h>
 #include <lustre_lib.h>
 #include <lustre_net.h>
@@ -906,7 +906,7 @@ out:
 }
 
 static int lmv_statfs(struct obd_device *obd, struct obd_statfs *osfs,
-                      unsigned long max_age)
+                      __u64 max_age)
 {
         struct lmv_obd *lmv = &obd->u.lmv;
         struct obd_statfs *temp;
@@ -1060,7 +1060,7 @@ static int lmv_getattr(struct obd_export *exp, struct lu_fid *fid,
                         RETURN(rc);
                 }
 
-                body = lustre_msg_buf((*request)->rq_repmsg, 0,
+                body = lustre_msg_buf((*request)->rq_repmsg, REQ_REC_OFF,
                                       sizeof(*body));
                 LASSERT(body != NULL);
 
@@ -1235,7 +1235,7 @@ repeat:
                 if (*request == NULL)
                         RETURN(rc);
 
-                body = lustre_msg_buf((*request)->rq_repmsg, 0,
+                body = lustre_msg_buf((*request)->rq_repmsg, REQ_REC_OFF,
                                       sizeof(*body));
                 if (body == NULL)
                         RETURN(-ENOMEM);
@@ -1351,7 +1351,7 @@ lmv_enqueue_remote(struct obd_export *exp, int lock_type,
         int i, rc = 0, pmode;
         ENTRY;
 
-        body = lustre_msg_buf(req->rq_repmsg, 1, sizeof(*body));
+        body = lustre_msg_buf(req->rq_repmsg, DLM_REPLY_REC_OFF, sizeof(*body));
         LASSERT(body != NULL);
 
         if (!(body->valid & OBD_MD_MDS))
@@ -1488,7 +1488,7 @@ repeat:
                              &rid, filename, namelen,
                              valid, ea_size, request);
         if (rc == 0) {
-                body = lustre_msg_buf((*request)->rq_repmsg, 0, sizeof(*body));
+                body = lustre_msg_buf((*request)->rq_repmsg, REQ_REC_OFF, sizeof(*body));
                 LASSERT(body != NULL);
 
                 if (body->valid & OBD_MD_MDS) {
@@ -1724,7 +1724,7 @@ static int lmv_setattr(struct obd_export *exp, struct md_op_data *op_data,
                 rc = md_setattr(lmv->tgts[mds].ltd_exp, op_data, iattr, ea,
                                 ealen, ea2, ea2len, request);
                 if (rc == 0) {
-                        body = lustre_msg_buf((*request)->rq_repmsg, 0,
+                        body = lustre_msg_buf((*request)->rq_repmsg, REQ_REC_OFF,
                                               sizeof(*body));
                         LASSERT(body != NULL);
                 }
@@ -1796,7 +1796,7 @@ int lmv_blocking_ast(struct ldlm_lock *lock,
 static void lmv_remove_dots(struct page *page)
 {
         unsigned limit = PAGE_CACHE_SIZE;
-        char *kaddr = page_address(page);
+        char *kaddr = cfs_page_address(page);
         struct ext2_dir_entry_2 *p;
         unsigned offs, rec_len;
 
index 438422f..4a6a951 100755 (executable)
@@ -86,7 +86,6 @@ static void lsm_unpackmd_common(struct lov_stripe_md *lsm,
         lsm->lsm_object_gr = le64_to_cpu(lmm->lmm_object_gr);
         lsm->lsm_stripe_size = le32_to_cpu(lmm->lmm_stripe_size);
         lsm->lsm_pattern = le32_to_cpu(lmm->lmm_pattern);
-        lsm->lsm_xfersize = lsm->lsm_stripe_size * lsm->lsm_stripe_count;
 }
 
 static void
@@ -177,6 +176,11 @@ int lsm_unpackmd_plain(struct lov_obd *lov, struct lov_stripe_md *lsm,
                         lov_dump_lmm_v1(D_WARNING, lmm);
                         return -EINVAL;
                 }
+                if (!lov->lov_tgts[loi->loi_ost_idx]) {
+                        CERROR("OST index %d missing\n", loi->loi_ost_idx);
+                        lov_dump_lmm_v1(D_WARNING, lmm);
+                        return -EINVAL;
+                }
                 loi++;
         }
 
@@ -212,7 +216,7 @@ struct lov_extent *lovea_off2le(struct lov_stripe_md *lsm, obd_off lov_off)
                ; /* empty loop */
         }
 
-        CDEBUG(D_INFO, "off "LPU64" idx%d, ext"LPU64":"LPU64"idx%d sc%d\n",
+        CDEBUG(D_INFO, "off "LPU64" idx %d, ext "LPU64":"LPU64" idx %d sc %d\n",
                lov_off, i, le->le_start, le->le_len, le->le_loi_idx,
                le->le_stripe_count);
 
@@ -237,13 +241,12 @@ struct lov_extent *lovea_idx2le(struct lov_stripe_md *lsm, int stripe_no)
                 ; /* empty loop */
         }
 
-        CDEBUG(D_INFO, "stripe %d idx%d, ext"LPU64":"LPU64"idx %d scount%d\n",
+        CDEBUG(D_INFO, "stripe %d idx %d, ext "LPU64":"LPU64" idx %d sc %d\n",
                stripe_no, i, le->le_start, le->le_len, le->le_loi_idx,
                le->le_stripe_count);
         RETURN(le);
 }
 
-
 static void lovea_free_array_info(struct lov_stripe_md *lsm)
 {
         if (!lsm || !lsm->lsm_array)
index 5829fa9..1b6f31b 100644 (file)
@@ -20,29 +20,34 @@ struct lov_lock_handles {
 };
 
 struct lov_request {
+        struct obd_info          rq_oi;
+        struct lov_request_set  *rq_rqset;
+
         struct list_head         rq_link;
-        struct ldlm_extent       rq_extent;
+
         int                      rq_idx;        /* index in lov->tgts array */
         int                      rq_stripe;     /* stripe number */
         int                      rq_complete;
         int                      rq_rc;
         int                      rq_buflen;     /* length of sub_md */
-        struct obdo             *rq_oa;
-        struct lov_stripe_md    *rq_md;
+
         obd_count                rq_oabufs;
         obd_count                rq_pgaidx;
 };
 
 struct lov_request_set {
+        struct obd_enqueue_info *set_ei;
+        struct obd_info         *set_oi;
         atomic_t                 set_refcount;
         struct obd_export       *set_exp;
+        /* XXX: There is @set_exp already, however obd_statfs gets obd_device
+           only. */
+        struct obd_device       *set_obd;
         int                      set_count;
         int                      set_completes;
         int                      set_success;
         struct llog_cookie      *set_cookies;
         int                      set_cookie_sent;
-        struct lov_stripe_md    *set_md;
-        struct obdo             *set_oa;
         struct obd_trans_info   *set_oti;
         obd_count                set_oabufs;
         struct brw_page         *set_pga;
@@ -50,7 +55,7 @@ struct lov_request_set {
         struct list_head         set_list;
 };
 
-#define LAP_MAGIC 8200
+#define LOV_AP_MAGIC 8200
 
 struct lov_async_page {
         int                             lap_magic;
@@ -62,8 +67,8 @@ struct lov_async_page {
         void                            *lap_caller_data;
 };
 
-#define LAP_FROM_COOKIE(c)                                                      \
-        (LASSERT(((struct lov_async_page *)(c))->lap_magic == LAP_MAGIC),       \
+#define LAP_FROM_COOKIE(c)                                                     \
+        (LASSERT(((struct lov_async_page *)(c))->lap_magic == LOV_AP_MAGIC),   \
          (struct lov_async_page *)(c))
 
 static inline void lov_llh_addref(void *llhp)
@@ -110,6 +115,9 @@ static inline void lov_llh_put(struct lov_lock_handles *llh)
         }
 }
 
+#define lov_uuid2str(lv, index) \
+        (char *)((lv)->lov_tgts[index]->ltd_uuid.uuid)
+
 /* lov_merge.c */
 void lov_merge_attrs(struct obdo *tgt, struct obdo *src, obd_flag valid,
                      struct lov_stripe_md *lsm, int stripeno, int *set);
@@ -131,6 +139,8 @@ int lov_stripe_intersects(struct lov_stripe_md *lsm, int stripeno,
 int lov_stripe_number(struct lov_stripe_md *lsm, obd_off lov_off);
 
 /* lov_qos.c */
+int qos_add_tgt(struct obd_device *obd, __u32 index);
+int qos_del_tgt(struct obd_device *obd, __u32 index);
 void qos_shrink_lsm(struct lov_request_set *set);
 int qos_prep_create(struct obd_export *exp, struct lov_request_set *set);
 void qos_update(struct lov_obd *lov, int idx, struct obd_statfs *osfs);
@@ -138,68 +148,76 @@ int qos_remedy_create(struct lov_request_set *set, struct lov_request *req);
 
 /* lov_request.c */
 void lov_set_add_req(struct lov_request *req, struct lov_request_set *set);
+void lov_update_set(struct lov_request_set *set,
+                    struct lov_request *req, int rc);
 int lov_update_common_set(struct lov_request_set *set,
                           struct lov_request *req, int rc);
-int lov_prep_create_set(struct obd_export *exp, struct lov_stripe_md **ea,
-                        struct obdo *src_oa, struct obd_trans_info *oti,
+int lov_prep_create_set(struct obd_export *exp, struct obd_info *oifo,
+                        struct lov_stripe_md **ea, struct obdo *src_oa,
+                        struct obd_trans_info *oti,
                         struct lov_request_set **reqset);
 int lov_update_create_set(struct lov_request_set *set,
                           struct lov_request *req, int rc);
 int lov_fini_create_set(struct lov_request_set *set, struct lov_stripe_md **ea);
-int lov_prep_brw_set(struct obd_export *exp, struct obdo *src_oa,
-                     struct lov_stripe_md *lsm, obd_count oa_bufs,
-                     struct brw_page *pga, struct obd_trans_info *oti,
+int lov_prep_brw_set(struct obd_export *exp, struct obd_info *oinfo,
+                     obd_count oa_bufs, struct brw_page *pga,
+                     struct obd_trans_info *oti,
                      struct lov_request_set **reqset);
 int lov_fini_brw_set(struct lov_request_set *set);
-int lov_prep_getattr_set(struct obd_export *exp, struct obdo *src_oa,
-                         struct lov_stripe_md *lsm,
+int lov_prep_getattr_set(struct obd_export *exp, struct obd_info *oinfo,
                          struct lov_request_set **reqset);
 int lov_fini_getattr_set(struct lov_request_set *set);
-int lov_prep_destroy_set(struct obd_export *exp, struct obdo *src_oa,
-                         struct lov_stripe_md *lsm,
+int lov_prep_destroy_set(struct obd_export *exp, struct obd_info *oinfo,
+                         struct obdo *src_oa, struct lov_stripe_md *lsm,
                          struct obd_trans_info *oti,
                          struct lov_request_set **reqset);
 int lov_update_destroy_set(struct lov_request_set *set,
                            struct lov_request *req, int rc);
 int lov_fini_destroy_set(struct lov_request_set *set);
-int lov_prep_setattr_set(struct obd_export *exp, struct obdo *src_oa,
-                         struct lov_stripe_md *lsm, struct obd_trans_info *oti,
+int lov_prep_setattr_set(struct obd_export *exp, struct obd_info *oinfo,
+                         struct obd_trans_info *oti,
                          struct lov_request_set **reqset);
 int lov_update_setattr_set(struct lov_request_set *set,
                            struct lov_request *req, int rc);
 int lov_fini_setattr_set(struct lov_request_set *set);
-int lov_prep_punch_set(struct obd_export *exp, struct obdo *src_oa,
-                       struct lov_stripe_md *lsm, obd_off start,
-                       obd_off end, struct obd_trans_info *oti,
+int lov_prep_punch_set(struct obd_export *exp, struct obd_info *oinfo,
+                       struct obd_trans_info *oti,
                        struct lov_request_set **reqset);
-int lov_update_punch_set(struct lov_request_set *set, struct lov_request *req,
-                         int rc);
 int lov_fini_punch_set(struct lov_request_set *set);
-int lov_prep_sync_set(struct obd_export *exp, struct obdo *src_oa,
+int lov_prep_sync_set(struct obd_export *exp, struct obd_info *obd_info,
+                      struct obdo *src_oa,
                       struct lov_stripe_md *lsm, obd_off start,
                       obd_off end, struct lov_request_set **reqset);
 int lov_fini_sync_set(struct lov_request_set *set);
-int lov_prep_enqueue_set(struct obd_export *exp, struct lov_stripe_md *lsm,
-                         ldlm_policy_data_t *policy, __u32 mode,
-                         struct lustre_handle *lockh,
+int lov_prep_enqueue_set(struct obd_export *exp, struct obd_info *oinfo,
+                         struct obd_enqueue_info *einfo,
                          struct lov_request_set **reqset);
-int lov_update_enqueue_set(struct lov_request_set *set,
-                           struct lov_request *req, int rc, int flags);
 int lov_fini_enqueue_set(struct lov_request_set *set, __u32 mode);
-int lov_prep_match_set(struct obd_export *exp, struct lov_stripe_md *lsm,
+int lov_prep_match_set(struct obd_export *exp, struct obd_info *oinfo,
+                       struct lov_stripe_md *lsm,
                        ldlm_policy_data_t *policy, __u32 mode,
                        struct lustre_handle *lockh,
                        struct lov_request_set **reqset);
 int lov_update_match_set(struct lov_request_set *set, struct lov_request *req,
                          int rc);
 int lov_fini_match_set(struct lov_request_set *set, __u32 mode, int flags);
-int lov_prep_cancel_set(struct obd_export *exp, struct lov_stripe_md *lsm,
+int lov_prep_cancel_set(struct obd_export *exp, struct obd_info *oinfo,
+                        struct lov_stripe_md *lsm,
                         __u32 mode, struct lustre_handle *lockh,
                         struct lov_request_set **reqset);
 int lov_fini_cancel_set(struct lov_request_set *set);
+int lov_prep_statfs_set(struct obd_device *obd, struct obd_info *oinfo,
+                        struct lov_request_set **reqset);
+void lov_update_statfs(struct obd_device *obd, struct obd_statfs *osfs,
+                       struct obd_statfs *lov_sfs, int success);
+int lov_fini_statfs(struct obd_device *obd, struct obd_statfs *osfs,
+                    int success);
+int lov_fini_statfs_set(struct lov_request_set *set);
 
 /* lov_obd.c */
 int lov_get_stripecnt(struct lov_obd *lov, int stripe_count);
+void lov_getref(struct obd_device *obd);
+void lov_putref(struct obd_device *obd);
 
 /* lov_log.c */
 int lov_llog_init(struct obd_device *obd, struct obd_device *tgt,
@@ -217,7 +235,7 @@ int lov_setea(struct obd_export *exp, struct lov_stripe_md **lsmp,
               struct lov_user_md *lump);
 int lov_getstripe(struct obd_export *exp,
                   struct lov_stripe_md *lsm, struct lov_user_md *lump);
-int lov_alloc_memmd(struct lov_stripe_md **lsmp, int stripe_count, 
+int lov_alloc_memmd(struct lov_stripe_md **lsmp, int stripe_count,
                       int pattern, int magic);
 void lov_free_memmd(struct lov_stripe_md **lsmp);
 
@@ -229,7 +247,7 @@ int lov_unpackmd_join(struct lov_obd *lov, struct lov_stripe_md *lsm,
 
 struct lov_extent *lovea_idx2le(struct lov_stripe_md *lsm, int stripe_no);
 struct lov_extent *lovea_off2le(struct lov_stripe_md *lsm, obd_off lov_off);
-int lovea_destroy_object(struct lov_obd *lov, struct lov_stripe_md *lsm, 
+int lovea_destroy_object(struct lov_obd *lov, struct lov_stripe_md *lsm,
                          struct obdo *oa, void *data);
 /* lproc_lov.c */
 extern struct file_operations lov_proc_target_fops;
index 5854b54..f7b41f7 100644 (file)
@@ -68,7 +68,8 @@ static int lov_llog_origin_add(struct llog_ctxt *ctxt,
                  logcookies, numcookies, lsm->lsm_stripe_count);
 
         for (i = 0,loi = lsm->lsm_oinfo; i < lsm->lsm_stripe_count; i++,loi++) {
-                struct obd_device *child = lov->tgts[loi->loi_ost_idx].ltd_exp->exp_obd; 
+                struct obd_device *child = 
+                        lov->lov_tgts[loi->loi_ost_idx]->ltd_exp->exp_obd; 
                 struct llog_ctxt *cctxt = llog_get_context(child, ctxt->loc_idx);
 
                 /* fill mds unlink/setattr log record */
@@ -103,7 +104,6 @@ static int lov_llog_origin_connect(struct llog_ctxt *ctxt, int count,
 {
         struct obd_device *obd = ctxt->loc_obd;
         struct lov_obd *lov = &obd->u.lov;
-        struct lov_tgt_desc *tgt;
         int i, rc = 0;
         ENTRY;
 
@@ -112,15 +112,16 @@ static int lov_llog_origin_connect(struct llog_ctxt *ctxt, int count,
                 CERROR("Origin connect mds cnt %d != lov cnt %d\n", count,
                        lov->desc.ld_tgt_count);
 
-        for (i = 0, tgt = lov->tgts; i < count; i++, tgt++) {
+        lov_getref(obd);
+        for (i = 0; i < count; i++) {
                 struct obd_device *child;
                 struct llog_ctxt *cctxt;
                 
-                if (!tgt->active)
+                if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_active)
                         continue;
-                child = tgt->ltd_exp->exp_obd;
+                child = lov->lov_tgts[i]->ltd_exp->exp_obd;
                 cctxt = llog_get_context(child, ctxt->loc_idx);
-                if (uuid && !obd_uuid_equals(uuid, &lov->tgts[i].uuid))
+                if (uuid && !obd_uuid_equals(uuid, &lov->lov_tgts[i]->ltd_uuid))
                         continue;
 
                 rc = llog_connect(cctxt, 1, logid, gen, uuid);
@@ -129,6 +130,7 @@ static int lov_llog_origin_connect(struct llog_ctxt *ctxt, int count,
                         break;
                 }
         }
+        lov_putref(obd);
 
         RETURN(rc);
 }
@@ -148,13 +150,16 @@ static int lov_llog_repl_cancel(struct llog_ctxt *ctxt, struct lov_stripe_md *ls
 
         loi = lsm->lsm_oinfo;
         lov = &obd->u.lov;
+        lov_getref(obd);
         for (i = 0; i < count; i++, cookies++, loi++) {
-                struct obd_device *child = lov->tgts[loi->loi_ost_idx].ltd_exp->exp_obd;
-                struct llog_ctxt *cctxt = llog_get_context(child, ctxt->loc_idx);
+                struct obd_device *child = 
+                        lov->lov_tgts[loi->loi_ost_idx]->ltd_exp->exp_obd;
+                struct llog_ctxt *cctxt = 
+                        llog_get_context(child, ctxt->loc_idx);
                 int err;
 
                 err = llog_cancel(cctxt, NULL, 1, cookies, flags);
-                if (err && lov->tgts[loi->loi_ost_idx].active) {
+                if (err && lov->lov_tgts[loi->loi_ost_idx]->ltd_active) {
                         CERROR("error: objid "LPX64" subobj "LPX64
                                " on OST idx %d: rc = %d\n", lsm->lsm_object_id,
                                loi->loi_id, loi->loi_ost_idx, err);
@@ -162,6 +167,7 @@ static int lov_llog_repl_cancel(struct llog_ctxt *ctxt, struct lov_stripe_md *ls
                                 rc = err;
                 }
         }
+        lov_putref(obd);
         RETURN(rc);
 }
 
@@ -178,8 +184,8 @@ int lov_llog_init(struct obd_device *obd, struct obd_device *tgt,
                   int count, struct llog_catid *logid)
 {
         struct lov_obd *lov = &obd->u.lov;
-        struct lov_tgt_desc *ctgt;
-        int i, rc = 0;
+        struct obd_device *child;
+        int i, rc = 0, err = 0;
         ENTRY;
 
         rc = llog_setup(obd, LLOG_MDS_OST_ORIG_CTXT, tgt, 0, NULL,
@@ -192,20 +198,33 @@ int lov_llog_init(struct obd_device *obd, struct obd_device *tgt,
         if (rc)
                 RETURN(rc);
 
-        CDEBUG(D_CONFIG, "llog init with %d targets\n", count);
+        CDEBUG(D_CONFIG, "llog init with %d/%d targets\n",
+               count, lov->desc.ld_tgt_count);
         /* count may not match ld_tgt_count during dynamic ost add */
-        for (i = 0, ctgt = lov->tgts; i < lov->desc.ld_tgt_count; i++, ctgt++) {
-                struct obd_device *child;
-                if (!ctgt->active)
+
+        lov_getref(obd);
+        for (i = 0; i < lov->desc.ld_tgt_count; i++) {
+                if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_active)
                         continue;
-                child = ctgt->ltd_exp->exp_obd;
+                LASSERT(lov->lov_tgts[i]->ltd_exp);
+                child = lov->lov_tgts[i]->ltd_exp->exp_obd;
+                if (lov->lov_tgts[i]->ltd_exp->exp_imp_reverse) {
+                        CERROR("NZR: idx %d import state %s\n", i,
+                               ptlrpc_import_state_name(lov->lov_tgts[i]->ltd_exp->exp_imp_reverse->imp_state));                
+                } else {
+                        CERROR("NZR: idx %d no import\n", i);
+                }
                 rc = obd_llog_init(child, tgt, 1, logid + i);
                 if (rc) {
-                        CERROR("error osc_llog_init %d (%d)\n", i, rc);
-                        break;
+                        CERROR("error osc_llog_init idx %d osc '%s' tgt '%s' "
+                               "(rc=%d)\n", i, child->obd_name, tgt->obd_name,
+                               rc);
+                        if (!err) 
+                                err = rc;
                 }
         }
-        RETURN(rc);
+        lov_putref(obd);
+        RETURN(err);
 }
 
 int lov_llog_finish(struct obd_device *obd, int count)
index ff20962..7df4cc0 100644 (file)
@@ -40,7 +40,7 @@
 
 /* Merge the lock value block(&lvb) attributes from each of the stripes in a
  * file into a single lvb. It is expected that the caller initializes the
- * current atime, mtime, ctime to avoid regressing a more uptodate time on 
+ * current atime, mtime, ctime to avoid regressing a more uptodate time on
  * the local client.
  *
  * If @kms_only is set then we do not consider the recently seen size (rss)
@@ -74,21 +74,26 @@ int lov_merge_lvb(struct obd_export *exp, struct lov_stripe_md *lsm,
                 lov_size = lov_stripe_size(lsm, tmpsize, i);
                 if (lov_size > size)
                         size = lov_size;
-                /* merge blocks, mtime, atime */ 
+                /* merge blocks, mtime, atime */
                 blocks += loi->loi_lvb.lvb_blocks;
-                if (loi->loi_lvb.lvb_mtime > current_mtime)
-                        current_mtime = loi->loi_lvb.lvb_mtime;
                 if (loi->loi_lvb.lvb_atime > current_atime)
                         current_atime = loi->loi_lvb.lvb_atime;
-                if (loi->loi_lvb.lvb_ctime > current_ctime)
+
+                /* mtime is always updated with ctime, but can be set in past.
+                   As write and utime(2) may happen within 1 second, and utime's
+                   mtime has a priority over write's one, leave mtime from mds 
+                   for the same ctimes. */
+                if (loi->loi_lvb.lvb_ctime > current_ctime) {
                         current_ctime = loi->loi_lvb.lvb_ctime;
+                        current_mtime = loi->loi_lvb.lvb_mtime;
+                }
         }
 
         lvb->lvb_size = size;
         lvb->lvb_blocks = blocks;
-        lvb->lvb_mtime = current_mtime; 
-        lvb->lvb_atime = current_atime; 
-        lvb->lvb_ctime = current_ctime; 
+        lvb->lvb_mtime = current_mtime;
+        lvb->lvb_atime = current_atime;
+        lvb->lvb_ctime = current_ctime;
         RETURN(0);
 }
 
@@ -153,6 +158,8 @@ void lov_merge_attrs(struct obdo *tgt, struct obdo *src, obd_flag valid,
                         tgt->o_blksize += src->o_blksize;
                 if (valid & OBD_MD_FLCTIME && tgt->o_ctime < src->o_ctime)
                         tgt->o_ctime = src->o_ctime;
+                /* Only mtime from OSTs are merged here, as they cannot be set
+                   in past (only MDS's mtime can) do not look at ctime. */
                 if (valid & OBD_MD_FLMTIME && tgt->o_mtime < src->o_mtime)
                         tgt->o_mtime = src->o_mtime;
         } else {
index cb2a4f9..0ff9f57 100644 (file)
@@ -1,10 +1,11 @@
 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
  * vim:expandtab:shiftwidth=8:tabstop=8:
  *
- * Copyright (C) 2002-2004 Cluster File Systems, Inc.
+ * Copyright (C) 2002-2006 Cluster File Systems, Inc.
  * Author: Phil Schwan <phil@clusterfs.com>
  *         Peter Braam <braam@clusterfs.com>
  *         Mike Shaver <shaver@clusterfs.com>
+ *         Nathan Rutman <nathan@clusterfs.com>
  *
  *   This file is part of the Lustre file system, http://www.lustre.org
  *   Lustre is a trademark of Cluster File Systems, Inc.
 #include "lov_internal.h"
 
 
-/* FIXME add lov_get/putrefs around every access to lov->tgts for on-line non-
-   quiescent ost removal */
-/* Keep a refcount of lov->tgt usage to prevent racing with deletion */
-static void lov_getref(struct obd_device *obd)
+/* Keep a refcount of lov->tgt usage to prevent racing with addition/deletion.
+   Any function that expects lov_tgts to remain stationary must take a ref. */
+void lov_getref(struct obd_device *obd)
 {
         struct lov_obd *lov = &obd->u.lov;
 
         /* nobody gets through here until lov_putref is done */
         mutex_down(&lov->lov_lock);
-        atomic_inc(&lov->refcount);
+        atomic_inc(&lov->lov_refcount);
         mutex_up(&lov->lov_lock);
         return;
 }
 
-static void __lov_del_obd(struct obd_device *obd, struct lov_tgt_desc *tgt);
+static void __lov_del_obd(struct obd_device *obd, __u32 index);
 
-static void lov_putref(struct obd_device *obd)
+void lov_putref(struct obd_device *obd)
 {
         struct lov_obd *lov = &obd->u.lov;
         mutex_down(&lov->lov_lock);
         /* ok to dec to 0 more than once -- ltd_exp's will be null */
-        if (atomic_dec_and_test(&lov->refcount) && lov->death_row) {
-                struct lov_tgt_desc *tgt;
+        if (atomic_dec_and_test(&lov->lov_refcount) && lov->lov_death_row) {
                 int i;
-                CDEBUG(D_CONFIG, "destroying %d lov targets\n", lov->death_row);
-                for (i = 0, tgt = lov->tgts; i < lov->desc.ld_tgt_count;
-                      i++, tgt++) {
-                        if (!tgt->reap)
+                CDEBUG(D_CONFIG, "destroying %d lov targets\n", 
+                       lov->lov_death_row);
+                for (i = 0; i < lov->desc.ld_tgt_count; i++) {
+                        if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_reap)
                                 continue;
                         /* Disconnect and delete from list */
-                        __lov_del_obd(obd, tgt);
-                        lov->death_row--;
+                        __lov_del_obd(obd, i);
+                        lov->lov_death_row--;
                 }
         }
         mutex_up(&lov->lov_lock);
 }
 
 #define MAX_STRING_SIZE 128
-static int lov_connect_obd(struct obd_device *obd, struct lov_tgt_desc *tgt,
-                           int activate, struct obd_connect_data *data)
+static int lov_connect_obd(struct obd_device *obd, __u32 index, int activate, 
+                           struct obd_connect_data *data)
 {
         struct lov_obd *lov = &obd->u.lov;
-        struct obd_uuid *tgt_uuid = &tgt->uuid;
+        struct obd_uuid tgt_uuid = lov->lov_tgts[index]->ltd_uuid;
         struct obd_device *tgt_obd;
         struct obd_uuid lov_osc_uuid = { "LOV_OSC_UUID" };
         struct lustre_handle conn = {0, };
@@ -104,19 +103,18 @@ static int lov_connect_obd(struct obd_device *obd, struct lov_tgt_desc *tgt,
         int rc;
         ENTRY;
 
-        tgt_obd = class_find_client_obd(tgt_uuid, LUSTRE_OSC_NAME,
+        if (!lov->lov_tgts[index])
+                RETURN(-EINVAL);
+
+        tgt_obd = class_find_client_obd(&tgt_uuid, LUSTRE_OSC_NAME,
                                         &obd->obd_uuid);
 
         if (!tgt_obd) {
-                CERROR("Target %s not attached\n", obd_uuid2str(tgt_uuid));
+                CERROR("Target %s not attached\n", obd_uuid2str(&tgt_uuid));
                 RETURN(-EINVAL);
         }
-
-        CDEBUG(D_CONFIG, "Connect tgt %s (%s)\n", obd_uuid2str(tgt_uuid),
-               tgt_obd->obd_name);
-
         if (!tgt_obd->obd_set_up) {
-                CERROR("Target %s not set up\n", obd_uuid2str(tgt_uuid));
+                CERROR("Target %s not set up\n", obd_uuid2str(&tgt_uuid));
                 RETURN(-EINVAL);
         }
 
@@ -134,36 +132,47 @@ static int lov_connect_obd(struct obd_device *obd, struct lov_tgt_desc *tgt,
 
         if (imp->imp_invalid) {
                 CERROR("not connecting OSC %s; administratively "
-                       "disabled\n", obd_uuid2str(tgt_uuid));
+                       "disabled\n", obd_uuid2str(&tgt_uuid));
                 rc = obd_register_observer(tgt_obd, obd);
                 if (rc) {
                         CERROR("Target %s register_observer error %d; "
                                "will not be able to reactivate\n",
-                               obd_uuid2str(tgt_uuid), rc);
+                               obd_uuid2str(&tgt_uuid), rc);
                 }
                 RETURN(0);
         }
 
+        if (data && (data->ocd_connect_flags & OBD_CONNECT_INDEX))
+                data->ocd_index = index;
+
         rc = obd_connect(NULL, &conn, tgt_obd, &lov_osc_uuid, data);
         if (rc) {
                 CERROR("Target %s connect error %d\n",
-                       obd_uuid2str(tgt_uuid), rc);
+                       obd_uuid2str(&tgt_uuid), rc);
                 RETURN(rc);
         }
-        tgt->ltd_exp = class_conn2export(&conn);
+        lov->lov_tgts[index]->ltd_exp = class_conn2export(&conn);
+        if (!lov->lov_tgts[index]->ltd_exp) {
+                CERROR("Target %s: null export!\n", obd_uuid2str(&tgt_uuid));
+                RETURN(-ENODEV);
+        }
 
         rc = obd_register_observer(tgt_obd, obd);
         if (rc) {
                 CERROR("Target %s register_observer error %d\n",
-                       obd_uuid2str(tgt_uuid), rc);
-                obd_disconnect(tgt->ltd_exp);
-                tgt->ltd_exp = NULL;
+                       obd_uuid2str(&tgt_uuid), rc);
+                obd_disconnect(lov->lov_tgts[index]->ltd_exp);
+                lov->lov_tgts[index]->ltd_exp = NULL;
                 RETURN(rc);
         }
 
-        tgt->active = 1;
-        tgt->reap = 0;
-        lov->desc.ld_active_tgt_count++;
+        lov->lov_tgts[index]->ltd_reap = 0;
+        if (activate) {
+                lov->lov_tgts[index]->ltd_active = 1;
+                lov->desc.ld_active_tgt_count++;
+        }
+        CDEBUG(D_CONFIG, "Connected tgt idx %d %s (%s) %sactive\n", index,
+               obd_uuid2str(&tgt_uuid), tgt_obd->obd_name, activate ? "":"in");
 
 #ifdef __KERNEL__
         lov_proc_dir = lprocfs_srch(obd->obd_proc_entry, "target_obds");
@@ -173,7 +182,7 @@ static int lov_connect_obd(struct obd_device *obd, struct lov_tgt_desc *tgt,
                 char name[MAX_STRING_SIZE];
 
                 LASSERT(osc_obd != NULL);
-                LASSERT(osc_obd->obd_type != NULL);
+                LASSERT(osc_obd->obd_magic == OBD_DEVICE_MAGIC);
                 LASSERT(osc_obd->obd_type->typ_name != NULL);
                 snprintf(name, MAX_STRING_SIZE, "../../../%s/%s",
                          osc_obd->obd_type->typ_name,
@@ -191,6 +200,10 @@ static int lov_connect_obd(struct obd_device *obd, struct lov_tgt_desc *tgt,
         }
 #endif
 
+        rc = qos_add_tgt(obd, index);
+        if (rc) 
+                CERROR("qos_add_tgt failed %d\n", rc);
+
         RETURN(0);
 }
 
@@ -199,34 +212,60 @@ static int lov_connect(const struct lu_context *ctx,
                        struct obd_uuid *cluuid, struct obd_connect_data *data)
 {
         struct lov_obd *lov = &obd->u.lov;
-        int rc;
+        struct lov_tgt_desc *tgt;
+        int i, rc;
         ENTRY;
 
-        lov->ocd.ocd_connect_flags = OBD_CONNECT_EMPTY;
-        if (data)
-                lov->ocd = *data;
+        CDEBUG(D_CONFIG, "connect #%d\n", lov->lov_connects);
 
         rc = class_connect(conn, obd, cluuid);
-        if (!rc)
-                lov->connects++;
-        CDEBUG(D_CONFIG, "connect #%d\n", lov->connects);
+        if (rc)
+                RETURN(rc);
 
-        /* target connects are done in lov_add_target */
+        /* Why should there ever be more than 1 connect? */
+        lov->lov_connects++;
+        LASSERT(lov->lov_connects == 1);
+        
+        memset(&lov->lov_ocd, 0, sizeof(lov->lov_ocd));
+        if (data)
+                lov->lov_ocd = *data;
 
-        RETURN (rc);
+        lov_getref(obd);
+        for (i = 0; i < lov->desc.ld_tgt_count; i++) {
+                tgt = lov->lov_tgts[i];
+                if (!tgt || obd_uuid_empty(&tgt->ltd_uuid))
+                        continue;
+                /* Flags will be lowest common denominator */
+                rc = lov_connect_obd(obd, i, lov->lov_tgts[i]->ltd_activate,
+                                     &lov->lov_ocd);
+                if (rc) {
+                        CERROR("%s: lov connect tgt %d failed: %d\n", 
+                               obd->obd_name, i, rc);
+                        continue;
+                }
+        }
+        lov_putref(obd);
+        
+        RETURN(0);
 }
 
-static int lov_disconnect_obd(struct obd_device *obd, struct lov_tgt_desc *tgt)
+static int lov_disconnect_obd(struct obd_device *obd, __u32 index)
 {
         cfs_proc_dir_entry_t *lov_proc_dir;
-        struct obd_device *osc_obd = class_exp2obd(tgt->ltd_exp);
         struct lov_obd *lov = &obd->u.lov;
+        struct obd_device *osc_obd =
+                class_exp2obd(lov->lov_tgts[index]->ltd_exp);
         int rc;
         ENTRY;
 
         CDEBUG(D_CONFIG, "%s: disconnecting target %s\n",
                obd->obd_name, osc_obd->obd_name);
 
+        if (lov->lov_tgts[index]->ltd_active) {
+                lov->lov_tgts[index]->ltd_active = 0;
+                lov->desc.ld_active_tgt_count--;
+        }
+
         lov_proc_dir = lprocfs_srch(obd->obd_proc_entry, "target_obds");
         if (lov_proc_dir) {
                 cfs_proc_dir_entry_t *osc_symlink;
@@ -252,53 +291,47 @@ static int lov_disconnect_obd(struct obd_device *obd, struct lov_tgt_desc *tgt)
 
         obd_register_observer(osc_obd, NULL);
 
-        rc = obd_disconnect(tgt->ltd_exp);
+        rc = obd_disconnect(lov->lov_tgts[index]->ltd_exp);
         if (rc) {
-                if (tgt->active) {
-                        CERROR("Target %s disconnect error %d\n",
-                               tgt->uuid.uuid, rc);
-                }
+                CERROR("Target %s disconnect error %d\n",
+                       lov_uuid2str(lov, index), rc);
                 rc = 0;
         }
 
-        if (tgt->active) {
-                tgt->active = 0;
-                lov->desc.ld_active_tgt_count--;
-        }
+        qos_del_tgt(obd, index);
 
-        tgt->ltd_exp = NULL;
+        lov->lov_tgts[index]->ltd_exp = NULL;
         RETURN(0);
 }
 
-static int lov_del_target(struct obd_device *obd, struct obd_uuid *uuidp,
-                          int index, int gen);
+static int lov_del_target(struct obd_device *obd, __u32 index, 
+                          struct obd_uuid *uuidp, int gen);
 
 static int lov_disconnect(struct obd_export *exp)
 {
         struct obd_device *obd = class_exp2obd(exp);
         struct lov_obd *lov = &obd->u.lov;
-        struct lov_tgt_desc *tgt;
         int i, rc;
         ENTRY;
 
-        if (!lov->tgts)
+        if (!lov->lov_tgts)
                 goto out;
 
         /* Only disconnect the underlying layers on the final disconnect. */
-        lov->connects--;
-        if (lov->connects != 0) {
+        lov->lov_connects--;
+        if (lov->lov_connects != 0) {
                 /* why should there be more than 1 connect? */
-                CERROR("disconnect #%d\n", lov->connects);
+                CERROR("disconnect #%d\n", lov->lov_connects);
                 goto out;
         }
 
         /* Let's hold another reference so lov_del_obd doesn't spin through
            putref every time */
         lov_getref(obd);
-        for (i = 0, tgt = lov->tgts; i < lov->desc.ld_tgt_count; i++, tgt++) {
-                if (tgt->ltd_exp) {
+        for (i = 0; i < lov->desc.ld_tgt_count; i++) {
+                if (lov->lov_tgts[i] && lov->lov_tgts[i]->ltd_exp) {
                         /* Disconnection is the last we know about an obd */
-                        lov_del_target(obd, &tgt->uuid, i, tgt->ltd_gen);
+                        lov_del_target(obd, i, 0, lov->lov_tgts[i]->ltd_gen);
                 }
         }
         lov_putref(obd);
@@ -314,9 +347,10 @@ out:
  *  -ENOTCONN: The UUID is found, but the target connection is bad (!)
  *  -EBADF   : The UUID is found, but the OBD is the wrong type (!)
  */
-static int lov_set_osc_active(struct lov_obd *lov, struct obd_uuid *uuid,
+static int lov_set_osc_active(struct obd_device *obd, struct obd_uuid *uuid,
                               int activate)
 {
+        struct lov_obd *lov = &obd->u.lov;
         struct lov_tgt_desc *tgt;
         int i, rc = 0;
         ENTRY;
@@ -324,37 +358,42 @@ static int lov_set_osc_active(struct lov_obd *lov, struct obd_uuid *uuid,
         CDEBUG(D_INFO, "Searching in lov %p for uuid %s (activate=%d)\n",
                lov, uuid->uuid, activate);
 
-        for (i = 0, tgt = lov->tgts; i < lov->desc.ld_tgt_count; i++, tgt++) {
-                if (tgt->ltd_exp == NULL)
+        lov_getref(obd);
+        for (i = 0; i < lov->desc.ld_tgt_count; i++) {
+                tgt = lov->lov_tgts[i];
+                if (!tgt || !tgt->ltd_exp)
                         continue;
 
                 CDEBUG(D_INFO, "lov idx %d is %s conn "LPX64"\n",
-                       i, tgt->uuid.uuid, tgt->ltd_exp->exp_handle.h_cookie);
-                if (strncmp(uuid->uuid, tgt->uuid.uuid, sizeof uuid->uuid) == 0)
+                       i, obd_uuid2str(&tgt->ltd_uuid),
+                       tgt->ltd_exp->exp_handle.h_cookie);
+                if (obd_uuid_equals(uuid, &tgt->ltd_uuid))
                         break;
         }
 
         if (i == lov->desc.ld_tgt_count)
                 GOTO(out, rc = -EINVAL);
 
-        if (tgt->active == activate) {
+        if (lov->lov_tgts[i]->ltd_active == activate) {
                 CDEBUG(D_INFO, "OSC %s already %sactive!\n", uuid->uuid,
                        activate ? "" : "in");
                 GOTO(out, rc);
         }
 
-        CDEBUG(D_INFO, "Marking OSC %s %sactive\n", uuid->uuid,
+        CDEBUG(D_CONFIG, "Marking OSC %s %sactive\n", obd_uuid2str(uuid),
                activate ? "" : "in");
 
-        tgt->active = activate;
+        lov->lov_tgts[i]->ltd_active = activate;
         if (activate)
                 lov->desc.ld_active_tgt_count++;
         else
                 lov->desc.ld_active_tgt_count--;
+        /* remove any old qos penalty */
+        lov->lov_tgts[i]->ltd_qos.ltq_penalty = 0;
 
-        EXIT;
  out:
-        return rc;
+        lov_putref(obd);
+        RETURN(rc);
 }
 
 static int lov_notify(struct obd_device *obd, struct obd_device *watched,
@@ -379,10 +418,7 @@ static int lov_notify(struct obd_device *obd, struct obd_device *watched,
                 /* Set OSC as active before notifying the observer, so the
                  * observer can use the OSC normally.
                  */
-                lov_getref(obd);
-                rc = lov_set_osc_active(&obd->u.lov, uuid,
-                                        ev == OBD_NOTIFY_ACTIVE);
-                lov_putref(obd);
+                rc = lov_set_osc_active(obd, uuid, ev == OBD_NOTIFY_ACTIVE);
                 if (rc) {
                         CERROR("%sactivation of %s failed: %d\n",
                                (ev == OBD_NOTIFY_ACTIVE) ? "" : "de",
@@ -397,14 +433,13 @@ static int lov_notify(struct obd_device *obd, struct obd_device *watched,
         } else {
                 /* NULL watched means all osc's in the lov (only for syncs) */
                 struct lov_obd *lov = &obd->u.lov;
-                struct lov_tgt_desc *tgt;
                 struct obd_device *tgt_obd;
                 int i;
-                for (i = 0, tgt = lov->tgts; i < lov->desc.ld_tgt_count;
-                      i++, tgt++) {
-                        if (obd_uuid_empty(&tgt->uuid))
+                lov_getref(obd);
+                for (i = 0; i < lov->desc.ld_tgt_count; i++) {
+                        if (!lov->lov_tgts[i])
                                 continue;
-                        tgt_obd = class_exp2obd(tgt->ltd_exp);
+                        tgt_obd = class_exp2obd(lov->lov_tgts[i]->ltd_exp);
                         rc = obd_notify_observer(obd, tgt_obd, ev, data);
                         if (rc) {
                                 CERROR("%s: notify %s of %s failed %d\n",
@@ -414,123 +449,125 @@ static int lov_notify(struct obd_device *obd, struct obd_device *watched,
                                 break;
                         }
                 }
+                lov_putref(obd);
         }
 
         RETURN(rc);
 }
 
 static int lov_add_target(struct obd_device *obd, struct obd_uuid *uuidp,
-                          int index, int gen, int active)
+                          __u32 index, int gen, int active)
 {
         struct lov_obd *lov = &obd->u.lov;
         struct lov_tgt_desc *tgt;
-        struct obd_connect_data *ocd = NULL;
-        __u32 bufsize, idx;
         int rc;
         ENTRY;
 
         CDEBUG(D_CONFIG, "uuid:%s idx:%d gen:%d active:%d\n",
                uuidp->uuid, index, gen, active);
 
-        if (index < 0) {
-                CERROR("request to add OBD %s at invalid index: %d\n",
-                       uuidp->uuid, index);
-                RETURN(-EINVAL);
-        }
-
         if (gen <= 0) {
                 CERROR("request to add OBD %s with invalid generation: %d\n",
                        uuidp->uuid, gen);
                 RETURN(-EINVAL);
         }
 
-        bufsize = sizeof(struct lov_tgt_desc) * (index + 1);
-        if (bufsize > lov->bufsize) {
-                OBD_ALLOC(tgt, bufsize);
-                if (tgt == NULL) {
-                        CERROR("couldn't allocate %d bytes for new table.\n",
-                               bufsize);
+        mutex_down(&lov->lov_lock);
+
+        if ((index < lov->lov_tgt_size) && (lov->lov_tgts[index] != NULL)) {
+                tgt = lov->lov_tgts[index];
+                CERROR("UUID %s already assigned at LOV target index %d\n",
+                       obd_uuid2str(&tgt->ltd_uuid), index);
+                mutex_up(&lov->lov_lock);
+                RETURN(-EEXIST);
+        }
+
+        if (index >= lov->lov_tgt_size) {
+                /* We need to reallocate the lov target array. */
+                struct lov_tgt_desc **newtgts, **old = NULL;
+                __u32 newsize, oldsize = 0;
+
+                newsize = max(lov->lov_tgt_size, (__u32)2);
+                while (newsize < index + 1) 
+                        newsize = newsize << 1;
+                OBD_ALLOC(newtgts, sizeof(*newtgts) * newsize);
+                if (newtgts == NULL) {
+                        mutex_up(&lov->lov_lock);
                         RETURN(-ENOMEM);
                 }
 
-                if (lov->tgts) {
-                        int i;
-                        memcpy(tgt, lov->tgts, lov->bufsize);
-                        LASSERT(index == lov->desc.ld_tgt_count);
-                        for (i = 0; i < index; i++) {
-                                INIT_LIST_HEAD(&tgt[i].qos_bavail_list);
-                                list_splice(&lov->tgts[i].qos_bavail_list,
-                                            &tgt[i].qos_bavail_list);
-                        }
-                        OBD_FREE(lov->tgts, lov->bufsize);
+                if (lov->lov_tgt_size) {
+                        memcpy(newtgts, lov->lov_tgts, sizeof(*newtgts) * 
+                               lov->lov_tgt_size);
+                        old = lov->lov_tgts;
+                        oldsize = lov->lov_tgt_size;
                 }
 
-                lov->tgts = tgt;
-                lov->bufsize = bufsize;
-                CDEBUG(D_CONFIG, "tgts: %p bufsize: %d\n",
-                       lov->tgts, lov->bufsize);
-        }
+                lov->lov_tgts = newtgts;
+                lov->lov_tgt_size = newsize;
+#ifdef __KERNEL__
+                smp_rmb();
+#endif
+                if (old)
+                        OBD_FREE(old, sizeof(*old) * oldsize);
 
-        tgt = &lov->tgts[index];
-        if (!obd_uuid_empty(&tgt->uuid)) {
-                CERROR("UUID %s already assigned at LOV target index %d\n",
-                       obd_uuid2str(&tgt->uuid), index);
-                RETURN(-EEXIST);
+                CDEBUG(D_CONFIG, "tgts: %p size: %d\n",
+                       lov->lov_tgts, lov->lov_tgt_size);
+        }       
+
+
+        OBD_ALLOC_PTR(tgt);
+        if (!tgt) {
+                mutex_up(&lov->lov_lock);
+                RETURN(-ENOMEM);
         }
 
-        tgt->uuid = *uuidp;
+        memset(tgt, 0, sizeof(*tgt));
+        tgt->ltd_uuid = *uuidp;
         /* XXX - add a sanity check on the generation number. */
         tgt->ltd_gen = gen;
-        tgt->index = index;
-        INIT_LIST_HEAD(&tgt->qos_bavail_list);
-
+        tgt->ltd_index = index;
+        tgt->ltd_activate = active;
+        lov->lov_tgts[index] = tgt;
         if (index >= lov->desc.ld_tgt_count)
                 lov->desc.ld_tgt_count = index + 1;
+        mutex_up(&lov->lov_lock);
 
         CDEBUG(D_CONFIG, "idx=%d ltd_gen=%d ld_tgt_count=%d\n",
                 index, tgt->ltd_gen, lov->desc.ld_tgt_count);
-
-        if (tgt->ltd_exp) {
-                struct obd_device *osc_obd;
-
-                osc_obd = class_exp2obd(tgt->ltd_exp);
-                if (osc_obd)
-                        osc_obd->obd_no_recov = 0;
+        
+        if (lov->lov_connects == 0) { 
+                /* lov_connect hasn't been called yet. We'll do the
+                   lov_connect_obd on this target when that fn first runs,
+                   because we don't know the connect flags yet. */
+                RETURN(0);
         }
 
-        if (lov->ocd.ocd_connect_flags != OBD_CONNECT_EMPTY) {
-                /* Keep the original connect flags pristine */
-                OBD_ALLOC(ocd, sizeof(*ocd));
-                if (!ocd)
-                        RETURN(-ENOMEM);
-                *ocd = lov->ocd;
-        }
-        rc = lov_connect_obd(obd, tgt, active, ocd);
-        if (ocd)
-                OBD_FREE(ocd, sizeof(*ocd));
+        lov_getref(obd);
+
+        rc = lov_connect_obd(obd, index, active, &lov->lov_ocd);
         if (rc)
                 GOTO(out, rc);
 
-        idx = index;
-        rc = lov_notify(obd, tgt->ltd_exp->exp_obd,
+        rc = lov_notify(obd, tgt->ltd_exp->exp_obd, 
                         active ? OBD_NOTIFY_ACTIVE : OBD_NOTIFY_INACTIVE,
-                        (void *)&idx);
+                        (void *)&index);
 
 out:
         if (rc) {
-                CERROR("add failed (%d), deleting %s\n", rc,
-                       (char *)tgt->uuid.uuid);
-                lov_del_target(obd, &tgt->uuid, index, 0);
+                CERROR("add failed (%d), deleting %s\n", rc, 
+                       obd_uuid2str(&tgt->ltd_uuid));
+                lov_del_target(obd, index, 0, 0);
         }
+        lov_putref(obd);
         RETURN(rc);
 }
 
 /* Schedule a target for deletion */
-static int lov_del_target(struct obd_device *obd, struct obd_uuid *uuidp,
-                          int index, int gen)
+static int lov_del_target(struct obd_device *obd, __u32 index, 
+                          struct obd_uuid *uuidp, int gen)
 {
         struct lov_obd *lov = &obd->u.lov;
-        struct lov_tgt_desc *tgt;
         int count = lov->desc.ld_tgt_count;
         int rc = 0;
         ENTRY;
@@ -541,50 +578,59 @@ static int lov_del_target(struct obd_device *obd, struct obd_uuid *uuidp,
                 RETURN(-EINVAL);
         }
 
-        tgt = &lov->tgts[index];
+        lov_getref(obd);
 
-        if (obd_uuid_empty(&tgt->uuid)) {
+        if (!lov->lov_tgts[index]) {
                 CERROR("LOV target at index %d is not setup.\n", index);
-                RETURN(-EINVAL);
+                GOTO(out, rc = -EINVAL);
         }
 
-        if (!obd_uuid_equals(uuidp, &tgt->uuid)) {
+        if (uuidp && !obd_uuid_equals(uuidp, &lov->lov_tgts[index]->ltd_uuid)) {
                 CERROR("LOV target UUID %s at index %d doesn't match %s.\n",
-                       tgt->uuid.uuid, index, uuidp->uuid);
-                RETURN(-EINVAL);
+                       lov_uuid2str(lov, index), index,
+                       obd_uuid2str(uuidp));
+                GOTO(out, rc = -EINVAL);
         }
 
         CDEBUG(D_CONFIG, "uuid: %s idx: %d gen: %d exp: %p active: %d\n",
-               tgt->uuid.uuid, index, tgt->ltd_gen, tgt->ltd_exp, tgt->active);
+               lov_uuid2str(lov, index), index,
+               lov->lov_tgts[index]->ltd_gen, lov->lov_tgts[index]->ltd_exp, 
+               lov->lov_tgts[index]->ltd_active);
 
-        lov_getref(obd);
-        tgt->reap = 1;
-        lov->death_row++;
+        lov->lov_tgts[index]->ltd_reap = 1;
+        lov->lov_death_row++;
         /* we really delete it from lov_putref */
+out:
         lov_putref(obd);
 
         RETURN(rc);
 }
 
-static void __lov_del_obd(struct obd_device *obd, struct lov_tgt_desc *tgt)
+/* We are holding lov_lock */
+static void __lov_del_obd(struct obd_device *obd, __u32 index)
 {
+        struct lov_obd *lov = &obd->u.lov;
         struct obd_device *osc_obd;
+        struct lov_tgt_desc *tgt = lov->lov_tgts[index];
+
+        LASSERT(tgt);
+        LASSERT(tgt->ltd_reap);
 
-        LASSERT(tgt->reap);
         osc_obd = class_exp2obd(tgt->ltd_exp);
 
-        CDEBUG(D_CONFIG, "Removing tgt %s : %s\n", tgt->uuid.uuid,
+        CDEBUG(D_CONFIG, "Removing tgt %s : %s\n",
+               lov_uuid2str(lov, index), 
                osc_obd ? osc_obd->obd_name : "<no obd>");
 
         if (tgt->ltd_exp)
-                lov_disconnect_obd(obd, tgt);
+                lov_disconnect_obd(obd, index);
 
         /* XXX - right now there is a dependency on ld_tgt_count being the
          * maximum tgt index for computing the mds_max_easize. So we can't
          * shrink it. */
 
-        /* lt_gen = 0 will mean it will not match the gen of any valid loi */
-        memset(tgt, 0, sizeof(*tgt));
+        lov->lov_tgts[index] = NULL;
+        OBD_FREE_PTR(tgt);        
 
         /* Manual cleanup - no cleanup logs to clean up the osc's.  We must
            do it ourselves. And we can't do it from lov_cleanup,
@@ -627,8 +673,7 @@ static int lov_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
         struct lprocfs_static_vars lvars;
         struct lov_desc *desc;
         struct lov_obd *lov = &obd->u.lov;
-        struct lov_tgt_desc *tgts;
-        int count, i;
+        int count;
         ENTRY;
 
         if (LUSTRE_CFG_BUFLEN(lcfg, 1) < 1) {
@@ -669,25 +714,16 @@ static int lov_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
                 RETURN(-EINVAL);
         }
 
-        /* Allocate space for target list */
-        if (desc->ld_tgt_count)
-                count = desc->ld_tgt_count;
-        lov->bufsize = sizeof(struct lov_tgt_desc) * max(count, 1);
-        OBD_ALLOC(lov->tgts, lov->bufsize);
-        if (lov->tgts == NULL) {
-                CERROR("Out of memory\n");
-                RETURN(-EINVAL);
-        }
-        for (i = 0, tgts = lov->tgts; i < max(count, 1); i++, tgts++) {
-                tgts->index = i;
-                INIT_LIST_HEAD(&tgts->qos_bavail_list);
-        }
-
         desc->ld_active_tgt_count = 0;
         lov->desc = *desc;
+        lov->lov_tgt_size = 0;
         sema_init(&lov->lov_lock, 1);
-        atomic_set(&lov->refcount, 0);
-        INIT_LIST_HEAD(&lov->qos_bavail_list);
+        atomic_set(&lov->lov_refcount, 0);
+        INIT_LIST_HEAD(&lov->lov_qos.lq_oss_list);
+        init_rwsem(&lov->lov_qos.lq_rw_sem);
+        lov->lov_qos.lq_dirty = 1;
+        lov->lov_qos.lq_dirty_rr = 1;
+        lov->lov_qos.lq_reset = 1;
 
         lprocfs_init_vars(lov, &lvars);
         lprocfs_obd_setup(obd, lvars.obd_vars);
@@ -717,9 +753,9 @@ static int lov_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
                 struct lov_obd *lov = &obd->u.lov;
                 int i;
                 for (i = 0; i < lov->desc.ld_tgt_count; i++) {
-                        if (!lov->tgts[i].active)
+                        if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_active)
                                 continue;
-                        obd_precleanup(class_exp2obd(lov->tgts[i].ltd_exp),
+                        obd_precleanup(class_exp2obd(lov->lov_tgts[i]->ltd_exp),
                                        OBD_CLEANUP_EARLY);
                 }
                 break;
@@ -742,23 +778,27 @@ static int lov_cleanup(struct obd_device *obd)
         struct lov_obd *lov = &obd->u.lov;
 
         lprocfs_obd_cleanup(obd);
-        if (lov->tgts) {
+        if (lov->lov_tgts) {
                 int i;
-                struct lov_tgt_desc *tgt;
-                for (i = 0, tgt = lov->tgts;
-                      i < lov->desc.ld_tgt_count; i++, tgt++) {
+                for (i = 0; i < lov->desc.ld_tgt_count; i++) {
                         /* We should never get here - these should have
                            been removed in the disconnect. */
-                        if (!obd_uuid_empty(&tgt->uuid)) {
+                        if (lov->lov_tgts[i]) {
                                 CERROR("lov tgt %d not cleaned!"
                                        " deathrow=%d, lovrc=%d\n",
-                                       i, lov->death_row,
-                                       atomic_read(&lov->refcount));
-                                lov_del_target(obd, &tgt->uuid, i, 0);
+                                       i, lov->lov_death_row, 
+                                       atomic_read(&lov->lov_refcount));
+                                lov_del_target(obd, i, 0, 0);
                         }
                 }
-                OBD_FREE(lov->tgts, lov->bufsize);
+                OBD_FREE(lov->lov_tgts, sizeof(*lov->lov_tgts) * 
+                         lov->lov_tgt_size);
+                lov->lov_tgt_size = 0;
         }
+        
+        if (lov->lov_qos.lq_rr_size) 
+                OBD_FREE(lov->lov_qos.lq_rr_array, lov->lov_qos.lq_rr_size);
+
         RETURN(0);
 }
 
@@ -767,8 +807,6 @@ static int lov_process_config(struct obd_device *obd, obd_count len, void *buf)
         struct lustre_cfg *lcfg = buf;
         struct obd_uuid obd_uuid;
         int cmd;
-        int index;
-        int gen;
         int rc = 0;
         ENTRY;
 
@@ -776,6 +814,8 @@ static int lov_process_config(struct obd_device *obd, obd_count len, void *buf)
         case LCFG_LOV_ADD_OBD:
         case LCFG_LOV_ADD_INA:
         case LCFG_LOV_DEL_OBD: {
+                __u32 index;
+                int gen;
                 /* lov_modify_tgts add  0:lov_mdsA  1:ost1_UUID  2:0  3:1 */
                 if (LUSTRE_CFG_BUFLEN(lcfg, 1) > sizeof(obd_uuid.uuid))
                         GOTO(out, rc = -EINVAL);
@@ -791,17 +831,21 @@ static int lov_process_config(struct obd_device *obd, obd_count len, void *buf)
                 else if (cmd == LCFG_LOV_ADD_INA)
                         rc = lov_add_target(obd, &obd_uuid, index, gen, 0);
                 else
-                        rc = lov_del_target(obd, &obd_uuid, index, gen);
+                        rc = lov_del_target(obd, index, &obd_uuid, gen);
                 GOTO(out, rc);
         }
         case LCFG_PARAM: {
-                int i;
+                struct lprocfs_static_vars lvars;
                 struct lov_obd *lov = &obd->u.lov;
                 struct lov_desc *desc = &(lov->desc);
+                int i;
+                
                 if (!desc)
                         GOTO(out, rc = -EINVAL);
-                /* see jt_obd_lov_getconfig for variable names */
-                /* setparam 0:lov_mdsA 1:default_stripe_size=1048576
+                
+                lprocfs_init_vars(lov, &lvars);
+                
+                /* setparam 0:lov_mdsA 1:default_stripe_size=1048576 
                    2:default_stripe_pattern=0 3:default_stripe_offset=0 */
                 for (i = 1; i < lcfg->lcfg_bufcount; i++) {
                         char *key, *sval;
@@ -814,23 +858,29 @@ static int lov_process_config(struct obd_device *obd, obd_count len, void *buf)
                                 /* continue parsing other params */
                                 continue;
                         }
-                        *sval = 0;
                         val = simple_strtol(sval + 1, NULL, 0);
-                        if (strcmp(key, PARAM_D_STRIPE_SIZE) == 0)
+                        rc = 0;
+                        /* LOV_STRIPE_* aren't settable in proc */
+                        if (class_match_param(key, 
+                                              PARAM_LOV_STRIPE_SIZE,0) == 0)
                                 desc->ld_default_stripe_size = val;
-                        else if (strcmp(key, PARAM_D_STRIPE_COUNT) == 0)
+                        else if (class_match_param(key, 
+                                              PARAM_LOV_STRIPE_COUNT, 0) == 0)
                                 desc->ld_default_stripe_count = val;
-                        else if (strcmp(key, PARAM_D_STRIPE_OFFSET) == 0)
+                        else if (class_match_param(key, 
+                                              PARAM_LOV_STRIPE_OFFSET, 0) == 0)
                                 desc->ld_default_stripe_offset = val;
-                        else if (strcmp(key, PARAM_D_STRIPE_PATTERN) == 0)
+                        else if (class_match_param(key, 
+                                              PARAM_LOV_STRIPE_PATTERN, 0) == 0)
                                 desc->ld_pattern = val;
-                        else {
-                                CERROR("Unknown param %s\n", key);
-                                rc = -EINVAL;
-                                /* continue parsing other params */
-                                continue;
+                        else 
+                                rc = class_process_proc_param(PARAM_LOV, 
+                                                              lvars.obd_vars,
+                                                              lcfg, obd);
+                        if (rc >= 0) {
+                                LCONSOLE_INFO("set %s to %ld\n", key, val);
+                                rc = 0;
                         }
-                        LCONSOLE_INFO("set %s to %ld\n", key, val);
                 }
                 lov_fix_desc(desc);
                 GOTO(out, rc);
@@ -874,28 +924,36 @@ static int lov_clear_orphans(struct obd_export *export, struct obdo *src_oa,
                        ost_uuid->uuid);
         }
 
+        lov_getref(export->exp_obd);
         for (i = 0; i < lov->desc.ld_tgt_count; i++) {
                 struct lov_stripe_md obj_md;
                 struct lov_stripe_md *obj_mdp = &obj_md;
+                struct lov_tgt_desc *tgt;
                 int err;
 
+                tgt = lov->lov_tgts[i];
+                if (!tgt)
+                        continue;
+
                 /* if called for a specific target, we don't
                    care if it is not active. */
-                if (lov->tgts[i].active == 0 && ost_uuid == NULL) {
+                if (!lov->lov_tgts[i]->ltd_active == 0 && ost_uuid == NULL) {
                         CDEBUG(D_HA, "lov idx %d inactive\n", i);
                         continue;
                 }
 
-                if (ost_uuid && !obd_uuid_equals(ost_uuid, &lov->tgts[i].uuid))
+                if (ost_uuid && !obd_uuid_equals(ost_uuid, &tgt->ltd_uuid))
                         continue;
 
-                CDEBUG(D_CONFIG,"Clear orphans for %d:%s\n", i, ost_uuid->uuid);
+                CDEBUG(D_CONFIG,"Clear orphans for %d:%s\n", i, 
+                       obd_uuid2str(ost_uuid));
 
                 memcpy(tmp_oa, src_oa, sizeof(*tmp_oa));
 
-                LASSERT(lov->tgts[i].ltd_exp);
+                LASSERT(lov->lov_tgts[i]->ltd_exp);
                 /* XXX: LOV STACKING: use real "obj_mdp" sub-data */
-                err = obd_create(lov->tgts[i].ltd_exp, tmp_oa, &obj_mdp, oti);
+                err = obd_create(lov->lov_tgts[i]->ltd_exp, 
+                                 tmp_oa, &obj_mdp, oti);
                 if (err)
                         /* This export will be disabled until it is recovered,
                            and then orphan recovery will be completed. */
@@ -905,6 +963,8 @@ static int lov_clear_orphans(struct obd_export *export, struct obdo *src_oa,
                 if (ost_uuid)
                         break;
         }
+        lov_putref(export->exp_obd);
+
         obdo_free(tmp_oa);
         RETURN(rc);
 }
@@ -929,7 +989,8 @@ static int lov_recreate(struct obd_export *exp, struct obdo *src_oa,
         lsm = *ea;
         if (lsm == NULL)
                 GOTO(out, rc = -EINVAL);
-        if (ost_idx >= lov->desc.ld_tgt_count)
+        if (ost_idx >= lov->desc.ld_tgt_count ||
+            !lov->lov_tgts[ost_idx])
                 GOTO(out, rc = -EINVAL);
 
         for (i = 0; i < lsm->lsm_stripe_count; i++) {
@@ -942,7 +1003,7 @@ static int lov_recreate(struct obd_export *exp, struct obdo *src_oa,
         if (i == lsm->lsm_stripe_count)
                 GOTO(out, rc = -EINVAL);
 
-        rc = obd_create(lov->tgts[ost_idx].ltd_exp, src_oa, &obj_mdp, oti);
+        rc = obd_create(lov->lov_tgts[ost_idx]->ltd_exp, src_oa, &obj_mdp, oti);
 out:
         OBD_FREE(obj_mdp, sizeof(*obj_mdp));
         RETURN(rc);
@@ -953,10 +1014,11 @@ static int lov_create(struct obd_export *exp, struct obdo *src_oa,
                       struct lov_stripe_md **ea, struct obd_trans_info *oti)
 {
         struct lov_obd *lov;
+        struct obd_info oinfo;
         struct lov_request_set *set = NULL;
-        struct obd_statfs osfs;
-        unsigned long maxage;
         struct lov_request *req;
+        struct obd_statfs osfs;
+        __u64 maxage;
         int rc = 0;
         ENTRY;
 
@@ -981,17 +1043,17 @@ static int lov_create(struct obd_export *exp, struct obdo *src_oa,
                  RETURN(rc);
         }
 
-        maxage = cfs_time_shift(-lov->desc.ld_qos_maxage);
-        obd_statfs(exp->exp_obd, &osfs, maxage);
+        maxage = cfs_time_shift_64(-lov->desc.ld_qos_maxage);
+        obd_statfs_rqset(exp->exp_obd, &osfs, maxage);
 
-        rc = lov_prep_create_set(exp, ea, src_oa, oti, &set);
+        rc = lov_prep_create_set(exp, &oinfo, ea, src_oa, oti, &set);
         if (rc)
                 RETURN(rc);
 
         list_for_each_entry(req, &set->set_list, rq_link) {
                 /* XXX: LOV STACKING: use real "obj_mdp" sub-data */
-                rc = obd_create(lov->tgts[req->rq_idx].ltd_exp,
-                                req->rq_oa, &req->rq_md, oti);
+                rc = obd_create(lov->lov_tgts[req->rq_idx]->ltd_exp,
+                                req->rq_oi.oi_oa, &req->rq_oi.oi_md, oti);
                 lov_update_create_set(set, req, rc);
         }
         rc = lov_fini_create_set(set, ea);
@@ -1011,10 +1073,11 @@ static int lov_destroy(struct obd_export *exp, struct obdo *oa,
                        struct obd_export *md_exp)
 {
         struct lov_request_set *set;
+        struct obd_info oinfo;
         struct lov_request *req;
         struct list_head *pos;
         struct lov_obd *lov;
-        int rc = 0;
+        int rc = 0, err;
         ENTRY;
 
         ASSERT_LSM_MAGIC(lsm);
@@ -1022,8 +1085,13 @@ static int lov_destroy(struct obd_export *exp, struct obdo *oa,
         if (!exp || !exp->exp_obd)
                 RETURN(-ENODEV);
 
+        if (oa->o_valid & OBD_MD_FLCOOKIE) {
+                LASSERT(oti);
+                LASSERT(oti->oti_logcookies);
+        }
+
         lov = &exp->exp_obd->u.lov;
-        rc = lov_prep_destroy_set(exp, oa, lsm, oti, &set);
+        rc = lov_prep_destroy_set(exp, &oinfo, oa, lsm, oti, &set);
         if (rc)
                 RETURN(rc);
 
@@ -1031,30 +1099,31 @@ static int lov_destroy(struct obd_export *exp, struct obdo *oa,
                 int err;
                 req = list_entry(pos, struct lov_request, rq_link);
 
-                /* XXX update the cookie position */
-                oti->oti_logcookies = set->set_cookies + req->rq_stripe;
-                rc = obd_destroy(lov->tgts[req->rq_idx].ltd_exp, req->rq_oa,
-                                 NULL, oti, NULL);
-                err = lov_update_common_set(set, req, rc);
-                if (rc) {
+                if (oa->o_valid & OBD_MD_FLCOOKIE)
+                        oti->oti_logcookies = set->set_cookies + req->rq_stripe;
+
+                err = obd_destroy(lov->lov_tgts[req->rq_idx]->ltd_exp,
+                                  req->rq_oi.oi_oa, NULL, oti, NULL);
+                err = lov_update_common_set(set, req, err);
+                if (err) {
                         CERROR("error: destroying objid "LPX64" subobj "
                                LPX64" on OST idx %d: rc = %d\n",
-                               set->set_oa->o_id, req->rq_oa->o_id,
-                               req->rq_idx, rc);
+                               oa->o_id, req->rq_oi.oi_oa->o_id,
+                               req->rq_idx, err);
                         if (!rc)
                                 rc = err;
                 }
         }
-        lov_fini_destroy_set(set);
+
         if (rc == 0) {
                 LASSERT(lsm_op_find(lsm->lsm_magic) != NULL);
                 rc = lsm_op_find(lsm->lsm_magic)->lsm_destroy(lsm, oa, md_exp);
         }
-        RETURN(rc);
+        err = lov_fini_destroy_set(set);
+        RETURN(rc ? rc : err);
 }
 
-static int lov_getattr(struct obd_export *exp, struct obdo *oa,
-                       struct lov_stripe_md *lsm)
+static int lov_getattr(struct obd_export *exp, struct obd_info *oinfo)
 {
         struct lov_request_set *set;
         struct lov_request *req;
@@ -1063,14 +1132,15 @@ static int lov_getattr(struct obd_export *exp, struct obdo *oa,
         int err = 0, rc = 0;
         ENTRY;
 
-        ASSERT_LSM_MAGIC(lsm);
+        LASSERT(oinfo);
+        ASSERT_LSM_MAGIC(oinfo->oi_md);
 
         if (!exp || !exp->exp_obd)
                 RETURN(-ENODEV);
 
         lov = &exp->exp_obd->u.lov;
 
-        rc = lov_prep_getattr_set(exp, oa, lsm, &set);
+        rc = lov_prep_getattr_set(exp, oinfo, &set);
         if (rc)
                 RETURN(rc);
 
@@ -1078,16 +1148,16 @@ static int lov_getattr(struct obd_export *exp, struct obdo *oa,
                 req = list_entry(pos, struct lov_request, rq_link);
 
                 CDEBUG(D_INFO, "objid "LPX64"[%d] has subobj "LPX64" at idx "
-                       "%u\n", oa->o_id, req->rq_stripe, req->rq_oa->o_id,
-                       req->rq_idx);
+                       "%u\n", oinfo->oi_oa->o_id, req->rq_stripe, 
+                       req->rq_oi.oi_oa->o_id, req->rq_idx);
 
-                rc = obd_getattr(lov->tgts[req->rq_idx].ltd_exp,
-                                 req->rq_oa, NULL);
+                rc = obd_getattr(lov->lov_tgts[req->rq_idx]->ltd_exp,
+                                 &req->rq_oi);
                 err = lov_update_common_set(set, req, rc);
                 if (err) {
                         CERROR("error: getattr objid "LPX64" subobj "
                                LPX64" on OST idx %d: rc = %d\n",
-                               set->set_oa->o_id, req->rq_oa->o_id,
+                               oinfo->oi_oa->o_id, req->rq_oi.oi_oa->o_id,
                                req->rq_idx, err);
                         break;
                 }
@@ -1099,78 +1169,79 @@ static int lov_getattr(struct obd_export *exp, struct obdo *oa,
         RETURN(rc);
 }
 
-static int lov_getattr_interpret(struct ptlrpc_request_set *rqset, void *data,
-                                 int rc)
+static int lov_getattr_interpret(struct ptlrpc_request_set *rqset, 
+                                 void *data, int rc)
 {
         struct lov_request_set *lovset = (struct lov_request_set *)data;
+        int err;
         ENTRY;
 
         /* don't do attribute merge if this aysnc op failed */
-        if (rc) {
+        if (rc)
                 lovset->set_completes = 0;
-                lov_fini_getattr_set(lovset);
-        } else {
-                rc = lov_fini_getattr_set(lovset);
-        }
-        RETURN (rc);
+        err = lov_fini_getattr_set(lovset);
+        RETURN(rc ? rc : err);
 }
 
-static int lov_getattr_async(struct obd_export *exp, struct obdo *oa,
-                              struct lov_stripe_md *lsm,
+static int lov_getattr_async(struct obd_export *exp, struct obd_info *oinfo,
                               struct ptlrpc_request_set *rqset)
 {
         struct lov_request_set *lovset;
         struct lov_obd *lov;
         struct list_head *pos;
         struct lov_request *req;
-        int rc = 0;
+        int rc = 0, err;
         ENTRY;
 
-        ASSERT_LSM_MAGIC(lsm);
+        LASSERT(oinfo);
+        ASSERT_LSM_MAGIC(oinfo->oi_md);
 
         if (!exp || !exp->exp_obd)
                 RETURN(-ENODEV);
 
         lov = &exp->exp_obd->u.lov;
 
-        rc = lov_prep_getattr_set(exp, oa, lsm, &lovset);
+        rc = lov_prep_getattr_set(exp, oinfo, &lovset);
         if (rc)
                 RETURN(rc);
 
         CDEBUG(D_INFO, "objid "LPX64": %ux%u byte stripes\n",
-               lsm->lsm_object_id, lsm->lsm_stripe_count, lsm->lsm_stripe_size);
+               oinfo->oi_md->lsm_object_id, oinfo->oi_md->lsm_stripe_count, 
+               oinfo->oi_md->lsm_stripe_size);
 
         list_for_each (pos, &lovset->set_list) {
                 req = list_entry(pos, struct lov_request, rq_link);
 
                 CDEBUG(D_INFO, "objid "LPX64"[%d] has subobj "LPX64" at idx "
-                       "%u\n", oa->o_id, req->rq_stripe, req->rq_oa->o_id,
-                       req->rq_idx);
-                rc = obd_getattr_async(lov->tgts[req->rq_idx].ltd_exp,
-                                       req->rq_oa, NULL, rqset);
+                       "%u\n", oinfo->oi_oa->o_id, req->rq_stripe, 
+                       req->rq_oi.oi_oa->o_id, req->rq_idx);
+                rc = obd_getattr_async(lov->lov_tgts[req->rq_idx]->ltd_exp,
+                                       &req->rq_oi, rqset);
                 if (rc) {
                         CERROR("error: getattr objid "LPX64" subobj "
                                LPX64" on OST idx %d: rc = %d\n",
-                               lovset->set_oa->o_id, req->rq_oa->o_id,
+                               oinfo->oi_oa->o_id, req->rq_oi.oi_oa->o_id,
                                req->rq_idx, rc);
                         GOTO(out, rc);
                 }
-                lov_update_common_set(lovset, req, rc);
         }
 
-        LASSERT(rc == 0);
-        LASSERT (rqset->set_interpret == NULL);
-        rqset->set_interpret = lov_getattr_interpret;
-        rqset->set_arg = (void *)lovset;
-        RETURN(rc);
+        if (!list_empty(&rqset->set_requests)) {
+                LASSERT(rc == 0);
+                LASSERT (rqset->set_interpret == NULL);
+                rqset->set_interpret = lov_getattr_interpret;
+                rqset->set_arg = (void *)lovset;
+                RETURN(rc);
+        }
 out:
-        LASSERT(rc);
-        lov_fini_getattr_set(lovset);
-        RETURN(rc);
+        if (rc)
+                lovset->set_completes = 0;
+        err = lov_fini_getattr_set(lovset);
+        RETURN(rc ? rc : err);
 }
 
-static int lov_setattr(struct obd_export *exp, struct obdo *src_oa,
-                       struct lov_stripe_md *lsm, struct obd_trans_info *oti)
+static int lov_setattr(struct obd_export *exp, struct obd_info *oinfo,
+                       struct obd_trans_info *oti)
 {
         struct lov_request_set *set;
         struct lov_obd *lov;
@@ -1179,33 +1250,36 @@ static int lov_setattr(struct obd_export *exp, struct obdo *src_oa,
         int err = 0, rc = 0;
         ENTRY;
 
-        ASSERT_LSM_MAGIC(lsm);
+        LASSERT(oinfo);
+        ASSERT_LSM_MAGIC(oinfo->oi_md);
 
         if (!exp || !exp->exp_obd)
                 RETURN(-ENODEV);
 
         /* for now, we only expect the following updates here */
-        LASSERT(!(src_oa->o_valid & ~(OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE |
-                                      OBD_MD_FLATIME | OBD_MD_FLMTIME | OBD_MD_FLCTIME |
-                                      OBD_MD_FLFLAGS | OBD_MD_FLSIZE | OBD_MD_FLGROUP |
-                                      OBD_MD_FLUID | OBD_MD_FLGID | OBD_MD_FLINLINE |
-                                      OBD_MD_FLFID | OBD_MD_FLGENER)));
+        LASSERT(!(oinfo->oi_oa->o_valid & ~(OBD_MD_FLID | OBD_MD_FLTYPE | 
+                                            OBD_MD_FLMODE | OBD_MD_FLATIME | 
+                                            OBD_MD_FLMTIME | OBD_MD_FLCTIME |
+                                            OBD_MD_FLFLAGS | OBD_MD_FLSIZE | 
+                                            OBD_MD_FLGROUP | OBD_MD_FLUID | 
+                                            OBD_MD_FLGID | OBD_MD_FLINLINE |
+                                            OBD_MD_FLFID | OBD_MD_FLGENER)));
         lov = &exp->exp_obd->u.lov;
-        rc = lov_prep_setattr_set(exp, src_oa, lsm, oti, &set);
+        rc = lov_prep_setattr_set(exp, oinfo, oti, &set);
         if (rc)
                 RETURN(rc);
 
         list_for_each (pos, &set->set_list) {
                 req = list_entry(pos, struct lov_request, rq_link);
 
-                rc = obd_setattr(lov->tgts[req->rq_idx].ltd_exp, req->rq_oa,
-                                 NULL, NULL);
+                rc = obd_setattr(lov->lov_tgts[req->rq_idx]->ltd_exp, 
+                                 &req->rq_oi, NULL);
                 err = lov_update_setattr_set(set, req, rc);
                 if (err) {
                         CERROR("error: setattr objid "LPX64" subobj "
                                LPX64" on OST idx %d: rc = %d\n",
-                               set->set_oa->o_id, req->rq_oa->o_id,
-                               req->rq_idx, err);
+                               set->set_oi->oi_oa->o_id, 
+                               req->rq_oi.oi_oa->o_id, req->rq_idx, err);
                         if (!rc)
                                 rc = err;
                 }
@@ -1216,106 +1290,159 @@ static int lov_setattr(struct obd_export *exp, struct obdo *src_oa,
         RETURN(rc);
 }
 
-static int lov_setattr_async(struct obd_export *exp, struct obdo *src_oa,
-                       struct lov_stripe_md *lsm, struct obd_trans_info *oti)
+static int lov_setattr_interpret(struct ptlrpc_request_set *rqset,
+                                 void *data, int rc)
 {
+        struct lov_request_set *lovset = (struct lov_request_set *)data;
+        int err;
+        ENTRY;
+
+        if (rc)
+                lovset->set_completes = 0;
+        err = lov_fini_setattr_set(lovset);
+        RETURN(rc ? rc : err);
+}
+
+/* If @oti is given, the request goes from MDS and responses from OSTs are not
+   needed. Otherwise, a client is waiting for responses. */
+static int lov_setattr_async(struct obd_export *exp, struct obd_info *oinfo,
+                             struct obd_trans_info *oti,
+                             struct ptlrpc_request_set *rqset)
+{
+        struct lov_request_set *set;
+        struct lov_request *req;
+        struct list_head *pos;
         struct lov_obd *lov;
-        struct lov_oinfo *loi = NULL;
-        int rc = 0, err;
-        obd_id objid = src_oa->o_id;
-        int i;
+        int rc = 0;
         ENTRY;
 
-        ASSERT_LSM_MAGIC(lsm);
-        LASSERT(oti);
-        if (src_oa->o_valid & OBD_MD_FLCOOKIE)
+        LASSERT(oinfo);
+        ASSERT_LSM_MAGIC(oinfo->oi_md);
+        if (oinfo->oi_oa->o_valid & OBD_MD_FLCOOKIE) {
+                LASSERT(oti);
                 LASSERT(oti->oti_logcookies);
+        }
 
         if (!exp || !exp->exp_obd)
                 RETURN(-ENODEV);
 
-        LASSERT(!(src_oa->o_valid &  ~(OBD_MD_FLID | OBD_MD_FLUID |
-                                       OBD_MD_FLGID| OBD_MD_FLCOOKIE |
-                                       OBD_MD_FLFID | OBD_MD_FLGENER)));
         lov = &exp->exp_obd->u.lov;
+        rc = lov_prep_setattr_set(exp, oinfo, oti, &set);
+        if (rc)
+                RETURN(rc);
 
-        loi = lsm->lsm_oinfo;
-        for (i = 0; i < lsm->lsm_stripe_count; i++, loi++) {
-                if (lov->tgts[loi->loi_ost_idx].active == 0) {
-                        CDEBUG(D_HA, "lov idx %d inactive\n", loi->loi_ost_idx);
-                        goto next;
-                }
+        CDEBUG(D_INFO, "objid "LPX64": %ux%u byte stripes\n",
+               oinfo->oi_md->lsm_object_id, oinfo->oi_md->lsm_stripe_count,
+               oinfo->oi_md->lsm_stripe_size);
+
+        list_for_each (pos, &set->set_list) {
+                req = list_entry(pos, struct lov_request, rq_link);
 
-                src_oa->o_id = loi->loi_id;
-                src_oa->o_stripe_idx = i;
+                if (oinfo->oi_oa->o_valid & OBD_MD_FLCOOKIE)
+                        oti->oti_logcookies = set->set_cookies + req->rq_stripe;
 
-                /* do chown/chgrp on OST asynchronously */
-                err = obd_setattr_async(lov->tgts[loi->loi_ost_idx].ltd_exp,
-                                        src_oa, NULL, oti);
-                if (err) {
+                CDEBUG(D_INFO, "objid "LPX64"[%d] has subobj "LPX64" at idx "
+                       "%u\n", oinfo->oi_oa->o_id, req->rq_stripe,
+                       req->rq_oi.oi_oa->o_id, req->rq_idx);
+
+                rc = obd_setattr_async(lov->lov_tgts[req->rq_idx]->ltd_exp,
+                                       &req->rq_oi, oti, rqset);
+                if (rc) {
                         CERROR("error: setattr objid "LPX64" subobj "
                                LPX64" on OST idx %d: rc = %d\n",
-                               objid, src_oa->o_id, i, err);
-                        if (!rc)
-                                rc = err;
+                               set->set_oi->oi_oa->o_id,
+                               req->rq_oi.oi_oa->o_id,
+                               req->rq_idx, rc);
+                        break;
                 }
-        next:
-                if (src_oa->o_valid & OBD_MD_FLCOOKIE)
-                        oti->oti_logcookies++;
         }
 
-        RETURN(rc);
+        /* If we are not waiting for responses on async requests, return. */
+        if (rc || !rqset || list_empty(&rqset->set_requests)) {
+                int err;
+                if (rc)
+                        set->set_completes = 0;
+                err = lov_fini_setattr_set(set);
+                RETURN(rc ? rc : err);
+        }
+
+        LASSERT(rqset->set_interpret == NULL);
+        rqset->set_interpret = lov_setattr_interpret;
+        rqset->set_arg = (void *)set;
+
+        RETURN(0);
+}
+
+static int lov_punch_interpret(struct ptlrpc_request_set *rqset,
+                               void *data, int rc)
+{
+        struct lov_request_set *lovset = (struct lov_request_set *)data;
+        int err;
+        ENTRY;
+
+        if (rc)
+                lovset->set_completes = 0;
+        err = lov_fini_punch_set(lovset);
+        RETURN(rc ? rc : err);
 }
 
 /* FIXME: maybe we'll just make one node the authoritative attribute node, then
  * we can send this 'punch' to just the authoritative node and the nodes
  * that the punch will affect. */
-static int lov_punch(struct obd_export *exp, struct obdo *oa,
-                     struct lov_stripe_md *lsm,
-                     obd_off start, obd_off end, struct obd_trans_info *oti)
+static int lov_punch(struct obd_export *exp, struct obd_info *oinfo,
+                     struct obd_trans_info *oti,
+                     struct ptlrpc_request_set *rqset)
 {
         struct lov_request_set *set;
         struct lov_obd *lov;
         struct list_head *pos;
         struct lov_request *req;
-        int err = 0, rc = 0;
+        int rc = 0;
         ENTRY;
 
-        ASSERT_LSM_MAGIC(lsm);
+        LASSERT(oinfo);
+        ASSERT_LSM_MAGIC(oinfo->oi_md);
 
         if (!exp || !exp->exp_obd)
                 RETURN(-ENODEV);
 
         lov = &exp->exp_obd->u.lov;
-        rc = lov_prep_punch_set(exp, oa, lsm, start, end, oti, &set);
+        rc = lov_prep_punch_set(exp, oinfo, oti, &set);
         if (rc)
                 RETURN(rc);
 
         list_for_each (pos, &set->set_list) {
                 req = list_entry(pos, struct lov_request, rq_link);
 
-                rc = obd_punch(lov->tgts[req->rq_idx].ltd_exp, req->rq_oa,
-                               NULL, req->rq_extent.start,
-                               req->rq_extent.end, NULL);
-                err = lov_update_punch_set(set, req, rc);
-                if (err) {
+                rc = obd_punch(lov->lov_tgts[req->rq_idx]->ltd_exp,
+                               &req->rq_oi, NULL, rqset);
+                if (rc) {
                         CERROR("error: punch objid "LPX64" subobj "LPX64
-                               " on OST idx %d: rc = %d\n", set->set_oa->o_id,
-                               req->rq_oa->o_id, req->rq_idx, rc);
-                        if (!rc)
-                                rc = err;
+                               " on OST idx %d: rc = %d\n",
+                               set->set_oi->oi_oa->o_id,
+                               req->rq_oi.oi_oa->o_id, req->rq_idx, rc);
+                        break;
                 }
         }
-        err = lov_fini_punch_set(set);
-        if (!rc)
-                rc = err;
-        RETURN(rc);
+
+        if (rc || list_empty(&rqset->set_requests)) {
+                int err;
+                err = lov_fini_punch_set(set);
+                RETURN(rc ? rc : err);
+        }
+
+        LASSERT(rqset->set_interpret == NULL);
+        rqset->set_interpret = lov_punch_interpret;
+        rqset->set_arg = (void *)set;
+
+        RETURN(0);
 }
 
 static int lov_sync(struct obd_export *exp, struct obdo *oa,
                     struct lov_stripe_md *lsm, obd_off start, obd_off end)
 {
         struct lov_request_set *set;
+        struct obd_info oinfo;
         struct lov_obd *lov;
         struct list_head *pos;
         struct lov_request *req;
@@ -1328,20 +1455,23 @@ static int lov_sync(struct obd_export *exp, struct obdo *oa,
                 RETURN(-ENODEV);
 
         lov = &exp->exp_obd->u.lov;
-        rc = lov_prep_sync_set(exp, oa, lsm, start, end, &set);
+        rc = lov_prep_sync_set(exp, &oinfo, oa, lsm, start, end, &set);
         if (rc)
                 RETURN(rc);
 
         list_for_each (pos, &set->set_list) {
                 req = list_entry(pos, struct lov_request, rq_link);
 
-                rc = obd_sync(lov->tgts[req->rq_idx].ltd_exp, req->rq_oa,
-                              NULL, req->rq_extent.start, req->rq_extent.end);
+                rc = obd_sync(lov->lov_tgts[req->rq_idx]->ltd_exp, 
+                              req->rq_oi.oi_oa, NULL, 
+                              req->rq_oi.oi_policy.l_extent.start,
+                              req->rq_oi.oi_policy.l_extent.end);
                 err = lov_update_common_set(set, req, rc);
                 if (err) {
                         CERROR("error: fsync objid "LPX64" subobj "LPX64
-                               " on OST idx %d: rc = %d\n", set->set_oa->o_id,
-                               req->rq_oa->o_id, req->rq_idx, rc);
+                               " on OST idx %d: rc = %d\n",
+                               set->set_oi->oi_oa->o_id,
+                               req->rq_oi.oi_oa->o_id, req->rq_idx, rc);
                         if (!rc)
                                 rc = err;
                 }
@@ -1352,39 +1482,42 @@ static int lov_sync(struct obd_export *exp, struct obdo *oa,
         RETURN(rc);
 }
 
-static int lov_brw_check(struct lov_obd *lov, struct obdo *oa,
-                         struct lov_stripe_md *lsm,
+static int lov_brw_check(struct lov_obd *lov, struct obd_info *lov_oinfo,
                          obd_count oa_bufs, struct brw_page *pga)
 {
+        struct obd_info oinfo = { { { 0 } } };
         int i, rc = 0;
 
+        oinfo.oi_oa = lov_oinfo->oi_oa;
+
         /* The caller just wants to know if there's a chance that this
          * I/O can succeed */
         for (i = 0; i < oa_bufs; i++) {
-                int stripe = lov_stripe_number(lsm, pga[i].off);
-                int ost = lsm->lsm_oinfo[stripe].loi_ost_idx;
+                int stripe = lov_stripe_number(lov_oinfo->oi_md, pga[i].off);
+                int ost = lov_oinfo->oi_md->lsm_oinfo[stripe].loi_ost_idx;
                 obd_off start, end;
 
-                if (!lov_stripe_intersects(lsm, i, pga[i].off,
+                if (!lov_stripe_intersects(lov_oinfo->oi_md, i, pga[i].off,
                                            pga[i].off + pga[i].count,
                                            &start, &end))
                         continue;
 
-                if (lov->tgts[ost].active == 0) {
+                if (!lov->lov_tgts[ost] || !lov->lov_tgts[ost]->ltd_active) {
                         CDEBUG(D_HA, "lov idx %d inactive\n", ost);
                         return -EIO;
                 }
-                rc = obd_brw(OBD_BRW_CHECK, lov->tgts[ost].ltd_exp, oa,
-                             NULL, 1, &pga[i], NULL);
+
+                rc = obd_brw(OBD_BRW_CHECK, lov->lov_tgts[ost]->ltd_exp, &oinfo,
+                             1, &pga[i], NULL);
                 if (rc)
                         break;
         }
         return rc;
 }
 
-static int lov_brw(int cmd, struct obd_export *exp, struct obdo *src_oa,
-                   struct lov_stripe_md *lsm, obd_count oa_bufs,
-                   struct brw_page *pga, struct obd_trans_info *oti)
+static int lov_brw(int cmd, struct obd_export *exp, struct obd_info *oinfo,
+                   obd_count oa_bufs, struct brw_page *pga,
+                   struct obd_trans_info *oti)
 {
         struct lov_request_set *set;
         struct lov_request *req;
@@ -1393,14 +1526,14 @@ static int lov_brw(int cmd, struct obd_export *exp, struct obdo *src_oa,
         int err, rc = 0;
         ENTRY;
 
-        ASSERT_LSM_MAGIC(lsm);
+        ASSERT_LSM_MAGIC(oinfo->oi_md);
 
         if (cmd == OBD_BRW_CHECK) {
-                rc = lov_brw_check(lov, src_oa, lsm, oa_bufs, pga);
+                rc = lov_brw_check(lov, oinfo, oa_bufs, pga);
                 RETURN(rc);
         }
 
-        rc = lov_prep_brw_set(exp, src_oa, lsm, oa_bufs, pga, oti, &set);
+        rc = lov_prep_brw_set(exp, oinfo, oa_bufs, pga, oti, &set);
         if (rc)
                 RETURN(rc);
 
@@ -1409,10 +1542,10 @@ static int lov_brw(int cmd, struct obd_export *exp, struct obdo *src_oa,
                 struct brw_page *sub_pga;
                 req = list_entry(pos, struct lov_request, rq_link);
 
-                sub_exp = lov->tgts[req->rq_idx].ltd_exp;
+                sub_exp = lov->lov_tgts[req->rq_idx]->ltd_exp;
                 sub_pga = set->set_pga + req->rq_pgaidx;
-                rc = obd_brw(cmd, sub_exp, req->rq_oa, req->rq_md,
-                             req->rq_oabufs, sub_pga, oti);
+                rc = obd_brw(cmd, sub_exp, &req->rq_oi, req->rq_oabufs,
+                             sub_pga, oti);
                 if (rc)
                         break;
                 lov_update_common_set(set, req, rc);
@@ -1440,10 +1573,10 @@ static int lov_brw_interpret(struct ptlrpc_request_set *reqset, void *data,
         RETURN(rc);
 }
 
-static int lov_brw_async(int cmd, struct obd_export *exp, struct obdo *oa,
-                         struct lov_stripe_md *lsm, obd_count oa_bufs,
-                         struct brw_page *pga, struct ptlrpc_request_set *set,
-                         struct obd_trans_info *oti)
+static int lov_brw_async(int cmd, struct obd_export *exp,
+                         struct obd_info *oinfo, obd_count oa_bufs,
+                         struct brw_page *pga, struct obd_trans_info *oti,
+                         struct ptlrpc_request_set *set)
 {
         struct lov_request_set *lovset;
         struct lov_request *req;
@@ -1452,14 +1585,15 @@ static int lov_brw_async(int cmd, struct obd_export *exp, struct obdo *oa,
         int rc = 0;
         ENTRY;
 
-        ASSERT_LSM_MAGIC(lsm);
+        LASSERT(oinfo);
+        ASSERT_LSM_MAGIC(oinfo->oi_md);
 
         if (cmd == OBD_BRW_CHECK) {
-                rc = lov_brw_check(lov, oa, lsm, oa_bufs, pga);
+                rc = lov_brw_check(lov, oinfo, oa_bufs, pga);
                 RETURN(rc);
         }
 
-        rc = lov_prep_brw_set(exp, oa, lsm, oa_bufs, pga, oti, &lovset);
+        rc = lov_prep_brw_set(exp, oinfo, oa_bufs, pga, oti, &lovset);
         if (rc)
                 RETURN(rc);
 
@@ -1468,10 +1602,10 @@ static int lov_brw_async(int cmd, struct obd_export *exp, struct obdo *oa,
                 struct brw_page *sub_pga;
                 req = list_entry(pos, struct lov_request, rq_link);
 
-                sub_exp = lov->tgts[req->rq_idx].ltd_exp;
+                sub_exp = lov->lov_tgts[req->rq_idx]->ltd_exp;
                 sub_pga = lovset->set_pga + req->rq_pgaidx;
-                rc = obd_brw_async(cmd, sub_exp, req->rq_oa, req->rq_md,
-                                   req->rq_oabufs, sub_pga, set, oti);
+                rc = obd_brw_async(cmd, sub_exp, &req->rq_oi, req->rq_oabufs,
+                                   sub_pga, oti, set);
                 if (rc)
                         GOTO(out, rc);
                 lov_update_common_set(lovset, req, rc);
@@ -1512,20 +1646,30 @@ static void lov_ap_fill_obdo(void *data, int cmd, struct obdo *oa)
         oa->o_stripe_idx = lap->lap_stripe;
 }
 
-static void lov_ap_completion(void *data, int cmd, struct obdo *oa, int rc)
+static void lov_ap_update_obdo(void *data, int cmd, struct obdo *oa,
+                               obd_valid valid)
+{
+        struct lov_async_page *lap = LAP_FROM_COOKIE(data);
+
+        lap->lap_caller_ops->ap_update_obdo(lap->lap_caller_data, cmd,oa,valid);
+}
+
+static int lov_ap_completion(void *data, int cmd, struct obdo *oa, int rc)
 {
         struct lov_async_page *lap = LAP_FROM_COOKIE(data);
 
         /* in a raid1 regime this would down a count of many ios
          * in flight, onl calling the caller_ops completion when all
          * the raid1 ios are complete */
-        lap->lap_caller_ops->ap_completion(lap->lap_caller_data, cmd, oa, rc);
+        rc = lap->lap_caller_ops->ap_completion(lap->lap_caller_data,cmd,oa,rc);
+        return rc;
 }
 
 static struct obd_async_page_ops lov_async_page_ops = {
         .ap_make_ready =        lov_ap_make_ready,
         .ap_refresh_count =     lov_ap_refresh_count,
         .ap_fill_obdo =         lov_ap_fill_obdo,
+        .ap_update_obdo =       lov_ap_update_obdo,
         .ap_completion =        lov_ap_completion,
 };
 
@@ -1544,21 +1688,22 @@ int lov_prep_async_page(struct obd_export *exp, struct lov_stripe_md *lsm,
                 /* Find an existing osc so we can get it's stupid sizeof(*oap).
                    Only because of this layering limitation will a client
                    mount with no osts fail */
-                while (!lov->tgts[i].ltd_exp) {
+                while (!lov->lov_tgts || !lov->lov_tgts[i] || 
+                       !lov->lov_tgts[i]->ltd_exp) {
                         i++;
-                        if (i >= lov->desc.ld_tgt_count)
-                                RETURN(-ENOTBLK);
+                        if (i >= lov->desc.ld_tgt_count) 
+                                RETURN(-ENOMEDIUM);
                 }
                 rc = size_round(sizeof(*lap)) +
-                        obd_prep_async_page(lov->tgts[i].ltd_exp, NULL, NULL,
-                                            NULL, 0, NULL, NULL, NULL);
+                        obd_prep_async_page(lov->lov_tgts[i]->ltd_exp, NULL,
+                                            NULL, NULL, 0, NULL, NULL, NULL);
                 RETURN(rc);
         }
         ASSERT_LSM_MAGIC(lsm);
         LASSERT(loi == NULL);
 
         lap = *res;
-        lap->lap_magic = LAP_MAGIC;
+        lap->lap_magic = LOV_AP_MAGIC;
         lap->lap_caller_ops = ops;
         lap->lap_caller_data = data;
 
@@ -1572,7 +1717,7 @@ int lov_prep_async_page(struct obd_export *exp, struct lov_stripe_md *lsm,
 
         lap->lap_sub_cookie = (void *)lap + size_round(sizeof(*lap));
 
-        rc = obd_prep_async_page(lov->tgts[loi->loi_ost_idx].ltd_exp,
+        rc = obd_prep_async_page(lov->lov_tgts[loi->loi_ost_idx]->ltd_exp,
                                  lsm, loi, page, lap->lap_sub_offset,
                                  &lov_async_page_ops, lap,
                                  &lap->lap_sub_cookie);
@@ -1601,7 +1746,7 @@ static int lov_queue_async_io(struct obd_export *exp,
 
         loi = &lsm->lsm_oinfo[lap->lap_stripe];
 
-        rc = obd_queue_async_io(lov->tgts[loi->loi_ost_idx].ltd_exp, lsm,
+        rc = obd_queue_async_io(lov->lov_tgts[loi->loi_ost_idx]->ltd_exp, lsm,
                                 loi, lap->lap_sub_cookie, cmd, off, count,
                                 brw_flags, async_flags);
         RETURN(rc);
@@ -1624,7 +1769,7 @@ static int lov_set_async_flags(struct obd_export *exp,
 
         loi = &lsm->lsm_oinfo[lap->lap_stripe];
 
-        rc = obd_set_async_flags(lov->tgts[loi->loi_ost_idx].ltd_exp,
+        rc = obd_set_async_flags(lov->lov_tgts[loi->loi_ost_idx]->ltd_exp,
                                  lsm, loi, lap->lap_sub_cookie, async_flags);
         RETURN(rc);
 }
@@ -1648,8 +1793,8 @@ static int lov_queue_group_io(struct obd_export *exp,
 
         loi = &lsm->lsm_oinfo[lap->lap_stripe];
 
-        rc = obd_queue_group_io(lov->tgts[loi->loi_ost_idx].ltd_exp, lsm, loi,
-                                oig, lap->lap_sub_cookie, cmd, off, count,
+        rc = obd_queue_group_io(lov->lov_tgts[loi->loi_ost_idx]->ltd_exp, lsm,
+                                loi, oig, lap->lap_sub_cookie, cmd, off, count,
                                 brw_flags, async_flags);
         RETURN(rc);
 }
@@ -1671,12 +1816,13 @@ static int lov_trigger_group_io(struct obd_export *exp,
 
         loi = lsm->lsm_oinfo;
         for (i = 0; i < lsm->lsm_stripe_count; i++, loi++) {
-                if (lov->tgts[loi->loi_ost_idx].active == 0) {
+                if (!lov->lov_tgts[loi->loi_ost_idx] || 
+                    !lov->lov_tgts[loi->loi_ost_idx]->ltd_active) {
                         CDEBUG(D_HA, "lov idx %d inactive\n", loi->loi_ost_idx);
                         continue;
                 }
 
-                err = obd_trigger_group_io(lov->tgts[loi->loi_ost_idx].ltd_exp,
+                err = obd_trigger_group_io(lov->lov_tgts[loi->loi_ost_idx]->ltd_exp,
                                            lsm, loi, oig);
                 if (rc == 0 && err != 0)
                         rc = err;
@@ -1700,7 +1846,7 @@ static int lov_teardown_async_page(struct obd_export *exp,
 
         loi = &lsm->lsm_oinfo[lap->lap_stripe];
 
-        rc = obd_teardown_async_page(lov->tgts[loi->loi_ost_idx].ltd_exp,
+        rc = obd_teardown_async_page(lov->lov_tgts[loi->loi_ost_idx]->ltd_exp,
                                      lsm, loi, lap->lap_sub_cookie);
         if (rc) {
                 CERROR("unable to teardown sub cookie %p: %d\n",
@@ -1710,53 +1856,63 @@ static int lov_teardown_async_page(struct obd_export *exp,
         RETURN(rc);
 }
 
-static int lov_enqueue(struct obd_export *exp, struct lov_stripe_md *lsm,
-                       __u32 type, ldlm_policy_data_t *policy, __u32 mode,
-                       int *flags, void *bl_cb, void *cp_cb, void *gl_cb,
-                       void *data,__u32 lvb_len, void *lvb_swabber,
-                       struct lustre_handle *lockh)
+static int lov_enqueue_interpret(struct ptlrpc_request_set *rqset,
+                                 void *data, int rc)
+{
+        struct lov_request_set *lovset = (struct lov_request_set *)data;
+        int err;
+        ENTRY;
+
+        if (rc)
+                lovset->set_completes = 0;
+        err = lov_fini_enqueue_set(lovset, lovset->set_ei->ei_mode);
+        RETURN(rc ? rc : err);
+}
+
+static int lov_enqueue(struct obd_export *exp, struct obd_info *oinfo,
+                       struct obd_enqueue_info *einfo)
 {
         struct lov_request_set *set;
         struct lov_request *req;
         struct list_head *pos;
-        struct lustre_handle *lov_lockhp;
         struct lov_obd *lov;
         ldlm_error_t rc;
-        int save_flags = *flags;
         ENTRY;
 
-        ASSERT_LSM_MAGIC(lsm);
+        LASSERT(oinfo);
+        ASSERT_LSM_MAGIC(oinfo->oi_md);
 
         /* we should never be asked to replay a lock this way. */
-        LASSERT((*flags & LDLM_FL_REPLAY) == 0);
+        LASSERT((einfo->ei_flags & LDLM_FL_REPLAY) == 0);
 
         if (!exp || !exp->exp_obd)
                 RETURN(-ENODEV);
 
         lov = &exp->exp_obd->u.lov;
-        rc = lov_prep_enqueue_set(exp, lsm, policy, mode, lockh, &set);
+        rc = lov_prep_enqueue_set(exp, oinfo, einfo, &set);
         if (rc)
                 RETURN(rc);
 
         list_for_each (pos, &set->set_list) {
-                ldlm_policy_data_t sub_policy;
                 req = list_entry(pos, struct lov_request, rq_link);
-                lov_lockhp = set->set_lockh->llh_handles + req->rq_stripe;
-                LASSERT(lov_lockhp);
-
-                *flags = save_flags;
-                sub_policy.l_extent = req->rq_extent;
 
-                rc = obd_enqueue(lov->tgts[req->rq_idx].ltd_exp, req->rq_md,
-                                 type, &sub_policy, mode, flags, bl_cb,
-                                 cp_cb, gl_cb, data, lvb_len, lvb_swabber,
-                                 lov_lockhp);
-                rc = lov_update_enqueue_set(set, req, rc, save_flags);
+                rc = obd_enqueue(lov->lov_tgts[req->rq_idx]->ltd_exp,
+                                 &req->rq_oi, einfo);
                 if (rc != ELDLM_OK)
-                        break;
+                        GOTO(out, rc);
         }
 
-        lov_fini_enqueue_set(set, mode);
+        if (einfo->ei_rqset && !list_empty(&einfo->ei_rqset->set_requests)) {
+                LASSERT(rc == 0);
+                LASSERT(einfo->ei_rqset->set_interpret == NULL);
+                einfo->ei_rqset->set_interpret = lov_enqueue_interpret;
+                einfo->ei_rqset->set_arg = (void *)set;
+                RETURN(rc);
+        }
+out:
+        if (rc)
+                set->set_completes = 0;
+        lov_fini_enqueue_set(set, einfo->ei_mode);
         RETURN(rc);
 }
 
@@ -1765,6 +1921,7 @@ static int lov_match(struct obd_export *exp, struct lov_stripe_md *lsm,
                      int *flags, void *data, struct lustre_handle *lockh)
 {
         struct lov_request_set *set;
+        struct obd_info oinfo;
         struct lov_request *req;
         struct list_head *pos;
         struct lov_obd *lov = &exp->exp_obd->u.lov;
@@ -1778,7 +1935,7 @@ static int lov_match(struct obd_export *exp, struct lov_stripe_md *lsm,
                 RETURN(-ENODEV);
 
         lov = &exp->exp_obd->u.lov;
-        rc = lov_prep_match_set(exp, lsm, policy, mode, lockh, &set);
+        rc = lov_prep_match_set(exp, &oinfo, lsm, policy, mode, lockh, &set);
         if (rc)
                 RETURN(rc);
 
@@ -1789,11 +1946,11 @@ static int lov_match(struct obd_export *exp, struct lov_stripe_md *lsm,
                 LASSERT(lov_lockhp);
 
                 lov_flags = *flags;
-                sub_policy.l_extent = req->rq_extent;
+                sub_policy.l_extent = req->rq_oi.oi_policy.l_extent;
 
-                rc = obd_match(lov->tgts[req->rq_idx].ltd_exp, req->rq_md,
-                               type, &sub_policy, mode, &lov_flags, data,
-                               lov_lockhp);
+                rc = obd_match(lov->lov_tgts[req->rq_idx]->ltd_exp,
+                               req->rq_oi.oi_md, type, &sub_policy,
+                               mode, &lov_flags, data, lov_lockhp);
                 rc = lov_update_match_set(set, req, rc);
                 if (rc != 1)
                         break;
@@ -1822,7 +1979,7 @@ static int lov_change_cbdata(struct obd_export *exp,
 
                 submd.lsm_object_id = loi->loi_id;
                 submd.lsm_stripe_count = 0;
-                rc = obd_change_cbdata(lov->tgts[loi->loi_ost_idx].ltd_exp,
+                rc = obd_change_cbdata(lov->lov_tgts[loi->loi_ost_idx]->ltd_exp,
                                        &submd, it, data);
         }
         RETURN(rc);
@@ -1832,6 +1989,7 @@ static int lov_cancel(struct obd_export *exp, struct lov_stripe_md *lsm,
                       __u32 mode, struct lustre_handle *lockh)
 {
         struct lov_request_set *set;
+        struct obd_info oinfo;
         struct lov_request *req;
         struct list_head *pos;
         struct lov_obd *lov = &exp->exp_obd->u.lov;
@@ -1846,7 +2004,7 @@ static int lov_cancel(struct obd_export *exp, struct lov_stripe_md *lsm,
 
         LASSERT(lockh);
         lov = &exp->exp_obd->u.lov;
-        rc = lov_prep_cancel_set(exp, lsm, mode, lockh, &set);
+        rc = lov_prep_cancel_set(exp, &oinfo, lsm, mode, lockh, &set);
         if (rc)
                 RETURN(rc);
 
@@ -1854,14 +2012,15 @@ static int lov_cancel(struct obd_export *exp, struct lov_stripe_md *lsm,
                 req = list_entry(pos, struct lov_request, rq_link);
                 lov_lockhp = set->set_lockh->llh_handles + req->rq_stripe;
 
-                rc = obd_cancel(lov->tgts[req->rq_idx].ltd_exp, req->rq_md,
-                                mode, lov_lockhp);
+                rc = obd_cancel(lov->lov_tgts[req->rq_idx]->ltd_exp,
+                                req->rq_oi.oi_md, mode, lov_lockhp);
                 rc = lov_update_common_set(set, req, rc);
                 if (rc) {
                         CERROR("error: cancel objid "LPX64" subobj "
                                LPX64" on OST idx %d: rc = %d\n",
                                lsm->lsm_object_id,
-                               req->rq_md->lsm_object_id, req->rq_idx, rc);
+                               req->rq_oi.oi_md->lsm_object_id,
+                               req->rq_idx, rc);
                         err = rc;
                 }
 
@@ -1879,14 +2038,17 @@ static int lov_cancel_unused(struct obd_export *exp,
         int rc = 0, i;
         ENTRY;
 
+        if (!exp || !exp->exp_obd)
+                RETURN(-ENODEV);
+
         lov = &exp->exp_obd->u.lov;
         if (lsm == NULL) {
                 for (i = 0; i < lov->desc.ld_tgt_count; i++) {
                         int err;
-                        if (!lov->tgts[i].ltd_exp)
+                        if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_exp)
                                 continue;
 
-                        err = obd_cancel_unused(lov->tgts[i].ltd_exp, NULL,
+                        err = obd_cancel_unused(lov->lov_tgts[i]->ltd_exp, NULL,
                                                 flags, opaque);
                         if (!rc)
                                 rc = err;
@@ -1896,21 +2058,19 @@ static int lov_cancel_unused(struct obd_export *exp,
 
         ASSERT_LSM_MAGIC(lsm);
 
-        if (!exp || !exp->exp_obd)
-                RETURN(-ENODEV);
-
         for (i = 0,loi = lsm->lsm_oinfo; i < lsm->lsm_stripe_count; i++,loi++) {
                 struct lov_stripe_md submd;
                 int err;
 
-                if (lov->tgts[loi->loi_ost_idx].active == 0)
+                if (!lov->lov_tgts[loi->loi_ost_idx] || 
+                    !lov->lov_tgts[loi->loi_ost_idx]->ltd_active)
                         CDEBUG(D_HA, "lov idx %d inactive\n", loi->loi_ost_idx);
 
                 submd.lsm_object_id = loi->loi_id;
                 submd.lsm_stripe_count = 0;
-                err = obd_cancel_unused(lov->tgts[loi->loi_ost_idx].ltd_exp,
+                err = obd_cancel_unused(lov->lov_tgts[loi->loi_ost_idx]->ltd_exp,
                                         &submd, flags, opaque);
-                if (err && lov->tgts[loi->loi_ost_idx].active) {
+                if (err && lov->lov_tgts[loi->loi_ost_idx]->ltd_active) {
                         CERROR("error: cancel unused objid "LPX64" subobj "LPX64
                                " on OST idx %d: rc = %d\n", lsm->lsm_object_id,
                                loi->loi_id, loi->loi_ost_idx, err);
@@ -1938,12 +2098,13 @@ static int lov_join_lru(struct obd_export *exp,
                 struct lov_stripe_md submd;
                 int rc = 0;
 
-                if (lov->tgts[loi->loi_ost_idx].active == 0)
+                if (!lov->lov_tgts[loi->loi_ost_idx] || 
+                    !lov->lov_tgts[loi->loi_ost_idx]->ltd_active)
                         CDEBUG(D_HA, "lov idx %d inactive\n", loi->loi_ost_idx);
 
                 submd.lsm_object_id = loi->loi_id;
                 submd.lsm_stripe_count = 0;
-                rc = obd_join_lru(lov->tgts[loi->loi_ost_idx].ltd_exp,
+                rc = obd_join_lru(lov->lov_tgts[loi->loi_ost_idx]->ltd_exp,
                                   &submd, join);
                 if (rc < 0) {
                         CERROR("join lru failed. objid: "LPX64" subobj: "LPX64
@@ -1957,90 +2118,95 @@ static int lov_join_lru(struct obd_export *exp,
         RETURN(count);
 }
 
-#define LOV_U64_MAX ((__u64)~0ULL)
-#define LOV_SUM_MAX(tot, add)                                           \
-        do {                                                            \
-                if ((tot) + (add) < (tot))                              \
-                        (tot) = LOV_U64_MAX;                            \
-                else                                                    \
-                        (tot) += (add);                                 \
-        } while(0)
+static int lov_statfs_interpret(struct ptlrpc_request_set *rqset,
+                                void *data, int rc)
+{
+        struct lov_request_set *lovset = (struct lov_request_set *)data;
+        int err;
+        ENTRY;
+
+        if (rc)
+                lovset->set_completes = 0;
+
+        err = lov_fini_statfs_set(lovset);
+        RETURN(rc ? rc : err);
+}
+
+static int lov_statfs_async(struct obd_device *obd, struct obd_info *oinfo,
+                            __u64 max_age, struct ptlrpc_request_set *rqset)
+{
+        struct lov_request_set *set;
+        struct lov_request *req;
+        struct list_head *pos;
+        struct lov_obd *lov;
+        int rc = 0;
+
+        LASSERT(oinfo != NULL);
+        LASSERT(oinfo->oi_osfs != NULL);
+
+        lov = &obd->u.lov;
+        rc = lov_prep_statfs_set(obd, oinfo, &set);
+        if (rc)
+                RETURN(rc);
+
+        list_for_each (pos, &set->set_list) {
+                struct obd_device *osc_obd;
+
+                req = list_entry(pos, struct lov_request, rq_link);
+
+                osc_obd = class_exp2obd(lov->lov_tgts[req->rq_idx]->ltd_exp);
+                rc = obd_statfs_async(osc_obd, &req->rq_oi, max_age, rqset);
+                if (rc)
+                        break;
+        }
+
+        if (rc || list_empty(&rqset->set_requests)) {
+                int err;
+                if (rc)
+                        set->set_completes = 0;
+                err = lov_fini_statfs_set(set);
+                RETURN(rc ? rc : err);
+        }
+
+        LASSERT(rqset->set_interpret == NULL);
+        rqset->set_interpret = lov_statfs_interpret;
+        rqset->set_arg = (void *)set;
+        RETURN(0);
+}
 
 static int lov_statfs(struct obd_device *obd, struct obd_statfs *osfs,
-                      cfs_time_t max_age)
+                      __u64 max_age)
 {
         struct lov_obd *lov = &obd->u.lov;
         struct obd_statfs lov_sfs;
         int set = 0;
-        int rc = 0;
+        int rc = 0, err;
         int i;
         ENTRY;
 
-
         /* We only get block data from the OBD */
         for (i = 0; i < lov->desc.ld_tgt_count; i++) {
-                int err;
-                if (!lov->tgts[i].active) {
+                if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_active) {
                         CDEBUG(D_HA, "lov idx %d inactive\n", i);
                         continue;
                 }
 
-                err = obd_statfs(class_exp2obd(lov->tgts[i].ltd_exp), &lov_sfs,
-                                 max_age);
+                err = obd_statfs(class_exp2obd(lov->lov_tgts[i]->ltd_exp), 
+                                 &lov_sfs, max_age);
                 if (err) {
-                        if (lov->tgts[i].active && !rc)
+                        if (lov->lov_tgts[i]->ltd_active && !rc)
                                 rc = err;
                         continue;
                 }
                 qos_update(lov, i, &lov_sfs);
 
-                if (!set) {
-                        memcpy(osfs, &lov_sfs, sizeof(lov_sfs));
-                        set = 1;
-                } else {
-#ifdef MIN_DF
-                        /* Sandia requested that df (and so, statfs) only
-                           returned minimal available space on
-                           a single OST, so people would be able to
-                           write this much data guaranteed. */
-                        if (osfs->os_bavail > lov_sfs.os_bavail) {
-                                /* Presumably if new bavail is smaller,
-                                   new bfree is bigger as well */
-                                osfs->os_bfree = lov_sfs.os_bfree;
-                                osfs->os_bavail = lov_sfs.os_bavail;
-                        }
-#else
-                        osfs->os_bfree += lov_sfs.os_bfree;
-                        osfs->os_bavail += lov_sfs.os_bavail;
-#endif
-                        osfs->os_blocks += lov_sfs.os_blocks;
-                        /* XXX not sure about this one - depends on policy.
-                         *   - could be minimum if we always stripe on all OBDs
-                         *     (but that would be wrong for any other policy,
-                         *     if one of the OBDs has no more objects left)
-                         *   - could be sum if we stripe whole objects
-                         *   - could be average, just to give a nice number
-                         *
-                         * To give a "reasonable" (if not wholly accurate)
-                         * number, we divide the total number of free objects
-                         * by expected stripe count (watch out for overflow).
-                         */
-                        LOV_SUM_MAX(osfs->os_files, lov_sfs.os_files);
-                        LOV_SUM_MAX(osfs->os_ffree, lov_sfs.os_ffree);
-                }
+                lov_update_statfs(class_exp2obd(lov->lov_tgts[i]->ltd_exp),
+                                  osfs, &lov_sfs, set);
+                set++;
         }
 
-        if (set) {
-                __u32 expected_stripes = lov_get_stripecnt(lov, 0);
-
-                if (osfs->os_files != LOV_U64_MAX)
-                        do_div(osfs->os_files, expected_stripes);
-                if (osfs->os_ffree != LOV_U64_MAX)
-                        do_div(osfs->os_ffree, expected_stripes);
-        } else if (!rc)
-                rc = -EIO;
-
-        RETURN(rc);
+        err = lov_fini_statfs(obd, osfs, set);
+        RETURN(rc ? rc : err);
 }
 
 static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
@@ -2054,13 +2220,11 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
 
         switch (cmd) {
         case OBD_IOC_LOV_GET_CONFIG: {
-                struct obd_ioctl_data *data = karg;
-                struct lov_tgt_desc *tgtdesc;
+                struct obd_ioctl_data *data;
                 struct lov_desc *desc;
                 char *buf = NULL;
                 __u32 *genp;
 
-                buf = NULL;
                 len = 0;
                 if (obd_ioctl_getdata(&buf, &len, (void *)uarg))
                         RETURN(-EINVAL);
@@ -2087,11 +2251,12 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
 
                 uuidp = (struct obd_uuid *)data->ioc_inlbuf2;
                 genp = (__u32 *)data->ioc_inlbuf3;
-                tgtdesc = lov->tgts;
                 /* the uuid will be empty for deleted OSTs */
-                for (i = 0; i < count; i++, uuidp++, genp++, tgtdesc++) {
-                        obd_str2uuid(uuidp, tgtdesc->uuid.uuid);
-                        *genp = tgtdesc->ltd_gen;
+                for (i = 0; i < count; i++, uuidp++, genp++) {
+                        if (!lov->lov_tgts[i]) 
+                                continue;
+                        *uuidp = lov->lov_tgts[i]->ltd_uuid;
+                        *genp = lov->lov_tgts[i]->ltd_gen;
                 }
 
                 rc = copy_to_user((void *)uarg, buf, len);
@@ -2120,24 +2285,26 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
                         int err;
 
                         /* OST was disconnected */
-                        if (!lov->tgts[i].ltd_exp)
+                        if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_exp)
                                 continue;
 
-                        err = obd_iocontrol(cmd, lov->tgts[i].ltd_exp,
+                        err = obd_iocontrol(cmd, lov->lov_tgts[i]->ltd_exp,
                                             len, karg, uarg);
                         if (err == -ENODATA && cmd == OBD_IOC_POLL_QUOTACHECK) {
                                 RETURN(err);
                         } else if (err) {
-                                if (lov->tgts[i].active) {
-                                        CERROR("error: iocontrol OSC %s on OST "
+                                if (lov->lov_tgts[i]->ltd_active) {
+                                        CDEBUG(D_WARNING,
+                                               "iocontrol OSC %s on OST "
                                                "idx %d cmd %x: err = %d\n",
-                                               lov->tgts[i].uuid.uuid, i,
-                                               cmd, err);
+                                               lov_uuid2str(lov, i),
+                                               i, cmd, err);
                                         if (!rc)
                                                 rc = err;
                                 }
-                        } else
+                        } else {
                                 set = 1;
+                        }
                 }
                 if (!set && !rc)
                         rc = -EIO;
@@ -2184,10 +2351,12 @@ static int lov_get_info(struct obd_export *exp, __u32 keylen,
                 for (i = 0, loi = data->lsm->lsm_oinfo;
                      i < data->lsm->lsm_stripe_count;
                      i++, loi++) {
-                         if (lov->tgts[loi->loi_ost_idx].ltd_exp ==
-                             data->lock->l_conn_export &&
-                             loi->loi_id == res_id->name[0] &&
-                             loi->loi_gr == res_id->name[2]) {
+                        if (!lov->lov_tgts[loi->loi_ost_idx])
+                                continue;
+                        if (lov->lov_tgts[loi->loi_ost_idx]->ltd_exp ==
+                            data->lock->l_conn_export &&
+                            loi->loi_id == res_id->name[0] &&
+                            loi->loi_gr == res_id->name[1]) {
                                 *stripe = i;
                                 GOTO(out, rc = 0);
                         }
@@ -2199,9 +2368,9 @@ static int lov_get_info(struct obd_export *exp, __u32 keylen,
                 obd_id *ids = val;
                 int size = sizeof(obd_id);
                 for (i = 0; i < lov->desc.ld_tgt_count; i++) {
-                        if (!lov->tgts[i].active)
+                        if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_active)
                                 continue;
-                        rc = obd_get_info(lov->tgts[i].ltd_exp,
+                        rc = obd_get_info(lov->lov_tgts[i]->ltd_exp,
                                           keylen, key, &size, &(ids[i]));
                         if (rc != 0)
                                 GOTO(out, rc);
@@ -2248,12 +2417,12 @@ static int lov_set_info_async(struct obd_export *exp, obd_count keylen,
         if (KEY_IS(KEY_NEXT_ID) || KEY_IS("checksum")) {
                 for (i = 0; i < lov->desc.ld_tgt_count; i++) {
                         /* OST was disconnected */
-                        if (!lov->tgts[i].ltd_exp)
+                        if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_exp)
                                 continue;
 
                         /* hit all OSCs, even inactive ones */
-                        err = obd_set_info_async(lov->tgts[i].ltd_exp, keylen,
-                                                 key, vallen,
+                        err = obd_set_info_async(lov->lov_tgts[i]->ltd_exp,
+                                                 keylen, key, vallen,
                                                  ((obd_id*)val) + i, set);
                         if (!rc)
                                 rc = err;
@@ -2264,11 +2433,11 @@ static int lov_set_info_async(struct obd_export *exp, obd_count keylen,
         if (KEY_IS("evict_by_nid")) {
                 for (i = 0; i < lov->desc.ld_tgt_count; i++) {
                         /* OST was disconnected or is inactive */
-                        if (!lov->tgts[i].ltd_exp || !lov->tgts[i].active)
+                        if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_active)
                                 continue;
 
-                        err = obd_set_info_async(lov->tgts[i].ltd_exp, keylen,
-                                                 key, vallen, val, set);
+                        err = obd_set_info_async(lov->lov_tgts[i]->ltd_exp, 
+                                                 keylen, key, vallen, val, set);
                         if (!rc)
                                 rc = err;
                 }
@@ -2283,17 +2452,16 @@ static int lov_set_info_async(struct obd_export *exp, obd_count keylen,
         }
 
         for (i = 0; i < lov->desc.ld_tgt_count; i++) {
-                if (val && !obd_uuid_equals(val, &lov->tgts[i].uuid))
+                if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_exp)
                         continue;
-
-                /* OST was disconnected */
-                if (!lov->tgts[i].ltd_exp)
+                
+                if (val && !obd_uuid_equals(val, &lov->lov_tgts[i]->ltd_uuid))
                         continue;
 
-                if (!val && !lov->tgts[i].active)
+                if (!val && !lov->lov_tgts[i]->ltd_active)
                         continue;
 
-                err = obd_set_info_async(lov->tgts[i].ltd_exp,
+                err = obd_set_info_async(lov->lov_tgts[i]->ltd_exp,
                                          keylen, key, vallen, val, set);
                 if (!rc)
                         rc = err;
@@ -2340,6 +2508,31 @@ int lov_test_and_clear_async_rc(struct lov_stripe_md *lsm)
 }
 EXPORT_SYMBOL(lov_test_and_clear_async_rc);
 
+
+static int lov_extent_calc(struct obd_export *exp, struct lov_stripe_md *lsm,
+                           int cmd, obd_off *offset)
+{
+        unsigned long ssize  = lsm->lsm_stripe_size;
+        obd_off start;
+
+        start = *offset;
+        do_div(start, ssize);
+        start = start * ssize;
+
+        CDEBUG(D_DLMTRACE, "offset %Lu, stripe %lu, start %Lu, end %Lu\n", 
+               *offset, ssize, start, start + ssize - 1);
+        if (cmd == OBD_CALC_STRIPE_END) {
+                *offset = start + ssize - 1;
+        } else if (cmd == OBD_CALC_STRIPE_START) {
+                *offset = start;
+        } else {
+                LBUG();
+        }
+
+        RETURN(0);
+}
+
+
 #if 0
 struct lov_multi_wait {
         struct ldlm_lock *lock;
@@ -2386,7 +2579,6 @@ int lov_complete_many(struct obd_export *exp, struct lov_stripe_md *lsm,
              i++, loi++, lov_lockhp++) {
                 struct ldlm_lock *lock;
                 struct obd_device *obd;
-                unsigned long irqflags;
 
                 lock = ldlm_handle2lock(lov_lockhp);
                 if (lock == NULL) {
@@ -2404,9 +2596,9 @@ int lov_complete_many(struct obd_export *exp, struct lov_stripe_md *lsm,
                 if (obd != NULL)
                         imp = obd->u.cli.cl_import;
                 if (imp != NULL) {
-                        spin_lock_irqsave(&imp->imp_lock, irqflags);
+                        spin_lock(&imp->imp_lock);
                         queues[i].generation = imp->imp_generation;
-                        spin_unlock_irqrestore(&imp->imp_lock, irqflags);
+                        spin_unlock(&imp->imp_lock);
                 }
         }
 
@@ -2455,6 +2647,7 @@ struct obd_ops lov_obd_ops = {
         .o_connect             = lov_connect,
         .o_disconnect          = lov_disconnect,
         .o_statfs              = lov_statfs,
+        .o_statfs_async        = lov_statfs_async,
         .o_packmd              = lov_packmd,
         .o_unpackmd            = lov_unpackmd,
         .o_checkmd             = lov_checkmd,
@@ -2485,6 +2678,7 @@ struct obd_ops lov_obd_ops = {
         .o_iocontrol           = lov_iocontrol,
         .o_get_info            = lov_get_info,
         .o_set_info_async      = lov_set_info_async,
+        .o_extent_calc         = lov_extent_calc,
         .o_llog_init           = lov_llog_init,
         .o_llog_finish         = lov_llog_finish,
         .o_notify              = lov_notify,
@@ -2501,13 +2695,14 @@ int __init lov_init(void)
 
         lprocfs_init_vars(lov, &lvars);
 
+        request_module("lquota");
         quota_interface = PORTAL_SYMBOL_GET(lov_quota_interface);
         init_obd_quota_ops(quota_interface, &lov_obd_ops);
 
         rc = class_register_type(&lov_obd_ops, NULL, lvars.module_vars,
                                  LUSTRE_LOV_NAME, NULL);
         if (rc && quota_interface)
-                PORTAL_SYMBOL_PUT(osc_quota_interface);
+                PORTAL_SYMBOL_PUT(lov_quota_interface);
 
         RETURN(rc);
 }
@@ -2525,5 +2720,5 @@ MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
 MODULE_DESCRIPTION("Lustre Logical Object Volume OBD driver");
 MODULE_LICENSE("GPL");
 
-cfs_module(lov, "1.0.0", lov_init, lov_exit);
+cfs_module(lov, LUSTRE_VERSION_STRING, lov_init, lov_exit);
 #endif
index 7ad2745..c4b0751 100644 (file)
@@ -41,16 +41,15 @@ void lov_dump_lmm_v1(int level, struct lov_mds_md_v1 *lmm)
 {
         struct lov_ost_data_v1 *lod;
         int i;
-
-        CDEBUG_EX(level, "objid "LPX64", magic 0x%08X, pattern %#X\n",
+        CDEBUG(level, "objid "LPX64", magic 0x%08x, pattern %#x\n",
                le64_to_cpu(lmm->lmm_object_id), le32_to_cpu(lmm->lmm_magic),
                le32_to_cpu(lmm->lmm_pattern));
-        CDEBUG_EX(level,"stripe_size %u, stripe_count %u\n",
+        CDEBUG(level,"stripe_size %u, stripe_count %u\n",
                le32_to_cpu(lmm->lmm_stripe_size),
                le32_to_cpu(lmm->lmm_stripe_count));
         for (i = 0, lod = lmm->lmm_objects;
              i < le32_to_cpu(lmm->lmm_stripe_count); i++, lod++)
-                CDEBUG_EX(level, "stripe %u idx %u subobj "LPX64"/"LPX64"\n",
+                CDEBUG(level, "stripe %u idx %u subobj "LPX64"/"LPX64"\n",
                        i, le32_to_cpu(lod->l_ost_idx),
                        le64_to_cpu(lod->l_object_gr),
                        le64_to_cpu(lod->l_object_id));
@@ -59,11 +58,11 @@ void lov_dump_lmm_v1(int level, struct lov_mds_md_v1 *lmm)
 void lov_dump_lmm_join(int level, struct lov_mds_md_join *lmmj)
 {
 
-        CDEBUG_EX(level, "objid "LPX64", magic 0x%08X, pattern %#X\n",
+        CDEBUG(level, "objid "LPX64", magic 0x%08X, pattern %#X\n",
                le64_to_cpu(lmmj->lmmj_md.lmm_object_id),
                le32_to_cpu(lmmj->lmmj_md.lmm_magic),
                le32_to_cpu(lmmj->lmmj_md.lmm_pattern));
-        CDEBUG_EX(level,"stripe_size %u, stripe_count %u extent_count %u \n",
+        CDEBUG(level,"stripe_size %u, stripe_count %u extent_count %u \n",
                le32_to_cpu(lmmj->lmmj_md.lmm_stripe_size),
                le32_to_cpu(lmmj->lmmj_md.lmm_stripe_count),
                le32_to_cpu(lmmj->lmmj_extent_count));
@@ -204,7 +203,6 @@ int lov_alloc_memmd(struct lov_stripe_md **lsmp, int stripe_count,
         (*lsmp)->lsm_magic = magic;
         (*lsmp)->lsm_stripe_count = stripe_count;
         (*lsmp)->lsm_maxbytes = LUSTRE_STRIPE_MAXBYTES * stripe_count;
-        (*lsmp)->lsm_xfersize = PTLRPC_MAX_BRW_SIZE * stripe_count;
         (*lsmp)->lsm_pattern = pattern;
         (*lsmp)->lsm_oinfo[0].loi_ost_idx = ~0;
 
@@ -350,7 +348,6 @@ int lov_setstripe(struct obd_export *exp, struct lov_stripe_md **lsmp,
 
         (*lsmp)->lsm_oinfo[0].loi_ost_idx = lum.lmm_stripe_offset;
         (*lsmp)->lsm_stripe_size = lum.lmm_stripe_size;
-        (*lsmp)->lsm_xfersize = lum.lmm_stripe_size * stripe_count;
 
         RETURN(0);
 }
@@ -367,7 +364,7 @@ int lov_setea(struct obd_export *exp, struct lov_stripe_md **lsmp,
         ENTRY;
         for (i = 0; i < lump->lmm_stripe_count; i++) {
                 __u32 len = sizeof(last_id);
-                oexp = lov->tgts[lump->lmm_objects[i].l_ost_idx].ltd_exp;
+                oexp = lov->lov_tgts[lump->lmm_objects[i].l_ost_idx]->ltd_exp;
                 rc = obd_get_info(oexp, strlen("last_id"), "last_id",
                                   &len, &last_id);
                 if (rc)
index 84be134..2622590 100644 (file)
 
 #include <obd_class.h>
 #include <obd_lov.h>
-
 #include "lov_internal.h"
 
+               
+/* #define QOS_DEBUG 1 */
+#define D_QOS D_OTHER
+
+#define TGT_BAVAIL(i)  (lov->lov_tgts[i]->ltd_exp->exp_obd->obd_osfs.os_bavail * \
+                        lov->lov_tgts[i]->ltd_exp->exp_obd->obd_osfs.os_bsize) 
+#define TGT_FFREE(i)   (lov->lov_tgts[i]->ltd_exp->exp_obd->obd_osfs.os_ffree)
+
+
+int qos_add_tgt(struct obd_device *obd, __u32 index)
+{
+        struct lov_obd *lov = &obd->u.lov;
+        struct lov_qos_oss *oss, *temposs;
+        struct obd_export *exp = lov->lov_tgts[index]->ltd_exp;
+        int rc = 0, found = 0;
+        ENTRY;
+
+        /* We only need this QOS struct on MDT, not clients - but we may not
+           have registered the lov's observer yet, so there's no way to check
+           here. */
+                            
+        if (!exp || !exp->exp_connection) {
+                CERROR("Missing connection\n");
+                RETURN(-ENOTCONN);
+        }
+
+        down_write(&lov->lov_qos.lq_rw_sem);
+        mutex_down(&lov->lov_lock);
+        list_for_each_entry(oss, &lov->lov_qos.lq_oss_list, lqo_oss_list) {
+                if (obd_uuid_equals(&oss->lqo_uuid, 
+                                    &exp->exp_connection->c_remote_uuid)) {
+                        found++;
+                        break;
+                }
+        }
+
+        if (!found) {
+                OBD_ALLOC_PTR(oss);
+                if (!oss) 
+                        GOTO(out, rc = -ENOMEM);
+                memcpy(&oss->lqo_uuid,
+                       &exp->exp_connection->c_remote_uuid,
+                       sizeof(oss->lqo_uuid));
+        } else {
+                /* Assume we have to move this one */
+                list_del(&oss->lqo_oss_list);
+        }
+                        
+        oss->lqo_ost_count++;
+        lov->lov_tgts[index]->ltd_qos.ltq_oss = oss;
+
+        /* Add sorted by # of OSTs.  Find the first entry that we're
+           bigger than... */
+        list_for_each_entry(temposs, &lov->lov_qos.lq_oss_list, lqo_oss_list) {
+                if (oss->lqo_ost_count > temposs->lqo_ost_count) 
+                        break;
+        }
+        /* ...and add before it.  If we're the first or smallest, temposs
+           points to the list head, and we add to the end. */
+        list_add_tail(&oss->lqo_oss_list, &temposs->lqo_oss_list);
+
+        lov->lov_qos.lq_dirty = 1;
+        lov->lov_qos.lq_dirty_rr = 1;
+
+        CDEBUG(D_QOS, "add tgt %s to OSS %s (#%d)\n", 
+               obd_uuid2str(&lov->lov_tgts[index]->ltd_uuid),
+               obd_uuid2str(&oss->lqo_uuid),
+               oss->lqo_ost_count);
+
+out:
+        mutex_up(&lov->lov_lock);
+        up_write(&lov->lov_qos.lq_rw_sem);
+        RETURN(rc);
+}
+
+int qos_del_tgt(struct obd_device *obd, __u32 index)
+{
+        struct lov_obd *lov = &obd->u.lov;
+        struct lov_qos_oss *oss;
+        int rc = 0;
+        ENTRY;
+
+        down_write(&lov->lov_qos.lq_rw_sem);
+
+        oss = lov->lov_tgts[index]->ltd_qos.ltq_oss;
+        if (!oss)
+                GOTO(out, rc = -ENOENT);
+
+        oss->lqo_ost_count--;
+        if (oss->lqo_ost_count == 0) {
+                CDEBUG(D_QOS, "removing OSS %s\n", 
+                       obd_uuid2str(&oss->lqo_uuid));
+                list_del(&oss->lqo_oss_list);
+                OBD_FREE_PTR(oss);
+        }
+        
+        lov->lov_qos.lq_dirty = 1;
+        lov->lov_qos.lq_dirty_rr = 1;
+out:
+        up_write(&lov->lov_qos.lq_rw_sem);
+        RETURN(rc);
+}
+
+/* Recalculate per-object penalties for OSSs and OSTs, 
+   depends on size of each ost in an oss */  
+static int qos_calc_ppo(struct obd_device *obd)
+{
+        struct lov_obd *lov = &obd->u.lov;
+        struct lov_qos_oss *oss;
+        __u64 ba_max, ba_min, temp;
+        __u32 num_active;
+        int rc, i, prio_wide;
+        ENTRY;
+        
+        if (!lov->lov_qos.lq_dirty) 
+                GOTO(out, rc = 0);
+                
+        num_active = lov->desc.ld_active_tgt_count - 1; 
+        if (num_active < 1)
+                GOTO(out, rc = -EAGAIN);
+
+        /* find bavail on each OSS */
+        list_for_each_entry(oss, &lov->lov_qos.lq_oss_list, lqo_oss_list) {
+                oss->lqo_bavail = 0;
+        }
+        lov->lov_qos.lq_active_oss_count = 0;
+
+        /* How badly user wants to select osts "widely" (not recently chosen
+           and not on recent oss's).  As opposed to "freely" (free space
+           avail.) 0-256. */
+        prio_wide = 256 - lov->lov_qos.lq_prio_free;
+
+        ba_min = (__u64)(-1);
+        ba_max = 0;
+        /* Calculate OST penalty per object */
+        /* (lov ref taken in alloc_qos) */
+        for (i = 0; i < lov->desc.ld_tgt_count; i++) {
+                if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_active)
+                        continue;
+                temp = TGT_BAVAIL(i);
+                if (!temp)
+                        continue;
+                ba_min = min(temp, ba_min);
+                ba_max = max(temp, ba_max);
+                
+                /* Count the number of usable OSS's */
+                if (lov->lov_tgts[i]->ltd_qos.ltq_oss->lqo_bavail == 0)
+                        lov->lov_qos.lq_active_oss_count++;
+                lov->lov_tgts[i]->ltd_qos.ltq_oss->lqo_bavail += temp;
+
+                /* per-OST penalty is prio * TGT_bavail / (num_ost - 1) / 2 */
+                temp >>= 1;
+                do_div(temp, num_active);
+                lov->lov_tgts[i]->ltd_qos.ltq_penalty_per_obj = 
+                        (temp * prio_wide) >> 8;
+
+                if (lov->lov_qos.lq_reset == 0) 
+                        lov->lov_tgts[i]->ltd_qos.ltq_penalty = 0;
+        }
+
+        num_active = lov->lov_qos.lq_active_oss_count - 1;
+        if (num_active < 1) {
+                /* If there's only 1 OSS, we can't penalize it, so instead
+                   we have to double the OST penalty */
+                num_active = 1;
+                for (i = 0; i < lov->desc.ld_tgt_count; i++) 
+                        lov->lov_tgts[i]->ltd_qos.ltq_penalty_per_obj <<= 1;
+        }
+        
+        /* Per-OSS penalty is prio * oss_avail / oss_osts / (num_oss - 1) / 2 */
+        list_for_each_entry(oss, &lov->lov_qos.lq_oss_list, lqo_oss_list) {
+                temp = oss->lqo_bavail >> 1;
+                do_div(temp, oss->lqo_ost_count * num_active);
+                oss->lqo_penalty_per_obj = (temp * prio_wide) >> 8;
+                if (lov->lov_qos.lq_reset == 0) 
+                        oss->lqo_penalty = 0;
+        }
+
+        lov->lov_qos.lq_dirty = 0;
+        lov->lov_qos.lq_reset = 0;
+
+        /* If each ost has almost same free space, 
+         * do rr allocation for better creation performance */
+        lov->lov_qos.lq_same_space = 0;
+        temp = ba_max - ba_min;
+        ba_min = (ba_min * 51) >> 8;     /* 51/256 = .20 */  
+        if (temp < ba_min) {
+                /* Difference is less than 20% */ 
+                lov->lov_qos.lq_same_space = 1;
+                /* Reset weights for the next time we enter qos mode */
+                lov->lov_qos.lq_reset = 0;
+        }
+        rc = 0;
+
+out:
+        if (!rc && lov->lov_qos.lq_same_space)
+                RETURN(-EAGAIN);
+        RETURN(rc);
+}
+
+static int qos_calc_weight(struct lov_obd *lov, int i)
+{
+        __u64 temp, temp2;
+        
+        /* Final ost weight = TGT_BAVAIL - ost_penalty - oss_penalty */
+        temp = TGT_BAVAIL(i);
+        temp2 = lov->lov_tgts[i]->ltd_qos.ltq_penalty + 
+                lov->lov_tgts[i]->ltd_qos.ltq_oss->lqo_penalty;
+        if (temp < temp2) 
+                lov->lov_tgts[i]->ltd_qos.ltq_weight = 0;
+        else
+                lov->lov_tgts[i]->ltd_qos.ltq_weight = temp - temp2;
+        return 0;
+}
+
+/* We just used this index for a stripe; adjust everyone's weights */
+static int qos_used(struct lov_obd *lov, __u32 index, __u64 *total_wt)
+{
+        struct lov_qos_oss *oss;
+        int i;
+        ENTRY;
+
+        /* Don't allocate from this stripe anymore, until the next alloc_qos */
+        lov->lov_tgts[index]->ltd_qos.ltq_usable = 0;
+
+        oss = lov->lov_tgts[index]->ltd_qos.ltq_oss;
+        
+        /* Decay old penalty by half (we're adding max penalty, and don't
+           want it to run away.) */
+        lov->lov_tgts[index]->ltd_qos.ltq_penalty >>= 1;
+        oss->lqo_penalty >>= 1;
+
+        /* Set max penalties for this OST and OSS */
+        lov->lov_tgts[index]->ltd_qos.ltq_penalty +=
+                lov->lov_tgts[index]->ltd_qos.ltq_penalty_per_obj *
+                lov->desc.ld_active_tgt_count;
+        oss->lqo_penalty += oss->lqo_penalty_per_obj * 
+                lov->lov_qos.lq_active_oss_count;
+        
+        /* Decrease all OSS penalties */
+        list_for_each_entry(oss, &lov->lov_qos.lq_oss_list, lqo_oss_list) {
+                if (oss->lqo_penalty < oss->lqo_penalty_per_obj) 
+                        oss->lqo_penalty = 0;
+                else
+                        oss->lqo_penalty -= oss->lqo_penalty_per_obj;
+        }
+
+        *total_wt = 0;
+        /* Decrease all OST penalties */
+        for (i = 0; i < lov->desc.ld_tgt_count; i++) {
+                if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_active) 
+                        continue;
+                if (lov->lov_tgts[i]->ltd_qos.ltq_penalty <
+                    lov->lov_tgts[i]->ltd_qos.ltq_penalty_per_obj)
+                        lov->lov_tgts[i]->ltd_qos.ltq_penalty = 0;
+                else
+                        lov->lov_tgts[i]->ltd_qos.ltq_penalty -=
+                        lov->lov_tgts[i]->ltd_qos.ltq_penalty_per_obj;
+                
+                qos_calc_weight(lov, i);
+
+                /* Recalc the total weight of usable osts */
+                if (lov->lov_tgts[i]->ltd_qos.ltq_usable)
+                        *total_wt += lov->lov_tgts[i]->ltd_qos.ltq_weight;
+
+#ifdef QOS_DEBUG
+                CDEBUG(D_QOS, "recalc tgt %d avail="LPU64
+                       " ostppo="LPU64" ostp="LPU64" ossppo="LPU64
+                       " ossp="LPU64" wt="LPU64"\n",
+                       i, TGT_BAVAIL(i), 
+                       lov->lov_tgts[i]->ltd_qos.ltq_penalty_per_obj,
+                       lov->lov_tgts[i]->ltd_qos.ltq_penalty, 
+                       lov->lov_tgts[i]->ltd_qos.ltq_oss->lqo_penalty_per_obj,
+                       lov->lov_tgts[i]->ltd_qos.ltq_oss->lqo_penalty,
+                       lov->lov_tgts[i]->ltd_qos.ltq_weight);
+#endif
+        }
+
+        RETURN(0);
+}
+
+#define LOV_QOS_EMPTY ((__u32)-1)
+/* compute optimal round-robin order, based on OSTs per OSS */
+static int qos_calc_rr(struct lov_obd *lov)
+{
+        struct lov_qos_oss *oss;
+        unsigned ost_count, placed;
+        int i;
+        ENTRY;
+
+        if (!lov->lov_qos.lq_dirty_rr) {
+                LASSERT(lov->lov_qos.lq_rr_size);
+                RETURN(0);
+        }
+
+        down_write(&lov->lov_qos.lq_rw_sem);
+        ost_count = lov->desc.ld_tgt_count;
+
+        if (lov->lov_qos.lq_rr_size) 
+                OBD_FREE(lov->lov_qos.lq_rr_array, lov->lov_qos.lq_rr_size);
+        lov->lov_qos.lq_rr_size = ost_count * 
+                sizeof(lov->lov_qos.lq_rr_array[0]);
+        OBD_ALLOC(lov->lov_qos.lq_rr_array, lov->lov_qos.lq_rr_size);
+        if (!lov->lov_qos.lq_rr_array) {
+                lov->lov_qos.lq_rr_size = 0;
+                up_write(&lov->lov_qos.lq_rw_sem);
+                RETURN(-ENOMEM);
+        }
+
+        for (i = 0; i < ost_count; i++) 
+                lov->lov_qos.lq_rr_array[i] = LOV_QOS_EMPTY;
+
+        /* Place all the OSTs from 1 OSS at the same time. */
+        placed = 0;
+        list_for_each_entry(oss, &lov->lov_qos.lq_oss_list, lqo_oss_list) {
+                int j = 0;
+                for (i = 0; i < ost_count; i++) {
+                      if (lov->lov_tgts[i]->ltd_qos.ltq_oss == oss) {
+                              /* Evenly space these OSTs across arrayspace */
+                              int next = j * ost_count / oss->lqo_ost_count;
+                              while (lov->lov_qos.lq_rr_array[next] !=
+                                     LOV_QOS_EMPTY)
+                                      next = (next + 1) % ost_count;
+                              lov->lov_qos.lq_rr_array[next] = i;
+                              j++;
+                              placed++;
+                      }
+                }
+                LASSERT(j == oss->lqo_ost_count);
+        }
+
+        lov->lov_qos.lq_dirty_rr = 0;
+        up_write(&lov->lov_qos.lq_rw_sem);
+
+#ifdef QOS_DEBUG
+        for (i = 0; i < ost_count; i++) {
+                LCONSOLE(D_QOS, "rr %d ost %d\n", i, 
+                         lov->lov_qos.lq_rr_array[i]);
+        }
+#endif
+
+        if (placed != ost_count) {
+                /* This should never happen */
+                CERROR("Placed %d of %d osts\n", placed, ost_count);
+                for (i = 0; i < ost_count; i++) {
+                        LCONSOLE(D_WARNING, "rr %d ost %d\n", i,
+                                 lov->lov_qos.lq_rr_array[i]);
+                }
+                LBUG();
+        }
+        
+        RETURN(0);
+}
+
+
 void qos_shrink_lsm(struct lov_request_set *set)
 {
-        struct lov_stripe_md *lsm = set->set_md, *lsm_new;
+        struct lov_stripe_md *lsm = set->set_oi->oi_md, *lsm_new;
         /* XXX LOV STACKING call into osc for sizes */
         unsigned oldsize, newsize;
 
@@ -70,7 +424,7 @@ void qos_shrink_lsm(struct lov_request_set *set)
                 memcpy(lsm_new, lsm, newsize);
                 lsm_new->lsm_stripe_count = set->set_count;
                 OBD_FREE(lsm, oldsize);
-                set->set_md = lsm_new;
+                set->set_oi->oi_md = lsm_new;
         } else {
                 CWARN("'leaking' %d bytes\n", oldsize - newsize);
         }
@@ -78,7 +432,7 @@ void qos_shrink_lsm(struct lov_request_set *set)
 
 int qos_remedy_create(struct lov_request_set *set, struct lov_request *req)
 {
-        struct lov_stripe_md *lsm = set->set_md;
+        struct lov_stripe_md *lsm = set->set_oi->oi_md;
         struct lov_obd *lov = &set->set_exp->exp_obd->u.lov;
         unsigned ost_idx, ost_count = lov->desc.ld_tgt_count;
         int stripe, i, rc = -EIO;
@@ -86,10 +440,9 @@ int qos_remedy_create(struct lov_request_set *set, struct lov_request *req)
 
         ost_idx = (req->rq_idx + lsm->lsm_stripe_count) % ost_count;
         for (i = 0; i < ost_count; i++, ost_idx = (ost_idx + 1) % ost_count) {
-                if (lov->tgts[ost_idx].active == 0) {
-                        CDEBUG(D_HA, "lov idx %d inactive\n", ost_idx);
+                if (!lov->lov_tgts[ost_idx] || 
+                    !lov->lov_tgts[ost_idx]->ltd_active) 
                         continue;
-                }
                 /* check if objects has been created on this ost */
                 for (stripe = 0; stripe < lsm->lsm_stripe_count; stripe++) {
                         if (stripe == req->rq_stripe)
@@ -100,8 +453,9 @@ int qos_remedy_create(struct lov_request_set *set, struct lov_request *req)
 
                 if (stripe >= lsm->lsm_stripe_count) {
                         req->rq_idx = ost_idx;
-                        rc = obd_create(lov->tgts[ost_idx].ltd_exp, req->rq_oa, 
-                                        &req->rq_md, set->set_oti);
+                        rc = obd_create(lov->lov_tgts[ost_idx]->ltd_exp,
+                                        req->rq_oi.oi_oa, &req->rq_oi.oi_md,
+                                        set->set_oti);
                         if (!rc)
                                 break;
                 }
@@ -111,41 +465,60 @@ int qos_remedy_create(struct lov_request_set *set, struct lov_request *req)
 
 #define LOV_CREATE_RESEED_MULT 4
 #define LOV_CREATE_RESEED_MIN  1000
-/* alloc objects on osts with round-robin algorithm */
+/* Allocate objects on osts with round-robin algorithm */
 static int alloc_rr(struct lov_obd *lov, int *idx_arr, int *stripe_cnt)
 {
-        static int ost_start_count, ost_start_idx;
-        unsigned ost_idx, ost_count = lov->desc.ld_tgt_count;
+        unsigned array_idx, ost_count = lov->desc.ld_tgt_count;
         unsigned ost_active_count = lov->desc.ld_active_tgt_count;
         int i, *idx_pos = idx_arr;
+        __u32 ost_idx;
         ENTRY;
-        
-        if (--ost_start_count <= 0) {
-                ost_start_idx = ll_rand();
-                ost_start_count = 
+
+        i = qos_calc_rr(lov);
+        if (i) 
+                RETURN(i);
+
+        if (--lov->lov_start_count <= 0) {
+                lov->lov_start_idx = ll_rand() % ost_count;
+                lov->lov_start_count =
                         (LOV_CREATE_RESEED_MIN / max(ost_active_count, 1U) +
                          LOV_CREATE_RESEED_MULT) * max(ost_active_count, 1U);
-        } else if (*stripe_cnt >= lov->desc.ld_active_tgt_count) {
-                /* If we allocate from all of the stripes, make the
-                 * next file start on the next OST. */
-                ++ost_start_idx;
+        } else if (*stripe_cnt >= ost_active_count || 
+                   lov->lov_start_idx > ost_count) {
+                /* If we have allocated from all of the OSTs, slowly
+                   precess the next start */
+                lov->lov_start_idx %= ost_count;
+                ++lov->lov_offset_idx;
         }
-        ost_idx = ost_start_idx % ost_count;
+        array_idx = (lov->lov_start_idx + lov->lov_offset_idx) % ost_count;
+#ifdef QOS_DEBUG
+        CDEBUG(D_QOS, "want %d startidx %d startcnt %d offset %d arrayidx %d\n",
+               *stripe_cnt, lov->lov_start_idx, lov->lov_start_count,
+               lov->lov_offset_idx, array_idx);
+#endif
 
-        for (i = 0; i < ost_count; i++, ost_idx = (ost_idx + 1) % ost_count) {
-                ++ost_start_idx;
-                
-                if (lov->tgts[ost_idx].active == 0) {
-                        CDEBUG(D_HA, "lov idx %d inactive\n", ost_idx);
+        down_read(&lov->lov_qos.lq_rw_sem);
+        for (i = 0; i < ost_count; i++, array_idx=(array_idx + 1) % ost_count) {
+                ++lov->lov_start_idx;
+                ost_idx = lov->lov_qos.lq_rr_array[array_idx];
+#ifdef QOS_DEBUG
+                CDEBUG(D_QOS, "#%d strt %d act %d strp %d ary %d idx %d\n",
+                       i, lov->lov_start_idx, 
+                       lov->lov_tgts[ost_idx] ? 
+                       lov->lov_tgts[ost_idx].ltd_active : 0,
+                       idx_pos - idx_arr, array_idx, ost_idx);
+#endif
+                if (!lov->lov_tgts[ost_idx] || 
+                    !lov->lov_tgts[ost_idx]->ltd_active) 
                         continue;
-                }
-                
                 *idx_pos = ost_idx;
                 idx_pos++;
-                /* got enough ost */
-                if (idx_pos - idx_arr == *stripe_cnt)
-                        RETURN(0);
+                /* We have enough stripes */
+                if (idx_pos - idx_arr == *stripe_cnt) 
+                        break;
         }
+        up_read(&lov->lov_qos.lq_rw_sem);
+
         *stripe_cnt = idx_pos - idx_arr;
         RETURN(0);
 }
@@ -160,8 +533,8 @@ static int alloc_specific(struct lov_obd *lov, struct lov_stripe_md *lsm,
 
         ost_idx = lsm->lsm_oinfo[0].loi_ost_idx;
         for (i = 0; i < ost_count; i++, ost_idx = (ost_idx + 1) % ost_count) {
-                if (lov->tgts[ost_idx].active == 0) {
-                        CDEBUG(D_HA, "lov idx %d inactive\n", ost_idx);
+                if (!lov->lov_tgts[ost_idx] || 
+                    !lov->lov_tgts[ost_idx]->ltd_active) {
                         continue;
                 }
                 *idx_pos = ost_idx;
@@ -181,165 +554,125 @@ static int alloc_specific(struct lov_obd *lov, struct lov_stripe_md *lsm,
         RETURN(-EFBIG);
 }
 
-/* free space OST must have to be used for object allocation. */
-#define QOS_MIN                 (lov->desc.ld_qos_threshold << 20)
-
-#define TGT_BAVAIL(tgt)         (tgt->ltd_exp->exp_obd->obd_osfs.os_bavail * \
-                                 tgt->ltd_exp->exp_obd->obd_osfs.os_bsize) 
-#define TGT_FFREE(tgt)          (tgt->ltd_exp->exp_obd->obd_osfs.os_ffree)
-
-/* alloc objects on osts with free space weighted algorithm */
+/* Alloc objects on osts with optimization based on:
+   - free space
+   - network resources (shared OSS's)
+*/
 static int alloc_qos(struct obd_export *exp, int *idx_arr, int *stripe_cnt)
 {
         struct lov_obd *lov = &exp->exp_obd->u.lov;
-        unsigned ost_count = lov->desc.ld_tgt_count;
-        __u64 cur_bavail, rand, *availspace, total_bavail = 0;
-        int *indexes, nfound, good_osts, i, warn = 0, rc = 0;
-        struct lov_tgt_desc *tgt;
-        int shift, require_stripes = *stripe_cnt;
         static time_t last_warn = 0;
         time_t now = cfs_time_current_sec();
+        __u64 cur_weight, temp, rand, bavail, total_bavail, total_weight = 0;
+        __u32 ost_count;
+        int nfound, good_osts, i, warn = 0, rc = 0;
         ENTRY;
         
-        availspace = NULL;
-        indexes = NULL;
-        OBD_ALLOC(availspace, sizeof(__u64) * ost_count);
-        OBD_ALLOC(indexes, sizeof(int) * require_stripes);
-        if (!availspace || !indexes)
-                GOTO(out_free, rc = -EAGAIN);
-        
-        mutex_down(&lov->lov_lock);
-        /* if free space is below some threshold, just go
-         * to do round-robin allocation */
-        total_bavail = (exp->exp_obd->obd_osfs.os_bavail * \
-                        exp->exp_obd->obd_osfs.os_bsize);
-        if (ost_count < 2 || total_bavail <= QOS_MIN) {
-                mutex_up(&lov->lov_lock);
-                GOTO(out_free, rc = -EAGAIN);
-        }
+        lov_getref(exp->exp_obd);
+        down_write(&lov->lov_qos.lq_rw_sem);
 
-        /* if each ost has almost same free space, go to 
-         * do rr allocation for better creation performance */
-        if (!list_empty(&lov->qos_bavail_list)) {
-                __u64 max, min, val;
-                tgt = list_entry(lov->qos_bavail_list.next, 
-                                 struct lov_tgt_desc, qos_bavail_list);
-                max = TGT_BAVAIL(tgt);
-                tgt = list_entry(lov->qos_bavail_list.prev,
-                                 struct lov_tgt_desc, qos_bavail_list);
-                min = TGT_BAVAIL(tgt);
-
-                val = (max >= min) ? (max - min) : (min - max);
-                min = (min * 13) >> 8;          /* less than 5% of gap */ 
-
-                if (val < min) {
-                        mutex_up(&lov->lov_lock);
-                        GOTO(out_free, rc = -EAGAIN);
-                }
-        } else {
-                mutex_up(&lov->lov_lock);
-                GOTO(out_free, rc = -EAGAIN);
-        }
+        ost_count = lov->desc.ld_tgt_count;
+
+        if (lov->desc.ld_active_tgt_count < 2) 
+                GOTO(out, rc = -EAGAIN);
+
+        rc = qos_calc_ppo(exp->exp_obd);
+        if (rc) 
+                GOTO(out, rc);
         
         total_bavail = 0;
         good_osts = 0;
-        /* warn zero available space/inode every 30 min */
+        /* Warn users about zero available space/inode every 30 min */
         if (cfs_time_sub(now, last_warn) > 60 * 30)
                 warn = 1;
-        /* Find all the OSTs big enough to be stripe candidates */
-        list_for_each_entry(tgt, &lov->qos_bavail_list, qos_bavail_list) {
-                if (!tgt->active)
+        /* Find all the OSTs that are valid stripe candidates */
+        for (i = 0; i < ost_count; i++) {
+                if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_active)
                         continue;
-                if (!TGT_BAVAIL(tgt)) {
+                bavail = TGT_BAVAIL(i);
+                if (!bavail) {
                         if (warn) {
-                                CWARN("no free space on %s\n", 
-                                      tgt->uuid.uuid);
+                                CDEBUG(D_QOS, "no free space on %s\n", 
+                                       obd_uuid2str(&lov->lov_tgts[i]->ltd_uuid));
                                 last_warn = now;
                         }
                         continue;
                 }
-                if (!TGT_FFREE(tgt)) {
+                if (!TGT_FFREE(i)) {
                         if (warn) {
-                                CWARN("no free inodes on %s\n", 
-                                      tgt->uuid.uuid);
+                                CDEBUG(D_QOS, "no free inodes on %s\n", 
+                                       obd_uuid2str(&lov->lov_tgts[i]->ltd_uuid));
                                 last_warn = now;
                         }
                         continue;
                 }
-                /* We can stop if we have enough good osts and our osts
-                   are getting too small */ 
-                if ((TGT_BAVAIL(tgt) <= QOS_MIN) && (good_osts >= *stripe_cnt))
-                        break;
-                availspace[good_osts] = TGT_BAVAIL(tgt);
-                indexes[good_osts] = tgt->index;
-                total_bavail += availspace[good_osts];
+
+                lov->lov_tgts[i]->ltd_qos.ltq_usable = 1;
+                qos_calc_weight(lov, i);
+                total_bavail += bavail;
+                total_weight += lov->lov_tgts[i]->ltd_qos.ltq_weight;
+
                 good_osts++;
         }
         
-        mutex_up(&lov->lov_lock);
-        
         if (!total_bavail)
-                GOTO(out_free, rc = -ENOSPC);
+                GOTO(out, rc = -ENOSPC);
        
         /* if we don't have enough good OSTs, we reduce the stripe count. */
         if (good_osts < *stripe_cnt)
                 *stripe_cnt = good_osts;
 
         if (!*stripe_cnt) 
-                GOTO(out_free, rc = -EAGAIN);
+                GOTO(out, rc = -EAGAIN);
         
-        /* The point of all this shift and rand is to choose a 64-bit 
-           random number between 0 and total_bavail. Apparently '%' doesn't
-           work for 64bit numbers. */
-        nfound = shift = 0;
-        while ((total_bavail >> shift) > 0)
-                shift++;
-        shift++;
-        /* Find enough OSTs with free space weighted random allocation */
+        /* Find enough OSTs with weighted random allocation. */
+        nfound = 0;
         while (nfound < *stripe_cnt) {
-                cur_bavail = 0;
-
-                /* If the total storage left is < 4GB, don't use random order, 
-                   store in biggest OST first. (Low storage situation.) 
-                   Otherwise, choose a 64bit random number... */
-                rand = (shift < 32 ? 0ULL : (__u64)ll_rand() << 32) | ll_rand();
-                /* ... mask everything above shift... */
-                if (shift < 64)
-                        rand &= ((1ULL << shift) - 1);
-                /* ... and this while should execute at most once... */
-                while (rand > total_bavail)
-                        rand -= total_bavail;
-                /* ... leaving us a 64bit number between 0 and total_bavail. */
-                
-                /* Try to fit in bigger OSTs first. On average, this will
-                   fill more toward the front of the OST array */
-                for (i = 0; i < good_osts; i++) {
-                        cur_bavail += availspace[i];
-                        if (cur_bavail >= rand) {
-                                total_bavail -= availspace[i];
-                                availspace[i] = 0;
-                                idx_arr[nfound] = indexes[i];
-                                nfound++;
+                cur_weight = 0;
+                rc = -ENODEV;
+
+                if (total_weight) {
+                        /* If total_weight > 32-bit, make a 64-bit random # */
+                        temp = (total_weight & 0xffffffff00000000ULL ?
+                                (__u64)ll_rand() << 32 : 0ULL) | ll_rand();
+                        /* Random number between 0 and total_weight */
+                        rand = do_div(temp, total_weight); 
+                } else {
+                        rand = 0;
+                }
+
+                /* On average, this will hit larger-weighted osts more often.
+                   0-weight osts will always get used last (only when rand=0).*/
+                for (i = 0; i < ost_count; i++) {
+                        if (!lov->lov_tgts[i]->ltd_qos.ltq_usable)
+                                continue;
+                        cur_weight += lov->lov_tgts[i]->ltd_qos.ltq_weight;
+                        if (cur_weight >= rand) {
+#ifdef QOS_DEBUG
+                                CDEBUG(D_QOS, "assigned stripe=%d to idx=%d\n",
+                                       nfound, i);
+#endif
+                                idx_arr[nfound++] = i;
+                                qos_used(lov, i, &total_weight);
+                                rc = 0;
                                 break;
                         }
                 }
                 /* should never satisfy below condition */
-                if (cur_bavail == 0)
+                if (rc) {
+                        CERROR("Didn't find any OSTs?\n");
                         break;
+                }
         }
         LASSERT(nfound == *stripe_cnt);
         
-out_free:
-        if (availspace)
-                OBD_FREE(availspace, sizeof(__u64) * ost_count);
-        if (indexes)
-                OBD_FREE(indexes, sizeof(int) * require_stripes);
-        if (rc != -EAGAIN)
-                /* rc == 0 or err */
-                RETURN(rc);
-
-        rc = alloc_rr(lov, idx_arr, stripe_cnt);
+out:
+        up_write(&lov->lov_qos.lq_rw_sem);
+        
+        if (rc == -EAGAIN)
+                rc = alloc_rr(lov, idx_arr, stripe_cnt);
+        
+        lov_putref(exp->exp_obd);
         RETURN(rc);
 }
 
@@ -387,7 +720,7 @@ int qos_prep_create(struct obd_export *exp, struct lov_request_set *set)
 {
         struct lov_obd *lov = &exp->exp_obd->u.lov;
         struct lov_stripe_md *lsm;
-        struct obdo *src_oa = set->set_oa;
+        struct obdo *src_oa = set->set_oi->oi_oa;
         struct obd_trans_info *oti = set->set_oti;
         int i, stripes, rc = 0, newea = 0;
         int *idx_arr, idx_cnt = 0;
@@ -395,31 +728,29 @@ int qos_prep_create(struct obd_export *exp, struct lov_request_set *set)
 
         LASSERT(src_oa->o_valid & OBD_MD_FLID);
  
-        if (set->set_md == NULL) {
+        if (set->set_oi->oi_md == NULL) {
                 int stripe_cnt = lov_get_stripecnt(lov, 0);
 
                 /* If the MDS file was truncated up to some size, stripe over
                  * enough OSTs to allow the file to be created at that size. 
                  * This may mean we use more than the default # of stripes. */
                 if (src_oa->o_valid & OBD_MD_FLSIZE) {
-                        struct lov_tgt_desc *tgt;
+                        obd_size min_bavail = (obd_size)-1;
                         
-                        /* Find the smallest number of stripes we can use 
+                        /* Find a small number of stripes we can use 
                            (up to # of active osts). */
                         stripes = 1;
-                        mutex_down(&lov->lov_lock);
-                        list_for_each_entry(tgt, &lov->qos_bavail_list, 
-                                            qos_bavail_list) {
-                                if (!tgt->active)
+                        lov_getref(exp->exp_obd);
+                        for (i = 0; i < lov->desc.ld_tgt_count; i++) {
+                                if (!lov->lov_tgts[i] || 
+                                    !lov->lov_tgts[i]->ltd_active)
                                         continue;
-                                /* All earlier tgts have at least this many 
-                                   bytes available also, since our list is
-                                   sorted by size  */
-                                if (TGT_BAVAIL(tgt) * stripes > src_oa->o_size)
+                                min_bavail = min(min_bavail, TGT_BAVAIL(i));
+                                if (min_bavail * stripes > src_oa->o_size)
                                         break;
                                 stripes++;
                         }
-                        mutex_up(&lov->lov_lock);
+                        lov_putref(exp->exp_obd);
 
                         if (stripes < stripe_cnt)
                                 stripes = stripe_cnt;
@@ -427,7 +758,7 @@ int qos_prep_create(struct obd_export *exp, struct lov_request_set *set)
                         stripes = stripe_cnt;
                 }
 
-                rc = lov_alloc_memmd(&set->set_md, stripes, 
+                rc = lov_alloc_memmd(&set->set_oi->oi_md, stripes, 
                                      lov->desc.ld_pattern ?
                                      lov->desc.ld_pattern : LOV_PATTERN_RAID0,
                                      LOV_MAGIC);
@@ -436,8 +767,8 @@ int qos_prep_create(struct obd_export *exp, struct lov_request_set *set)
                 rc = 0;
                 newea = 1;
         }
-        lsm = set->set_md;
-       
+
+        lsm = set->set_oi->oi_md;
         lsm->lsm_object_id = src_oa->o_id;
         if (!lsm->lsm_stripe_size)
                 lsm->lsm_stripe_size = lov->desc.ld_default_stripe_size;
@@ -455,36 +786,36 @@ int qos_prep_create(struct obd_export *exp, struct lov_request_set *set)
                 struct lov_request *req;
                 int ost_idx = idx_arr[i];
                 LASSERT(ost_idx >= 0);
-                
+
                 OBD_ALLOC(req, sizeof(*req));
                 if (req == NULL)
                         GOTO(out_err, rc = -ENOMEM);
                 lov_set_add_req(req, set);
 
-                req->rq_buflen = sizeof(*req->rq_md);
-                OBD_ALLOC(req->rq_md, req->rq_buflen);
-                if (req->rq_md == NULL)
+                req->rq_buflen = sizeof(*req->rq_oi.oi_md);
+                OBD_ALLOC(req->rq_oi.oi_md, req->rq_buflen);
+                if (req->rq_oi.oi_md == NULL)
                         GOTO(out_err, rc = -ENOMEM);
-                
-                req->rq_oa = obdo_alloc();
-                if (req->rq_oa == NULL)
+
+                req->rq_oi.oi_oa = obdo_alloc();
+                if (req->rq_oi.oi_oa == NULL)
                         GOTO(out_err, rc = -ENOMEM);
-                
+
                 req->rq_idx = ost_idx;
                 req->rq_stripe = i;
                 /* create data objects with "parent" OA */
-                memcpy(req->rq_oa, src_oa, sizeof(*req->rq_oa));
+                memcpy(req->rq_oi.oi_oa, src_oa, sizeof(*req->rq_oi.oi_oa));
 
                 /* XXX When we start creating objects on demand, we need to
                  *     make sure that we always create the object on the
                  *     stripe which holds the existing file size.
                  */
                 if (src_oa->o_valid & OBD_MD_FLSIZE) {
-                        req->rq_oa->o_size = 
+                        req->rq_oi.oi_oa->o_size = 
                                 lov_size_to_stripe(lsm, src_oa->o_size, i);
 
                         CDEBUG(D_INODE, "stripe %d has size "LPU64"/"LPU64"\n",
-                               i, req->rq_oa->o_size, src_oa->o_size);
+                               i, req->rq_oi.oi_oa->o_size, src_oa->o_size);
                 }
 
         }
@@ -501,53 +832,15 @@ int qos_prep_create(struct obd_export *exp, struct lov_request_set *set)
         }
 out_err:
         if (newea && rc)
-                obd_free_memmd(exp, &set->set_md);
+                obd_free_memmd(exp, &set->set_oi->oi_md);
         free_idx_array(idx_arr, idx_cnt);
         EXIT;
         return rc;
 }
 
-/* An caveat here is don't use list_move() on same list */
-#define list_adjust(tgt, lov, list_name, value) \
-{ \
-        struct list_head *element; \
-        struct lov_tgt_desc *tmp;  \
-        if (list_empty(&(tgt)->list_name)) \
-                list_add(&(tgt)->list_name, &(lov)->list_name); \
-        element = (tgt)->list_name.next; \
-        while((element != &(lov)->list_name) && \
-              (tmp = list_entry(element, struct lov_tgt_desc, list_name)) && \
-              (value(tgt) < value(tmp))) \
-                element = element->next; \
-        if (element != (tgt)->list_name.next) { \
-                list_del_init(&(tgt)->list_name); \
-                list_add(&(tgt)->list_name, element->prev); \
-        } \
-        element = (tgt)->list_name.prev; \
-        while ((element != &(lov)->list_name) && \
-               (tmp = list_entry(element, struct lov_tgt_desc, list_name)) && \
-               (value(tgt) > value(tmp))) \
-                element = element->prev; \
-        if (element != (tgt)->list_name.prev) { \
-                list_del_init(&(tgt)->list_name); \
-                list_add_tail(&(tgt)->list_name, element->prev); \
-        } \
-}
-
 void qos_update(struct lov_obd *lov, int idx, struct obd_statfs *osfs)
 {
-        struct lov_tgt_desc *tgt = &lov->tgts[idx];
-        __u64 bavail;
         ENTRY;
-        
-        bavail = osfs->os_bavail * osfs->os_bsize;
-        if (!bavail) 
-                CWARN("ost %d has zero avail space!\n", idx);
-        
-        CDEBUG(D_OTHER, "QOS: bfree now "LPU64"\n", bavail);
-        
-        mutex_down(&lov->lov_lock);
-        list_adjust(tgt, lov, qos_bavail_list, TGT_BAVAIL);
-        mutex_up(&lov->lov_lock);
+        lov->lov_qos.lq_dirty = 1;
 }
 
index a3a4372..f441f25 100644 (file)
@@ -44,6 +44,7 @@ static void lov_init_set(struct lov_request_set *set)
         set->set_count = 0;
         set->set_completes = 0;
         set->set_success = 0;
+        set->set_cookies = 0;
         CFS_INIT_LIST_HEAD(&set->set_list);
         atomic_set(&set->set_refcount, 1);
 }
@@ -59,10 +60,13 @@ static void lov_finish_set(struct lov_request_set *set)
                                                      rq_link);
                 list_del_init(&req->rq_link);
 
-                if (req->rq_oa)
-                        obdo_free(req->rq_oa);
-                if (req->rq_md)
-                        OBD_FREE(req->rq_md, req->rq_buflen);
+                if (req->rq_oi.oi_oa)
+                        obdo_free(req->rq_oi.oi_oa);
+                if (req->rq_oi.oi_md)
+                        OBD_FREE(req->rq_oi.oi_md, req->rq_buflen);
+                if (req->rq_oi.oi_osfs)
+                        OBD_FREE(req->rq_oi.oi_osfs,
+                                 sizeof(*req->rq_oi.oi_osfs));
                 OBD_FREE(req, sizeof(*req));
         }
 
@@ -77,8 +81,8 @@ static void lov_finish_set(struct lov_request_set *set)
         EXIT;
 }
 
-static void lov_update_set(struct lov_request_set *set,
-                           struct lov_request *req, int rc)
+void lov_update_set(struct lov_request_set *set,
+                    struct lov_request *req, int rc)
 {
         req->rq_complete = 1;
         req->rq_rc = rc;
@@ -97,7 +101,8 @@ int lov_update_common_set(struct lov_request_set *set,
         lov_update_set(set, req, rc);
 
         /* grace error on inactive ost */
-        if (rc && !lov->tgts[req->rq_idx].active)
+        if (rc && !(lov->lov_tgts[req->rq_idx] && 
+                    lov->lov_tgts[req->rq_idx]->ltd_active))
                 rc = 0;
 
         /* FIXME in raid1 regime, should return 0 */
@@ -110,30 +115,33 @@ void lov_set_add_req(struct lov_request *req, struct lov_request_set *set)
         set->set_count++;
 }
 
-int lov_update_enqueue_set(struct lov_request_set *set,
-                           struct lov_request *req, int rc, int flags)
+int lov_update_enqueue_set(struct lov_request *req, __u32 mode, int rc)
 {
+        struct lov_request_set *set = req->rq_rqset;
         struct lustre_handle *lov_lockhp;
         struct lov_oinfo *loi;
         ENTRY;
 
+        LASSERT(set != NULL);
+        LASSERT(set->set_oi != NULL);
+
         lov_lockhp = set->set_lockh->llh_handles + req->rq_stripe;
-        loi = &set->set_md->lsm_oinfo[req->rq_stripe];
+        loi = &set->set_oi->oi_md->lsm_oinfo[req->rq_stripe];
 
-        /* XXX FIXME: This unpleasantness doesn't belong here at *all*.
-         * It belongs in the OSC, except that the OSC doesn't have
-         * access to the real LOI -- it gets a copy, that we created
-         * above, and that copy can be arbitrarily out of date.
+        /* XXX LOV STACKING: OSC gets a copy, created in lov_prep_enqueue_set
+         * and that copy can be arbitrarily out of date.
          *
          * The LOV API is due for a serious rewriting anyways, and this
          * can be addressed then. */
+
         if (rc == ELDLM_OK) {
                 struct ldlm_lock *lock = ldlm_handle2lock(lov_lockhp);
-                __u64 tmp = req->rq_md->lsm_oinfo->loi_lvb.lvb_size;
+                __u64 tmp;
 
                 LASSERT(lock != NULL);
-                lov_stripe_lock(set->set_md);
-                loi->loi_lvb = req->rq_md->lsm_oinfo->loi_lvb;
+                lov_stripe_lock(set->set_oi->oi_md);
+                loi->loi_lvb = req->rq_oi.oi_md->lsm_oinfo->loi_lvb;
+                tmp = loi->loi_lvb.lvb_size;
                 /* Extend KMS up to the end of this lock and no further
                  * A lock on [x,y] means a KMS of up to y + 1 bytes! */
                 if (tmp > lock->l_policy_data.l_extent.end)
@@ -149,14 +157,15 @@ int lov_update_enqueue_set(struct lov_request_set *set,
                                    loi->loi_lvb.lvb_size, loi->loi_kms,
                                    lock->l_policy_data.l_extent.end);
                 }
-                lov_stripe_unlock(set->set_md);
+                lov_stripe_unlock(set->set_oi->oi_md);
                 ldlm_lock_allow_match(lock);
                 LDLM_LOCK_PUT(lock);
-        } else if (rc == ELDLM_LOCK_ABORTED && flags & LDLM_FL_HAS_INTENT) {
+        } else if ((rc == ELDLM_LOCK_ABORTED) &&
+                   (set->set_ei->ei_flags & LDLM_FL_HAS_INTENT)) {
                 memset(lov_lockhp, 0, sizeof(*lov_lockhp));
-                lov_stripe_lock(set->set_md);
-                loi->loi_lvb = req->rq_md->lsm_oinfo->loi_lvb;
-                lov_stripe_unlock(set->set_md);
+                lov_stripe_lock(set->set_oi->oi_md);
+                loi->loi_lvb = req->rq_oi.oi_md->lsm_oinfo->loi_lvb;
+                lov_stripe_unlock(set->set_oi->oi_md);
                 CDEBUG(D_INODE, "glimpsed, setting rss="LPU64"; leaving"
                        " kms="LPU64"\n", loi->loi_lvb.lvb_size, loi->loi_kms);
                 rc = ELDLM_OK;
@@ -165,11 +174,12 @@ int lov_update_enqueue_set(struct lov_request_set *set,
                 struct lov_obd *lov = &exp->exp_obd->u.lov;
 
                 memset(lov_lockhp, 0, sizeof(*lov_lockhp));
-                if (lov->tgts[req->rq_idx].active) {
+                if (lov->lov_tgts[req->rq_idx] && 
+                    lov->lov_tgts[req->rq_idx]->ltd_active) {
                         CERROR("error: enqueue objid "LPX64" subobj "
                                 LPX64" on OST idx %d: rc = %d\n",
-                                set->set_md->lsm_object_id, loi->loi_id,
-                                loi->loi_ost_idx, rc);
+                                set->set_oi->oi_md->lsm_object_id,
+                                loi->loi_id, loi->loi_ost_idx, rc);
                 } else {
                         rc = ELDLM_OK;
                 }
@@ -178,10 +188,20 @@ int lov_update_enqueue_set(struct lov_request_set *set,
         RETURN(rc);
 }
 
+/* The callback for osc_enqueue that updates lov info for every OSC request. */
+static int cb_update_enqueue(struct obd_info *oinfo, int rc)
+{
+        struct obd_enqueue_info *einfo;
+        struct lov_request *lovreq;
+
+        lovreq = container_of(oinfo, struct lov_request, rq_oi);
+        einfo = lovreq->rq_rqset->set_ei;
+        return lov_update_enqueue_set(lovreq, einfo->ei_mode, rc);
+}
+
 static int enqueue_done(struct lov_request_set *set, __u32 mode)
 {
         struct lov_request *req;
-        struct lustre_handle *lov_lockhp = NULL;
         struct lov_obd *lov = &set->set_exp->exp_obd->u.lov;
         int rc = 0;
         ENTRY;
@@ -193,6 +213,8 @@ static int enqueue_done(struct lov_request_set *set, __u32 mode)
 
         /* cancel enqueued/matched locks */
         list_for_each_entry(req, &set->set_list, rq_link) {
+                struct lustre_handle *lov_lockhp;
+
                 if (!req->rq_complete || req->rq_rc)
                         continue;
 
@@ -201,12 +223,14 @@ static int enqueue_done(struct lov_request_set *set, __u32 mode)
                 if (!lustre_handle_is_used(lov_lockhp))
                         continue;
 
-                rc = obd_cancel(lov->tgts[req->rq_idx].ltd_exp, req->rq_md,
-                                mode, lov_lockhp);
-                if (rc && lov->tgts[req->rq_idx].active)
+                rc = obd_cancel(lov->lov_tgts[req->rq_idx]->ltd_exp,
+                                req->rq_oi.oi_md, mode, lov_lockhp);
+                if (rc && lov->lov_tgts[req->rq_idx] &&
+                    lov->lov_tgts[req->rq_idx]->ltd_active)
                         CERROR("cancelling obdjid "LPX64" on OST "
                                "idx %d error: rc = %d\n",
-                               req->rq_md->lsm_object_id, req->rq_idx, rc);
+                               req->rq_oi.oi_md->lsm_object_id,
+                               req->rq_idx, rc);
         }
         lov_llh_put(set->set_lockh);
         RETURN(rc);
@@ -220,7 +244,9 @@ int lov_fini_enqueue_set(struct lov_request_set *set, __u32 mode)
         if (set == NULL)
                 RETURN(0);
         LASSERT(set->set_exp);
-        if (set->set_completes)
+        /* Do enqueue_done only for sync requests and if any request
+           succeeded. */
+        if (!set->set_ei->ei_rqset && set->set_completes)
                 rc = enqueue_done(set, mode);
         else
                 lov_llh_put(set->set_lockh);
@@ -231,9 +257,8 @@ int lov_fini_enqueue_set(struct lov_request_set *set, __u32 mode)
         RETURN(rc);
 }
 
-int lov_prep_enqueue_set(struct obd_export *exp, struct lov_stripe_md *lsm,
-                         ldlm_policy_data_t *policy, __u32 mode,
-                         struct lustre_handle *lockh,
+int lov_prep_enqueue_set(struct obd_export *exp, struct obd_info *oinfo,
+                         struct obd_enqueue_info *einfo,
                          struct lov_request_set **reqset)
 {
         struct lov_obd *lov = &exp->exp_obd->u.lov;
@@ -248,22 +273,26 @@ int lov_prep_enqueue_set(struct obd_export *exp, struct lov_stripe_md *lsm,
         lov_init_set(set);
 
         set->set_exp = exp;
-        set->set_md = lsm;
-        set->set_lockh = lov_llh_new(lsm);
+        set->set_oi = oinfo;
+        set->set_ei = einfo;
+        set->set_lockh = lov_llh_new(oinfo->oi_md);
         if (set->set_lockh == NULL)
                 GOTO(out_set, rc = -ENOMEM);
-        lockh->cookie = set->set_lockh->llh_handle.h_cookie;
+        oinfo->oi_lockh->cookie = set->set_lockh->llh_handle.h_cookie;
 
-        loi = lsm->lsm_oinfo;
-        for (i = 0; i < lsm->lsm_stripe_count; i++, loi++) {
+        loi = oinfo->oi_md->lsm_oinfo;
+        for (i = 0; i < oinfo->oi_md->lsm_stripe_count; i++, loi++) {
                 struct lov_request *req;
                 obd_off start, end;
 
-                if (!lov_stripe_intersects(lsm, i, policy->l_extent.start,
-                                           policy->l_extent.end, &start, &end))
+                if (!lov_stripe_intersects(oinfo->oi_md, i,
+                                           oinfo->oi_policy.l_extent.start,
+                                           oinfo->oi_policy.l_extent.end,
+                                           &start, &end))
                         continue;
 
-                if (lov->tgts[loi->loi_ost_idx].active == 0) {
+                if (!lov->lov_tgts[loi->loi_ost_idx] ||
+                    !lov->lov_tgts[loi->loi_ost_idx]->ltd_active) {
                         CDEBUG(D_HA, "lov idx %d inactive\n", loi->loi_ost_idx);
                         continue;
                 }
@@ -272,25 +301,36 @@ int lov_prep_enqueue_set(struct obd_export *exp, struct lov_stripe_md *lsm,
                 if (req == NULL)
                         GOTO(out_set, rc = -ENOMEM);
 
-                req->rq_buflen = sizeof(*req->rq_md) +
+                req->rq_buflen = sizeof(*req->rq_oi.oi_md) +
                         sizeof(struct lov_oinfo);
-                OBD_ALLOC(req->rq_md, req->rq_buflen);
-                if (req->rq_md == NULL)
+                OBD_ALLOC(req->rq_oi.oi_md, req->rq_buflen);
+                if (req->rq_oi.oi_md == NULL) {
+                        OBD_FREE(req, sizeof(*req));
                         GOTO(out_set, rc = -ENOMEM);
+                }
 
-                req->rq_extent.start = start;
-                req->rq_extent.end = end;
-                req->rq_extent.gid = policy->l_extent.gid;
+                req->rq_rqset = set;
+                /* Set lov request specific parameters. */
+                req->rq_oi.oi_lockh = set->set_lockh->llh_handles + i;
+                req->rq_oi.oi_cb_up = cb_update_enqueue;
+
+                LASSERT(req->rq_oi.oi_lockh);
+
+                req->rq_oi.oi_policy.l_extent.gid =
+                        oinfo->oi_policy.l_extent.gid;
+                req->rq_oi.oi_policy.l_extent.start = start;
+                req->rq_oi.oi_policy.l_extent.end = end;
 
                 req->rq_idx = loi->loi_ost_idx;
                 req->rq_stripe = i;
 
                 /* XXX LOV STACKING: submd should be from the subobj */
-                req->rq_md->lsm_object_id = loi->loi_id;
-                req->rq_md->lsm_stripe_count = 0;
-                req->rq_md->lsm_oinfo->loi_kms_valid = loi->loi_kms_valid;
-                req->rq_md->lsm_oinfo->loi_kms = loi->loi_kms;
-                req->rq_md->lsm_oinfo->loi_lvb = loi->loi_lvb;
+                req->rq_oi.oi_md->lsm_object_id = loi->loi_id;
+                req->rq_oi.oi_md->lsm_stripe_count = 0;
+                req->rq_oi.oi_md->lsm_oinfo->loi_kms_valid =
+                        loi->loi_kms_valid;
+                req->rq_oi.oi_md->lsm_oinfo->loi_kms = loi->loi_kms;
+                req->rq_oi.oi_md->lsm_oinfo->loi_lvb = loi->loi_lvb;
 
                 lov_set_add_req(req, set);
         }
@@ -299,7 +339,7 @@ int lov_prep_enqueue_set(struct obd_export *exp, struct lov_stripe_md *lsm,
         *reqset = set;
         RETURN(0);
 out_set:
-        lov_fini_enqueue_set(set, mode);
+        lov_fini_enqueue_set(set, einfo->ei_mode);
         RETURN(rc);
 }
 
@@ -338,9 +378,9 @@ int lov_fini_match_set(struct lov_request_set *set, __u32 mode, int flags)
         RETURN(rc);
 }
 
-int lov_prep_match_set(struct obd_export *exp, struct lov_stripe_md *lsm,
-                       ldlm_policy_data_t *policy, __u32 mode,
-                       struct lustre_handle *lockh,
+int lov_prep_match_set(struct obd_export *exp, struct obd_info *oinfo,
+                       struct lov_stripe_md *lsm, ldlm_policy_data_t *policy,
+                       __u32 mode, struct lustre_handle *lockh,
                        struct lov_request_set **reqset)
 {
         struct lov_obd *lov = &exp->exp_obd->u.lov;
@@ -355,7 +395,8 @@ int lov_prep_match_set(struct obd_export *exp, struct lov_stripe_md *lsm,
         lov_init_set(set);
 
         set->set_exp = exp;
-        set->set_md = lsm;
+        set->set_oi = oinfo;
+        set->set_oi->oi_md = lsm;
         set->set_lockh = lov_llh_new(lsm);
         if (set->set_lockh == NULL)
                 GOTO(out_set, rc = -ENOMEM);
@@ -370,7 +411,8 @@ int lov_prep_match_set(struct obd_export *exp, struct lov_stripe_md *lsm,
                         continue;
 
                 /* FIXME raid1 should grace this error */
-                if (lov->tgts[loi->loi_ost_idx].active == 0) {
+                if (!lov->lov_tgts[loi->loi_ost_idx] ||
+                    !lov->lov_tgts[loi->loi_ost_idx]->ltd_active) {
                         CDEBUG(D_HA, "lov idx %d inactive\n", loi->loi_ost_idx);
                         GOTO(out_set, rc = -EIO);
                 }
@@ -379,21 +421,23 @@ int lov_prep_match_set(struct obd_export *exp, struct lov_stripe_md *lsm,
                 if (req == NULL)
                         GOTO(out_set, rc = -ENOMEM);
 
-                req->rq_buflen = sizeof(*req->rq_md);
-                OBD_ALLOC(req->rq_md, req->rq_buflen);
-                if (req->rq_md == NULL)
+                req->rq_buflen = sizeof(*req->rq_oi.oi_md);
+                OBD_ALLOC(req->rq_oi.oi_md, req->rq_buflen);
+                if (req->rq_oi.oi_md == NULL) {
+                        OBD_FREE(req, sizeof(*req));
                         GOTO(out_set, rc = -ENOMEM);
+                }
 
-                req->rq_extent.start = start;
-                req->rq_extent.end = end;
-                req->rq_extent.gid = policy->l_extent.gid;
+                req->rq_oi.oi_policy.l_extent.start = start;
+                req->rq_oi.oi_policy.l_extent.end = end;
+                req->rq_oi.oi_policy.l_extent.gid = policy->l_extent.gid;
 
                 req->rq_idx = loi->loi_ost_idx;
                 req->rq_stripe = i;
 
                 /* XXX LOV STACKING: submd should be from the subobj */
-                req->rq_md->lsm_object_id = loi->loi_id;
-                req->rq_md->lsm_stripe_count = 0;
+                req->rq_oi.oi_md->lsm_object_id = loi->loi_id;
+                req->rq_oi.oi_md->lsm_stripe_count = 0;
 
                 lov_set_add_req(req, set);
         }
@@ -424,8 +468,9 @@ int lov_fini_cancel_set(struct lov_request_set *set)
         RETURN(rc);
 }
 
-int lov_prep_cancel_set(struct obd_export *exp, struct lov_stripe_md *lsm,
-                        __u32 mode, struct lustre_handle *lockh,
+int lov_prep_cancel_set(struct obd_export *exp, struct obd_info *oinfo,
+                        struct lov_stripe_md *lsm, __u32 mode,
+                        struct lustre_handle *lockh,
                         struct lov_request_set **reqset)
 {
         struct lov_request_set *set;
@@ -439,7 +484,8 @@ int lov_prep_cancel_set(struct obd_export *exp, struct lov_stripe_md *lsm,
         lov_init_set(set);
 
         set->set_exp = exp;
-        set->set_md = lsm;
+        set->set_oi = oinfo;
+        set->set_oi->oi_md = lsm;
         set->set_lockh = lov_handle2llh(lockh);
         if (set->set_lockh == NULL) {
                 CERROR("LOV: invalid lov lock handle %p\n", lockh);
@@ -462,17 +508,19 @@ int lov_prep_cancel_set(struct obd_export *exp, struct lov_stripe_md *lsm,
                 if (req == NULL)
                         GOTO(out_set, rc = -ENOMEM);
 
-                req->rq_buflen = sizeof(*req->rq_md);
-                OBD_ALLOC(req->rq_md, req->rq_buflen);
-                if (req->rq_md == NULL)
+                req->rq_buflen = sizeof(*req->rq_oi.oi_md);
+                OBD_ALLOC(req->rq_oi.oi_md, req->rq_buflen);
+                if (req->rq_oi.oi_md == NULL) {
+                        OBD_FREE(req, sizeof(*req));
                         GOTO(out_set, rc = -ENOMEM);
+                }
 
                 req->rq_idx = loi->loi_ost_idx;
                 req->rq_stripe = i;
 
                 /* XXX LOV STACKING: submd should be from the subobj */
-                req->rq_md->lsm_object_id = loi->loi_id;
-                req->rq_md->lsm_stripe_count = 0;
+                req->rq_oi.oi_md->lsm_object_id = loi->loi_id;
+                req->rq_oi.oi_md->lsm_stripe_count = 0;
 
                 lov_set_add_req(req, set);
         }
@@ -490,7 +538,7 @@ static int create_done(struct obd_export *exp, struct lov_request_set *set,
 {
         struct lov_obd *lov = &exp->exp_obd->u.lov;
         struct obd_trans_info *oti = set->set_oti;
-        struct obdo *src_oa = set->set_oa;
+        struct obdo *src_oa = set->set_oi->oi_oa;
         struct lov_request *req;
         struct obdo *ret_oa = NULL;
         int attrset = 0, rc = 0;
@@ -504,10 +552,10 @@ static int create_done(struct obd_export *exp, struct lov_request_set *set,
                 list_for_each_entry (req, &set->set_list, rq_link) {
                         if (req->rq_rc == 0)
                                 continue;
-                        
+
                         set->set_completes--;
                         req->rq_complete = 0;
-                        
+
                         rc = qos_remedy_create(set, req);
                         lov_update_create_set(set, req, rc);
 
@@ -519,7 +567,7 @@ static int create_done(struct obd_export *exp, struct lov_request_set *set,
         /* no successful creates */
         if (set->set_success == 0)
                 GOTO(cleanup, rc);
-        
+
         /* If there was an explicit stripe set, fail.  Otherwise, we
          * got some objects and that's not bad. */
         if (set->set_count != set->set_success) {
@@ -536,8 +584,9 @@ static int create_done(struct obd_export *exp, struct lov_request_set *set,
         list_for_each_entry(req, &set->set_list, rq_link) {
                 if (!req->rq_complete || req->rq_rc)
                         continue;
-                lov_merge_attrs(ret_oa, req->rq_oa, req->rq_oa->o_valid,
-                                set->set_md, req->rq_stripe, &attrset);
+                lov_merge_attrs(ret_oa, req->rq_oi.oi_oa,
+                                req->rq_oi.oi_oa->o_valid, set->set_oi->oi_md,
+                                req->rq_stripe, &attrset);
         }
         if (src_oa->o_valid & OBD_MD_FLSIZE &&
             ret_oa->o_size != src_oa->o_size) {
@@ -549,7 +598,7 @@ static int create_done(struct obd_export *exp, struct lov_request_set *set,
         memcpy(src_oa, ret_oa, sizeof(*src_oa));
         obdo_free(ret_oa);
 
-        *lsmp = set->set_md;
+        *lsmp = set->set_oi->oi_md;
         GOTO(done, rc = 0);
 
 cleanup:
@@ -560,16 +609,16 @@ cleanup:
                 if (!req->rq_complete || req->rq_rc)
                         continue;
 
-                sub_exp = lov->tgts[req->rq_idx].ltd_exp;
-                err = obd_destroy(sub_exp, req->rq_oa, NULL, oti, NULL);
+                sub_exp = lov->lov_tgts[req->rq_idx]->ltd_exp;
+                err = obd_destroy(sub_exp, req->rq_oi.oi_oa, NULL, oti, NULL);
                 if (err)
                         CERROR("Failed to uncreate objid "LPX64" subobj "
                                LPX64" on OST idx %d: rc = %d\n",
-                               set->set_oa->o_id, req->rq_oa->o_id,
+                               src_oa->o_id, req->rq_oi.oi_oa->o_id,
                                req->rq_idx, rc);
         }
         if (*lsmp == NULL)
-                obd_free_memmd(exp, &set->set_md);
+                obd_free_memmd(exp, &set->set_oi->oi_md);
 done:
         if (oti && set->set_cookies) {
                 oti->oti_logcookies = set->set_cookies;
@@ -604,7 +653,7 @@ int lov_update_create_set(struct lov_request_set *set,
                           struct lov_request *req, int rc)
 {
         struct obd_trans_info *oti = set->set_oti;
-        struct lov_stripe_md *lsm = set->set_md;
+        struct lov_stripe_md *lsm = set->set_oi->oi_md;
         struct lov_oinfo *loi;
         struct lov_obd *lov = &set->set_exp->exp_obd->u.lov;
         ENTRY;
@@ -612,10 +661,11 @@ int lov_update_create_set(struct lov_request_set *set,
         req->rq_stripe = set->set_success;
         loi = &lsm->lsm_oinfo[req->rq_stripe];
 
-        if (rc && lov->tgts[req->rq_idx].active) {
+        if (rc && lov->lov_tgts[req->rq_idx] &&
+            lov->lov_tgts[req->rq_idx]->ltd_active) {
                 CERROR("error creating fid "LPX64" sub-object"
                        " on OST idx %d/%d: rc = %d\n",
-                       set->set_oa->o_id, req->rq_idx,
+                       set->set_oi->oi_oa->o_id, req->rq_idx,
                        lsm->lsm_stripe_count, rc);
                 if (rc > 0) {
                         CERROR("obd_create returned invalid err %d\n", rc);
@@ -627,24 +677,25 @@ int lov_update_create_set(struct lov_request_set *set,
                 RETURN(rc);
 
         if (oti && oti->oti_objid)
-                oti->oti_objid[req->rq_idx] = req->rq_oa->o_id;
+                oti->oti_objid[req->rq_idx] = req->rq_oi.oi_oa->o_id;
 
-        loi->loi_id = req->rq_oa->o_id;
+        loi->loi_id = req->rq_oi.oi_oa->o_id;
         loi->loi_ost_idx = req->rq_idx;
         CDEBUG(D_INODE, "objid "LPX64" has subobj "LPX64"/"LPX64" at idx %d\n",
                lsm->lsm_object_id, loi->loi_id, loi->loi_id, req->rq_idx);
         loi_init(loi);
 
-        if (set->set_cookies)
+        if (oti && set->set_cookies)
                 ++oti->oti_logcookies;
-        if (req->rq_oa->o_valid & OBD_MD_FLCOOKIE)
+        if (req->rq_oi.oi_oa->o_valid & OBD_MD_FLCOOKIE)
                 set->set_cookie_sent++;
 
         RETURN(0);
 }
 
-int lov_prep_create_set(struct obd_export *exp, struct lov_stripe_md **lsmp,
-                        struct obdo *src_oa, struct obd_trans_info *oti,
+int lov_prep_create_set(struct obd_export *exp, struct obd_info *oinfo,
+                        struct lov_stripe_md **lsmp, struct obdo *src_oa,
+                        struct obd_trans_info *oti,
                         struct lov_request_set **reqset)
 {
         struct lov_request_set *set;
@@ -657,8 +708,9 @@ int lov_prep_create_set(struct obd_export *exp, struct lov_stripe_md **lsmp,
         lov_init_set(set);
 
         set->set_exp = exp;
-        set->set_md = *lsmp;
-        set->set_oa = src_oa;
+        set->set_oi = oinfo;
+        set->set_oi->oi_md = *lsmp;
+        set->set_oi->oi_oa = src_oa;
         set->set_oti = oti;
 
         rc = qos_prep_create(exp, set);
@@ -677,7 +729,9 @@ static int common_attr_done(struct lov_request_set *set)
         int rc = 0, attrset = 0;
         ENTRY;
 
-        if (set->set_oa == NULL)
+        LASSERT(set->set_oi != NULL);
+
+        if (set->set_oi->oi_oa == NULL)
                 RETURN(0);
 
         if (!set->set_success)
@@ -692,17 +746,18 @@ static int common_attr_done(struct lov_request_set *set)
 
                 if (!req->rq_complete || req->rq_rc)
                         continue;
-                if (req->rq_oa->o_valid == 0)   /* inactive stripe */
+                if (req->rq_oi.oi_oa->o_valid == 0)   /* inactive stripe */
                         continue;
-                lov_merge_attrs(tmp_oa, req->rq_oa, req->rq_oa->o_valid,
-                                set->set_md, req->rq_stripe, &attrset);
+                lov_merge_attrs(tmp_oa, req->rq_oi.oi_oa,
+                                req->rq_oi.oi_oa->o_valid,
+                                set->set_oi->oi_md, req->rq_stripe, &attrset);
         }
         if (!attrset) {
                 CERROR("No stripes had valid attrs\n");
                 rc = -EIO;
         }
-        tmp_oa->o_id = set->set_oa->o_id;
-        memcpy(set->set_oa, tmp_oa, sizeof(*set->set_oa));
+        tmp_oa->o_id = set->set_oi->oi_oa->o_id;
+        memcpy(set->set_oi->oi_oa, tmp_oa, sizeof(*set->set_oi->oi_oa));
 out:
         if (tmp_oa)
                 obdo_free(tmp_oa);
@@ -712,7 +767,7 @@ out:
 
 static int brw_done(struct lov_request_set *set)
 {
-        struct lov_stripe_md *lsm = set->set_md;
+        struct lov_stripe_md *lsm = set->set_oi->oi_md;
         struct lov_oinfo     *loi = NULL;
         struct list_head *pos;
         struct lov_request *req;
@@ -726,8 +781,8 @@ static int brw_done(struct lov_request_set *set)
 
                 loi = &lsm->lsm_oinfo[req->rq_stripe];
 
-                if (req->rq_oa->o_valid & OBD_MD_FLBLOCKS)
-                        loi->loi_lvb.lvb_blocks = req->rq_oa->o_blocks;
+                if (req->rq_oi.oi_oa->o_valid & OBD_MD_FLBLOCKS)
+                        loi->loi_lvb.lvb_blocks = req->rq_oi.oi_oa->o_blocks;
         }
 
         RETURN(0);
@@ -751,9 +806,9 @@ int lov_fini_brw_set(struct lov_request_set *set)
         RETURN(rc);
 }
 
-int lov_prep_brw_set(struct obd_export *exp, struct obdo *src_oa,
-                     struct lov_stripe_md *lsm, obd_count oa_bufs,
-                     struct brw_page *pga, struct obd_trans_info *oti,
+int lov_prep_brw_set(struct obd_export *exp, struct obd_info *oinfo,
+                     obd_count oa_bufs, struct brw_page *pga,
+                     struct obd_trans_info *oti,
                      struct lov_request_set **reqset)
 {
         struct {
@@ -773,33 +828,34 @@ int lov_prep_brw_set(struct obd_export *exp, struct obdo *src_oa,
         lov_init_set(set);
 
         set->set_exp = exp;
-        set->set_md = lsm;
-        set->set_oa = src_oa;
         set->set_oti = oti;
+        set->set_oi = oinfo;
         set->set_oabufs = oa_bufs;
         OBD_ALLOC(set->set_pga, oa_bufs * sizeof(*set->set_pga));
         if (!set->set_pga)
                 GOTO(out, rc = -ENOMEM);
 
-        OBD_ALLOC(info, sizeof(*info) * lsm->lsm_stripe_count);
+        OBD_ALLOC(info, sizeof(*info) * oinfo->oi_md->lsm_stripe_count);
         if (!info)
                 GOTO(out, rc = -ENOMEM);
 
         /* calculate the page count for each stripe */
         for (i = 0; i < oa_bufs; i++) {
-                int stripe = lov_stripe_number(lsm, pga[i].off);
+                int stripe = lov_stripe_number(oinfo->oi_md, pga[i].off);
                 info[stripe].count++;
         }
 
         /* alloc and initialize lov request */
         shift = 0;
-        for (i = 0,loi = lsm->lsm_oinfo; i < lsm->lsm_stripe_count; i++, loi++){
+        for (i = 0, loi = oinfo->oi_md->lsm_oinfo;
+             i < oinfo->oi_md->lsm_stripe_count; i++, loi++){
                 struct lov_request *req;
 
                 if (info[i].count == 0)
                         continue;
 
-                if (lov->tgts[loi->loi_ost_idx].active == 0) {
+                if (!lov->lov_tgts[loi->loi_ost_idx] || 
+                    !lov->lov_tgts[loi->loi_ost_idx]->ltd_active) {
                         CDEBUG(D_HA, "lov idx %d inactive\n", loi->loi_ost_idx);
                         GOTO(out, rc = -EIO);
                 }
@@ -808,26 +864,33 @@ int lov_prep_brw_set(struct obd_export *exp, struct obdo *src_oa,
                 if (req == NULL)
                         GOTO(out, rc = -ENOMEM);
 
-                req->rq_oa = obdo_alloc();
-                if (req->rq_oa == NULL)
+                req->rq_oi.oi_oa = obdo_alloc();
+                if (req->rq_oi.oi_oa == NULL) {
+                        OBD_FREE(req, sizeof(*req));
                         GOTO(out, rc = -ENOMEM);
+                }
 
-                if (src_oa)
-                        memcpy(req->rq_oa, src_oa, sizeof(*req->rq_oa));
-                req->rq_oa->o_id = loi->loi_id;
-                req->rq_oa->o_stripe_idx = i;
-
-                req->rq_buflen = sizeof(*req->rq_md);
-                OBD_ALLOC(req->rq_md, req->rq_buflen);
-                if (req->rq_md == NULL)
+                if (oinfo->oi_oa) {
+                        memcpy(req->rq_oi.oi_oa, oinfo->oi_oa,
+                               sizeof(*req->rq_oi.oi_oa));
+                }
+                req->rq_oi.oi_oa->o_id = loi->loi_id;
+                req->rq_oi.oi_oa->o_stripe_idx = i;
+
+                req->rq_buflen = sizeof(*req->rq_oi.oi_md);
+                OBD_ALLOC(req->rq_oi.oi_md, req->rq_buflen);
+                if (req->rq_oi.oi_md == NULL) {
+                        obdo_free(req->rq_oi.oi_oa);
+                        OBD_FREE(req, sizeof(*req));
                         GOTO(out, rc = -ENOMEM);
+                }
 
                 req->rq_idx = loi->loi_ost_idx;
                 req->rq_stripe = i;
 
                 /* XXX LOV STACKING */
-                req->rq_md->lsm_object_id = loi->loi_id;
-                req->rq_md->lsm_object_gr = lsm->lsm_object_gr;
+                req->rq_oi.oi_md->lsm_object_id = loi->loi_id;
+                req->rq_oi.oi_md->lsm_object_gr = oinfo->oi_md->lsm_object_gr;
                 req->rq_oabufs = info[i].count;
                 req->rq_pgaidx = shift;
                 shift += req->rq_oabufs;
@@ -842,18 +905,18 @@ int lov_prep_brw_set(struct obd_export *exp, struct obdo *src_oa,
 
         /* rotate & sort the brw_page array */
         for (i = 0; i < oa_bufs; i++) {
-                int stripe = lov_stripe_number(lsm, pga[i].off);
+                int stripe = lov_stripe_number(oinfo->oi_md, pga[i].off);
 
                 shift = info[stripe].index + info[stripe].off;
                 LASSERT(shift < oa_bufs);
                 set->set_pga[shift] = pga[i];
-                lov_stripe_offset(lsm, pga[i].off, stripe,
+                lov_stripe_offset(oinfo->oi_md, pga[i].off, stripe,
                                   &set->set_pga[shift].off);
                 info[stripe].off++;
         }
 out:
         if (info)
-                OBD_FREE(info, sizeof(*info) * lsm->lsm_stripe_count);
+                OBD_FREE(info, sizeof(*info) * oinfo->oi_md->lsm_stripe_count);
 
         if (rc == 0)
                 *reqset = set;
@@ -880,8 +943,16 @@ int lov_fini_getattr_set(struct lov_request_set *set)
         RETURN(rc);
 }
 
-int lov_prep_getattr_set(struct obd_export *exp, struct obdo *src_oa,
-                         struct lov_stripe_md *lsm,
+/* The callback for osc_getattr_async that finilizes a request info when a
+ * response is recieved. */
+static int cb_getattr_update(struct obd_info *oinfo, int rc)
+{
+        struct lov_request *lovreq;
+        lovreq = container_of(oinfo, struct lov_request, rq_oi);
+        return lov_update_common_set(lovreq->rq_rqset, lovreq, rc);
+}
+
+int lov_prep_getattr_set(struct obd_export *exp, struct obd_info *oinfo,
                          struct lov_request_set **reqset)
 {
         struct lov_request_set *set;
@@ -896,14 +967,14 @@ int lov_prep_getattr_set(struct obd_export *exp, struct obdo *src_oa,
         lov_init_set(set);
 
         set->set_exp = exp;
-        set->set_md = lsm;
-        set->set_oa = src_oa;
+        set->set_oi = oinfo;
 
-        loi = lsm->lsm_oinfo;
-        for (i = 0; i < lsm->lsm_stripe_count; i++, loi++) {
+        loi = oinfo->oi_md->lsm_oinfo;
+        for (i = 0; i < oinfo->oi_md->lsm_stripe_count; i++, loi++) {
                 struct lov_request *req;
 
-                if (lov->tgts[loi->loi_ost_idx].active == 0) {
+                if (!lov->lov_tgts[loi->loi_ost_idx] ||
+                    !lov->lov_tgts[loi->loi_ost_idx]->ltd_active) {
                         CDEBUG(D_HA, "lov idx %d inactive\n", loi->loi_ost_idx);
                         continue;
                 }
@@ -915,11 +986,15 @@ int lov_prep_getattr_set(struct obd_export *exp, struct obdo *src_oa,
                 req->rq_stripe = i;
                 req->rq_idx = loi->loi_ost_idx;
 
-                req->rq_oa = obdo_alloc();
-                if (req->rq_oa == NULL)
+                req->rq_oi.oi_oa = obdo_alloc();
+                if (req->rq_oi.oi_oa == NULL) {
+                        OBD_FREE(req, sizeof(*req));
                         GOTO(out_set, rc = -ENOMEM);
-                memcpy(req->rq_oa, src_oa, sizeof(*req->rq_oa));
-                req->rq_oa->o_id = loi->loi_id;
+                }
+                memcpy(req->rq_oi.oi_oa, oinfo->oi_oa,
+                       sizeof(*req->rq_oi.oi_oa));
+                req->rq_oi.oi_oa->o_id = loi->loi_id;
+                req->rq_oi.oi_cb_up = cb_getattr_update;
 
                 lov_set_add_req(req, set);
         }
@@ -949,15 +1024,15 @@ int lov_fini_destroy_set(struct lov_request_set *set)
         RETURN(0);
 }
 
-int lov_prep_destroy_set(struct obd_export *exp, struct obdo *src_oa,
-                         struct lov_stripe_md *lsm,
+int lov_prep_destroy_set(struct obd_export *exp, struct obd_info *oinfo,
+                         struct obdo *src_oa, struct lov_stripe_md *lsm,
                          struct obd_trans_info *oti,
                          struct lov_request_set **reqset)
 {
         struct lov_request_set *set;
         struct lov_oinfo *loi = NULL;
         struct lov_obd *lov = &exp->exp_obd->u.lov;
-        int rc = 0, cookie_set = 0, i;
+        int rc = 0, i;
         ENTRY;
 
         OBD_ALLOC(set, sizeof(*set));
@@ -966,8 +1041,9 @@ int lov_prep_destroy_set(struct obd_export *exp, struct obdo *src_oa,
         lov_init_set(set);
 
         set->set_exp = exp;
-        set->set_md = lsm;
-        set->set_oa = src_oa;
+        set->set_oi = oinfo;
+        set->set_oi->oi_md = lsm;
+        set->set_oi->oi_oa = src_oa;
         set->set_oti = oti;
         if (oti != NULL && src_oa->o_valid & OBD_MD_FLCOOKIE)
                 set->set_cookies = oti->oti_logcookies;
@@ -976,7 +1052,8 @@ int lov_prep_destroy_set(struct obd_export *exp, struct obdo *src_oa,
         for (i = 0; i < lsm->lsm_stripe_count; i++, loi++) {
                 struct lov_request *req;
 
-                if (lov->tgts[loi->loi_ost_idx].active == 0) {
+                if (!lov->lov_tgts[loi->loi_ost_idx] || 
+                    !lov->lov_tgts[loi->loi_ost_idx]->ltd_active) {
                         CDEBUG(D_HA, "lov idx %d inactive\n", loi->loi_ost_idx);
                         continue;
                 }
@@ -988,17 +1065,13 @@ int lov_prep_destroy_set(struct obd_export *exp, struct obdo *src_oa,
                 req->rq_stripe = i;
                 req->rq_idx = loi->loi_ost_idx;
 
-                req->rq_oa = obdo_alloc();
-                if (req->rq_oa == NULL)
+                req->rq_oi.oi_oa = obdo_alloc();
+                if (req->rq_oi.oi_oa == NULL) {
+                        OBD_FREE(req, sizeof(*req));
                         GOTO(out_set, rc = -ENOMEM);
-                memcpy(req->rq_oa, src_oa, sizeof(*req->rq_oa));
-                req->rq_oa->o_id = loi->loi_id;
-
-                /* Setup the first request's cookie position */
-                if (!cookie_set && set->set_cookies) {
-                        oti->oti_logcookies = set->set_cookies + i;
-                        cookie_set = 1;
                 }
+                memcpy(req->rq_oi.oi_oa, src_oa, sizeof(*req->rq_oi.oi_oa));
+                req->rq_oi.oi_oa->o_id = loi->loi_id;
                 lov_set_add_req(req, set);
         }
         if (!set->set_count)
@@ -1028,8 +1101,46 @@ int lov_fini_setattr_set(struct lov_request_set *set)
         RETURN(rc);
 }
 
-int lov_prep_setattr_set(struct obd_export *exp, struct obdo *src_oa,
-                         struct lov_stripe_md *lsm, struct obd_trans_info *oti,
+int lov_update_setattr_set(struct lov_request_set *set,
+                           struct lov_request *req, int rc)
+{
+        struct lov_obd *lov = &req->rq_rqset->set_exp->exp_obd->u.lov;
+        struct lov_stripe_md *lsm = req->rq_rqset->set_oi->oi_md;
+        ENTRY;
+
+        lov_update_set(set, req, rc);
+
+        /* grace error on inactive ost */
+        if (rc && !(lov->lov_tgts[req->rq_idx] && 
+                    lov->lov_tgts[req->rq_idx]->ltd_active))
+                rc = 0;
+
+        if (rc == 0) {
+                if (req->rq_oi.oi_oa->o_valid & OBD_MD_FLCTIME)
+                        lsm->lsm_oinfo[req->rq_stripe].loi_lvb.lvb_ctime =
+                                req->rq_oi.oi_oa->o_ctime;
+                if (req->rq_oi.oi_oa->o_valid & OBD_MD_FLMTIME)
+                        lsm->lsm_oinfo[req->rq_stripe].loi_lvb.lvb_mtime =
+                                req->rq_oi.oi_oa->o_mtime;
+                if (req->rq_oi.oi_oa->o_valid & OBD_MD_FLATIME)
+                        lsm->lsm_oinfo[req->rq_stripe].loi_lvb.lvb_atime =
+                                req->rq_oi.oi_oa->o_atime;
+        }
+
+        RETURN(rc);
+}
+
+/* The callback for osc_setattr_async that finilizes a request info when a
+ * response is recieved. */
+static int cb_setattr_update(struct obd_info *oinfo, int rc)
+{
+        struct lov_request *lovreq;
+        lovreq = container_of(oinfo, struct lov_request, rq_oi);
+        return lov_update_setattr_set(lovreq->rq_rqset, lovreq, rc);
+}
+
+int lov_prep_setattr_set(struct obd_export *exp, struct obd_info *oinfo,
+                         struct obd_trans_info *oti,
                          struct lov_request_set **reqset)
 {
         struct lov_request_set *set;
@@ -1044,14 +1155,17 @@ int lov_prep_setattr_set(struct obd_export *exp, struct obdo *src_oa,
         lov_init_set(set);
 
         set->set_exp = exp;
-        set->set_md = lsm;
-        set->set_oa = src_oa;
+        set->set_oti = oti;
+        set->set_oi = oinfo;
+        if (oti != NULL && oinfo->oi_oa->o_valid & OBD_MD_FLCOOKIE)
+                set->set_cookies = oti->oti_logcookies;
 
-        loi = lsm->lsm_oinfo;
-        for (i = 0; i < lsm->lsm_stripe_count; i++, loi++) {
+        loi = oinfo->oi_md->lsm_oinfo;
+        for (i = 0; i < oinfo->oi_md->lsm_stripe_count; i++, loi++) {
                 struct lov_request *req;
 
-                if (lov->tgts[loi->loi_ost_idx].active == 0) {
+                if (!lov->lov_tgts[loi->loi_ost_idx] ||
+                    !lov->lov_tgts[loi->loi_ost_idx]->ltd_active) {
                         CDEBUG(D_HA, "lov idx %d inactive\n", loi->loi_ost_idx);
                         continue;
                 }
@@ -1062,20 +1176,29 @@ int lov_prep_setattr_set(struct obd_export *exp, struct obdo *src_oa,
                 req->rq_stripe = i;
                 req->rq_idx = loi->loi_ost_idx;
 
-                req->rq_oa = obdo_alloc();
-                if (req->rq_oa == NULL)
+                req->rq_oi.oi_oa = obdo_alloc();
+                if (req->rq_oi.oi_oa == NULL) {
+                        OBD_FREE(req, sizeof(*req));
                         GOTO(out_set, rc = -ENOMEM);
-                memcpy(req->rq_oa, src_oa, sizeof(*req->rq_oa));
-                req->rq_oa->o_id = loi->loi_id;
-                req->rq_oa->o_stripe_idx = i;
-
-                if (src_oa->o_valid & OBD_MD_FLSIZE) {
-                        if (lov_stripe_offset(lsm, src_oa->o_size, i,
-                                              &req->rq_oa->o_size) < 0 &&
-                            req->rq_oa->o_size)
-                                req->rq_oa->o_size--;
+                }
+                memcpy(req->rq_oi.oi_oa, oinfo->oi_oa,
+                       sizeof(*req->rq_oi.oi_oa));
+                req->rq_oi.oi_oa->o_id = loi->loi_id;
+                req->rq_oi.oi_oa->o_stripe_idx = i;
+                req->rq_oi.oi_cb_up = cb_setattr_update;
+                req->rq_rqset = set;
+
+                if (oinfo->oi_oa->o_valid & OBD_MD_FLSIZE) {
+                        int off = lov_stripe_offset(oinfo->oi_md,
+                                                    oinfo->oi_oa->o_size, i,
+                                                    &req->rq_oi.oi_oa->o_size);
+
+                        if (off < 0 && req->rq_oi.oi_oa->o_size)
+                                req->rq_oi.oi_oa->o_size--;
+
                         CDEBUG(D_INODE, "stripe %d has size "LPU64"/"LPU64"\n",
-                               i, req->rq_oa->o_size, src_oa->o_size);
+                               i, req->rq_oi.oi_oa->o_size,
+                               oinfo->oi_oa->o_size);
                 }
                 lov_set_add_req(req, set);
         }
@@ -1088,49 +1211,6 @@ out_set:
         RETURN(rc);
 }
 
-int lov_update_setattr_set(struct lov_request_set *set,
-                           struct lov_request *req, int rc)
-{
-        struct lov_obd *lov = &set->set_exp->exp_obd->u.lov;
-        struct lov_stripe_md *lsm = set->set_md;
-        ENTRY;
-
-        lov_update_set(set, req, rc);
-
-        /* grace error on inactive ost */
-        if (rc && !lov->tgts[req->rq_idx].active)
-                rc = 0;
-
-        /* FIXME: LOV STACKING update loi data should be done by OSC *
-         * when this is gone we can go back to using lov_update_common_set() */
-        if (rc == 0) {
-                if (req->rq_oa->o_valid & OBD_MD_FLMTIME)
-                        lsm->lsm_oinfo[req->rq_stripe].loi_lvb.lvb_ctime =
-                                req->rq_oa->o_ctime;
-                if (req->rq_oa->o_valid & OBD_MD_FLMTIME)
-                        lsm->lsm_oinfo[req->rq_stripe].loi_lvb.lvb_mtime =
-                                req->rq_oa->o_mtime;
-                if (req->rq_oa->o_valid & OBD_MD_FLATIME)
-                        lsm->lsm_oinfo[req->rq_stripe].loi_lvb.lvb_atime =
-                                req->rq_oa->o_atime;
-        }
-
-        RETURN(rc);
-}
-
-int lov_update_punch_set(struct lov_request_set *set, struct lov_request *req,
-                         int rc)
-{
-        struct lov_obd *lov = &set->set_exp->exp_obd->u.lov;
-        ENTRY;
-
-        lov_update_set(set, req, rc);
-        if (rc && !lov->tgts[req->rq_idx].active)
-                rc = 0;
-        /* FIXME in raid1 regime, should return 0 */
-        RETURN(rc);
-}
-
 int lov_fini_punch_set(struct lov_request_set *set)
 {
         int rc = 0;
@@ -1151,9 +1231,17 @@ int lov_fini_punch_set(struct lov_request_set *set)
         RETURN(rc);
 }
 
-int lov_prep_punch_set(struct obd_export *exp, struct obdo *src_oa,
-                       struct lov_stripe_md *lsm, obd_off start,
-                       obd_off end, struct obd_trans_info *oti,
+/* The callback for osc_punch that finilizes a request info when a response
+ * is recieved. */
+static int cb_update_punch(struct obd_info *oinfo, int rc)
+{
+        struct lov_request *lovreq;
+        lovreq = container_of(oinfo, struct lov_request, rq_oi);
+        return lov_update_common_set(lovreq->rq_rqset, lovreq, rc);
+}
+
+int lov_prep_punch_set(struct obd_export *exp, struct obd_info *oinfo,
+                       struct obd_trans_info *oti,
                        struct lov_request_set **reqset)
 {
         struct lov_request_set *set;
@@ -1167,21 +1255,24 @@ int lov_prep_punch_set(struct obd_export *exp, struct obdo *src_oa,
                 RETURN(-ENOMEM);
         lov_init_set(set);
 
+        set->set_oi = oinfo;
         set->set_exp = exp;
-        set->set_md = lsm;
-        set->set_oa = src_oa;
 
-        loi = lsm->lsm_oinfo;
-        for (i = 0; i < lsm->lsm_stripe_count; i++, loi++) {
+        loi = oinfo->oi_md->lsm_oinfo;
+        for (i = 0; i < oinfo->oi_md->lsm_stripe_count; i++, loi++) {
                 struct lov_request *req;
                 obd_off rs, re;
 
-                if (lov->tgts[loi->loi_ost_idx].active == 0) {
+                if (!lov->lov_tgts[loi->loi_ost_idx] ||
+                    !lov->lov_tgts[loi->loi_ost_idx]->ltd_active) {
                         CDEBUG(D_HA, "lov idx %d inactive\n", loi->loi_ost_idx);
                         continue;
                 }
 
-                if (!lov_stripe_intersects(lsm, i, start, end, &rs, &re))
+                if (!lov_stripe_intersects(oinfo->oi_md, i,
+                                           oinfo->oi_policy.l_extent.start,
+                                           oinfo->oi_policy.l_extent.end,
+                                           &rs, &re))
                         continue;
 
                 OBD_ALLOC(req, sizeof(*req));
@@ -1190,16 +1281,21 @@ int lov_prep_punch_set(struct obd_export *exp, struct obdo *src_oa,
                 req->rq_stripe = i;
                 req->rq_idx = loi->loi_ost_idx;
 
-                req->rq_oa = obdo_alloc();
-                if (req->rq_oa == NULL)
+                req->rq_oi.oi_oa = obdo_alloc();
+                if (req->rq_oi.oi_oa == NULL) {
+                        OBD_FREE(req, sizeof(*req));
                         GOTO(out_set, rc = -ENOMEM);
-                memcpy(req->rq_oa, src_oa, sizeof(*req->rq_oa));
-                req->rq_oa->o_id = loi->loi_id;
-                req->rq_oa->o_stripe_idx = i;
+                }
+                memcpy(req->rq_oi.oi_oa, oinfo->oi_oa,
+                       sizeof(*req->rq_oi.oi_oa));
+                req->rq_oi.oi_oa->o_id = loi->loi_id;
+                req->rq_oi.oi_oa->o_stripe_idx = i;
+                req->rq_oi.oi_cb_up = cb_update_punch;
+                req->rq_rqset = set;
 
-                req->rq_extent.start = rs;
-                req->rq_extent.end = re;
-                req->rq_extent.gid = -1;
+                req->rq_oi.oi_policy.l_extent.start = rs;
+                req->rq_oi.oi_policy.l_extent.end = re;
+                req->rq_oi.oi_policy.l_extent.gid = -1;
 
                 lov_set_add_req(req, set);
         }
@@ -1232,9 +1328,10 @@ int lov_fini_sync_set(struct lov_request_set *set)
         RETURN(rc);
 }
 
-int lov_prep_sync_set(struct obd_export *exp, struct obdo *src_oa,
-                      struct lov_stripe_md *lsm, obd_off start,
-                      obd_off end, struct lov_request_set **reqset)
+int lov_prep_sync_set(struct obd_export *exp, struct obd_info *oinfo,
+                      struct obdo *src_oa, struct lov_stripe_md *lsm,
+                      obd_off start, obd_off end,
+                      struct lov_request_set **reqset)
 {
         struct lov_request_set *set;
         struct lov_oinfo *loi = NULL;
@@ -1248,15 +1345,17 @@ int lov_prep_sync_set(struct obd_export *exp, struct obdo *src_oa,
         lov_init_set(set);
 
         set->set_exp = exp;
-        set->set_md = lsm;
-        set->set_oa = src_oa;
+        set->set_oi = oinfo;
+        set->set_oi->oi_md = lsm;
+        set->set_oi->oi_oa = src_oa;
 
         loi = lsm->lsm_oinfo;
         for (i = 0; i < lsm->lsm_stripe_count; i++, loi++) {
                 struct lov_request *req;
                 obd_off rs, re;
 
-                if (lov->tgts[loi->loi_ost_idx].active == 0) {
+                if (!lov->lov_tgts[loi->loi_ost_idx] ||
+                    !lov->lov_tgts[loi->loi_ost_idx]->ltd_active) {
                         CDEBUG(D_HA, "lov idx %d inactive\n", loi->loi_ost_idx);
                         continue;
                 }
@@ -1270,16 +1369,18 @@ int lov_prep_sync_set(struct obd_export *exp, struct obdo *src_oa,
                 req->rq_stripe = i;
                 req->rq_idx = loi->loi_ost_idx;
 
-                req->rq_oa = obdo_alloc();
-                if (req->rq_oa == NULL)
+                req->rq_oi.oi_oa = obdo_alloc();
+                if (req->rq_oi.oi_oa == NULL) {
+                        OBD_FREE(req, sizeof(*req));
                         GOTO(out_set, rc = -ENOMEM);
-                memcpy(req->rq_oa, src_oa, sizeof(*req->rq_oa));
-                req->rq_oa->o_id = loi->loi_id;
-                req->rq_oa->o_stripe_idx = i;
+                }
+                memcpy(req->rq_oi.oi_oa, src_oa, sizeof(*req->rq_oi.oi_oa));
+                req->rq_oi.oi_oa->o_id = loi->loi_id;
+                req->rq_oi.oi_oa->o_stripe_idx = i;
 
-                req->rq_extent.start = rs;
-                req->rq_extent.end = re;
-                req->rq_extent.gid = -1;
+                req->rq_oi.oi_policy.l_extent.start = rs;
+                req->rq_oi.oi_policy.l_extent.end = re;
+                req->rq_oi.oi_policy.l_extent.gid = -1;
 
                 lov_set_add_req(req, set);
         }
@@ -1291,3 +1392,180 @@ out_set:
         lov_fini_sync_set(set);
         RETURN(rc);
 }
+
+#define LOV_U64_MAX ((__u64)~0ULL)
+#define LOV_SUM_MAX(tot, add)                                           \
+        do {                                                            \
+                if ((tot) + (add) < (tot))                              \
+                        (tot) = LOV_U64_MAX;                            \
+                else                                                    \
+                        (tot) += (add);                                 \
+        } while(0)
+
+int lov_fini_statfs(struct obd_device *obd, struct obd_statfs *osfs,int success)
+{
+        ENTRY;
+
+        if (success) {
+                __u32 expected_stripes = lov_get_stripecnt(&obd->u.lov, 0);
+
+                if (osfs->os_files != LOV_U64_MAX)
+                        do_div(osfs->os_files, expected_stripes);
+                if (osfs->os_ffree != LOV_U64_MAX)
+                        do_div(osfs->os_ffree, expected_stripes);
+
+                spin_lock(&obd->obd_osfs_lock);
+                memcpy(&obd->obd_osfs, osfs, sizeof(osfs));
+                obd->obd_osfs_age = cfs_time_current_64();
+                spin_unlock(&obd->obd_osfs_lock);
+                RETURN(0);
+        }
+
+        RETURN(-EIO);
+}
+
+int lov_fini_statfs_set(struct lov_request_set *set)
+{
+        int rc = 0;
+        ENTRY;
+
+        if (set == NULL)
+                RETURN(0);
+
+        if (set->set_completes) {
+                rc = lov_fini_statfs(set->set_obd, set->set_oi->oi_osfs,
+                                     set->set_success);
+        }
+
+        if (atomic_dec_and_test(&set->set_refcount))
+                lov_finish_set(set);
+
+        RETURN(rc);
+}
+
+void lov_update_statfs(struct obd_device *obd, struct obd_statfs *osfs,
+                       struct obd_statfs *lov_sfs, int success)
+{
+        spin_lock(&obd->obd_osfs_lock);
+        memcpy(&obd->obd_osfs, lov_sfs, sizeof(osfs));
+        obd->obd_osfs_age = cfs_time_current_64();
+        spin_unlock(&obd->obd_osfs_lock);
+
+        if (success == 0) {
+                memcpy(osfs, lov_sfs, sizeof(*lov_sfs));
+        } else {
+#ifdef MIN_DF
+                /* Sandia requested that df (and so, statfs) only
+                   returned minimal available space on
+                   a single OST, so people would be able to
+                   write this much data guaranteed. */
+                if (osfs->os_bavail > lov_sfs->os_bavail) {
+                        /* Presumably if new bavail is smaller,
+                           new bfree is bigger as well */
+                        osfs->os_bfree = lov_sfs->os_bfree;
+                        osfs->os_bavail = lov_sfs->os_bavail;
+                }
+#else
+                osfs->os_bfree += lov_sfs->os_bfree;
+                osfs->os_bavail += lov_sfs->os_bavail;
+#endif
+                osfs->os_blocks += lov_sfs->os_blocks;
+                /* XXX not sure about this one - depends on policy.
+                 *   - could be minimum if we always stripe on all OBDs
+                 *     (but that would be wrong for any other policy,
+                 *     if one of the OBDs has no more objects left)
+                 *   - could be sum if we stripe whole objects
+                 *   - could be average, just to give a nice number
+                 *
+                 * To give a "reasonable" (if not wholly accurate)
+                 * number, we divide the total number of free objects
+                 * by expected stripe count (watch out for overflow).
+                 */
+                LOV_SUM_MAX(osfs->os_files, lov_sfs->os_files);
+                LOV_SUM_MAX(osfs->os_ffree, lov_sfs->os_ffree);
+        }
+}
+
+/* The callback for osc_statfs_async that finilizes a request info when a
+ * response is recieved. */
+static int cb_statfs_update(struct obd_info *oinfo, int rc)
+{
+        struct lov_request *lovreq;
+        struct obd_statfs *osfs, *lov_sfs;
+        struct obd_device *obd;
+        struct lov_obd *lov;
+        int success;
+        ENTRY;
+
+        lovreq = container_of(oinfo, struct lov_request, rq_oi);
+        lov = &lovreq->rq_rqset->set_obd->u.lov;
+        obd = class_exp2obd(lov->lov_tgts[lovreq->rq_idx]->ltd_exp);
+
+        osfs = lovreq->rq_rqset->set_oi->oi_osfs;
+        lov_sfs = oinfo->oi_osfs;
+
+        success = lovreq->rq_rqset->set_success;
+
+        /* XXX: the same is done in lov_update_common_set, however
+           lovset->set_exp is not initialized. */
+        lov_update_set(lovreq->rq_rqset, lovreq, rc);
+        if (rc) {
+                if (rc && !(lov->lov_tgts[lovreq->rq_idx] &&
+                            lov->lov_tgts[lovreq->rq_idx]->ltd_active))
+                        rc = 0;
+                RETURN(rc);
+        }
+
+        lov_update_statfs(obd, osfs, lov_sfs, success);
+        RETURN(0);
+}
+
+int lov_prep_statfs_set(struct obd_device *obd, struct obd_info *oinfo,
+                        struct lov_request_set **reqset)
+{
+        struct lov_request_set *set;
+        struct lov_obd *lov = &obd->u.lov;
+        int rc = 0, i;
+        ENTRY;
+
+        OBD_ALLOC(set, sizeof(*set));
+        if (set == NULL)
+                RETURN(-ENOMEM);
+        lov_init_set(set);
+
+        set->set_obd = obd;
+        set->set_oi = oinfo;
+
+        /* We only get block data from the OBD */
+        for (i = 0; i < lov->desc.ld_tgt_count; i++) {
+                struct lov_request *req;
+
+                if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_active) {
+                        CDEBUG(D_HA, "lov idx %d inactive\n", i);
+                        continue;
+                }
+
+                OBD_ALLOC(req, sizeof(*req));
+                if (req == NULL)
+                        GOTO(out_set, rc = -ENOMEM);
+
+                OBD_ALLOC(req->rq_oi.oi_osfs, sizeof(*req->rq_oi.oi_osfs));
+                if (req->rq_oi.oi_osfs == NULL) {
+                        OBD_FREE(req, sizeof(*req));
+                        GOTO(out_set, rc = -ENOMEM);
+                }
+
+                req->rq_idx = i;
+                req->rq_oi.oi_cb_up = cb_statfs_update;
+                req->rq_rqset = set;
+
+                lov_set_add_req(req, set);
+        }
+        if (!set->set_count)
+                GOTO(out_set, rc = -EIO);
+        *reqset = set;
+        RETURN(rc);
+out_set:
+        lov_fini_statfs_set(set);
+        RETURN(rc);
+}
index 5ae9f62..8930167 100644 (file)
@@ -118,8 +118,9 @@ static int lov_rd_desc_uuid(char *page, char **start, off_t off, int count,
         return snprintf(page, count, "%s\n", lov->desc.ld_uuid.uuid);
 }
 
-static int lov_rd_qos_threshold(char *page, char **start, off_t off, int count,
-                                int *eof, void *data)
+/* free priority (0-255): how badly user wants to choose empty osts */ 
+static int lov_rd_qos_priofree(char *page, char **start, off_t off, int count,
+                               int *eof, void *data)
 {
         struct obd_device *dev = (struct obd_device*) data;
         struct lov_obd *lov;
@@ -127,11 +128,12 @@ static int lov_rd_qos_threshold(char *page, char **start, off_t off, int count,
         LASSERT(dev != NULL);
         lov = &dev->u.lov;
         *eof = 1;
-        return snprintf(page, count, "%u MB\n", lov->desc.ld_qos_threshold);
+        return snprintf(page, count, "%d%%\n", 
+                        (lov->lov_qos.lq_prio_free * 100) >> 8);
 }
 
-static int lov_wr_qos_threshold(struct file *file, const char *buffer,
-                                unsigned long count, void *data)
+static int lov_wr_qos_priofree(struct file *file, const char *buffer,
+                               unsigned long count, void *data)
 {
         struct obd_device *dev = (struct obd_device *)data;
         struct lov_obd *lov;
@@ -143,9 +145,11 @@ static int lov_wr_qos_threshold(struct file *file, const char *buffer,
         if (rc)
                 return rc;
 
-        if (val <= 0)
+        if (val > 100)
                 return -EINVAL;
-        lov->desc.ld_qos_threshold = val;
+        lov->lov_qos.lq_prio_free = (val << 8) / 100;
+        lov->lov_qos.lq_dirty = 1;
+        lov->lov_qos.lq_reset = 1;
         return count;
 }
 
@@ -185,7 +189,7 @@ static void *lov_tgt_seq_start(struct seq_file *p, loff_t *pos)
         struct obd_device *dev = p->private;
         struct lov_obd *lov = &dev->u.lov;
 
-        return (*pos >= lov->desc.ld_tgt_count) ? NULL : &(lov->tgts[*pos]);
+        return (*pos >= lov->desc.ld_tgt_count) ? NULL : lov->lov_tgts[*pos];
 
 }
 
@@ -199,17 +203,15 @@ static void *lov_tgt_seq_next(struct seq_file *p, void *v, loff_t *pos)
         struct lov_obd *lov = &dev->u.lov;
 
         ++*pos;
-        return (*pos >=lov->desc.ld_tgt_count) ? NULL : &(lov->tgts[*pos]);
+        return (*pos >= lov->desc.ld_tgt_count) ? NULL : lov->lov_tgts[*pos];
 }
 
 static int lov_tgt_seq_show(struct seq_file *p, void *v)
 {
         struct lov_tgt_desc *tgt = v;
-        struct obd_device *dev = p->private;
-        struct lov_obd *lov = &dev->u.lov;
-        int idx = tgt - &(lov->tgts[0]);
-        return seq_printf(p, "%d: %s %sACTIVE\n", idx, tgt->uuid.uuid,
-                          tgt->active ? "" : "IN");
+        return seq_printf(p, "%d: %s %sACTIVE\n", tgt->ltd_index, 
+                          obd_uuid2str(&tgt->ltd_uuid), 
+                          tgt->ltd_active ? "" : "IN");
 }
 
 struct seq_operations lov_tgt_sops = {
@@ -236,6 +238,8 @@ static int lov_target_seq_open(struct inode *inode, struct file *file)
 
 struct lprocfs_vars lprocfs_obd_vars[] = {
         { "uuid",         lprocfs_rd_uuid,        0, 0 },
+        /* If you change the stripe* names, 
+           make sure lustre_param.h is updated */
         { "stripesize",   lov_rd_stripesize,      0, 0 },
         { "stripeoffset", lov_rd_stripeoffset,    0, 0 },
         { "stripecount",  lov_rd_stripecount,     0, 0 },
@@ -244,13 +248,13 @@ struct lprocfs_vars lprocfs_obd_vars[] = {
         { "activeobd",    lov_rd_activeobd,       0, 0 },
         { "filestotal",   lprocfs_rd_filestotal,  0, 0 },
         { "filesfree",    lprocfs_rd_filesfree,   0, 0 },
-        //{ "filegroups",   lprocfs_rd_filegroups,  0, 0 },
+        /*{ "filegroups",   lprocfs_rd_filegroups,  0, 0 },*/
         { "blocksize",    lprocfs_rd_blksize,     0, 0 },
         { "kbytestotal",  lprocfs_rd_kbytestotal, 0, 0 },
         { "kbytesfree",   lprocfs_rd_kbytesfree,  0, 0 },
         { "kbytesavail",  lprocfs_rd_kbytesavail, 0, 0 },
         { "desc_uuid",    lov_rd_desc_uuid,       0, 0 },
-        { "qos_threshold",lov_rd_qos_threshold, lov_wr_qos_threshold, 0 },
+        { "qos_prio_free", lov_rd_qos_priofree, lov_wr_qos_priofree, 0 },
         { "qos_maxage",   lov_rd_qos_maxage, lov_wr_qos_maxage, 0 },
         { 0 }
 };
index 533f0d3..06296b8 100644 (file)
 #include <linux/iobuf.h>
 #endif
 #include <linux/lustre_compat25.h>
+#include <linux/lprocfs_status.h>
 
 #ifdef EXT3_MULTIBLOCK_ALLOCATOR
 #include <linux/ext3_extents.h>
 #endif
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
+#define FSFILT_DATA_TRANS_BLOCKS(sb)      EXT3_DATA_TRANS_BLOCKS
+#define FSFILT_DELETE_TRANS_BLOCKS(sb)    EXT3_DELETE_TRANS_BLOCKS
+#else
+#define FSFILT_DATA_TRANS_BLOCKS(sb)      EXT3_DATA_TRANS_BLOCKS(sb)
+#define FSFILT_DELETE_TRANS_BLOCKS(sb)    EXT3_DELETE_TRANS_BLOCKS(sb)
+#endif
+
 static kmem_cache_t *fcb_cache;
 
 struct fsfilt_cb_data {
@@ -140,7 +149,7 @@ static void *fsfilt_ext3_start(struct inode *inode, int op, void *desc_private,
         case FSFILT_OP_RMDIR:
         case FSFILT_OP_UNLINK:
                 /* delete one file + create/update logs for each stripe */
-                nblocks += EXT3_DELETE_TRANS_BLOCKS;
+                nblocks += FSFILT_DELETE_TRANS_BLOCKS(inode->i_sb);
                 nblocks += (EXT3_INDEX_EXTRA_TRANS_BLOCKS +
                             EXT3_SINGLEDATA_TRANS_BLOCKS) * logs;
                 break;
@@ -177,7 +186,7 @@ static void *fsfilt_ext3_start(struct inode *inode, int op, void *desc_private,
         case FSFILT_OP_LINK:
                 /* modify parent directory */
                 nblocks += EXT3_INDEX_EXTRA_TRANS_BLOCKS +
-                        EXT3_DATA_TRANS_BLOCKS;
+                         FSFILT_DATA_TRANS_BLOCKS(inode->i_sb);
                 /* create/update logs for each stripe */
                 nblocks += (EXT3_INDEX_EXTRA_TRANS_BLOCKS +
                             EXT3_SINGLEDATA_TRANS_BLOCKS) * logs;
@@ -186,7 +195,7 @@ static void *fsfilt_ext3_start(struct inode *inode, int op, void *desc_private,
                 /* Setattr on inode */
                 nblocks += 1;
                 nblocks += EXT3_INDEX_EXTRA_TRANS_BLOCKS +
-                        EXT3_DATA_TRANS_BLOCKS;
+                         FSFILT_DATA_TRANS_BLOCKS(inode->i_sb);
                 /* quota chown log for each stripe */
                 nblocks += (EXT3_INDEX_EXTRA_TRANS_BLOCKS +
                             EXT3_SINGLEDATA_TRANS_BLOCKS) * logs;
@@ -195,12 +204,12 @@ static void *fsfilt_ext3_start(struct inode *inode, int op, void *desc_private,
                 /* blocks for log header bitmap update OR
                  * blocks for catalog header bitmap update + unlink of logs */
                 nblocks = (LLOG_CHUNK_SIZE >> inode->i_blkbits) +
-                        EXT3_DELETE_TRANS_BLOCKS * logs;
+                        FSFILT_DELETE_TRANS_BLOCKS(inode->i_sb) * logs;
                 break;
         case FSFILT_OP_JOIN:
                 /* delete 2 file(file + array id) + create 1 file (array id) 
                  * create/update logs for each stripe */
-                nblocks += 2 * EXT3_DELETE_TRANS_BLOCKS;
+                nblocks += 2 * FSFILT_DELETE_TRANS_BLOCKS(inode->i_sb);
                
                 /*create array log for head file*/ 
                 nblocks += 3;
@@ -208,7 +217,7 @@ static void *fsfilt_ext3_start(struct inode *inode, int op, void *desc_private,
                             EXT3_SINGLEDATA_TRANS_BLOCKS);
                 /*update head file array */
                 nblocks += EXT3_INDEX_EXTRA_TRANS_BLOCKS +
-                        EXT3_DATA_TRANS_BLOCKS;
+                         FSFILT_DATA_TRANS_BLOCKS(inode->i_sb);
                 break;
         default: CERROR("unknown transaction start op %d\n", op);
                 LBUG();
@@ -306,7 +315,7 @@ static int fsfilt_ext3_credits_needed(int objcount, struct fsfilt_objinfo *fso,
         needed += nbitmaps + ngdblocks;
 
         /* last_rcvd update */
-        needed += EXT3_DATA_TRANS_BLOCKS;
+        needed += FSFILT_DATA_TRANS_BLOCKS(sb);
 
 #if defined(CONFIG_QUOTA)
         /* We assume that there will be 1 bit set in s_dquot.flags for each
@@ -454,26 +463,39 @@ static int fsfilt_ext3_setattr(struct dentry *dentry, void *handle,
                                struct iattr *iattr, int do_trunc)
 {
         struct inode *inode = dentry->d_inode;
-        int rc;
+        int rc = 0;
 
         lock_kernel();
 
-        /* A _really_ horrible hack to avoid removing the data stored
-         * in the block pointers; this is really the "small" stripe MD data.
-         * We can avoid further hackery by virtue of the MDS file size being
-         * zero all the time (which doesn't invoke block truncate at unlink
-         * time), so we assert we never change the MDS file size from zero. */
+        /* Avoid marking the inode dirty on the superblock list unnecessarily.
+         * We are already writing the inode to disk as part of this
+         * transaction and want to avoid a lot of extra inode writeout
+         * later on. b=9828 */
         if (iattr->ia_valid & ATTR_SIZE && !do_trunc) {
                 /* ATTR_SIZE would invoke truncate: clear it */
                 iattr->ia_valid &= ~ATTR_SIZE;
                 EXT3_I(inode)->i_disksize = inode->i_size = iattr->ia_size;
 
-                /* make sure _something_ gets set - so new inode
-                 * goes to disk (probably won't work over XFS */
-                if (!(iattr->ia_valid & (ATTR_MODE | ATTR_MTIME | ATTR_CTIME))){
-                        iattr->ia_valid |= ATTR_MTIME;
-                        iattr->ia_mtime = inode->i_mtime;
+                if (iattr->ia_valid & ATTR_UID)
+                        inode->i_uid = iattr->ia_uid;
+                if (iattr->ia_valid & ATTR_GID)
+                        inode->i_gid = iattr->ia_gid;
+                if (iattr->ia_valid & ATTR_ATIME)
+                        inode->i_atime = iattr->ia_atime;
+                if (iattr->ia_valid & ATTR_MTIME)
+                        inode->i_mtime = iattr->ia_mtime;
+                if (iattr->ia_valid & ATTR_CTIME)
+                        inode->i_ctime = iattr->ia_ctime;
+                if (iattr->ia_valid & ATTR_MODE) {
+                        inode->i_mode = iattr->ia_mode;
+
+                        if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
+                                inode->i_mode &= ~S_ISGID;
                 }
+
+                inode->i_sb->s_op->dirty_inode(inode);
+
+                goto out;
         }
 
         /* Don't allow setattr to change file type */
@@ -493,8 +515,9 @@ static int fsfilt_ext3_setattr(struct dentry *dentry, void *handle,
                         rc = inode_setattr(inode, iattr);
         }
 
+ out:
         unlock_kernel();
-        return rc;
+        RETURN(rc);
 }
 
 static int fsfilt_ext3_iocontrol(struct inode * inode, struct file *file,
@@ -646,7 +669,7 @@ static ssize_t fsfilt_ext3_readpage(struct file *file, char *buf, size_t count,
 
                                 CDEBUG(D_EXT2, "fake %u@%llu\n", blksize, *off);
                                 memset(fake, 0, sizeof(*fake));
-                                fake->rec_len = cpu_to_le32(blksize);
+                                fake->rec_len = cpu_to_le16(blksize);
                         }
                         count -= blksize;
                         buf += blksize;
@@ -733,9 +756,12 @@ static int fsfilt_ext3_sync(struct super_block *sb)
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
 #define ext3_up_truncate_sem(inode)  up_write(&EXT3_I(inode)->truncate_sem);
 #define ext3_down_truncate_sem(inode)  down_write(&EXT3_I(inode)->truncate_sem);
-#else
+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17))
 #define ext3_up_truncate_sem(inode)  up(&EXT3_I(inode)->truncate_sem);
 #define ext3_down_truncate_sem(inode)  down(&EXT3_I(inode)->truncate_sem);
+#else
+#define ext3_up_truncate_sem(inode)  mutex_unlock(&EXT3_I(inode)->truncate_mutex);
+#define ext3_down_truncate_sem(inode)  mutex_lock(&EXT3_I(inode)->truncate_mutex);
 #endif
 
 #include <linux/lustre_version.h>
@@ -860,7 +886,7 @@ static int ext3_ext_new_extent_cb(struct ext3_extents_tree *tree,
                 return EXT_CONTINUE;
         }
 
-        tgen = EXT_GENERATION(EXT_ROOT_HDR(tree));
+        tgen = EXT_GENERATION(tree);
         count = ext3_ext_calc_credits_for_insert(tree, path);
         ext3_up_truncate_sem(inode);
 
@@ -873,7 +899,7 @@ static int ext3_ext_new_extent_cb(struct ext3_extents_tree *tree,
         }
 
         ext3_down_truncate_sem(inode);
-        if (tgen != EXT_GENERATION(EXT_ROOT_HDR(tree))) {
+        if (tgen != EXT_GENERATION(tree)) {
                 /* the tree has changed. so path can be invalid at moment */
                 lock_24kernel();
                 journal_stop(handle);
@@ -1159,11 +1185,11 @@ static int fsfilt_ext3_write_record(struct file *file, void *buf, int bufsize,
         journal = EXT3_SB(inode->i_sb)->s_journal;
         lock_24kernel();
         handle = journal_start(journal,
-                               block_count * EXT3_DATA_TRANS_BLOCKS + 2);
+                               block_count * FSFILT_DATA_TRANS_BLOCKS(inode->i_sb) + 2);
         unlock_24kernel();
         if (IS_ERR(handle)) {
                 CERROR("can't start transaction for %d blocks (%d bytes)\n",
-                       block_count * EXT3_DATA_TRANS_BLOCKS + 2, bufsize);
+                       block_count * FSFILT_DATA_TRANS_BLOCKS(inode->i_sb) + 2, bufsize);
                 return PTR_ERR(handle);
         }
 
index 3f662d7..f89cc99 100644 (file)
@@ -160,7 +160,7 @@ void push_ctxt(struct lvfs_run_ctxt *save, struct lvfs_run_ctxt *new_ctx,
         }
         current->fs->umask = 0; /* umask already applied on client */
         set_fs(new_ctx->fs);
-        set_fs_pwd(current->fs, new_ctx->pwdmnt, new_ctx->pwd);
+        ll_set_fs_pwd(current->fs, new_ctx->pwdmnt, new_ctx->pwd);
 
         /*
         CDEBUG(D_INFO,
@@ -200,7 +200,7 @@ void pop_ctxt(struct lvfs_run_ctxt *saved, struct lvfs_run_ctxt *new_ctx,
                  current->fs->pwdmnt, new_ctx->pwdmnt);
 
         set_fs(saved->fs);
-        set_fs_pwd(current->fs, saved->pwdmnt, saved->pwd);
+        ll_set_fs_pwd(current->fs, saved->pwdmnt, saved->pwd);
 
         dput(saved->pwd);
         mntput(saved->pwdmnt);
@@ -425,6 +425,7 @@ EXPORT_SYMBOL(l_readdir);
 EXPORT_SYMBOL(obd_memory);
 EXPORT_SYMBOL(obd_memmax);
 
+#ifdef LUSTRE_KERNEL_VERSION
 #ifdef HAVE_OLD_DEV_SET_RDONLY
 void dev_set_rdonly(lvfs_sbdev_type dev, int no_write);
 void dev_clear_rdonly(int no_write);
@@ -471,6 +472,7 @@ void lvfs_clear_rdonly(lvfs_sbdev_type dev)
 EXPORT_SYMBOL(lvfs_set_rdonly);
 EXPORT_SYMBOL(lvfs_check_rdonly);
 EXPORT_SYMBOL(lvfs_clear_rdonly);
+#endif
 
 int lvfs_check_io_health(struct obd_device *obd, struct file *file)
 {
@@ -503,7 +505,7 @@ static void __exit lvfs_linux_exit(void)
         ENTRY;
 
         leaked = atomic_read(&obd_memory);
-        CDEBUG_EX(leaked ? D_ERROR : D_INFO,
+        CDEBUG(leaked ? D_ERROR : D_INFO,
                "obd mem max: %d leaked: %d\n", obd_memmax, leaked);
 
         EXIT;
index 6de1dac..d2f5b0c 100644 (file)
@@ -415,7 +415,7 @@ int upcall_cache_downcall(struct upcall_cache *hash, __u32 err, __u64 key,
         }
 
         if (!UC_CACHE_IS_ACQUIRING(entry)) {
-                CERROR("%s: found uptodate entry %p (key "LPU64") in ioctl\n",
+                CWARN("%s: found uptodate entry %p (key "LPU64") in ioctl\n",
                        hash->uc_name, entry, entry->ue_key);
                 GOTO(out, rc = 0);
         }
index 0092084..27107cd 100644 (file)
 #include <lprocfs_status.h>
 
 #ifdef LPROCFS
+
+static int mdc_rd_max_rpcs_in_flight(char *page, char **start, off_t off,
+                                     int count, int *eof, void *data)
+{
+        struct obd_device *dev = data;
+        struct client_obd *cli = &dev->u.cli;
+        int rc;
+
+        spin_lock(&cli->cl_loi_list_lock);
+        rc = snprintf(page, count, "%u\n", cli->cl_max_rpcs_in_flight);
+        spin_unlock(&cli->cl_loi_list_lock);
+        return rc;
+}
+
+static int mdc_wr_max_rpcs_in_flight(struct file *file, const char *buffer,
+                                     unsigned long count, void *data)
+{
+        struct obd_device *dev = data;
+        struct client_obd *cli = &dev->u.cli;
+        int val, rc;
+
+        rc = lprocfs_write_helper(buffer, count, &val);
+        if (rc)
+                return rc;
+
+        if (val < 1 || val > MDC_MAX_RIF_MAX)
+                return -ERANGE;
+
+        spin_lock(&cli->cl_loi_list_lock);
+        cli->cl_max_rpcs_in_flight = val;
+        spin_unlock(&cli->cl_loi_list_lock);
+
+        return count;
+}
 static struct lprocfs_vars lprocfs_obd_vars[] = {
         { "uuid",            lprocfs_rd_uuid,        0, 0 },
         { "ping",            0, lprocfs_wr_ping,        0 },
@@ -43,6 +77,8 @@ static struct lprocfs_vars lprocfs_obd_vars[] = {
         //{ "filegroups",      lprocfs_rd_filegroups,  0, 0 },
         { "mds_server_uuid", lprocfs_rd_server_uuid, 0, 0 },
         { "mds_conn_uuid",   lprocfs_rd_conn_uuid,   0, 0 },
+        { "max_rpcs_in_flight", mdc_rd_max_rpcs_in_flight,
+                                mdc_wr_max_rpcs_in_flight, 0 },
         { 0 }
 };
 
index 41cea63..ceab76f 100644 (file)
 #include <lustre_mdc.h>
 
 void mdc_pack_req_body(struct ptlrpc_request *req, int offset,
-                       __u64 valid, struct lu_fid *fid, int ea_size);
+                       __u64 valid, struct lu_fid *fid, int ea_size, int flags);
 void mdc_pack_rep_body(struct ptlrpc_request *);
 void mdc_readdir_pack(struct ptlrpc_request *req, int pos, __u64 offset,
                      __u32 size, struct lu_fid *fid);
-void mdc_getattr_pack(struct ptlrpc_request *req, int valid, int offset,
-                      int flags, struct md_op_data *op_data);
+void mdc_getattr_pack(struct ptlrpc_request *req, int offset, int valid,
+                      int flags, struct md_op_data *data);
 void mdc_setattr_pack(struct ptlrpc_request *req, int offset,
                       struct md_op_data *op_data,
                       struct iattr *iattr, void *ea, int ealen,
-                     void *ea2, int ea2len);
+                      void *ea2, int ea2len);
 void mdc_create_pack(struct ptlrpc_request *req, int offset,
                      struct md_op_data *op_data, const void *data, int datalen,
                     __u32 mode, __u32 uid, __u32 gid, __u32 cap_effective,
@@ -56,6 +56,8 @@ void mdc_rename_pack(struct ptlrpc_request *req, int offset,
                      const char *old, int oldlen, const char *new, int newlen);
 void mdc_close_pack(struct ptlrpc_request *req, int offset, struct md_op_data *op_data,
                    int valid, struct obd_client_handle *och);
+void mdc_exit_request(struct client_obd *cli);
+void mdc_enter_request(struct client_obd *cli);
 
 struct mdc_open_data {
         struct obd_client_handle *mod_och;
@@ -74,30 +76,26 @@ static inline void mdc_init_rpc_lock(struct mdc_rpc_lock *lck)
         lck->rpcl_it = NULL;
 }
 
-static inline void mdc_get_rpc_lock(struct mdc_rpc_lock *lck, 
+static inline void mdc_get_rpc_lock(struct mdc_rpc_lock *lck,
                                     struct lookup_intent *it)
 {
         ENTRY;
-        down(&lck->rpcl_sem);
-        if (it) { 
+        if (!it || (it->it_op != IT_GETATTR && it->it_op != IT_LOOKUP)) {
+                down(&lck->rpcl_sem);
+                LASSERT(lck->rpcl_it == NULL);
                 lck->rpcl_it = it;
         }
 }
 
-static inline void mdc_put_rpc_lock(struct mdc_rpc_lock *lck, 
+static inline void mdc_put_rpc_lock(struct mdc_rpc_lock *lck,
                                     struct lookup_intent *it)
 {
-        EXIT;
-        if (it == NULL) {
-                LASSERT(it == lck->rpcl_it);
-                up(&lck->rpcl_sem);
-                return;
-        }
-        if (it) {
+        if (!it || (it->it_op != IT_GETATTR && it->it_op != IT_LOOKUP)) {
                 LASSERT(it == lck->rpcl_it);
                 lck->rpcl_it = NULL;
                 up(&lck->rpcl_sem);
         }
+        EXIT;
 }
 
 /* Quota stuff */
index aa10f6a..2c423c0 100644 (file)
@@ -43,7 +43,7 @@ void mdc_readdir_pack(struct ptlrpc_request *req, int pos, __u64 offset,
 {
         struct mdt_body *b;
 
-        b = lustre_msg_buf(req->rq_reqmsg, pos, sizeof (*b));
+        b = lustre_msg_buf(req->rq_reqmsg, pos, sizeof(*b));
         b->fsuid = current->fsuid;
         b->fsgid = current->fsgid;
         b->capability = current->cap_effective;
@@ -63,7 +63,7 @@ static void mdc_pack_body(struct mdt_body *b)
 }
 
 void mdc_pack_req_body(struct ptlrpc_request *req, int offset,
-                       __u64 valid, struct lu_fid *fid, int ea_size)
+                       __u64 valid, struct lu_fid *fid, int ea_size, int flags)
 {
         struct mdt_body *b = lustre_msg_buf(req->rq_reqmsg, offset, sizeof(*b));
 
@@ -71,6 +71,7 @@ void mdc_pack_req_body(struct ptlrpc_request *req, int offset,
                 b->fid1 = *fid;
         b->valid = valid;
         b->eadatasize = ea_size;
+        b->flags = flags;
         mdc_pack_body(b);
 }
 /* packing of MDS records */
@@ -108,7 +109,8 @@ static __u32 mds_pack_open_flags(__u32 flags)
         return
                 (flags & (FMODE_READ | FMODE_WRITE |
                           MDS_OPEN_DELAY_CREATE | MDS_OPEN_HAS_EA |
-                          MDS_OPEN_HAS_OBJS | MDS_OPEN_OWNEROVERRIDE)) |
+                          MDS_OPEN_HAS_OBJS | MDS_OPEN_OWNEROVERRIDE |
+                          MDS_OPEN_LOCK)) |
                 ((flags & O_CREAT) ? MDS_OPEN_CREAT : 0) |
                 ((flags & O_EXCL) ? MDS_OPEN_EXCL : 0) |
                 ((flags & O_TRUNC) ? MDS_OPEN_TRUNC : 0) |
@@ -165,6 +167,10 @@ void mdc_open_pack(struct ptlrpc_request *req, int offset,
 
         if (lmm) {
                 rec->cr_flags |= MDS_OPEN_HAS_EA;
+#ifndef __KERNEL__
+                /*XXX a hack for liblustre to set EA (LL_IOC_LOV_SETSTRIPE) */
+                rec->cr_fid2 = op_data->fid2;
+#endif
                 tmp = lustre_msg_buf(req->rq_reqmsg, offset + 2, lmmlen);
                 memcpy (tmp, lmm, lmmlen);
         }
@@ -194,7 +200,6 @@ void mdc_setattr_pack(struct ptlrpc_request *req, int offset,
                 rec->sa_ctime = LTIME_S(iattr->ia_ctime);
                 rec->sa_attr_flags =
                                ((struct ll_iattr_struct *)iattr)->ia_attr_flags;
-
                 if ((iattr->ia_valid & ATTR_GID) && in_group_p(iattr->ia_gid))
                         rec->sa_suppgid = iattr->ia_gid;
                 else
@@ -297,10 +302,11 @@ void mdc_getattr_pack(struct ptlrpc_request *req, int offset, int valid,
         b->fsgid = current->fsgid;
         b->capability = current->cap_effective;
         b->valid = valid;
-        b->flags = flags;
+        b->flags = flags | MDS_BFLAG_EXT_FLAGS;
         b->suppgid = op_data->suppgids[0];
 
         b->fid1 = op_data->fid1;
+        b->fid2 = op_data->fid2;
         if (op_data->name) {
                 char *tmp;
                 tmp = lustre_msg_buf(req->rq_reqmsg, offset + 1,
@@ -315,7 +321,7 @@ void mdc_close_pack(struct ptlrpc_request *req, int offset,
 {
         struct mdt_body *body;
 
-        body = lustre_msg_buf(req->rq_reqmsg, 0, sizeof(*body));
+        body = lustre_msg_buf(req->rq_reqmsg, offset, sizeof(*body));
 
         body->fid1 = op_data->fid1;
         memcpy(&body->handle, &och->och_fh, sizeof(body->handle));
@@ -344,3 +350,62 @@ void mdc_close_pack(struct ptlrpc_request *req, int offset,
                 body->valid |= OBD_MD_FLFLAGS;
         }
 }
+
+struct mdc_cache_waiter {       
+        struct list_head        mcw_entry;
+        wait_queue_head_t       mcw_waitq;
+};
+
+static int mdc_req_avail(struct client_obd *cli, struct mdc_cache_waiter *mcw)
+{
+        int rc;
+        ENTRY;
+        spin_lock(&cli->cl_loi_list_lock);
+        rc = list_empty(&mcw->mcw_entry);
+        spin_unlock(&cli->cl_loi_list_lock);
+        RETURN(rc);
+};
+
+/* We record requests in flight in cli->cl_r_in_flight here.
+ * There is only one write rpc possible in mdc anyway. If this to change
+ * in the future - the code may need to be revisited. */
+void mdc_enter_request(struct client_obd *cli)
+{
+        struct mdc_cache_waiter mcw;
+        struct l_wait_info lwi = { 0 };
+
+        spin_lock(&cli->cl_loi_list_lock);
+        if (cli->cl_r_in_flight >= cli->cl_max_rpcs_in_flight) {
+                list_add_tail(&mcw.mcw_entry, &cli->cl_cache_waiters);
+                init_waitqueue_head(&mcw.mcw_waitq);
+                spin_unlock(&cli->cl_loi_list_lock);
+                l_wait_event(mcw.mcw_waitq, mdc_req_avail(cli, &mcw), &lwi);
+        } else {
+                cli->cl_r_in_flight++;
+                spin_unlock(&cli->cl_loi_list_lock);
+        }
+}
+
+void mdc_exit_request(struct client_obd *cli)
+{
+        struct list_head *l, *tmp;
+        struct mdc_cache_waiter *mcw;
+
+        spin_lock(&cli->cl_loi_list_lock);
+        cli->cl_r_in_flight--;
+        list_for_each_safe(l, tmp, &cli->cl_cache_waiters) {
+                
+                if (cli->cl_r_in_flight >= cli->cl_max_rpcs_in_flight) {
+                        /* No free request slots anymore */
+                        break;
+                }
+
+                mcw = list_entry(l, struct mdc_cache_waiter, mcw_entry);
+                list_del_init(&mcw->mcw_entry);
+                cli->cl_r_in_flight++;
+                wake_up(&mcw->mcw_waitq);
+        }
+        /* Empty waiting list? Decrease reqs in-flight number */
+        
+        spin_unlock(&cli->cl_loi_list_lock);
+}
index 2513771..6ab7e49 100644 (file)
@@ -58,6 +58,7 @@ void it_clear_disposition(struct lookup_intent *it, int flag)
 {
         it->d.lustre.it_disposition &= ~flag;
 }
+EXPORT_SYMBOL(it_clear_disposition);
 
 static int it_to_lock_mode(struct lookup_intent *it)
 {
@@ -121,7 +122,7 @@ int mdc_set_lock_data(struct obd_export *exp, __u64 *lockh, void *data)
         lock = ldlm_handle2lock((struct lustre_handle *)lockh);
 
         LASSERT(lock != NULL);
-        l_lock(&lock->l_resource->lr_namespace->ns_lock);
+        lock_res_and_lock(lock);
 #ifdef __KERNEL__
         if (lock->l_ast_data && lock->l_ast_data != data) {
                 struct inode *new_inode = data;
@@ -135,7 +136,7 @@ int mdc_set_lock_data(struct obd_export *exp, __u64 *lockh, void *data)
         }
 #endif
         lock->l_ast_data = data;
-        l_unlock(&lock->l_resource->lr_namespace->ns_lock);
+        unlock_res_and_lock(lock);
         LDLM_LOCK_PUT(lock);
 
         RETURN(0);
@@ -188,8 +189,8 @@ int mdc_change_cbdata(struct obd_export *exp, struct lu_fid *fid,
         res_id.name[1] = fid_oid(fid);
         res_id.name[2] = fid_ver(fid);
 
-        ldlm_change_cbdata(class_exp2obd(exp)->obd_namespace, 
-                           &res_id, it, data);
+        ldlm_resource_iterate(class_exp2obd(exp)->obd_namespace, 
+                              &res_id, it, data);
 
         EXIT;
         return 0;
@@ -199,10 +200,9 @@ static inline void mdc_clear_replay_flag(struct ptlrpc_request *req, int rc)
 {
         /* Don't hold error requests for replay. */
         if (req->rq_replay) {
-                unsigned long irqflags;
-                spin_lock_irqsave(&req->rq_lock, irqflags);
+                spin_lock(&req->rq_lock);
                 req->rq_replay = 0;
-                spin_unlock_irqrestore(&req->rq_lock, irqflags);
+                spin_unlock(&req->rq_lock);
         }
         if (rc && req->rq_transno != 0) {
                 DEBUG_REQ(D_ERROR, req, "transno returned on error rc %d", rc);
@@ -232,30 +232,30 @@ static int round_up(int val)
  * but this is incredibly unlikely, and questionable whether the client
  * could do MDS recovery under OOM anyways... */
 static void mdc_realloc_openmsg(struct ptlrpc_request *req,
-                                struct mdt_body *body, int size[5])
+                                struct mdt_body *body, int size[6])
 {
         int new_size, old_size;
         struct lustre_msg *new_msg;
 
         /* save old size */
-        old_size = lustre_msg_size(5, size);
+        old_size = lustre_msg_size(lustre_request_magic(req), 6, size);
 
-        size[4] = body->eadatasize;
-        new_size = lustre_msg_size(5, size);
+        size[DLM_INTENT_REC_OFF + 2] = body->eadatasize;
+        new_size = lustre_msg_size(lustre_request_magic(req), 6, size);
         OBD_ALLOC(new_msg, new_size);
         if (new_msg != NULL) {
                 struct lustre_msg *old_msg = req->rq_reqmsg;
-                unsigned long irqflags;
 
                 DEBUG_REQ(D_INFO, req, "replace reqmsg for larger EA %u\n",
                           body->eadatasize);
                 memcpy(new_msg, old_msg, old_size);
-                new_msg->buflens[4] = body->eadatasize;
+                lustre_msg_set_buflen(new_msg, DLM_INTENT_REC_OFF + 2,
+                                      body->eadatasize);
 
-                spin_lock_irqsave(&req->rq_lock, irqflags);
+                spin_lock(&req->rq_lock);
                 req->rq_reqmsg = new_msg;
                 req->rq_reqlen = new_size;
-                spin_unlock_irqrestore(&req->rq_lock, irqflags);
+                spin_unlock(&req->rq_lock);
 
                 OBD_FREE(old_msg, old_size);
         } else {
@@ -287,16 +287,18 @@ int mdc_enqueue(struct obd_export *exp,
         ldlm_policy_data_t policy = { .l_inodebits = { MDS_INODELOCK_LOOKUP } };
         struct ldlm_request *lockreq;
         struct ldlm_intent *lit;
-        int size[6] = {[MDS_REQ_INTENT_LOCKREQ_OFF] = sizeof(*lockreq),
-                       [MDS_REQ_INTENT_IT_OFF] = sizeof(*lit) };
-        struct ldlm_reply *dlm_rep;
-        int repsize[4] = {sizeof(*dlm_rep),
-                          sizeof(struct mdt_body),
-                          obddev->u.cli.cl_max_mds_easize};
+        struct ldlm_reply *lockrep;
+        int size[7] = { [MSG_PTLRPC_BODY_OFF] = sizeof(struct ptlrpc_body),
+                        [DLM_LOCKREQ_OFF]     = sizeof(*lockreq),
+                        [DLM_INTENT_IT_OFF]   = sizeof(*lit) };
+        int repsize[5] = { [MSG_PTLRPC_BODY_OFF] = sizeof(struct ptlrpc_body),
+                           [DLM_LOCKREPLY_OFF]   = sizeof(*lockrep),
+                           [DLM_REPLY_REC_OFF]   = sizeof(struct mdt_body),
+                           [DLM_REPLY_REC_OFF+1] = obddev->u.cli.
+                                                   cl_max_mds_easize };
+        int flags = extra_lock_flags | LDLM_FL_HAS_INTENT;
+        int repbufcnt = 4, rc;
         void *eadata;
-        unsigned long irqflags;
-        int repbufcnt = 3, req_buffers = 2;
-        int rc, flags = extra_lock_flags | LDLM_FL_HAS_INTENT;
         ENTRY;
 
         LASSERTF(lock_type == LDLM_IBITS, "lock type %d\n", lock_type);
@@ -306,21 +308,22 @@ int mdc_enqueue(struct obd_export *exp,
         if (it->it_op & IT_OPEN) {
                 it->it_create_mode = (it->it_create_mode & ~S_IFMT) | S_IFREG;
 
-                size[req_buffers++] = sizeof(struct mdt_rec_create);
-                size[req_buffers++] = op_data->namelen + 1;
+                size[DLM_INTENT_REC_OFF] = sizeof(struct mdt_rec_create);
+                size[DLM_INTENT_REC_OFF + 1] = op_data->namelen + 1;
                 /* As an optimization, we allocate an RPC request buffer for
                  * at least a default-sized LOV EA even if we aren't sending
                  * one.  We grow the whole request to the next power-of-two
                  * size since we get that much from a slab allocation anyways.
                  * This avoids an allocation below in the common case where
                  * we need to save a default-sized LOV EA for open replay. */
-                size[req_buffers++] = max(lmmsize,
+                size[DLM_INTENT_REC_OFF + 2] = max(lmmsize,
                                           obddev->u.cli.cl_default_mds_easize);
-                rc = lustre_msg_size(req_buffers, size);
+                rc = lustre_msg_size(class_exp2cliimp(exp)->imp_msg_magic, 6,
+                                     size);
                 if (rc & (rc - 1))
-                        size[req_buffers - 1] = min(size[req_buffers - 1] +
-                                                    round_up(rc) - rc,
-                                        obddev->u.cli.cl_max_mds_easize);
+                        size[DLM_INTENT_REC_OFF + 2] =
+                                 min(size[DLM_INTENT_REC_OFF+2]+round_up(rc)-rc,
+                                     obddev->u.cli.cl_max_mds_easize);
 
                 if (it->it_flags & O_JOIN_FILE) {
                         __u64 head_size = *(__u32*)cb_data;
@@ -328,109 +331,115 @@ int mdc_enqueue(struct obd_export *exp,
 
                         /* join is like an unlink of the tail */
                         policy.l_inodebits.bits = MDS_INODELOCK_UPDATE;
-                        size[req_buffers++] = sizeof(struct mdt_rec_join);
+                        size[DLM_INTENT_REC_OFF + 3] =
+                                                 sizeof(struct mdt_rec_join);
                         req = ptlrpc_prep_req(class_exp2cliimp(exp),
                                               LUSTRE_DLM_VERSION, LDLM_ENQUEUE,
-                                              req_buffers, size, NULL);
+                                              7, size, NULL);
                         /* when joining file, cb_data and lmm args together
                          * indicate the head file size*/
-                        mdc_join_pack(req, req_buffers - 1, op_data,
+                        mdc_join_pack(req, DLM_INTENT_REC_OFF + 3, op_data,
                                       (head_size << 32) | tsize);
                         cb_data = NULL;
                         lmm = NULL;
-                } else
+                } else {
                         req = ptlrpc_prep_req(class_exp2cliimp(exp),
                                               LUSTRE_DLM_VERSION, LDLM_ENQUEUE,
-                                              req_buffers, size, NULL);
+                                              6, size, NULL);
+                }
+
                 if (!req)
                         RETURN(-ENOMEM);
 
-                spin_lock_irqsave (&req->rq_lock, irqflags);
+                spin_lock(&req->rq_lock);
                 req->rq_replay = 1;
-                spin_unlock_irqrestore (&req->rq_lock, irqflags);
+                spin_unlock(&req->rq_lock);
 
                 /* pack the intent */
-                lit = lustre_msg_buf(req->rq_reqmsg, MDS_REQ_INTENT_IT_OFF,
-                                     sizeof (*lit));
+                lit = lustre_msg_buf(req->rq_reqmsg, DLM_INTENT_IT_OFF,
+                                     sizeof(*lit));
                 lit->opc = (__u64)it->it_op;
 
                 /* pack the intended request */
-                mdc_open_pack(req, MDS_REQ_INTENT_REC_OFF, op_data,
-                              it->it_create_mode, 0,
-                              it->it_flags, lmm, lmmsize);
+                mdc_open_pack(req, DLM_INTENT_REC_OFF, op_data, 
+                              it->it_create_mode, 0, it->it_flags, 
+                              lmm, lmmsize);
 
                 repsize[repbufcnt++] = LUSTRE_POSIX_ACL_MAX_SIZE;
         } else if (it->it_op & IT_UNLINK) {
-                size[req_buffers++] = sizeof(struct mdt_rec_unlink);
-                size[req_buffers++] = op_data->namelen + 1;
+                size[DLM_INTENT_REC_OFF] = sizeof(struct mdt_rec_unlink);
+                size[DLM_INTENT_REC_OFF + 1] = op_data->namelen + 1;
                 policy.l_inodebits.bits = MDS_INODELOCK_UPDATE;
                 req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_DLM_VERSION,
-                                      LDLM_ENQUEUE, req_buffers, size, NULL);
+                                      LDLM_ENQUEUE, 5, size, NULL);
                 if (!req)
                         RETURN(-ENOMEM);
 
                 /* pack the intent */
-                lit = lustre_msg_buf(req->rq_reqmsg, MDS_REQ_INTENT_IT_OFF,
-                                     sizeof (*lit));
+                lit = lustre_msg_buf(req->rq_reqmsg, DLM_INTENT_IT_OFF,
+                                     sizeof(*lit));
                 lit->opc = (__u64)it->it_op;
 
                 /* pack the intended request */
-                mdc_unlink_pack(req, MDS_REQ_INTENT_REC_OFF, op_data);
-                /* get ready for the reply */
+                mdc_unlink_pack(req, DLM_INTENT_REC_OFF, op_data);
+
                 repsize[repbufcnt++] = obddev->u.cli.cl_max_mds_cookiesize;
         } else if (it->it_op & (IT_GETATTR | IT_LOOKUP)) {
                 obd_valid valid = OBD_MD_FLGETATTR | OBD_MD_FLEASIZE |
                                   OBD_MD_FLACL | OBD_MD_FLMODEASIZE |
                                   OBD_MD_FLDIREA;
-                size[req_buffers++] = sizeof(struct mdt_body);
-                size[req_buffers++] = op_data->namelen + 1;
+                size[DLM_INTENT_REC_OFF] = sizeof(struct mdt_body);
+                size[DLM_INTENT_REC_OFF + 1] = op_data->namelen + 1;
 
                 if (it->it_op & IT_GETATTR)
                         policy.l_inodebits.bits = MDS_INODELOCK_UPDATE;
 
                 req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_DLM_VERSION,
-                                      LDLM_ENQUEUE, req_buffers, size, NULL);
+                                      LDLM_ENQUEUE, 5, size, NULL);
                 if (!req)
                         RETURN(-ENOMEM);
 
                 /* pack the intent */
-                lit = lustre_msg_buf(req->rq_reqmsg, MDS_REQ_INTENT_IT_OFF,
-                                     sizeof (*lit));
+                lit = lustre_msg_buf(req->rq_reqmsg, DLM_INTENT_IT_OFF,
+                                     sizeof(*lit));
                 lit->opc = (__u64)it->it_op;
 
                 /* pack the intended request */
-                mdc_getattr_pack(req, MDS_REQ_INTENT_REC_OFF, valid,
+                mdc_getattr_pack(req, DLM_INTENT_REC_OFF, valid,
                                  it->it_flags, op_data);
-                /* get ready for the reply */
+
                 repsize[repbufcnt++] = LUSTRE_POSIX_ACL_MAX_SIZE;
         } else if (it->it_op == IT_READDIR) {
                 policy.l_inodebits.bits = MDS_INODELOCK_UPDATE;
                 req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_DLM_VERSION,
-                                      LDLM_ENQUEUE, 1, size, NULL);
+                                      LDLM_ENQUEUE, 2, size, NULL);
                 if (!req)
                         RETURN(-ENOMEM);
 
-                /* get ready for the reply */
-                repbufcnt = 1;
+                repbufcnt = 2;
         } else {
                 LBUG();
                 RETURN(-EINVAL);
         }
 
-        req->rq_replen = lustre_msg_size(repbufcnt, repsize);
+        /* get ready for the reply */
+        ptlrpc_req_set_repsize(req, repbufcnt, repsize);
 
+         /* It is important to obtain rpc_lock first (if applicable), so that
+          * threads that are serialised with rpc_lock are not polluting our
+          * rpcs in flight counter */
         mdc_get_rpc_lock(obddev->u.cli.cl_rpc_lock, it);
-        rc = ldlm_cli_enqueue(exp, req, obddev->obd_namespace, res_id,
-                              lock_type, &policy,lock_mode, &flags, cb_blocking,
-                              cb_completion, NULL, cb_data, NULL, 0, NULL,
-                              lockh);
+        mdc_enter_request(&obddev->u.cli);
+        rc = ldlm_cli_enqueue(exp, &req, res_id, lock_type, &policy,
+                              lock_mode, &flags, cb_blocking, cb_completion,
+                              NULL, cb_data, NULL, 0, NULL, lockh, 0);
+        mdc_exit_request(&obddev->u.cli);
         mdc_put_rpc_lock(obddev->u.cli.cl_rpc_lock, it);
 
         /* Similarly, if we're going to replay this request, we don't want to
          * actually get a lock, just perform the intent. */
         if (req->rq_transno || req->rq_replay) {
-                lockreq = lustre_msg_buf(req->rq_reqmsg,
-                                         MDS_REQ_INTENT_LOCKREQ_OFF,
+                lockreq = lustre_msg_buf(req->rq_reqmsg, DLM_LOCKREQ_OFF,
                                          sizeof(*lockreq));
                 lockreq->lock_flags |= LDLM_FL_INTENT_ONLY;
         }
@@ -463,12 +472,13 @@ int mdc_enqueue(struct obd_export *exp,
                 LDLM_LOCK_PUT(lock);
         }
 
-        dlm_rep = lustre_msg_buf(req->rq_repmsg, 0, sizeof (*dlm_rep));
-        LASSERT(dlm_rep != NULL);           /* checked by ldlm_cli_enqueue() */
-        LASSERT_REPSWABBED(req, 0);         /* swabbed by ldlm_cli_enqueue() */
+        lockrep = lustre_msg_buf(req->rq_repmsg, DLM_LOCKREPLY_OFF,
+                                 sizeof(*lockrep));
+        LASSERT(lockrep != NULL);                 /* checked by ldlm_cli_enqueue() */
+        LASSERT_REPSWABBED(req, DLM_LOCKREPLY_OFF); /* swabbed by ldlm_cli_enqueue() */
 
-        it->d.lustre.it_disposition = (int) dlm_rep->lock_policy_res1;
-        it->d.lustre.it_status = (int) dlm_rep->lock_policy_res2;
+        it->d.lustre.it_disposition = (int)lockrep->lock_policy_res1;
+        it->d.lustre.it_status = (int)lockrep->lock_policy_res2;
         it->d.lustre.it_lock_mode = lock_mode;
         it->d.lustre.it_data = req;
 
@@ -479,22 +489,30 @@ int mdc_enqueue(struct obd_export *exp,
                   it->it_op,it->d.lustre.it_disposition,it->d.lustre.it_status);
 
         /* We know what to expect, so we do any byte flipping required here */
-        LASSERT(repbufcnt == 4 || repbufcnt == 1);
-        if (repbufcnt == 4) {
+        LASSERT(repbufcnt == 5 || repbufcnt == 2);
+        if (repbufcnt == 5) {
                 struct mdt_body *body;
 
-                body = lustre_swab_repbuf(req, 1, sizeof (*body),
-                                          lustre_swab_mdt_body);
+                body = lustre_swab_repbuf(req, DLM_REPLY_REC_OFF, sizeof(*body),
+                                         lustre_swab_mdt_body);
                 if (body == NULL) {
                         CERROR ("Can't swab mdt_body\n");
                         RETURN (-EPROTO);
                 }
 
+                /* If this is a successful OPEN request, we need to set
+                   replay handler and data early, so that if replay happens
+                   immediately after swabbing below, new reply is swabbed
+                   by that handler correctly */
+                if (it_disposition(it, DISP_OPEN_OPEN) &&
+                    !it_open_error(DISP_OPEN_OPEN, it))
+                        mdc_set_open_replay_data(NULL, NULL, req);
+
                 if ((body->valid & OBD_MD_FLEASIZE) != 0) {
                         /* The eadata is opaque; just check that it is there.
                          * Eventually, obd_unpackmd() will check the contents */
-                        eadata = lustre_swab_repbuf(req, 2, body->eadatasize,
-                                                    NULL);
+                        eadata = lustre_swab_repbuf(req, DLM_REPLY_REC_OFF + 1,
+                                                    body->eadatasize, NULL);
                         if (eadata == NULL) {
                                 CERROR ("Missing/short eadata\n");
                                 RETURN (-EPROTO);
@@ -520,13 +538,13 @@ int mdc_enqueue(struct obd_export *exp,
                          * large enough request buffer above we need to
                          * reallocate it here to hold the actual LOV EA. */
                         if (it->it_op & IT_OPEN) {
-                                int pos = MDS_REQ_INTENT_REC_OFF + 2;
+                                int offset = DLM_INTENT_REC_OFF + 2;
 
-                                if (req->rq_reqmsg->buflens[pos] <
+                                if (lustre_msg_buflen(req->rq_reqmsg, offset) <
                                     body->eadatasize)
                                         mdc_realloc_openmsg(req, body, size);
 
-                                lmm = lustre_msg_buf(req->rq_reqmsg, pos,
+                                lmm = lustre_msg_buf(req->rq_reqmsg, offset,
                                                      body->eadatasize);
                                 if (lmm)
                                         memcpy(lmm, eadata, body->eadatasize);
@@ -595,8 +613,13 @@ int mdc_intent_lock(struct obd_export *exp, struct md_op_data *op_data,
                 ldlm_policy_data_t policy;
                 int mode = LCK_CR;
 
+                /* As not all attributes are kept under update lock, e.g. 
+                   owner/group/acls are under lookup lock, we need both 
+                   ibits for GETATTR. */
                 policy.l_inodebits.bits = (it->it_op == IT_GETATTR) ?
-                                MDS_INODELOCK_UPDATE : MDS_INODELOCK_LOOKUP;
+                        MDS_INODELOCK_UPDATE | MDS_INODELOCK_LOOKUP :
+                        MDS_INODELOCK_LOOKUP;
+
                 rc = ldlm_lock_match(exp->exp_obd->obd_namespace,
                                      LDLM_FL_BLOCK_GRANTED, &res_id,
                                      LDLM_IBITS, &policy, LCK_CR, &lockh);
@@ -604,20 +627,22 @@ int mdc_intent_lock(struct obd_export *exp, struct md_op_data *op_data,
                         mode = LCK_CW;
                         rc = ldlm_lock_match(exp->exp_obd->obd_namespace,
                                              LDLM_FL_BLOCK_GRANTED, &res_id,
-                                             LDLM_IBITS, &policy, LCK_CW, &lockh);
+                                             LDLM_IBITS, &policy,LCK_CW,&lockh);
                 }
                 if (!rc) {
                         mode = LCK_PR;
                         rc = ldlm_lock_match(exp->exp_obd->obd_namespace,
                                              LDLM_FL_BLOCK_GRANTED, &res_id,
-                                             LDLM_IBITS, &policy, LCK_PR, &lockh);
+                                             LDLM_IBITS, &policy,LCK_PR,&lockh);
                 }
                 if (rc) {
                         memcpy(&it->d.lustre.it_lock_handle, &lockh,
                                sizeof(lockh));
                         it->d.lustre.it_lock_mode = mode;
                 }
-        
+
+                /* Only return failure if it was not GETATTR by cfid
+                   (from inode_revalidate) */
                 if (rc || op_data->namelen != 0)
                         RETURN(rc);
         }
@@ -671,8 +696,9 @@ int mdc_intent_lock(struct obd_export *exp, struct md_op_data *op_data,
         if (rc)
                 RETURN(rc);
 
-        mdt_body = lustre_msg_buf(request->rq_repmsg, 1, sizeof(*mdt_body));
-        LASSERT(mdt_body != NULL);           /* mdc_enqueue checked */
+        mdt_body = lustre_msg_buf(request->rq_repmsg, DLM_REPLY_REC_OFF,
+                                  sizeof(*mdt_body));
+        LASSERT(mdt_body != NULL);      /* mdc_enqueue checked */
         LASSERT_REPSWABBED(request, 1); /* mdc_enqueue swabbed */
 
         /* If we were revalidating a fid/name pair, mark the intent in
@@ -694,12 +720,18 @@ int mdc_intent_lock(struct obd_export *exp, struct md_op_data *op_data,
         /* keep requests around for the multiple phases of the call
          * this shows the DISP_XX must guarantee we make it into the call
          */
-        if (it_disposition(it, DISP_OPEN_CREATE) &&
-            !it_open_error(DISP_OPEN_CREATE, it))
+        if (!it_disposition(it, DISP_ENQ_CREATE_REF) &&
+            it_disposition(it, DISP_OPEN_CREATE) &&
+            !it_open_error(DISP_OPEN_CREATE, it)) {
+                it_set_disposition(it, DISP_ENQ_CREATE_REF);
                 ptlrpc_request_addref(request); /* balanced in ll_create_node */
-        if (it_disposition(it, DISP_OPEN_OPEN) &&
-            !it_open_error(DISP_OPEN_OPEN, it))
+        }
+        if (!it_disposition(it, DISP_ENQ_OPEN_REF) &&
+            it_disposition(it, DISP_OPEN_OPEN) &&
+            !it_open_error(DISP_OPEN_OPEN, it)) {
+                it_set_disposition(it, DISP_ENQ_OPEN_REF);
                 ptlrpc_request_addref(request); /* balanced in ll_file_open */
+        }
 
         if (it->it_op & IT_CREAT) {
                 /* XXX this belongs in ll_create_it */
index e0ec343..45cd1eb 100644 (file)
@@ -51,9 +51,10 @@ static int mdc_reint(struct ptlrpc_request *request,
         mdc_put_rpc_lock(rpc_lock, NULL);
         if (rc)
                 CDEBUG(D_INFO, "error in handling %d\n", rc);
-        else if (!lustre_swab_repbuf(request, 0, sizeof(struct mdt_body),
+        else if (!lustre_swab_repbuf(request, REPLY_REC_OFF,
+                                     sizeof(struct mdt_body),
                                      lustre_swab_mdt_body)) {
-                CERROR ("Can't unpack mdt_body\n");
+                CERROR ("Can't unpack mds_body\n");
                 rc = -EPROTO;
         }
         return rc;
@@ -73,8 +74,9 @@ int mdc_setattr(struct obd_export *exp, struct md_op_data *op_data,
         struct mdt_rec_setattr *rec;
         struct mdc_rpc_lock *rpc_lock;
         struct obd_device *obd = exp->exp_obd;
-        int size[] = { sizeof(*rec), ealen, ea2len};
-        int rc, bufcount = 1;
+        int size[4] = { sizeof(struct ptlrpc_body),
+                        sizeof(*rec), ealen, ea2len };
+        int bufcount = 2, rc;
         ENTRY;
 
         LASSERT(iattr != NULL);
@@ -100,10 +102,10 @@ int mdc_setattr(struct obd_export *exp, struct md_op_data *op_data,
         if (iattr->ia_valid & (ATTR_MTIME | ATTR_CTIME))
                 CDEBUG(D_INODE, "setting mtime %lu, ctime %lu\n",
                        LTIME_S(iattr->ia_mtime), LTIME_S(iattr->ia_ctime));
-        mdc_setattr_pack(req, MDS_REQ_REC_OFF, op_data, iattr, ea, ealen, ea2, ea2len);
+        mdc_setattr_pack(req, REQ_REC_OFF, op_data, iattr, ea, ealen, ea2, ea2len);
 
-        size[0] = sizeof(struct mdt_body);
-        req->rq_replen = lustre_msg_size(1, size);
+        size[REPLY_REC_OFF] = sizeof(struct mdt_body);
+        ptlrpc_req_set_repsize(req, 2, size);
 
         rc = mdc_reint(req, rpc_lock, LUSTRE_IMP_FULL);
         *request = req;
@@ -119,8 +121,10 @@ int mdc_create(struct obd_export *exp, struct md_op_data *op_data,
 {
         struct obd_device *obd = exp->exp_obd;
         struct ptlrpc_request *req;
-        int size[] = { sizeof(struct mdt_rec_create), op_data->namelen + 1, 0};
-        int rc, level, bufcount = 2;
+        int level, bufcount = 3, rc;
+        int size[4] = { sizeof(struct ptlrpc_body),
+                        sizeof(struct mdt_rec_create),
+                        op_data->namelen + 1 };
         ENTRY;
 
         if (data && datalen) {
@@ -135,11 +139,11 @@ int mdc_create(struct obd_export *exp, struct md_op_data *op_data,
 
         /* mdc_create_pack fills msg->bufs[1] with name
          * and msg->bufs[2] with tgt, for symlinks or lov MD data */
-        mdc_create_pack(req, MDS_REQ_REC_OFF, op_data, data, datalen, mode,
-                        uid, gid, cap_effective, rdev);
+        mdc_create_pack(req, REQ_REC_OFF, op_data, data, datalen, mode, uid,
+                        gid, cap_effective, rdev);
 
-        size[0] = sizeof(struct mdt_body);
-        req->rq_replen = lustre_msg_size(1, size);
+        size[REPLY_REC_OFF] = sizeof(struct mdt_body);
+        ptlrpc_req_set_repsize(req, 2, size);
 
         level = LUSTRE_IMP_FULL;
  resend:
@@ -159,22 +163,25 @@ int mdc_unlink(struct obd_export *exp, struct md_op_data *op_data,
 {
         struct obd_device *obd = class_exp2obd(exp);
         struct ptlrpc_request *req = *request;
-        int rc, size[] = { sizeof(struct mdt_rec_unlink), op_data->namelen + 1};
+        int size[4] = { sizeof(struct ptlrpc_body),
+                        sizeof(struct mdt_rec_unlink),
+                        op_data->namelen + 1 };
+        int rc;
         ENTRY;
 
         LASSERT(req == NULL);
         req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_MDS_VERSION,
-                              MDS_REINT, 2, size, NULL);
+                              MDS_REINT, 3, size, NULL);
         if (req == NULL)
                 RETURN(-ENOMEM);
         *request = req;
 
-        size[0] = sizeof(struct mdt_body);
-        size[1] = obd->u.cli.cl_max_mds_easize;
-        size[2] = obd->u.cli.cl_max_mds_cookiesize;
-        req->rq_replen = lustre_msg_size(3, size);
+        size[REPLY_REC_OFF] = sizeof(struct mdt_body);
+        size[REPLY_REC_OFF + 1] = obd->u.cli.cl_max_mds_easize;
+        size[REPLY_REC_OFF + 2] = obd->u.cli.cl_max_mds_cookiesize;
+        ptlrpc_req_set_repsize(req, 4, size);
 
-        mdc_unlink_pack(req, MDS_REQ_REC_OFF, op_data);
+        mdc_unlink_pack(req, REQ_REC_OFF, op_data);
 
         rc = mdc_reint(req, obd->u.cli.cl_rpc_lock, LUSTRE_IMP_FULL);
         if (rc == -ERESTARTSYS)
@@ -187,18 +194,21 @@ int mdc_link(struct obd_export *exp, struct md_op_data *op_data,
 {
         struct obd_device *obd = exp->exp_obd;
         struct ptlrpc_request *req;
-        int rc, size[] = { sizeof(struct mdt_rec_link), op_data->namelen + 1};
+        int size[3] = { sizeof(struct ptlrpc_body),
+                        sizeof(struct mdt_rec_link),
+                        op_data->namelen + 1 };
+        int rc;
         ENTRY;
 
         req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_MDS_VERSION,
-                              MDS_REINT, 2, size, NULL);
+                              MDS_REINT, 3, size, NULL);
         if (req == NULL)
                 RETURN(-ENOMEM);
 
-        mdc_link_pack(req, MDS_REQ_REC_OFF, op_data);
+        mdc_link_pack(req, REQ_REC_OFF, op_data);
 
-        size[0] = sizeof(struct mdt_body);
-        req->rq_replen = lustre_msg_size(1, size);
+        size[REPLY_REC_OFF] = sizeof(struct mdt_body);
+        ptlrpc_req_set_repsize(req, 2, size);
 
         rc = mdc_reint(req, obd->u.cli.cl_rpc_lock, LUSTRE_IMP_FULL);
         *request = req;
@@ -214,20 +224,23 @@ int mdc_rename(struct obd_export *exp, struct md_op_data *op_data,
 {
         struct obd_device *obd = exp->exp_obd;
         struct ptlrpc_request *req;
-        int rc, size[] = { sizeof(struct mdt_rec_rename), oldlen +1, newlen +1};
+        int size[4] = { sizeof(struct ptlrpc_body),
+                        sizeof(struct mdt_rec_rename),
+                        oldlen + 1, newlen + 1 };
+        int rc;
         ENTRY;
 
         req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_MDS_VERSION,
-                              MDS_REINT, 3, size, NULL);
+                              MDS_REINT, 4, size, NULL);
         if (req == NULL)
                 RETURN(-ENOMEM);
 
-        mdc_rename_pack(req, MDS_REQ_REC_OFF, op_data, old, oldlen, new, newlen);
+        mdc_rename_pack(req, REQ_REC_OFF, op_data, old, oldlen, new, newlen);
 
-        size[0] = sizeof(struct mdt_body);
-        size[1] = obd->u.cli.cl_max_mds_easize;
-        size[2] = obd->u.cli.cl_max_mds_cookiesize;
-        req->rq_replen = lustre_msg_size(3, size);
+        size[REPLY_REC_OFF] = sizeof(struct mdt_body);
+        size[REPLY_REC_OFF + 1] = obd->u.cli.cl_max_mds_easize;
+        size[REPLY_REC_OFF + 2] = obd->u.cli.cl_max_mds_cookiesize;
+        ptlrpc_req_set_repsize(req, 4, size);
 
         rc = mdc_reint(req, obd->u.cli.cl_rpc_lock, LUSTRE_IMP_FULL);
         *request = req;
index 74cf5a5..c0b0ac3 100644 (file)
@@ -42,6 +42,7 @@
 #include <lustre_fid.h>
 #include <md_object.h>
 #include <lprocfs_status.h>
+#include <lustre_param.h>
 #include "mdc_internal.h"
 
 static quota_interface_t *quota_interface;
@@ -57,37 +58,37 @@ static int send_getstatus(struct obd_import *imp, struct lu_fid *rootfid,
                           int level, int msg_flags)
 {
         struct ptlrpc_request *req;
-        int rc, size[] = { [MDS_REQ_REC_OFF] = sizeof(struct mdt_body) };
+        struct mdt_body *body;
+        int rc, size[2] = { sizeof(struct ptlrpc_body), sizeof(*body) };
         ENTRY;
 
-        req = ptlrpc_prep_req(imp, LUSTRE_MDS_VERSION, MDS_GETSTATUS,
-                              1, size, NULL);
+        req = ptlrpc_prep_req(imp, LUSTRE_MDS_VERSION, MDS_GETSTATUS, 2, size,
+                              NULL);
         if (!req)
                 GOTO(out, rc = -ENOMEM);
 
         req->rq_send_state = level;
-        req->rq_replen = lustre_msg_size(1, size);
+        ptlrpc_req_set_repsize(req, 2, size);
 
-        mdc_pack_req_body(req, MDS_REQ_REC_OFF, 0, NULL, 0);
-        req->rq_reqmsg->flags |= msg_flags;
+        mdc_pack_req_body(req, REQ_REC_OFF, 0, NULL, 0, 0);
+        lustre_msg_add_flags(req->rq_reqmsg, msg_flags);
         rc = ptlrpc_queue_wait(req);
 
         if (!rc) {
-                struct mdt_body *body;
-
-                body = lustre_swab_repbuf(req, 0, sizeof(*body),
+                body = lustre_swab_repbuf(req, REPLY_REC_OFF, sizeof(*body),
                                           lustre_swab_mdt_body);
                 if (body == NULL) {
                         CERROR ("Can't extract mdt_body\n");
                         GOTO (out, rc = -EPROTO);
                 }
 
-                memcpy(rootfid, &body->fid1, sizeof(*rootfid));
+                *rootfid = body->fid1;
 
                 CDEBUG(D_NET, "root fid="DFID", last_committed="LPU64
                        ", last_xid="LPU64"\n",
-                       PFID(rootfid), req->rq_repmsg->last_committed,
-                       req->rq_repmsg->last_xid);
+                       PFID(rootfid),
+                       lustre_msg_get_last_committed(req->rq_repmsg),
+                       lustre_msg_get_last_xid(req->rq_repmsg));
         }
 
         EXIT;
@@ -108,35 +109,30 @@ int mdc_getattr_common(struct obd_export *exp, unsigned int ea_size,
                        unsigned int acl_size, struct ptlrpc_request *req)
 {
         struct mdt_body *body;
-        void            *eadata;
-        int              rc;
-        int              size[3] = {sizeof(*body)};
-        int              bufcount = 3, offset = 1;
+        void *eadata;
+        int size[4] = { sizeof(struct ptlrpc_body), sizeof(*body) };
+        int bufcount = 2, rc;
         ENTRY;
         
         /* request message already built */
         if (ea_size != 0) {
-                size[offset++] = ea_size;
+                size[bufcount++] = ea_size;
                 CDEBUG(D_INODE, "reserved %u bytes for MD/symlink in packet\n",
                        ea_size);
         }
         if (acl_size) {
-                size[offset++] = acl_size;
+                size[bufcount++] = acl_size;
                 CDEBUG(D_INODE, "reserved %u bytes for ACL\n", acl_size);
         }
-        /*For new req layout, different bufcount will cause different 
-         *replen, so we should make client/server has same bufcount,
-         *so we set bufcount to 3 here, although some msg size might be 0*/
-        req->rq_replen = lustre_msg_size(bufcount, size);
 
-        mdc_get_rpc_lock(exp->exp_obd->u.cli.cl_rpc_lock, NULL);
+        ptlrpc_req_set_repsize(req, bufcount, size);
+
         rc = ptlrpc_queue_wait(req);
-        mdc_put_rpc_lock(exp->exp_obd->u.cli.cl_rpc_lock, NULL);
         if (rc != 0)
                 RETURN (rc);
 
-        body = lustre_swab_repbuf (req, 0, sizeof (*body),
-                                   lustre_swab_mdt_body);
+        body = lustre_swab_repbuf(req, REPLY_REC_OFF, sizeof(*body),
+                                  lustre_swab_mdt_body);
         if (body == NULL) {
                 CERROR ("Can't unpack mdt_body\n");
                 RETURN (-EPROTO);
@@ -144,10 +140,11 @@ int mdc_getattr_common(struct obd_export *exp, unsigned int ea_size,
 
         CDEBUG(D_NET, "mode: %o\n", body->mode);
 
-        LASSERT_REPSWAB (req, 1);
+        LASSERT_REPSWAB(req, REPLY_REC_OFF + 1);
         if (body->eadatasize != 0) {
                 /* reply indicates presence of eadata; check it's there... */
-                eadata = lustre_msg_buf (req->rq_repmsg, 1, body->eadatasize);
+                eadata = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF + 1,
+                                        body->eadatasize);
                 if (eadata == NULL) {
                         CERROR ("Missing/short eadata\n");
                         RETURN (-EPROTO);
@@ -172,8 +169,7 @@ int mdc_getattr(struct obd_export *exp, struct lu_fid *fid,
                 struct ptlrpc_request **request)
 {
         struct ptlrpc_request *req;
-        struct mdt_body *body;
-        int size = sizeof(*body);
+        int size[2] = { sizeof(struct ptlrpc_body), sizeof(struct mdt_body) };
         int acl_size = 0, rc;
         ENTRY;
 
@@ -181,11 +177,12 @@ int mdc_getattr(struct obd_export *exp, struct lu_fid *fid,
          *     to do the lookup in the first place.
          */
         req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_MDS_VERSION,
-                              MDS_GETATTR, 1, &size, NULL);
+                              MDS_GETATTR, 2, size, NULL);
         if (!req)
                 GOTO(out, rc = -ENOMEM);
 
-        mdc_pack_req_body(req, MDS_REQ_REC_OFF, valid, fid, ea_size);
+        mdc_pack_req_body(req, REQ_REC_OFF, valid, fid, ea_size,
+                          MDS_BFLAG_EXT_FLAGS/*request "new" flags(bug 9486)*/);
 
         /* currently only root inode will call us with FLACL */
 
@@ -209,23 +206,26 @@ int mdc_getattr(struct obd_export *exp, struct lu_fid *fid,
 
 int mdc_getattr_name(struct obd_export *exp, struct lu_fid *fid,
                      const char *filename, int namelen, obd_valid valid,
-                     int ea_len, struct ptlrpc_request **request)
+                     int ea_size, struct ptlrpc_request **request)
 {
         struct ptlrpc_request *req;
-        int rc, size[] = { sizeof(struct mdt_body), namelen };
+        struct mdt_body *body;
+        int rc, size[3] = { sizeof(struct ptlrpc_body), sizeof(*body), namelen};
         ENTRY;
 
         req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_MDS_VERSION,
-                              MDS_GETATTR_NAME, 2, size, NULL);
+                              MDS_GETATTR_NAME, 3, size, NULL);
         if (!req)
                 GOTO(out, rc = -ENOMEM);
 
-        mdc_pack_req_body(req, MDS_REQ_REC_OFF, valid, fid, ea_len);
-
-        LASSERT (strnlen (filename, namelen) == namelen - 1);
-        memcpy(lustre_msg_buf(req->rq_reqmsg, 1, namelen), filename, namelen);
+        mdc_pack_req_body(req, REQ_REC_OFF, valid, fid, ea_size,
+                          MDS_BFLAG_EXT_FLAGS/*request "new" flags(bug 9486)*/);
+        LASSERT(strnlen(filename, namelen) == namelen - 1);
+        memcpy(lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF + 1, namelen),
+               filename, namelen);
 
-        rc = mdc_getattr_common(exp, ea_len, 0, req);
+        rc = mdc_getattr_common(exp, ea_size, 0, req);
         if (rc != 0) {
                 ptlrpc_req_finished (req);
                 req = NULL;
@@ -242,9 +242,9 @@ int mdc_xattr_common(struct obd_export *exp, struct lu_fid *fid,
                      int flags, struct ptlrpc_request **request)
 {
         struct ptlrpc_request *req;
-        struct mdt_body *body;
-        int size[3] = {sizeof(*body)}, bufcnt = 1, offset;
-        int xattr_namelen = 0, rc;
+        int size[4] = { sizeof(struct ptlrpc_body), sizeof(struct mdt_body) };
+        // int size[3] = {sizeof(struct mdt_body)}, bufcnt = 1;
+        int rc, xattr_namelen = 0, bufcnt = 2, offset;
         void *tmp;
         ENTRY;
 
@@ -257,38 +257,36 @@ int mdc_xattr_common(struct obd_export *exp, struct lu_fid *fid,
                 size[bufcnt++] = input_size;
         }
 
-        req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_MDS_VERSION, opcode,
-                              bufcnt, size, NULL);
+        req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_MDS_VERSION,
+                              opcode, bufcnt, size, NULL);
         if (!req)
                 GOTO(out, rc = -ENOMEM);
 
         /* request data */
-        body = lustre_msg_buf(req->rq_reqmsg, MDS_REQ_REC_OFF, sizeof(*body));
-        mdc_pack_req_body(req, MDS_REQ_REC_OFF, valid, fid, output_size);
-        body->flags = flags;
+        mdc_pack_req_body(req, REQ_REC_OFF, valid, fid, output_size, flags);
+
+        offset = REQ_REC_OFF + 1;
 
         if (xattr_name) {
-                tmp = lustre_msg_buf(req->rq_reqmsg, 1, xattr_namelen);
+                tmp = lustre_msg_buf(req->rq_reqmsg, offset++, xattr_namelen);
                 memcpy(tmp, xattr_name, xattr_namelen);
         }
         if (input_size) {
-                tmp = lustre_msg_buf(req->rq_reqmsg, bufcnt - 1, input_size);
+                tmp = lustre_msg_buf(req->rq_reqmsg, offset++, input_size);
                 memcpy(tmp, input, input_size);
         }
 
         /* reply buffers */
         if (opcode == MDS_GETXATTR) {
-                size[0] = sizeof(*body);
+                size[REPLY_REC_OFF] = sizeof(struct mdt_body);
                 bufcnt = 2;
-                offset = 1;
         } else {
                 bufcnt = 1;
-                offset = 0;
         }
 
-        if (output_size)
-                size[offset++] = output_size;
-        req->rq_replen = lustre_msg_size(bufcnt, size);
+        /* we do this even output_size is 0, because server is doing that */
+        size[bufcnt++] = output_size;
+        ptlrpc_req_set_repsize(req, bufcnt, size);
 
         /* make rpc */
         if (opcode == MDS_SETXATTR)
@@ -303,8 +301,8 @@ int mdc_xattr_common(struct obd_export *exp, struct lu_fid *fid,
                 GOTO(err_out, rc);
 
         if (opcode == MDS_GETXATTR) {
-                body = lustre_swab_repbuf(req, 0, sizeof(*body),
-                                          lustre_swab_mdt_body);
+                struct mdt_body * body = lustre_swab_repbuf(req, REPLY_REC_OFF,
+                                          sizeof(*body), lustre_swab_mdt_body);
                 if (body == NULL) {
                         CERROR ("Can't unpack mdt_body\n");
                         GOTO(err_out, rc = -EPROTO);
@@ -354,9 +352,9 @@ int mdc_unpack_acl(struct obd_export *exp, struct ptlrpc_request *req,
         buf = lustre_msg_buf(req->rq_repmsg, offset, body->aclsize);
         if (!buf) {
                 CERROR("aclsize %u, bufcount %u, bufsize %u\n",
-                       body->aclsize, req->rq_repmsg->bufcount,
-                       (req->rq_repmsg->bufcount <= offset) ? -1 :
-                       req->rq_repmsg->buflens[offset]);
+                       body->aclsize, lustre_msg_bufcount(req->rq_repmsg),
+                       (lustre_msg_bufcount(req->rq_repmsg) <= offset) ?
+                                -1 : lustre_msg_buflen(req->rq_repmsg, offset));
                 return -EPROTO;
         }
 
@@ -392,7 +390,7 @@ int mdc_get_lustre_md(struct obd_export *exp, struct ptlrpc_request *req,
 
         md->body = lustre_msg_buf(req->rq_repmsg, offset, sizeof (*md->body));
         LASSERT (md->body != NULL);
-        LASSERT_REPSWABBED (req, offset);
+        LASSERT_REPSWABBED(req, offset);
         offset++;
 
         if (!(md->body->valid & OBD_MD_FLEASIZE) &&
@@ -412,7 +410,7 @@ int mdc_get_lustre_md(struct obd_export *exp, struct ptlrpc_request *req,
                 lmmsize = md->body->eadatasize;
                 lmm = lustre_msg_buf(req->rq_repmsg, offset, lmmsize);
                 LASSERT (lmm != NULL);
-                LASSERT_REPSWABBED (req, offset);
+                LASSERT_REPSWABBED(req, offset);
 
                 rc = obd_unpackmd(dt_exp, &md->lsm, lmm, lmmsize);
                 if (rc < 0)
@@ -486,7 +484,8 @@ static void mdc_replay_open(struct ptlrpc_request *req)
         struct mdt_body *body;
         ENTRY;
 
-        body = lustre_swab_repbuf(req, 1, sizeof(*body), lustre_swab_mdt_body);
+        body = lustre_swab_repbuf(req, DLM_REPLY_REC_OFF, sizeof(*body),
+                                  lustre_swab_mdt_body);
         LASSERT (body != NULL);
 
         if (mod == NULL) {
@@ -510,9 +509,8 @@ static void mdc_replay_open(struct ptlrpc_request *req)
         close_req = mod->mod_close_req;
         if (close_req != NULL) {
                 struct mdt_body *close_body;
-                LASSERT(close_req->rq_reqmsg->opc == MDS_CLOSE);
-                close_body = lustre_msg_buf(close_req->rq_reqmsg,
-                                            MDS_REQ_REC_OFF,
+                LASSERT(lustre_msg_get_opc(close_req->rq_reqmsg) == MDS_CLOSE);
+                close_body = lustre_msg_buf(close_req->rq_reqmsg, REQ_REC_OFF,
                                             sizeof(*close_body));
                 if (och != NULL)
                         LASSERT(!memcmp(&old, &close_body->handle, sizeof old));
@@ -530,32 +528,40 @@ int mdc_set_open_replay_data(struct obd_export *exp,
 {
         struct mdc_open_data *mod;
         struct mdt_rec_create *rec = lustre_msg_buf(open_req->rq_reqmsg,
-                                                    MDS_REQ_INTENT_REC_OFF,
+                                                    DLM_INTENT_REC_OFF,
                                                     sizeof(*rec));
-        struct mdt_body *body = lustre_msg_buf(open_req->rq_repmsg, 1,
+        struct mdt_body *body = lustre_msg_buf(open_req->rq_repmsg,
+                                               DLM_REPLY_REC_OFF,
                                                sizeof(*body));
         ENTRY;
 
-        LASSERT(body != NULL);
         /* incoming message in my byte order (it's been swabbed) */
         LASSERT(rec != NULL);
+        LASSERT_REPSWABBED(open_req, DLM_REPLY_REC_OFF);
         /* outgoing messages always in my byte order */
-        LASSERT_REPSWABBED(open_req, 1);
+        LASSERT(body != NULL);
 
-        OBD_ALLOC(mod, sizeof(*mod));
-        if (mod == NULL) {
-                DEBUG_REQ(D_ERROR, open_req, "can't allocate mdc_open_data");
-                RETURN(0);
-        }
+        if (och) {
+                OBD_ALLOC(mod, sizeof(*mod));
+                if (mod == NULL) {
+                        DEBUG_REQ(D_ERROR, open_req, "can't allocate mdc_open_data");
+                        RETURN(0);
+                }
 
-        och->och_mod = mod;
-        mod->mod_och = och;
-        mod->mod_open_req = open_req;
+                och->och_mod = mod;
+                mod->mod_och = och;
+                mod->mod_open_req = open_req;
+                open_req->rq_cb_data = mod;
+                open_req->rq_commit_cb = mdc_commit_open;
+        }
 
         rec->cr_fid2 = body->fid1;
         open_req->rq_replay_cb = mdc_replay_open;
-        open_req->rq_commit_cb = mdc_commit_open;
-        open_req->rq_cb_data = mod;
+        if (!fid_is_sane(&body->fid1)) {
+                DEBUG_REQ(D_ERROR, open_req, "saving replay request with "
+                          "insane fid");
+                LBUG();
+        }
 
         DEBUG_REQ(D_HA, open_req, "set up replay data");
         RETURN(0);
@@ -612,19 +618,27 @@ int mdc_close(struct obd_export *exp, struct md_op_data *op_data,
               struct obd_client_handle *och, struct ptlrpc_request **request)
 {
         struct obd_device *obd = class_exp2obd(exp);
-        int size[] = { sizeof(struct mdt_body) };
-        int rc, repsize[] = { sizeof(struct mdt_body),
-                              obd->u.cli.cl_max_mds_easize,
-                              obd->u.cli.cl_max_mds_cookiesize};
+        int reqsize[2] = { sizeof(struct ptlrpc_body),
+                           sizeof(struct mdt_body) };
+        int rc, repsize[4] = { sizeof(struct ptlrpc_body),
+                               sizeof(struct mdt_body),
+                               obd->u.cli.cl_max_mds_easize,
+                               obd->u.cli.cl_max_mds_cookiesize };
         struct ptlrpc_request *req;
         struct mdc_open_data *mod;
         ENTRY;
 
         req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_MDS_VERSION,
-                              MDS_CLOSE, 1, size, NULL);
+                              MDS_CLOSE, 2, reqsize, NULL);
         if (req == NULL)
                 GOTO(out, rc = -ENOMEM);
 
+        /* To avoid a livelock (bug 7034), we need to send CLOSE RPCs to a
+         * portal whose threads are not taking any DLM locks and are therefore
+         * always progressing */
+        /* XXX FIXME bug 249 */
+        req->rq_request_portal = MDS_READPAGE_PORTAL;
+
         /* Ensure that this close's handle is fixed up during replay. */
         LASSERT(och != NULL);
         LASSERT(och->och_magic == OBD_CLIENT_HANDLE_MAGIC);
@@ -645,16 +659,16 @@ int mdc_close(struct obd_export *exp, struct md_op_data *op_data,
                 CDEBUG(D_HA, "couldn't find open req; expecting close error\n");
         }
 
-        mdc_close_pack(req, MDS_REQ_REC_OFF, op_data, op_data->valid, och);
+        mdc_close_pack(req, REQ_REC_OFF, op_data, op_data->valid, och);
 
-        req->rq_replen = lustre_msg_size(3, repsize);
+        ptlrpc_req_set_repsize(req, 4, repsize);
         req->rq_commit_cb = mdc_commit_close;
         LASSERT(req->rq_cb_data == NULL);
         req->rq_cb_data = mod;
 
-        mdc_get_rpc_lock(obd->u.cli.cl_rpc_lock, NULL);
+        mdc_get_rpc_lock(obd->u.cli.cl_close_lock, NULL);
         rc = ptlrpc_queue_wait(req);
-        mdc_put_rpc_lock(obd->u.cli.cl_rpc_lock, NULL);
+        mdc_put_rpc_lock(obd->u.cli.cl_close_lock, NULL);
 
         if (req->rq_repmsg == NULL) {
                 CDEBUG(D_HA, "request failed to send: %p, %d\n", req,
@@ -662,8 +676,8 @@ int mdc_close(struct obd_export *exp, struct md_op_data *op_data,
                 if (rc == 0)
                         rc = req->rq_status ? req->rq_status : -EIO;
         } else if (rc == 0) {
-                rc = req->rq_repmsg->status;
-                if (req->rq_repmsg->type == PTL_RPC_MSG_ERR) {
+                rc = lustre_msg_get_status(req->rq_repmsg);
+                if (lustre_msg_get_type(req->rq_repmsg) == PTL_RPC_MSG_ERR) {
                         DEBUG_REQ(D_ERROR, req, "type == PTL_RPC_MSG_ERR, err "
                                   "= %d", rc);
                         if (rc > 0)
@@ -672,7 +686,8 @@ int mdc_close(struct obd_export *exp, struct md_op_data *op_data,
                         CERROR("Unexpected: can't find mdc_open_data, but the "
                                "close succeeded.  Please tell CFS.\n");
                 }
-                if (!lustre_swab_repbuf(req, 0, sizeof(struct mdt_body),
+                if (!lustre_swab_repbuf(req, REPLY_REC_OFF,
+                                        sizeof(struct mdt_body),
                                         lustre_swab_mdt_body)) {
                         CERROR("Error unpacking mdt_body\n");
                         rc = -EPROTO;
@@ -692,22 +707,22 @@ int mdc_done_writing(struct obd_export *exp, struct md_op_data *op_data)
 {
         struct ptlrpc_request *req;
         struct mdt_body *body;
-        int rc, size[] = { [MDS_REQ_REC_OFF] = sizeof(*body) };
+        int rc, size[2] = { sizeof(struct ptlrpc_body), sizeof(*body) };
         ENTRY;
 
         req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_MDS_VERSION,
-                              MDS_DONE_WRITING, 1, size, NULL);
+                              MDS_DONE_WRITING, 2, size, NULL);
         if (req == NULL)
                 RETURN(-ENOMEM);
 
-        body = lustre_msg_buf(req->rq_reqmsg, MDS_REQ_REC_OFF, sizeof(*body));
+        body = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, sizeof(*body));
         body->fid1 = op_data->fid1;
         body->size = op_data->size;
         body->blocks = op_data->blocks;
         body->flags = op_data->flags;
         body->valid = op_data->valid;
 
-        req->rq_replen = lustre_msg_size(1, size);
+        ptlrpc_req_set_repsize(req, 2, size);
 
         rc = ptlrpc_queue_wait(req);
         ptlrpc_req_finished(req);
@@ -721,13 +736,13 @@ int mdc_readpage(struct obd_export *exp, struct lu_fid *fid, __u64 offset,
         struct ptlrpc_request *req = NULL;
         struct ptlrpc_bulk_desc *desc = NULL;
         struct mdt_body *body;
-        int rc, size[] = { sizeof(*body) };
+        int rc, size[2] = { sizeof(struct ptlrpc_body), sizeof(*body) };
         ENTRY;
 
         CDEBUG(D_INODE, "object: "DFID"\n", PFID(fid));
 
-        req = ptlrpc_prep_req(imp, LUSTRE_MDS_VERSION, MDS_READPAGE,
-                              1, size, NULL);
+        req = ptlrpc_prep_req(imp, LUSTRE_MDS_VERSION, MDS_READPAGE, 2, size,
+                              NULL);
         if (req == NULL)
                 GOTO(out, rc = -ENOMEM);
 
@@ -741,13 +756,13 @@ int mdc_readpage(struct obd_export *exp, struct lu_fid *fid, __u64 offset,
 
         ptlrpc_prep_bulk_page(desc, page, 0, PAGE_CACHE_SIZE);
 
-        mdc_readdir_pack(req, MDS_REQ_REC_OFF, offset, PAGE_CACHE_SIZE, fid);
+        mdc_readdir_pack(req, REQ_REC_OFF, offset, PAGE_CACHE_SIZE, fid);
 
-        req->rq_replen = lustre_msg_size(1, size);
+        ptlrpc_req_set_repsize(req, 2, size);
         rc = ptlrpc_queue_wait(req);
 
         if (rc == 0) {
-                body = lustre_swab_repbuf(req, 0, sizeof (*body),
+                body = lustre_swab_repbuf(req, REPLY_REC_OFF, sizeof(*body),
                                           lustre_swab_mdt_body);
                 if (body == NULL) {
                         CERROR("Can't unpack mdt_body\n");
@@ -857,26 +872,28 @@ int mdc_set_info_async(struct obd_export *exp, obd_count keylen,
         }
         if (KEY_IS("read-only")) {
                 struct ptlrpc_request *req;
-                int size[2] = {keylen, vallen};
-                char *bufs[2] = {key, val};
+                int size[3] = { sizeof(struct ptlrpc_body), keylen, vallen };
+                char *bufs[3] = { NULL, key, val };
 
                 if (vallen != sizeof(int))
                         RETURN(-EINVAL);
 
                 if (*((int *)val)) {
+                        imp->imp_connect_flags_orig |= OBD_CONNECT_RDONLY;
                         imp->imp_connect_data.ocd_connect_flags |=
                                 OBD_CONNECT_RDONLY;
                 } else {
+                        imp->imp_connect_flags_orig &= ~OBD_CONNECT_RDONLY;
                         imp->imp_connect_data.ocd_connect_flags &=
                                 ~OBD_CONNECT_RDONLY;
                 }
 
-                req = ptlrpc_prep_req(imp, LUSTRE_MDS_VERSION,
-                                      MDS_SET_INFO, 2, size, bufs);
+                req = ptlrpc_prep_req(imp, LUSTRE_MDS_VERSION, MDS_SET_INFO,
+                                      3, size, bufs);
                 if (req == NULL)
                         RETURN(-ENOMEM);
 
-                req->rq_replen = lustre_msg_size(0, NULL);
+                ptlrpc_req_set_repsize(req, 1, NULL);
                 if (set) {
                         rc = 0;
                         ptlrpc_set_add_req(set, req);
@@ -885,17 +902,40 @@ int mdc_set_info_async(struct obd_export *exp, obd_count keylen,
                         rc = ptlrpc_queue_wait(req);
                         ptlrpc_req_finished(req);
                 }
+
                 RETURN(rc);
         }
+
+        RETURN(rc);
+}
+
+int mdc_get_info(struct obd_export *exp, __u32 keylen, void *key,
+                 __u32 *vallen, void *val)
+{
+        int rc = -EINVAL;
+
+        if (keylen == strlen("max_easize") &&
+            memcmp(key, "max_easize", strlen("max_easize")) == 0) {
+                int mdsize, *max_easize;
+
+                if (*vallen != sizeof(int))
+                        RETURN(-EINVAL);
+                mdsize = *(int*)val;
+                if (mdsize > exp->exp_obd->u.cli.cl_max_mds_easize)
+                        exp->exp_obd->u.cli.cl_max_mds_easize = mdsize;
+                max_easize = val;
+                *max_easize = exp->exp_obd->u.cli.cl_max_mds_easize;
+                RETURN(0);
+        }
         RETURN(rc);
 }
 
 static int mdc_statfs(struct obd_device *obd, struct obd_statfs *osfs,
-                      cfs_time_t max_age)
+                      __u64 max_age)
 {
         struct ptlrpc_request *req;
         struct obd_statfs *msfs;
-        int rc, size = sizeof(*msfs);
+        int rc, size[2] = { sizeof(struct ptlrpc_body), sizeof(*msfs) };
         ENTRY;
 
         /* We could possibly pass max_age in the request (as an absolute
@@ -905,26 +945,25 @@ static int mdc_statfs(struct obd_device *obd, struct obd_statfs *osfs,
          * is not so great if request processing is slow, while absolute
          * timestamps are not ideal because they need time synchronization. */
         req = ptlrpc_prep_req(obd->u.cli.cl_import, LUSTRE_MDS_VERSION,
-                              MDS_STATFS, 0, NULL, NULL);
+                              MDS_STATFS, 1, NULL, NULL);
         if (!req)
                 RETURN(-ENOMEM);
 
-        req->rq_replen = lustre_msg_size(1, &size);
+        ptlrpc_req_set_repsize(req, 2, size);
 
-        mdc_get_rpc_lock(obd->u.cli.cl_rpc_lock, NULL);
         rc = ptlrpc_queue_wait(req);
-        mdc_put_rpc_lock(obd->u.cli.cl_rpc_lock, NULL);
 
         if (rc)
                 GOTO(out, rc);
 
-        msfs = lustre_swab_repbuf(req, 0, sizeof(*msfs),lustre_swab_obd_statfs);
+        msfs = lustre_swab_repbuf(req, REPLY_REC_OFF, sizeof(*msfs),
+                                  lustre_swab_obd_statfs);
         if (msfs == NULL) {
                 CERROR("Can't unpack obd_statfs\n");
                 GOTO(out, rc = -EPROTO);
         }
 
-        memcpy(osfs, msfs, sizeof (*msfs));
+        memcpy(osfs, msfs, sizeof(*msfs));
         EXIT;
 out:
         ptlrpc_req_finished(req);
@@ -937,19 +976,19 @@ static int mdc_pin(struct obd_export *exp, struct lu_fid *fid,
 {
         struct ptlrpc_request *req;
         struct mdt_body *body;
-        int rc, size[] = { [MDS_REQ_REC_OFF] = sizeof(struct mdt_body) };
+        int rc, size[2] = { sizeof(struct ptlrpc_body), sizeof(*body) };
         ENTRY;
 
         req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_MDS_VERSION,
-                              MDS_PIN, 1, size, NULL);
+                              MDS_PIN, 2, size, NULL);
         if (req == NULL)
                 RETURN(-ENOMEM);
 
-        body = lustre_msg_buf(req->rq_reqmsg, MDS_REQ_REC_OFF, sizeof (*body));
+        body = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, sizeof (*body));
         body->fid1 = *fid;
         body->flags = flag;
 
-        req->rq_replen = lustre_msg_size(1, size);
+        ptlrpc_req_set_repsize(req, 2, size);
 
         mdc_get_rpc_lock(exp->exp_obd->u.cli.cl_rpc_lock, NULL);
         rc = ptlrpc_queue_wait(req);
@@ -960,7 +999,8 @@ static int mdc_pin(struct obd_export *exp, struct lu_fid *fid,
                 RETURN(rc);
         }
 
-        body = lustre_swab_repbuf(req, 0, sizeof(*body), lustre_swab_mdt_body);
+        body = lustre_swab_repbuf(req, REPLY_REC_OFF, sizeof(*body),
+                                  lustre_swab_mdt_body);
         if (body == NULL) {
                 ptlrpc_req_finished(req);
                 RETURN(rc);
@@ -984,22 +1024,22 @@ static int mdc_unpin(struct obd_export *exp,
 {
         struct ptlrpc_request *req;
         struct mdt_body *body;
-        int rc, size[] = { [MDS_REQ_REC_OFF] = sizeof(struct mdt_body) };
+        int rc, size[2] = { sizeof(struct ptlrpc_body), sizeof(*body) };
         ENTRY;
 
         if (handle->och_magic != OBD_CLIENT_HANDLE_MAGIC)
                 RETURN(0);
 
         req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_MDS_VERSION,
-                              MDS_CLOSE, 1, size, NULL);
+                              MDS_CLOSE, 2, size, NULL);
         if (req == NULL)
                 RETURN(-ENOMEM);
 
-        body = lustre_msg_buf(req->rq_reqmsg, 1, sizeof(*body));
+        body = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, sizeof(*body));
         memcpy(&body->handle, &handle->och_fh, sizeof(body->handle));
         body->flags = flag;
 
-        req->rq_replen = lustre_msg_size(0, NULL);
+        ptlrpc_req_set_repsize(req, 1, NULL);
         mdc_get_rpc_lock(exp->exp_obd->u.cli.cl_rpc_lock, NULL);
         rc = ptlrpc_queue_wait(req);
         mdc_put_rpc_lock(exp->exp_obd->u.cli.cl_rpc_lock, NULL);
@@ -1017,17 +1057,18 @@ int mdc_sync(struct obd_export *exp, struct lu_fid *fid,
              struct ptlrpc_request **request)
 {
         struct ptlrpc_request *req;
-        int rc, size[] = { [MDS_REQ_REC_OFF] = sizeof(struct mdt_body) };
+        int size[2] = { sizeof(struct ptlrpc_body), sizeof(struct mdt_body) };
+        int rc;
         ENTRY;
 
         req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_MDS_VERSION,
-                              MDS_SYNC, 1, size, NULL);
+                              MDS_SYNC, 2, size, NULL);
         if (!req)
                 RETURN(rc = -ENOMEM);
 
-        mdc_pack_req_body(req, MDS_REQ_REC_OFF, 0, fid, 0);
+        mdc_pack_req_body(req, REQ_REC_OFF, 0, fid, 0, 0);
 
-        req->rq_replen = lustre_msg_size(1, size);
+        ptlrpc_req_set_repsize(req, 2, size);
 
         rc = ptlrpc_queue_wait(req);
         if (rc || request == NULL)
@@ -1038,27 +1079,6 @@ int mdc_sync(struct obd_export *exp, struct lu_fid *fid,
         RETURN(rc);
 }
 
-int mdc_get_info(struct obd_export *exp, __u32 keylen, void *key,
-                 __u32 *vallen, void *val)
-{
-        int rc = -EINVAL;
-
-        if (keylen == strlen("max_easize") &&
-            memcmp(key, "max_easize", strlen("max_easize")) == 0) {
-                int mdsize, *max_easize;
-
-                if (*vallen != sizeof(int))
-                        RETURN(-EINVAL);
-                mdsize = *(int*)val;
-                if (mdsize > exp->exp_obd->u.cli.cl_max_mds_easize)
-                        exp->exp_obd->u.cli.cl_max_mds_easize = mdsize;
-                max_easize = val;
-                *max_easize = exp->exp_obd->u.cli.cl_max_mds_easize;
-                RETURN(0);
-        }
-        RETURN(rc);
-}
-
 static int mdc_import_event(struct obd_device *obd, struct obd_import *imp,
                             enum obd_import_event event)
 {
@@ -1170,9 +1190,14 @@ static int mdc_setup(struct obd_device *obd, struct lustre_cfg *cfg)
                 GOTO(err_rpc_lock, rc = -ENOMEM);
         mdc_init_rpc_lock(cli->cl_setattr_lock);
 
+        OBD_ALLOC(cli->cl_close_lock, sizeof (*cli->cl_close_lock));
+        if (!cli->cl_close_lock)
+                GOTO(err_setattr_lock, rc = -ENOMEM);
+        mdc_init_rpc_lock(cli->cl_close_lock);
+
         rc = client_obd_setup(obd, cfg);
         if (rc)
-                GOTO(err_setattr_lock, rc);
+                GOTO(err_close_lock, rc);
         lprocfs_init_vars(mdc, &lvars);
         lprocfs_obd_setup(obd, lvars.obd_vars);
 
@@ -1184,6 +1209,8 @@ static int mdc_setup(struct obd_device *obd, struct lustre_cfg *cfg)
 
         RETURN(rc);
 
+err_close_lock:
+        OBD_FREE(cli->cl_close_lock, sizeof (*cli->cl_close_lock));
 err_setattr_lock:
         OBD_FREE(cli->cl_setattr_lock, sizeof (*cli->cl_setattr_lock));
 err_rpc_lock:
@@ -1240,6 +1267,7 @@ static int mdc_cleanup(struct obd_device *obd)
 
         OBD_FREE(cli->cl_rpc_lock, sizeof (*cli->cl_rpc_lock));
         OBD_FREE(cli->cl_setattr_lock, sizeof (*cli->cl_setattr_lock));
+        OBD_FREE(cli->cl_close_lock, sizeof (*cli->cl_close_lock));
 
         lprocfs_obd_cleanup(obd);
         ptlrpcd_decref();
@@ -1285,6 +1313,18 @@ static int mdc_llog_finish(struct obd_device *obd, int count)
         RETURN(rc);
 }
 
+static int mdc_process_config(struct obd_device *obd, obd_count len, void *buf)
+{
+        struct lustre_cfg *lcfg = buf;
+        struct lprocfs_static_vars lvars;
+        int rc = 0;
+
+        lprocfs_init_vars(mdc, &lvars);
+        
+        rc = class_process_proc_param(PARAM_MDC, lvars.obd_vars, lcfg, obd);
+        return(rc);
+}
+
 struct obd_ops mdc_obd_ops = {
         .o_owner            = THIS_MODULE,
         .o_setup            = mdc_setup,
@@ -1306,6 +1346,7 @@ struct obd_ops mdc_obd_ops = {
         .o_llog_init        = mdc_llog_init,
         .o_llog_finish      = mdc_llog_finish,
         .o_get_info         = mdc_get_info,
+        .o_process_config  = mdc_process_config,
 };
 
 struct md_ops mdc_md_ops = {
index e2abed2..8846b53 100644 (file)
@@ -336,6 +336,7 @@ int mdd_lov_create(const struct lu_context *ctxt, struct mdd_device *mdd,
         struct obd_device       *obd = mdd2obd_dev(mdd);
         struct obd_export       *lov_exp = obd->u.mds.mds_osc_exp;
         struct obdo             *oa;
+        struct obd_info          oinfo = { { { 0 } } };
         struct lov_stripe_md    *lsm = NULL;
         const void              *eadata = spec->u.sp_ea.eadata;
 /*      int                      eadatasize  = spec->u.sp_ea.eadatalen;*/
@@ -348,7 +349,9 @@ int mdd_lov_create(const struct lu_context *ctxt, struct mdd_device *mdd,
                 RETURN(0);
 
         oa = obdo_alloc();
-
+        if (oa == NULL)
+                RETURN(-ENOMEM);
+        
         oa->o_uid = 0; /* must have 0 uid / gid on OST */
         oa->o_gid = 0;
         oa->o_mode = S_IFREG | 0600;
@@ -417,8 +420,10 @@ int mdd_lov_create(const struct lu_context *ctxt, struct mdd_device *mdd,
                 oa->o_fid = lu_object_fid(mdd2lu_obj(child))->f_seq;
                 oa->o_generation = lu_object_fid(mdd2lu_obj(child))->f_oid;
                 oa->o_valid |= OBD_MD_FLFID | OBD_MD_FLGENER;
-
-                rc = obd_setattr(lov_exp, oa, lsm, NULL);
+                oinfo.oi_oa = oa;
+                oinfo.oi_md = lsm;
+                        
+                rc = obd_setattr(lov_exp, &oinfo, NULL);
                 if (rc) {
                         CERROR("error setting attrs for "DFID": rc %d\n",
                                PFID(mdo2fid(child)), rc);
@@ -453,8 +458,8 @@ int mdd_unlink_log(const struct lu_context *ctxt, struct mdd_device *mdd,
 {
         struct obd_device *obd = mdd2obd_dev(mdd);
 
-        if (mds_log_op_unlink(obd, NULL, ma->ma_lmm, ma->ma_lmm_size,
-                                 ma->ma_cookie, ma->ma_cookie_size) > 0) {
+        if (mds_log_op_unlink(obd, ma->ma_lmm, ma->ma_lmm_size,
+                              ma->ma_cookie, ma->ma_cookie_size) > 0) {
                 ma->ma_valid |= MA_COOKIE;
         }
         return 0;
index 8346d06..7212c59 100644 (file)
@@ -59,6 +59,7 @@
 #include <lustre_commit_confd.h>
 #include <lustre_quota.h>
 #include <lustre_disk.h>
+#include <lustre_param.h>
 #include <lustre_ver.h>
 
 #include "mds_internal.h"
@@ -175,8 +176,8 @@ struct dentry *mds_fid2locked_dentry(struct obd_device *obd, struct ll_fid *fid,
         struct mds_obd *mds = &obd->u.mds;
         struct dentry *de = mds_fid2dentry(mds, fid, mnt), *retval = de;
         struct ldlm_res_id res_id = { .name = {0} };
-        int flags = 0, rc;
-        ldlm_policy_data_t policy = { .l_inodebits = { lockpart} };
+        int flags = LDLM_FL_ATOMIC_CB, rc;
+        ldlm_policy_data_t policy = { .l_inodebits = { lockpart} }; 
         ENTRY;
 
         if (IS_ERR(de))
@@ -184,10 +185,10 @@ struct dentry *mds_fid2locked_dentry(struct obd_device *obd, struct ll_fid *fid,
 
         res_id.name[0] = de->d_inode->i_ino;
         res_id.name[1] = de->d_inode->i_generation;
-        rc = ldlm_cli_enqueue(NULL, NULL, obd->obd_namespace, res_id,
-                              LDLM_IBITS, &policy, lock_mode, &flags,
-                              ldlm_blocking_ast, ldlm_completion_ast,
-                              NULL, NULL, NULL, 0, NULL, lockh);
+        rc = ldlm_cli_enqueue_local(obd->obd_namespace, res_id, 
+                                    LDLM_IBITS, &policy, lock_mode, &flags, 
+                                    ldlm_blocking_ast, ldlm_completion_ast,
+                                    NULL, NULL, 0, NULL, lockh);
         if (rc != ELDLM_OK) {
                 l_dput(de);
                 retval = ERR_PTR(-EIO); /* XXX translate ldlm code */
@@ -422,7 +423,7 @@ static int mds_destroy_export(struct obd_export *export)
                 /* child orphan sem protects orphan_dec_test and
                  * is_orphan race, mds_mfd_close drops it */
                 MDS_DOWN_WRITE_ORPHAN_SEM(dentry->d_inode);
-                rc = mds_mfd_close(NULL, MDS_REQ_REC_OFF, obd, mfd,
+                rc = mds_mfd_close(NULL, REQ_REC_OFF, obd, mfd,
                                    !(export->exp_flags & OBD_OPT_FAILOVER));
 
                 if (rc)
@@ -438,7 +439,6 @@ static int mds_destroy_export(struct obd_export *export)
 
 static int mds_disconnect(struct obd_export *exp)
 {
-        unsigned long irqflags;
         int rc;
         ENTRY;
 
@@ -447,10 +447,11 @@ static int mds_disconnect(struct obd_export *exp)
 
         /* Disconnect early so that clients can't keep using export */
         rc = class_disconnect(exp);
-        ldlm_cancel_locks_for_export(exp);
+        if (exp->exp_obd->obd_namespace != NULL)
+                ldlm_cancel_locks_for_export(exp);
 
         /* complete all outstanding replies */
-        spin_lock_irqsave(&exp->exp_lock, irqflags);
+        spin_lock(&exp->exp_lock);
         while (!list_empty(&exp->exp_outstanding_replies)) {
                 struct ptlrpc_reply_state *rs =
                         list_entry(exp->exp_outstanding_replies.next,
@@ -462,7 +463,7 @@ static int mds_disconnect(struct obd_export *exp)
                 ptlrpc_schedule_difficult_reply(rs);
                 spin_unlock(&svc->srv_lock);
         }
-        spin_unlock_irqrestore(&exp->exp_lock, irqflags);
+        spin_unlock(&exp->exp_lock);
 
         class_export_put(exp);
         RETURN(rc);
@@ -472,17 +473,17 @@ static int mds_getstatus(struct ptlrpc_request *req)
 {
         struct mds_obd *mds = mds_req2mds(req);
         struct mds_body *body;
-        int rc, size = sizeof(*body);
+        int rc, size[2] = { sizeof(struct ptlrpc_body), sizeof(*body) };
         ENTRY;
 
-        rc = lustre_pack_reply(req, 1, &size, NULL);
+        rc = lustre_pack_reply(req, 2, size, NULL);
         if (rc || OBD_FAIL_CHECK(OBD_FAIL_MDS_GETSTATUS_PACK)) {
-                CERROR("mds: out of memory for message: size=%d\n", size);
+                CERROR("mds: out of memory for message\n");
                 req->rq_status = -ENOMEM;       /* superfluous? */
                 RETURN(-ENOMEM);
         }
 
-        body = lustre_msg_buf(req->rq_repmsg, 0, sizeof (*body));
+        body = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF, sizeof(*body));
         memcpy(&body->fid1, &mds->mds_rootfid, sizeof(body->fid1));
 
         /* the last_committed and last_xid fields are filled in for all
@@ -547,7 +548,7 @@ int mds_pack_md(struct obd_device *obd, struct lustre_msg *msg, int offset,
                        inode->i_ino);
                 RETURN(0);
         }
-        lmm_size = msg->buflens[offset];
+        lmm_size = lustre_msg_buflen(msg, offset);
 
         /* I don't really like this, but it is a sanity check on the client
          * MD request.  However, if the client doesn't know how much space
@@ -582,7 +583,7 @@ int mds_pack_posix_acl(struct inode *inode, struct lustre_msg *repmsg,
         ENTRY;
 
         LASSERT(repbody->aclsize == 0);
-        LASSERT(repmsg->bufcount > repoff);
+        LASSERT(lustre_msg_bufcount(repmsg) > repoff);
 
         buflen = lustre_msg_buflen(repmsg, repoff);
         if (!buflen)
@@ -592,7 +593,7 @@ int mds_pack_posix_acl(struct inode *inode, struct lustre_msg *repmsg,
                 GOTO(out, 0);
 
         lock_24kernel();
-        rc = inode->i_op->getxattr(&de, XATTR_NAME_ACL_ACCESS,
+        rc = inode->i_op->getxattr(&de, MDS_XATTR_NAME_ACL_ACCESS,
                                    lustre_msg_buf(repmsg, repoff, buflen),
                                    buflen);
         unlock_24kernel();
@@ -635,6 +636,7 @@ static int mds_getattr_internal(struct obd_device *obd, struct dentry *dentry,
         LASSERT(body != NULL);                 /* caller prepped reply */
 
         mds_pack_inode2fid(&body->fid1, inode);
+        body->flags = reqbody->flags; /* copy MDS_BFLAG_EXT_FLAGS if present */
         mds_pack_inode2body(body, inode);
         reply_off++;
 
@@ -658,7 +660,7 @@ static int mds_getattr_internal(struct obd_device *obd, struct dentry *dentry,
                 int len;
 
                 LASSERT (symname != NULL);       /* caller prepped reply */
-                len = req->rq_repmsg->buflens[reply_off];
+                len = lustre_msg_buflen(req->rq_repmsg, reply_off);
 
                 rc = inode->i_op->readlink(dentry, symname, len);
                 if (rc < 0) {
@@ -675,6 +677,16 @@ static int mds_getattr_internal(struct obd_device *obd, struct dentry *dentry,
                         rc = 0;
                 }
                 reply_off++;
+        } else if (reqbody->valid == OBD_MD_FLFLAGS &&
+                   reqbody->flags & MDS_BFLAG_EXT_FLAGS) {
+                int flags;
+
+                /* We only return the full set of flags on ioctl, otherwise we
+                 * get enough flags from the inode in mds_pack_inode2body(). */
+                rc = fsfilt_iocontrol(obd, inode, NULL, EXT3_IOC_GETFLAGS,
+                                      (long)&flags);
+                if (rc == 0)
+                        body->flags = flags | MDS_BFLAG_EXT_FLAGS;
         }
 
         if (reqbody->valid & OBD_MD_FLMODEASIZE) {
@@ -708,10 +720,13 @@ static int mds_getattr_pack_msg(struct ptlrpc_request *req, struct inode *inode,
 {
         struct mds_obd *mds = mds_req2mds(req);
         struct mds_body *body;
-        int rc, size[3] = {sizeof(*body)}, bufcount = 1;
+        int rc, bufcount = 2;
+        int size[4] = { sizeof(struct ptlrpc_body), sizeof(*body) };
         ENTRY;
 
-        body = lustre_msg_buf(req->rq_reqmsg, offset, sizeof (*body));
+        LASSERT(offset == REQ_REC_OFF); /* non-intent */
+
+        body = lustre_msg_buf(req->rq_reqmsg, offset, sizeof(*body));
         LASSERT(body != NULL);                 /* checked by caller */
         LASSERT_REQSWABBED(req, offset);       /* swabbed by caller */
 
@@ -756,7 +771,7 @@ static int mds_getattr_pack_msg(struct ptlrpc_request *req, struct inode *inode,
                 size[bufcount] = 0;
                 if (inode->i_op && inode->i_op->getxattr) {
                         lock_24kernel();
-                        rc = inode->i_op->getxattr(&de, XATTR_NAME_ACL_ACCESS,
+                        rc = inode->i_op->getxattr(&de, MDS_XATTR_NAME_ACL_ACCESS,
                                                    NULL, 0);
                         unlock_24kernel();
 
@@ -788,7 +803,7 @@ static int mds_getattr_pack_msg(struct ptlrpc_request *req, struct inode *inode,
         RETURN(0);
 }
 
-static int mds_getattr_name(int offset, struct ptlrpc_request *req,
+static int mds_getattr_lock(struct ptlrpc_request *req, int offset,
                             int child_part, struct lustre_handle *child_lockh)
 {
         struct obd_device *obd = req->rq_export->exp_obd;
@@ -807,7 +822,6 @@ static int mds_getattr_name(int offset, struct ptlrpc_request *req,
         LASSERT(!strcmp(obd->obd_type->typ_name, LUSTRE_MDS_NAME));
 
         /* Swab now, before anyone looks inside the request */
-
         body = lustre_swab_reqbuf(req, offset, sizeof(*body),
                                   lustre_swab_mds_body);
         if (body == NULL) {
@@ -822,16 +836,21 @@ static int mds_getattr_name(int offset, struct ptlrpc_request *req,
                 RETURN(-EFAULT);
         }
         namesize = lustre_msg_buflen(req->rq_reqmsg, offset + 1);
+        /* namesize less than 2 means we have empty name, probably came from
+           revalidate by cfid, so no point in having name to be set */
+        if (namesize <= 1)
+                name = NULL;
 
         rc = mds_init_ucred(&uc, req, offset);
         if (rc)
                 GOTO(cleanup, rc);
 
-        LASSERT (offset == MDS_REQ_REC_OFF || offset == MDS_REQ_INTENT_REC_OFF);
+        LASSERT(offset == REQ_REC_OFF || offset == DLM_INTENT_REC_OFF);
         /* if requests were at offset 2, the getattr reply goes back at 1 */
-        if (offset == MDS_REQ_INTENT_REC_OFF) {
-                rep = lustre_msg_buf(req->rq_repmsg, 0, sizeof (*rep));
-                offset = 1;
+        if (offset == DLM_INTENT_REC_OFF) {
+                rep = lustre_msg_buf(req->rq_repmsg, DLM_LOCKREPLY_OFF,
+                                     sizeof(*rep));
+                offset = DLM_REPLY_REC_OFF;
         }
 
         push_ctxt(&saved, &obd->obd_lvfs_ctxt, &uc);
@@ -867,25 +886,26 @@ static int mds_getattr_name(int offset, struct ptlrpc_request *req,
         }
 
         if (resent_req == 0) {
-            if (name) {
-                rc = mds_get_parent_child_locked(obd, &obd->u.mds, &body->fid1,
-                                                 &parent_lockh, &dparent,
-                                                 LCK_CR,
-                                                 MDS_INODELOCK_UPDATE,
-                                                 name, namesize,
-                                                 child_lockh, &dchild, LCK_CR,
-                                                 child_part);
-            } else {
+                if (name) {
+                        rc = mds_get_parent_child_locked(obd, &obd->u.mds, 
+                                                         &body->fid1,
+                                                         &parent_lockh, 
+                                                         &dparent, LCK_CR,
+                                                         MDS_INODELOCK_UPDATE,
+                                                         name, namesize,
+                                                         child_lockh, &dchild,
+                                                         LCK_CR, child_part);
+                } else {
                         /* For revalidate by fid we always take UPDATE lock */
                         dchild = mds_fid2locked_dentry(obd, &body->fid2, NULL,
                                                        LCK_CR, child_lockh,
-                                                       MDS_INODELOCK_UPDATE);
+                                                       child_part);
                         LASSERT(dchild);
                         if (IS_ERR(dchild))
                                 rc = PTR_ERR(dchild);
-            }
-            if (rc)
-                    GOTO(cleanup, rc);
+                } 
+                if (rc)
+                        GOTO(cleanup, rc);
         } else {
                 struct ldlm_lock *granted_lock;
                 struct ll_fid child_fid;
@@ -933,8 +953,10 @@ static int mds_getattr_name(int offset, struct ptlrpc_request *req,
                 if (resent_req == 0) {
                         if (rc && dchild->d_inode)
                                 ldlm_lock_decref(child_lockh, LCK_CR);
-                        ldlm_lock_decref(&parent_lockh, LCK_CR);
-                        l_dput(dparent);
+                        if (name) {
+                                ldlm_lock_decref(&parent_lockh, LCK_CR);
+                                l_dput(dparent);
+                        }
                 }
                 l_dput(dchild);
         case 1:
@@ -943,7 +965,7 @@ static int mds_getattr_name(int offset, struct ptlrpc_request *req,
                 mds_exit_ucred(&uc, mds);
                 if (req->rq_reply_state == NULL) {
                         req->rq_status = rc;
-                        lustre_pack_reply(req, 0, NULL, NULL);
+                        lustre_pack_reply(req, 1, NULL, NULL);
                 }
         }
         return rc;
@@ -956,7 +978,7 @@ static int mds_getattr(struct ptlrpc_request *req, int offset)
         struct lvfs_run_ctxt saved;
         struct dentry *de;
         struct mds_body *body;
-        struct lvfs_ucred uc = {NULL,};
+        struct lvfs_ucred uc = { NULL, };
         int rc = 0;
         ENTRY;
 
@@ -982,7 +1004,7 @@ static int mds_getattr(struct ptlrpc_request *req, int offset)
                 GOTO(out_pop, rc);
         }
 
-        req->rq_status = mds_getattr_internal(obd, de, req, body, 0);
+        req->rq_status = mds_getattr_internal(obd, de, req, body,REPLY_REC_OFF);
 
         l_dput(de);
         GOTO(out_pop, rc);
@@ -991,14 +1013,14 @@ out_pop:
 out_ucred:
         if (req->rq_reply_state == NULL) {
                 req->rq_status = rc;
-                lustre_pack_reply(req, 0, NULL, NULL);
+                lustre_pack_reply(req, 1, NULL, NULL);
         }
         mds_exit_ucred(&uc, mds);
         return rc;
 }
 
 static int mds_obd_statfs(struct obd_device *obd, struct obd_statfs *osfs,
-                          unsigned long max_age)
+                          __u64 max_age)
 {
         int rc;
 
@@ -1014,22 +1036,24 @@ static int mds_obd_statfs(struct obd_device *obd, struct obd_statfs *osfs,
 static int mds_statfs(struct ptlrpc_request *req)
 {
         struct obd_device *obd = req->rq_export->exp_obd;
-        int rc, size = sizeof(struct obd_statfs);
+        int rc, size[2] = { sizeof(struct ptlrpc_body),
+                            sizeof(struct obd_statfs) };
         ENTRY;
 
         /* This will trigger a watchdog timeout */
         OBD_FAIL_TIMEOUT(OBD_FAIL_MDS_STATFS_LCW_SLEEP,
                          (MDS_SERVICE_WATCHDOG_TIMEOUT / 1000) + 1);
 
-        rc = lustre_pack_reply(req, 1, &size, NULL);
+        rc = lustre_pack_reply(req, 2, size, NULL);
         if (rc || OBD_FAIL_CHECK(OBD_FAIL_MDS_STATFS_PACK)) {
                 CERROR("mds: statfs lustre_pack_reply failed: rc = %d\n", rc);
                 GOTO(out, rc);
         }
 
         /* We call this so that we can cache a bit - 1 jiffie worth */
-        rc = mds_obd_statfs(obd, lustre_msg_buf(req->rq_repmsg, 0, size),
-                            jiffies - HZ);
+        rc = mds_obd_statfs(obd, lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
+                                                size[REPLY_REC_OFF]),
+                            cfs_time_current_64() - HZ);
         if (rc) {
                 CERROR("mds_obd_statfs failed: rc %d\n", rc);
                 GOTO(out, rc);
@@ -1046,14 +1070,15 @@ static int mds_sync(struct ptlrpc_request *req, int offset)
         struct obd_device *obd = req->rq_export->exp_obd;
         struct mds_obd *mds = &obd->u.mds;
         struct mds_body *body;
-        int rc, size = sizeof(*body);
+        int rc, size[2] = { sizeof(struct ptlrpc_body), sizeof(*body) };
         ENTRY;
 
-        body = lustre_swab_reqbuf(req, 0, sizeof(*body), lustre_swab_mds_body);
+        body = lustre_swab_reqbuf(req, offset, sizeof(*body),
+                                  lustre_swab_mds_body);
         if (body == NULL)
                 GOTO(out, rc = -EFAULT);
 
-        rc = lustre_pack_reply(req, 1, &size, NULL);
+        rc = lustre_pack_reply(req, 2, size, NULL);
         if (rc || OBD_FAIL_CHECK(OBD_FAIL_MDS_SYNC_PACK)) {
                 CERROR("fsync lustre_pack_reply failed: rc = %d\n", rc);
                 GOTO(out, rc);
@@ -1074,7 +1099,8 @@ static int mds_sync(struct ptlrpc_request *req, int offset)
                 if (de->d_inode->i_fop && de->d_inode->i_fop->fsync)
                         rc = de->d_inode->i_fop->fsync(NULL, de, 1);
                 if (rc == 0) {
-                        body = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*body));
+                        body = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
+                                              sizeof(*body));
                         mds_pack_inode2fid(&body->fid1, de->d_inode);
                         mds_pack_inode2body(body, de->d_inode);
                 }
@@ -1101,14 +1127,14 @@ static int mds_readpage(struct ptlrpc_request *req, int offset)
         struct file *file;
         struct mds_body *body, *repbody;
         struct lvfs_run_ctxt saved;
-        int rc, size = sizeof(*repbody);
+        int rc, size[2] = { sizeof(struct ptlrpc_body), sizeof(*repbody) };
         struct lvfs_ucred uc = {NULL,};
         ENTRY;
 
         if (OBD_FAIL_CHECK(OBD_FAIL_MDS_READPAGE_PACK))
                 RETURN(-ENOMEM);
 
-        rc = lustre_pack_reply(req, 1, &size, NULL);
+        rc = lustre_pack_reply(req, 2, size, NULL);
         if (rc) {
                 CERROR("error packing readpage reply: rc %d\n", rc);
                 GOTO(out, rc);
@@ -1119,7 +1145,7 @@ static int mds_readpage(struct ptlrpc_request *req, int offset)
         if (body == NULL)
                 GOTO (out, rc = -EFAULT);
 
-        rc = mds_init_ucred(&uc, req, 0);
+        rc = mds_init_ucred(&uc, req, offset);
         if (rc)
                 GOTO(out, rc);
 
@@ -1149,7 +1175,8 @@ static int mds_readpage(struct ptlrpc_request *req, int offset)
                 GOTO(out_file, rc = -EFAULT);
         }
 
-        repbody = lustre_msg_buf(req->rq_repmsg, 0, sizeof (*repbody));
+        repbody = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
+                                 sizeof(*repbody));
         repbody->size = file->f_dentry->d_inode->i_size;
         repbody->valid = OBD_MD_FLSIZE;
 
@@ -1195,7 +1222,7 @@ int mds_reint(struct ptlrpc_request *req, int offset,
 int mds_filter_recovery_request(struct ptlrpc_request *req,
                                 struct obd_device *obd, int *process)
 {
-        switch (req->rq_reqmsg->opc) {
+        switch (lustre_msg_get_opc(req->rq_reqmsg)) {
         case MDS_CONNECT: /* This will never get here, but for completeness. */
         case OST_CONNECT: /* This will never get here, but for completeness. */
         case MDS_DISCONNECT:
@@ -1237,23 +1264,23 @@ static int mds_set_info_rpc(struct obd_export *exp, struct ptlrpc_request *req)
         int keylen, rc = 0;
         ENTRY;
 
-        key = lustre_msg_buf(req->rq_reqmsg, 0, 1);
+        key = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, 1);
         if (key == NULL) {
                 DEBUG_REQ(D_HA, req, "no set_info key");
                 RETURN(-EFAULT);
         }
-        keylen = req->rq_reqmsg->buflens[0];
+        keylen = lustre_msg_buflen(req->rq_reqmsg, REQ_REC_OFF);
 
-        val = lustre_msg_buf(req->rq_reqmsg, 1, sizeof(*val));
+        val = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF + 1, sizeof(*val));
         if (val == NULL) {
                 DEBUG_REQ(D_HA, req, "no set_info val");
                 RETURN(-EFAULT);
         }
 
-        rc = lustre_pack_reply(req, 0, NULL, NULL);
+        rc = lustre_pack_reply(req, 1, NULL, NULL);
         if (rc)
                 RETURN(rc);
-        req->rq_repmsg->status = 0;
+        lustre_msg_set_status(req->rq_repmsg, 0);
 
         if (keylen < strlen("read-only") ||
             memcmp(key, "read-only", keylen) != 0)
@@ -1273,12 +1300,12 @@ static int mds_handle_quotacheck(struct ptlrpc_request *req)
         int rc;
         ENTRY;
 
-        oqctl = lustre_swab_reqbuf(req, 0, sizeof(*oqctl),
+        oqctl = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*oqctl),
                                    lustre_swab_obd_quotactl);
         if (oqctl == NULL)
                 RETURN(-EPROTO);
 
-        rc = lustre_pack_reply(req, 0, NULL, NULL);
+        rc = lustre_pack_reply(req, 1, NULL, NULL);
         if (rc) {
                 CERROR("mds: out of memory while packing quotacheck reply\n");
                 RETURN(rc);
@@ -1291,19 +1318,19 @@ static int mds_handle_quotacheck(struct ptlrpc_request *req)
 static int mds_handle_quotactl(struct ptlrpc_request *req)
 {
         struct obd_quotactl *oqctl, *repoqc;
-        int rc, size = sizeof(*repoqc);
+        int rc, size[2] = { sizeof(struct ptlrpc_body), sizeof(*repoqc) };
         ENTRY;
 
-        oqctl = lustre_swab_reqbuf(req, 0, sizeof(*oqctl),
+        oqctl = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*oqctl),
                                    lustre_swab_obd_quotactl);
         if (oqctl == NULL)
                 RETURN(-EPROTO);
 
-        rc = lustre_pack_reply(req, 1, &size, NULL);
+        rc = lustre_pack_reply(req, 2, size, NULL);
         if (rc)
                 RETURN(rc);
 
-        repoqc = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*repoqc));
+        repoqc = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF, sizeof(*repoqc));
 
         req->rq_status = obd_quotactl(req->rq_export, oqctl);
         *repoqc = *oqctl;
@@ -1314,19 +1341,16 @@ int mds_msg_check_version(struct lustre_msg *msg)
 {
         int rc;
 
-        /* TODO: enable the below check while really introducing msg version.
-         * it's disabled because it will break compatibility with b1_4.
-         */
-        return (0);
-
-        switch (msg->opc) {
+        switch (lustre_msg_get_opc(msg)) {
         case MDS_CONNECT:
         case MDS_DISCONNECT:
         case OBD_PING:
                 rc = lustre_msg_check_version(msg, LUSTRE_OBD_VERSION);
                 if (rc)
                         CERROR("bad opc %u version %08x, expecting %08x\n",
-                               msg->opc, msg->version, LUSTRE_OBD_VERSION);
+                               lustre_msg_get_opc(msg),
+                               lustre_msg_get_version(msg),
+                               LUSTRE_OBD_VERSION);
                 break;
         case MDS_GETSTATUS:
         case MDS_GETATTR:
@@ -1348,7 +1372,9 @@ int mds_msg_check_version(struct lustre_msg *msg)
                 rc = lustre_msg_check_version(msg, LUSTRE_MDS_VERSION);
                 if (rc)
                         CERROR("bad opc %u version %08x, expecting %08x\n",
-                               msg->opc, msg->version, LUSTRE_MDS_VERSION);
+                               lustre_msg_get_opc(msg),
+                               lustre_msg_get_version(msg),
+                               LUSTRE_MDS_VERSION);
                 break;
         case LDLM_ENQUEUE:
         case LDLM_CONVERT:
@@ -1357,22 +1383,27 @@ int mds_msg_check_version(struct lustre_msg *msg)
                 rc = lustre_msg_check_version(msg, LUSTRE_DLM_VERSION);
                 if (rc)
                         CERROR("bad opc %u version %08x, expecting %08x\n",
-                               msg->opc, msg->version, LUSTRE_DLM_VERSION);
+                               lustre_msg_get_opc(msg),
+                               lustre_msg_get_version(msg),
+                               LUSTRE_DLM_VERSION);
                 break;
         case OBD_LOG_CANCEL:
         case LLOG_ORIGIN_HANDLE_CREATE:
         case LLOG_ORIGIN_HANDLE_NEXT_BLOCK:
-        case LLOG_ORIGIN_HANDLE_PREV_BLOCK:
         case LLOG_ORIGIN_HANDLE_READ_HEADER:
         case LLOG_ORIGIN_HANDLE_CLOSE:
+        case LLOG_ORIGIN_HANDLE_DESTROY:
+        case LLOG_ORIGIN_HANDLE_PREV_BLOCK:
         case LLOG_CATINFO:
                 rc = lustre_msg_check_version(msg, LUSTRE_LOG_VERSION);
                 if (rc)
                         CERROR("bad opc %u version %08x, expecting %08x\n",
-                               msg->opc, msg->version, LUSTRE_LOG_VERSION);
+                               lustre_msg_get_opc(msg),
+                               lustre_msg_get_version(msg),
+                               LUSTRE_LOG_VERSION);
                 break;
         default:
-                CERROR("MDS unknown opcode %d\n", msg->opc);
+                CERROR("MDS unknown opcode %d\n", lustre_msg_get_opc(msg));
                 rc = -ENOTSUPP;
         }
         return rc;
@@ -1398,13 +1429,13 @@ int mds_handle(struct ptlrpc_request *req)
         }
 
         /* XXX identical to OST */
-        if (req->rq_reqmsg->opc != MDS_CONNECT) {
+        if (lustre_msg_get_opc(req->rq_reqmsg) != MDS_CONNECT) {
                 struct mds_export_data *med;
                 int recovering, abort_recovery;
 
                 if (req->rq_export == NULL) {
                         CERROR("operation %d on unconnected MDS from %s\n",
-                               req->rq_reqmsg->opc,
+                               lustre_msg_get_opc(req->rq_reqmsg),
                                libcfs_id2str(req->rq_peer));
                         req->rq_status = -ENOTCONN;
                         GOTO(out, rc = -ENOTCONN);
@@ -1416,12 +1447,16 @@ int mds_handle(struct ptlrpc_request *req)
 
                 /* sanity check: if the xid matches, the request must
                  * be marked as a resent or replayed */
-                if (req->rq_xid == med->med_mcd->mcd_last_xid)
-                        LASSERTF(lustre_msg_get_flags(req->rq_reqmsg) &
-                                 (MSG_RESENT | MSG_REPLAY),
-                                 "rq_xid "LPU64" matches last_xid, "
-                                 "expected RESENT flag\n",
-                                 req->rq_xid);
+                if (req->rq_xid == le64_to_cpu(med->med_mcd->mcd_last_xid) ||
+                   req->rq_xid == le64_to_cpu(med->med_mcd->mcd_last_close_xid))
+                        if (!(lustre_msg_get_flags(req->rq_reqmsg) &
+                                 (MSG_RESENT | MSG_REPLAY))) {
+                                CERROR("rq_xid "LPU64" matches last_xid, "
+                                       "expected RESENT flag\n",
+                                        req->rq_xid);
+                                req->rq_status = -ENOTCONN;
+                                GOTO(out, rc = -EFAULT);
+                        }
                 /* else: note the opposite is not always true; a
                  * RESENT req after a failover will usually not match
                  * the last_xid, since it was likely never
@@ -1444,7 +1479,7 @@ int mds_handle(struct ptlrpc_request *req)
                 }
         }
 
-        switch (req->rq_reqmsg->opc) {
+        switch (lustre_msg_get_opc(req->rq_reqmsg)) {
         case MDS_CONNECT:
                 DEBUG_REQ(D_INODE, req, "connect");
                 OBD_FAIL_RETURN(OBD_FAIL_MDS_CONNECT_NET, 0);
@@ -1478,7 +1513,7 @@ int mds_handle(struct ptlrpc_request *req)
         case MDS_GETATTR:
                 DEBUG_REQ(D_INODE, req, "getattr");
                 OBD_FAIL_RETURN(OBD_FAIL_MDS_GETATTR_NET, 0);
-                rc = mds_getattr(req, MDS_REQ_REC_OFF);
+                rc = mds_getattr(req, REQ_REC_OFF);
                 break;
 
         case MDS_SETXATTR:
@@ -1499,11 +1534,11 @@ int mds_handle(struct ptlrpc_request *req)
                 OBD_FAIL_RETURN(OBD_FAIL_MDS_GETATTR_NAME_NET, 0);
 
                 /* If this request gets a reconstructed reply, we won't be
-                 * acquiring any new locks in mds_getattr_name, so we don't
+                 * acquiring any new locks in mds_getattr_lock, so we don't
                  * want to cancel.
                  */
-                rc = mds_getattr_name(MDS_REQ_REC_OFF, req,
-                                      MDS_INODELOCK_UPDATE, &lockh);
+                rc = mds_getattr_lock(req, REQ_REC_OFF, MDS_INODELOCK_UPDATE,
+                                      &lockh);
                 /* this non-intent call (from an ioctl) is special */
                 req->rq_status = rc;
                 if (rc == 0 && lustre_handle_is_used(&lockh))
@@ -1519,7 +1554,7 @@ int mds_handle(struct ptlrpc_request *req)
         case MDS_READPAGE:
                 DEBUG_REQ(D_INODE, req, "readpage");
                 OBD_FAIL_RETURN(OBD_FAIL_MDS_READPAGE_NET, 0);
-                rc = mds_readpage(req, MDS_REQ_REC_OFF);
+                rc = mds_readpage(req, REQ_REC_OFF);
 
                 if (OBD_FAIL_CHECK_ONCE(OBD_FAIL_MDS_SENDPAGE)) {
                         RETURN(0);
@@ -1528,11 +1563,13 @@ int mds_handle(struct ptlrpc_request *req)
                 break;
 
         case MDS_REINT: {
-                __u32 *opcp = lustre_msg_buf(req->rq_reqmsg, MDS_REQ_REC_OFF,
-                                             sizeof (*opcp));
+                __u32 *opcp = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF,
+                                             sizeof(*opcp));
                 __u32  opc;
-                int size[] = { sizeof(struct mds_body), mds->mds_max_mdsize,
-                               mds->mds_max_cookiesize};
+                int size[4] = { sizeof(struct ptlrpc_body),
+                                sizeof(struct mds_body),
+                                mds->mds_max_mdsize,
+                                mds->mds_max_cookiesize };
                 int bufcount;
 
                 /* NB only peek inside req now; mds_reint() will swab it */
@@ -1542,7 +1579,7 @@ int mds_handle(struct ptlrpc_request *req)
                         break;
                 }
                 opc = *opcp;
-                if (lustre_msg_swabbed (req->rq_reqmsg))
+                if (lustre_msg_swabbed(req->rq_reqmsg))
                         __swab32s(&opc);
 
                 DEBUG_REQ(D_INODE, req, "reint %d (%s)", opc,
@@ -1553,17 +1590,17 @@ int mds_handle(struct ptlrpc_request *req)
                 OBD_FAIL_RETURN(OBD_FAIL_MDS_REINT_NET, 0);
 
                 if (opc == REINT_UNLINK || opc == REINT_RENAME)
-                        bufcount = 3;
+                        bufcount = 4;
                 else if (opc == REINT_OPEN)
-                        bufcount = 2;
+                        bufcount = 3;
                 else
-                        bufcount = 1;
+                        bufcount = 2;
 
                 rc = lustre_pack_reply(req, bufcount, size, NULL);
                 if (rc)
                         break;
 
-                rc = mds_reint(req, MDS_REQ_REC_OFF, NULL);
+                rc = mds_reint(req, REQ_REC_OFF, NULL);
                 fail = OBD_FAIL_MDS_REINT_NET_REP;
                 break;
         }
@@ -1571,25 +1608,25 @@ int mds_handle(struct ptlrpc_request *req)
         case MDS_CLOSE:
                 DEBUG_REQ(D_INODE, req, "close");
                 OBD_FAIL_RETURN(OBD_FAIL_MDS_CLOSE_NET, 0);
-                rc = mds_close(req, MDS_REQ_REC_OFF);
+                rc = mds_close(req, REQ_REC_OFF);
                 break;
 
         case MDS_DONE_WRITING:
                 DEBUG_REQ(D_INODE, req, "done_writing");
                 OBD_FAIL_RETURN(OBD_FAIL_MDS_DONE_WRITING_NET, 0);
-                rc = mds_done_writing(req, MDS_REQ_REC_OFF);
+                rc = mds_done_writing(req, REQ_REC_OFF);
                 break;
 
         case MDS_PIN:
                 DEBUG_REQ(D_INODE, req, "pin");
                 OBD_FAIL_RETURN(OBD_FAIL_MDS_PIN_NET, 0);
-                rc = mds_pin(req, MDS_REQ_REC_OFF);
+                rc = mds_pin(req, REQ_REC_OFF);
                 break;
 
         case MDS_SYNC:
                 DEBUG_REQ(D_INODE, req, "sync");
                 OBD_FAIL_RETURN(OBD_FAIL_MDS_SYNC_NET, 0);
-                rc = mds_sync(req, MDS_REQ_REC_OFF);
+                rc = mds_sync(req, REQ_REC_OFF);
                 break;
 
         case MDS_SET_INFO:
@@ -1683,10 +1720,13 @@ int mds_handle(struct ptlrpc_request *req)
         LASSERT(current->journal_info == NULL);
 
         /* If we're DISCONNECTing, the mds_export_data is already freed */
-        if (!rc && req->rq_reqmsg->opc != MDS_DISCONNECT) {
+        if (!rc && lustre_msg_get_opc(req->rq_reqmsg) != MDS_DISCONNECT) {
                 struct mds_export_data *med = &req->rq_export->exp_mds_data;
-                req->rq_repmsg->last_xid =
-                        le64_to_cpu(med->med_mcd->mcd_last_xid);
+                
+                /* I don't think last_xid is used for anyway, so I'm not sure
+                   if we need to care about last_close_xid here.*/
+                lustre_msg_set_last_xid(req->rq_repmsg,
+                                       le64_to_cpu(med->med_mcd->mcd_last_xid));
 
                 target_committed_to_req(req);
         }
@@ -1718,7 +1758,6 @@ int mds_update_server_data(struct obd_device *obd, int force_sync)
 {
         struct mds_obd *mds = &obd->u.mds;
         struct lr_server_data *lsd = mds->mds_server_data;
-        struct lr_server_data *lsd_copy = NULL;
         struct file *filp = mds->mds_rcvd_filp;
         struct lvfs_run_ctxt saved;
         loff_t off = 0;
@@ -1730,40 +1769,21 @@ int mds_update_server_data(struct obd_device *obd, int force_sync)
 
         lsd->lsd_last_transno = cpu_to_le64(mds->mds_last_transno);
 
-        if (!(lsd->lsd_feature_incompat & cpu_to_le32(OBD_INCOMPAT_COMMON_LR))){
-                /* Swap to the old mds_server_data format, in case
-                   someone wants to revert to a pre-1.6 lustre */
-                CDEBUG(D_CONFIG, "writing old last_rcvd format\n");
-                /* malloc new struct instead of swap in-place because
-                   we don't have a lock on the last_trasno or mount count -
-                   someone may modify it while we're here, and we don't want
-                   them to inc the wrong thing. */
-                OBD_ALLOC(lsd_copy, sizeof(*lsd_copy));
-                if (!lsd_copy)
-                        RETURN(-ENOMEM);
-                *lsd_copy = *lsd;
-                lsd_copy->lsd_unused = lsd->lsd_last_transno;
-                lsd_copy->lsd_last_transno = lsd->lsd_mount_count;
-                lsd = lsd_copy;
-        }
-
         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
         rc = fsfilt_write_record(obd, filp, lsd, sizeof(*lsd), &off,force_sync);
         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
         if (rc)
                 CERROR("error writing MDS server data: rc = %d\n", rc);
-
-        if (lsd_copy)
-                OBD_FREE(lsd_copy, sizeof(*lsd_copy));
-
         RETURN(rc);
 }
 
-static
-void fsoptions_to_mds_flags(struct mds_obd *mds, char *options)
+static void fsoptions_to_mds_flags(struct mds_obd *mds, char *options)
 {
         char *p = options;
 
+        if (!options)
+                return;
+
         while (*options) {
                 int len;
 
@@ -1774,13 +1794,24 @@ void fsoptions_to_mds_flags(struct mds_obd *mds, char *options)
                 if (len == sizeof("user_xattr") - 1 &&
                     memcmp(options, "user_xattr", len) == 0) {
                         mds->mds_fl_user_xattr = 1;
+                        LCONSOLE_INFO("Enabling user_xattr\n");
+                } else if (len == sizeof("nouser_xattr") - 1 &&
+                           memcmp(options, "nouser_xattr", len) == 0) {
+                        mds->mds_fl_user_xattr = 0;
+                        LCONSOLE_INFO("Disabling user_xattr\n");
                 } else if (len == sizeof("acl") - 1 &&
-                         memcmp(options, "acl", len) == 0) {
+                           memcmp(options, "acl", len) == 0) {
 #ifdef CONFIG_FS_POSIX_ACL
                         mds->mds_fl_acl = 1;
+                        LCONSOLE_INFO("Enabling ACL\n");
 #else
                         CWARN("ignoring unsupported acl mount option\n");
-                        memmove(options, p, strlen(p) + 1);
+#endif
+                } else if (len == sizeof("noacl") - 1 &&
+                           memcmp(options, "noacl", len) == 0) {
+#ifdef CONFIG_FS_POSIX_ACL
+                        mds->mds_fl_acl = 0;
+                        LCONSOLE_INFO("Disabling ACL\n");
 #endif
                 }
 
@@ -1848,6 +1879,8 @@ static int mds_setup(struct obd_device *obd, struct lustre_cfg* lcfg)
                 /* We already mounted in lustre_fill_super.
                    lcfg bufs 1, 2, 4 (device, fstype, mount opts) are ignored.*/
                 struct lustre_sb_info *lsi = s2lsi(lmi->lmi_sb);
+                fsoptions_to_mds_flags(mds, lsi->lsi_ldd->ldd_mount_opts);
+                fsoptions_to_mds_flags(mds, lsi->lsi_lmd->lmd_opts);
                 mnt = lmi->lmi_mnt;
                 obd->obd_fsops = fsfilt_get_ops(MT_STR(lsi->lsi_ldd));
         } else {
@@ -1892,7 +1925,6 @@ static int mds_setup(struct obd_device *obd, struct lustre_cfg* lcfg)
 
         LASSERT(!lvfs_check_rdonly(lvfs_sbdev(mnt->mnt_sb)));
 
-        //sema_init(&mds->mds_orphan_recovery_sem, 1);
         sema_init(&mds->mds_epoch_sem, 1);
         spin_lock_init(&mds->mds_transno_lock);
         mds->mds_max_mdsize = sizeof(struct lov_mds_md);
@@ -1974,7 +2006,7 @@ static int mds_setup(struct obd_device *obd, struct lustre_cfg* lcfg)
                               obd->obd_replayable ? "enabled" : "disabled");
         }
 
-        ldlm_timeout = 2;
+        ldlm_timeout = 6;
 
         RETURN(0);
 
@@ -2055,7 +2087,7 @@ static int mds_postsetup(struct obd_device *obd)
                 struct lustre_profile *lprof;
                 /* The profile defines which osc and mdc to connect to, for a
                    client.  We reuse that here to figure out the name of the
-                   lov to use (and ignore lprof->lp_mdc).
+                   lov to use (and ignore lprof->lp_md).
                    The profile was set in the config log with
                    LCFG_MOUNTOPT profilenm oscnm mdcnm */
                 lprof = class_get_profile(mds->mds_profile);
@@ -2063,7 +2095,7 @@ static int mds_postsetup(struct obd_device *obd)
                         CERROR("No profile found: %s\n", mds->mds_profile);
                         GOTO(err_cleanup, rc = -ENOENT);
                 }
-                rc = mds_lov_connect(obd, lprof->lp_osc);
+                rc = mds_lov_connect(obd, lprof->lp_dt);
                 if (rc)
                         GOTO(err_cleanup, rc);
         }
@@ -2198,10 +2230,12 @@ static int mds_cleanup(struct obd_device *obd)
                 unlock_kernel();
                 must_relock++;
         }
-
-        if (must_put)
+        
+        if (must_put) {
                 /* In case we didn't mount with lustre_get_mount -- old method*/
                 mntput(mds->mds_vfsmnt);
+                lvfs_clear_rdonly(save_dev);
+        }
         obd->u.obt.obt_sb = NULL;
 
         ldlm_namespace_free(obd->obd_namespace, obd->obd_force);
@@ -2213,8 +2247,6 @@ static int mds_cleanup(struct obd_device *obd)
         }
         spin_unlock_bh(&obd->obd_processing_task_lock);
 
-        lvfs_clear_rdonly(save_dev);
-
         if (must_relock)
                 lock_kernel();
 
@@ -2233,14 +2265,14 @@ static void fixup_handle_for_resent_req(struct ptlrpc_request *req, int offset,
         struct obd_export *exp = req->rq_export;
         struct obd_device *obd = exp->exp_obd;
         struct ldlm_request *dlmreq =
-                lustre_msg_buf(req->rq_reqmsg, offset, sizeof (*dlmreq));
+                lustre_msg_buf(req->rq_reqmsg, offset, sizeof(*dlmreq));
         struct lustre_handle remote_hdl = dlmreq->lock_handle1;
         struct list_head *iter;
 
         if (!(lustre_msg_get_flags(req->rq_reqmsg) & MSG_RESENT))
                 return;
 
-        l_lock(&obd->obd_namespace->ns_lock);
+        spin_lock(&obd->obd_namespace->ns_hash_lock);
         list_for_each(iter, &exp->exp_ldlm_data.led_held_locks) {
                 struct ldlm_lock *lock;
                 lock = list_entry(iter, struct ldlm_lock, l_export_chain);
@@ -2253,11 +2285,11 @@ static void fixup_handle_for_resent_req(struct ptlrpc_request *req, int offset,
                                   lockh->cookie);
                         if (old_lock)
                                 *old_lock = LDLM_LOCK_GET(lock);
-                        l_unlock(&obd->obd_namespace->ns_lock);
+                        spin_unlock(&obd->obd_namespace->ns_hash_lock);
                         return;
                 }
         }
-        l_unlock(&obd->obd_namespace->ns_lock);
+        spin_unlock(&obd->obd_namespace->ns_hash_lock);
 
         /* If the xid matches, then we know this is a resent request,
          * and allow it. (It's probably an OPEN, for which we don't
@@ -2266,6 +2298,10 @@ static void fixup_handle_for_resent_req(struct ptlrpc_request *req, int offset,
             le64_to_cpu(exp->exp_mds_data.med_mcd->mcd_last_xid))
                 return;
 
+        if (req->rq_xid ==
+            le64_to_cpu(exp->exp_mds_data.med_mcd->mcd_last_close_xid))
+                return;
+
         /* This remote handle isn't enqueued, so we never received or
          * processed this request.  Clear MSG_RESENT, because it can
          * be handled like any normal request now. */
@@ -2302,24 +2338,23 @@ static int mds_intent_policy(struct ldlm_namespace *ns,
         struct lustre_handle lockh = { 0 };
         struct ldlm_lock *new_lock = NULL;
         int getattr_part = MDS_INODELOCK_UPDATE;
-        int repsize[4] = {sizeof(*rep),
-                          sizeof(struct mds_body),
-                          mds->mds_max_mdsize};
-        int repbufcnt = 3, offset = MDS_REQ_INTENT_REC_OFF;
-        int rc;
+        int repsize[5] = { [MSG_PTLRPC_BODY_OFF] = sizeof(struct ptlrpc_body),
+                           [DLM_LOCKREPLY_OFF]   = sizeof(struct ldlm_reply),
+                           [DLM_REPLY_REC_OFF]   = sizeof(struct mds_body),
+                           [DLM_REPLY_REC_OFF+1] = mds->mds_max_mdsize };
+        int repbufcnt = 4, rc;
         ENTRY;
 
         LASSERT(req != NULL);
 
-        if (req->rq_reqmsg->bufcount <= MDS_REQ_INTENT_IT_OFF) {
+        if (lustre_msg_bufcount(req->rq_reqmsg) <= DLM_INTENT_IT_OFF) {
                 /* No intent was provided */
-                int size = sizeof(struct ldlm_reply);
-                rc = lustre_pack_reply(req, 1, &size, NULL);
+                rc = lustre_pack_reply(req, 2, repsize, NULL);
                 LASSERT(rc == 0);
                 RETURN(0);
         }
 
-        it = lustre_swab_reqbuf(req, MDS_REQ_INTENT_IT_OFF, sizeof(*it),
+        it = lustre_swab_reqbuf(req, DLM_INTENT_IT_OFF, sizeof(*it),
                                 lustre_swab_ldlm_intent);
         if (it == NULL) {
                 CERROR("Intent missing\n");
@@ -2339,7 +2374,7 @@ static int mds_intent_policy(struct ldlm_namespace *ns,
         if (rc)
                 RETURN(req->rq_status = rc);
 
-        rep = lustre_msg_buf(req->rq_repmsg, 0, sizeof (*rep));
+        rep = lustre_msg_buf(req->rq_repmsg, DLM_LOCKREPLY_OFF, sizeof(*rep));
         intent_set_disposition(rep, DISP_IT_EXECD);
 
 
@@ -2347,11 +2382,12 @@ static int mds_intent_policy(struct ldlm_namespace *ns,
         switch ((long)it->opc) {
         case IT_OPEN:
         case IT_CREAT|IT_OPEN:
-                fixup_handle_for_resent_req(req, MDS_REQ_INTENT_LOCKREQ_OFF,
-                                            lock, NULL, &lockh);
+                fixup_handle_for_resent_req(req, DLM_LOCKREQ_OFF, lock, NULL,
+                                            &lockh);
                 /* XXX swab here to assert that an mds_open reint
                  * packet is following */
-                rep->lock_policy_res2 = mds_reint(req, offset, &lockh);
+                rep->lock_policy_res2 = mds_reint(req, DLM_INTENT_REC_OFF,
+                                                  &lockh);
 #if 0
                 /* We abort the lock if the lookup was negative and
                  * we did not make it to the OPEN portion */
@@ -2360,15 +2396,21 @@ static int mds_intent_policy(struct ldlm_namespace *ns,
                 if (intent_disposition(rep, DISP_LOOKUP_NEG) &&
                     !intent_disposition(rep, DISP_OPEN_OPEN))
 #endif
+                if (rep->lock_policy_res2) {
+                        /* mds_open returns ENOLCK where it should return zero,
+                           but it has no lock to return */
+                        if (rep->lock_policy_res2 == ENOLCK)
+                                rep->lock_policy_res2 = 0;
                         RETURN(ELDLM_LOCK_ABORTED);
+                }
                 break;
         case IT_LOOKUP:
                         getattr_part = MDS_INODELOCK_LOOKUP;
         case IT_GETATTR:
                         getattr_part |= MDS_INODELOCK_LOOKUP;
         case IT_READDIR:
-                fixup_handle_for_resent_req(req, MDS_REQ_INTENT_LOCKREQ_OFF,
-                                            lock, &new_lock, &lockh);
+                fixup_handle_for_resent_req(req, DLM_LOCKREQ_OFF, lock,
+                                            &new_lock, &lockh);
 
                 /* INODEBITS_INTEROP: if this lock was converted from a
                  * plain lock (client does not support inodebits), then
@@ -2379,7 +2421,7 @@ static int mds_intent_policy(struct ldlm_namespace *ns,
                         getattr_part = MDS_INODELOCK_LOOKUP |
                                        MDS_INODELOCK_UPDATE;
 
-                rep->lock_policy_res2 = mds_getattr_name(offset, req,
+                rep->lock_policy_res2 = mds_getattr_lock(req,DLM_INTENT_REC_OFF,
                                                          getattr_part, &lockh);
                 /* FIXME: LDLM can set req->rq_status. MDS sets
                    policy_res{1,2} with disposition and status.
@@ -2437,7 +2479,7 @@ static int mds_intent_policy(struct ldlm_namespace *ns,
         }
 
         /* Fixup the lock to be given to the client */
-        l_lock(&new_lock->l_resource->lr_namespace->ns_lock);
+        lock_res_and_lock(new_lock);
         new_lock->l_readers = 0;
         new_lock->l_writers = 0;
 
@@ -2453,8 +2495,8 @@ static int mds_intent_policy(struct ldlm_namespace *ns,
 
         new_lock->l_flags &= ~LDLM_FL_LOCAL;
 
+        unlock_res_and_lock(new_lock);
         LDLM_LOCK_PUT(new_lock);
-        l_unlock(&new_lock->l_resource->lr_namespace->ns_lock);
 
         RETURN(ELDLM_LOCK_REPLACED);
 }
@@ -2610,6 +2652,18 @@ static int mds_health_check(struct obd_device *obd)
         return rc;
 }
 
+static int mds_process_config(struct obd_device *obd, obd_count len, void *buf)
+{
+        struct lustre_cfg *lcfg = buf;
+        struct lprocfs_static_vars lvars;
+        int rc;
+
+        lprocfs_init_vars(mds, &lvars);
+        
+        rc = class_process_proc_param(PARAM_MDT, lvars.obd_vars, lcfg, obd);
+        return(rc);
+}
+
 struct lvfs_callback_ops mds_lvfs_ops = {
         l_fid2dentry:     mds_lvfs_fid2dentry,
 };
@@ -2634,6 +2688,7 @@ static struct obd_ops mds_obd_ops = {
         .o_llog_finish     = mds_llog_finish,
         .o_notify          = mds_notify,
         .o_health_check    = mds_health_check,
+        .o_process_config  = mds_process_config,
 };
 
 static struct obd_ops mdt_obd_ops = {
index 615937a..c223723 100644 (file)
@@ -172,7 +172,7 @@ int mds_client_free(struct obd_export *exp)
                                          sizeof(zero_mcd), &off, 1);
                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
 
-                CDEBUG_EX(rc == 0 ? D_INFO : D_ERROR,
+                CDEBUG(rc == 0 ? D_INFO : D_ERROR,
                        "zeroing out client %s idx %u in %s rc %d\n",
                        med->med_mcd->mcd_uuid, med->med_lr_idx, LAST_RCVD, rc);
         }
@@ -245,8 +245,7 @@ static int mds_init_server_data(struct obd_device *obd, struct file *file)
                 lsd->lsd_client_start = cpu_to_le32(LR_CLIENT_START);
                 lsd->lsd_client_size = cpu_to_le16(LR_CLIENT_SIZE);
                 lsd->lsd_feature_rocompat = cpu_to_le32(OBD_ROCOMPAT_LOVOBJID);
-                lsd->lsd_feature_incompat = cpu_to_le32(OBD_INCOMPAT_MDT |
-                                                        OBD_INCOMPAT_COMMON_LR);
+                lsd->lsd_feature_incompat = cpu_to_le32(OBD_INCOMPAT_MDT);
         } else {
                 rc = fsfilt_read_record(obd, file, lsd, sizeof(*lsd), &off);
                 if (rc) {
@@ -260,6 +259,12 @@ static int mds_init_server_data(struct obd_device *obd, struct file *file)
                                        obd->obd_uuid.uuid, lsd->lsd_uuid);
                         GOTO(err_msd, rc = -EINVAL);
                 }
+                /* COMPAT_146 */
+                /* Assume old last_rcvd format unless I_C_LR is set */
+                if (!(lsd->lsd_feature_incompat & 
+                      cpu_to_le32(OBD_INCOMPAT_COMMON_LR)))
+                        lsd->lsd_mount_count = lsd->lsd_compat14;
+                /* end COMPAT_146 */
                 mount_count = le64_to_cpu(lsd->lsd_mount_count);
         }
 
@@ -276,15 +281,6 @@ static int mds_init_server_data(struct obd_device *obd, struct file *file)
                 /* Do something like remount filesystem read-only */
                 GOTO(err_msd, rc = -EINVAL);
         }
-        if (!(lsd->lsd_feature_incompat & cpu_to_le32(OBD_INCOMPAT_COMMON_LR))){
-                CDEBUG(D_WARNING, "using old last_rcvd format\n");
-                lsd->lsd_mount_count = lsd->lsd_last_transno;
-                lsd->lsd_last_transno = lsd->lsd_unused;
-                /* If we update the last_rcvd, we can never go back to
-                   an old install, so leave this in the old format for now.
-                lsd->lsd_feature_incompat |= cpu_to_le32(LR_INCOMPAT_COMMON_LR);
-                */
-        }
         lsd->lsd_feature_compat = cpu_to_le32(OBD_COMPAT_MDT);
 
         mds->mds_last_transno = le64_to_cpu(lsd->lsd_last_transno);
@@ -345,7 +341,10 @@ static int mds_init_server_data(struct obd_device *obd, struct file *file)
                         continue;
                 }
 
-                last_transno = le64_to_cpu(mcd->mcd_last_transno);
+                last_transno = le64_to_cpu(mcd->mcd_last_transno) >
+                               le64_to_cpu(mcd->mcd_last_close_transno) ?
+                               le64_to_cpu(mcd->mcd_last_transno) :
+                               le64_to_cpu(mcd->mcd_last_close_transno);
 
                 /* These exports are cleaned up by mds_disconnect(), so they
                  * need to be set up like real exports as mds_connect() does.
@@ -397,7 +396,8 @@ static int mds_init_server_data(struct obd_device *obd, struct file *file)
         }
 
         mds->mds_mount_count = mount_count + 1;
-        lsd->lsd_mount_count = cpu_to_le64(mds->mds_mount_count);
+        lsd->lsd_mount_count = lsd->lsd_compat14 = 
+                cpu_to_le64(mds->mds_mount_count);
 
         /* save it, so mount count and last_transno is current */
         rc = mds_update_server_data(obd, 1);
@@ -741,6 +741,7 @@ int mds_obd_destroy(struct obd_export *exp, struct obdo *oa,
         struct lvfs_run_ctxt saved;
         struct lvfs_ucred ucred = { 0 };
         char fidname[LL_FID_NAMELEN];
+        struct inode *inode = NULL;
         struct dentry *de;
         void *handle;
         int err, namelen, rc = 0;
@@ -774,6 +775,10 @@ int mds_obd_destroy(struct obd_export *exp, struct obdo *oa,
         if (IS_ERR(handle))
                 GOTO(out_dput, rc = PTR_ERR(handle));
 
+        /* take a reference to protect inode from truncation within
+           vfs_unlink() context. bug 10409 */
+        inode = de->d_inode;
+        atomic_inc(&inode->i_count);
         rc = vfs_unlink(mds->mds_objects_dir->d_inode, de);
         if (rc)
                 CERROR("error destroying object "LPU64":%u: rc %d\n",
@@ -787,6 +792,9 @@ out_dput:
                 l_dput(de);
         UNLOCK_INODE_MUTEX(parent_inode);
 
+        if (inode)
+                iput(inode);
+
         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, &ucred);
         RETURN(rc);
 }
index c947cee..308102a 100644 (file)
@@ -18,7 +18,12 @@ struct mds_client_data {
         __u64 mcd_last_xid;     /* xid for the last transaction */
         __u32 mcd_last_result;  /* result from last RPC */
         __u32 mcd_last_data;    /* per-op data (disposition for open &c.) */
-        __u8 mcd_padding[LR_CLIENT_SIZE - 64];
+        /* for MDS_CLOSE requests */
+        __u64 mcd_last_close_transno; /* last completed transaction ID */
+        __u64 mcd_last_close_xid;     /* xid for the last transaction */
+        __u32 mcd_last_close_result;  /* result from last RPC */
+        __u32 mcd_last_close_data;  /* per-op data (disposition for open &c.) */
+        __u8 mcd_padding[LR_CLIENT_SIZE - 88];
 };
 
 #define MDS_SERVICE_WATCHDOG_TIMEOUT (obd_timeout * 1000)
@@ -103,9 +108,13 @@ static inline void mds_inode_unset_orphan(struct inode *inode)
         if (lustre_msg_get_flags(req->rq_reqmsg) & MSG_RESENT) {              \
                 struct mds_client_data *mcd =                                 \
                         req->rq_export->exp_mds_data.med_mcd;                 \
-                if (mcd->mcd_last_xid == req->rq_xid) {                       \
+                if (le64_to_cpu(mcd->mcd_last_xid) == req->rq_xid) {          \
                         reconstruct;                                          \
-                        RETURN(req->rq_repmsg->status);                       \
+                        RETURN(le32_to_cpu(mcd->mcd_last_result));            \
+                }                                                             \
+                if (le64_to_cpu(mcd->mcd_last_close_xid) == req->rq_xid) {    \
+                        reconstruct;                                          \
+                        RETURN(le32_to_cpu(mcd->mcd_last_close_result));      \
                 }                                                             \
                 DEBUG_REQ(D_HA, req, "no reply for RESENT req (have "LPD64")",\
                           mcd->mcd_last_xid);                                 \
@@ -153,7 +162,7 @@ int mds_get_parents_children_locked(struct obd_device *obd,
                                     int child_mode);
 
 void mds_shrink_reply(struct obd_device *obd, struct ptlrpc_request *req,
-                      struct mds_body *body);
+                      struct mds_body *body, int md_off);
 int mds_get_cookie_size(struct obd_device *obd, struct lov_mds_md *lmm);
 /* mds/mds_lib.c */
 int mds_update_unpack(struct ptlrpc_request *, int offset,
@@ -196,7 +205,7 @@ int mds_open(struct mds_update_record *rec, int offset,
              struct ptlrpc_request *req, struct lustre_handle *);
 int mds_pin(struct ptlrpc_request *req, int offset);
 void mds_mfd_unlink(struct mds_file_data *mfd, int decref);
-int mds_mfd_close(struct ptlrpc_request *req, int offset, struct obd_device *obd,
+int mds_mfd_close(struct ptlrpc_request *req, int offset,struct obd_device *obd,
                   struct mds_file_data *mfd, int unlink_orphan);
 int mds_close(struct ptlrpc_request *req, int offset);
 int mds_done_writing(struct ptlrpc_request *req, int offset);
index 3c17a05..c5c5e2c 100644 (file)
@@ -218,7 +218,7 @@ static void mds_finish_join(struct mds_obd *mds, struct ptlrpc_request *req,
                                 sizeof(struct llog_cookie);
         int max_easize = sizeof(*lmmj);
 
-        CDEBUG(D_INFO, "change the max md size from %d to %d \n",
+        CDEBUG(D_INFO, "change the max md size from %d to "LPSZ"\n",
                mds->mds_max_mdsize, sizeof(*lmmj));
 
         if (mds->mds_max_mdsize < max_easize ||
@@ -354,8 +354,9 @@ int mds_join_file(struct mds_update_record *rec, struct ptlrpc_request *req,
         struct mds_rec_join *join_rec;
         ENTRY;
 
-        join_rec = lustre_swab_reqbuf (req, 5, sizeof (*join_rec),
-                                       lustre_swab_mds_rec_join);
+        join_rec = lustre_swab_reqbuf(req, DLM_INTENT_REC_OFF + 3,
+                                      sizeof(*join_rec),
+                                      lustre_swab_mds_rec_join);
         if (join_rec == NULL)
                 RETURN (-EFAULT);
 
index c136494..a0f0a7a 100644 (file)
@@ -80,7 +80,7 @@ void mds_pack_inode2body(struct mds_body *b, struct inode *inode)
         b->blocks = inode->i_blocks;
         b->uid = inode->i_uid;
         b->gid = inode->i_gid;
-        b->flags = inode->i_flags;
+        b->flags = ll_inode_to_ext_flags(b->flags, inode->i_flags);
         b->rdev = inode->i_rdev;
         /* Return the correct link count for orphan inodes */
         b->nlink = mds_inode_is_orphan(inode) ? 0 : inode->i_nlink;
@@ -115,23 +115,22 @@ static int mds_setattr_unpack(struct ptlrpc_request *req, int offset,
         LTIME_S(attr->ia_atime) = rec->sa_atime;
         LTIME_S(attr->ia_mtime) = rec->sa_mtime;
         LTIME_S(attr->ia_ctime) = rec->sa_ctime;
-        attr->ia_attr_flags = rec->sa_attr_flags;
+        r->ur_flags = rec->sa_attr_flags;
 
         LASSERT_REQSWAB (req, offset + 1);
-        if (req->rq_reqmsg->bufcount > offset + 1) {
-                r->ur_eadata = lustre_msg_buf (req->rq_reqmsg,
-                                               offset + 1, 0);
+        if (lustre_msg_bufcount(req->rq_reqmsg) > offset + 1) {
+                r->ur_eadata = lustre_msg_buf(req->rq_reqmsg, offset + 1, 0);
                 if (r->ur_eadata == NULL)
-                        RETURN (-EFAULT);
-                r->ur_eadatalen = req->rq_reqmsg->buflens[offset + 1];
+                        RETURN(-EFAULT);
+                r->ur_eadatalen = lustre_msg_buflen(req->rq_reqmsg, offset + 1);
         }
 
-        if (req->rq_reqmsg->bufcount > offset + 2) {
+        if (lustre_msg_bufcount(req->rq_reqmsg) > offset + 2) {
                 r->ur_logcookies = lustre_msg_buf(req->rq_reqmsg, offset + 2,0);
                 if (r->ur_eadata == NULL)
                         RETURN (-EFAULT);
 
-                r->ur_cookielen = req->rq_reqmsg->buflens[offset + 2];
+                r->ur_cookielen = lustre_msg_buflen(req->rq_reqmsg, offset + 2);
         }
 
         RETURN(0);
@@ -143,8 +142,8 @@ static int mds_create_unpack(struct ptlrpc_request *req, int offset,
         struct mds_rec_create *rec;
         ENTRY;
 
-        rec = lustre_swab_reqbuf (req, offset, sizeof (*rec),
-                                  lustre_swab_mds_rec_create);
+        rec = lustre_swab_reqbuf(req, offset, sizeof (*rec),
+                                 lustre_swab_mds_rec_create);
         if (rec == NULL)
                 RETURN (-EFAULT);
 
@@ -160,14 +159,14 @@ static int mds_create_unpack(struct ptlrpc_request *req, int offset,
         r->ur_time = rec->cr_time;
         r->ur_flags = rec->cr_flags;
 
-        LASSERT_REQSWAB (req, offset + 1);
-        r->ur_name = lustre_msg_string (req->rq_reqmsg, offset + 1, 0);
+        LASSERT_REQSWAB(req, offset + 1);
+        r->ur_name = lustre_msg_string(req->rq_reqmsg, offset + 1, 0);
         if (r->ur_name == NULL)
                 RETURN (-EFAULT);
-        r->ur_namelen = req->rq_reqmsg->buflens[offset + 1];
+        r->ur_namelen = lustre_msg_buflen(req->rq_reqmsg, offset + 1);
 
-        LASSERT_REQSWAB (req, offset + 2);
-        if (req->rq_reqmsg->bufcount > offset + 2) {
+        LASSERT_REQSWAB(req, offset + 2);
+        if (lustre_msg_bufcount(req->rq_reqmsg) > offset + 2) {
                 /* NB for now, we only seem to pass NULL terminated symlink
                  * target strings here.  If this ever changes, we'll have
                  * to stop checking for a buffer filled completely with a
@@ -178,7 +177,7 @@ static int mds_create_unpack(struct ptlrpc_request *req, int offset,
                 r->ur_tgt = lustre_msg_string(req->rq_reqmsg, offset + 2, 0);
                 if (r->ur_tgt == NULL)
                         RETURN (-EFAULT);
-                r->ur_tgtlen = req->rq_reqmsg->buflens[offset + 2];
+                r->ur_tgtlen = lustre_msg_buflen(req->rq_reqmsg, offset + 2);
         }
         RETURN(0);
 }
@@ -189,8 +188,8 @@ static int mds_link_unpack(struct ptlrpc_request *req, int offset,
         struct mds_rec_link *rec;
         ENTRY;
 
-        rec = lustre_swab_reqbuf (req, offset, sizeof (*rec),
-                                  lustre_swab_mds_rec_link);
+        rec = lustre_swab_reqbuf(req, offset, sizeof (*rec),
+                                 lustre_swab_mds_rec_link);
         if (rec == NULL)
                 RETURN (-EFAULT);
 
@@ -203,11 +202,11 @@ static int mds_link_unpack(struct ptlrpc_request *req, int offset,
         r->ur_fid2 = &rec->lk_fid2;
         r->ur_time = rec->lk_time;
 
-        LASSERT_REQSWAB (req, offset + 1);
-        r->ur_name = lustre_msg_string (req->rq_reqmsg, offset + 1, 0);
+        LASSERT_REQSWAB(req, offset + 1);
+        r->ur_name = lustre_msg_string(req->rq_reqmsg, offset + 1, 0);
         if (r->ur_name == NULL)
                 RETURN (-EFAULT);
-        r->ur_namelen = req->rq_reqmsg->buflens[offset + 1];
+        r->ur_namelen = lustre_msg_buflen(req->rq_reqmsg, offset + 1);
         RETURN(0);
 }
 
@@ -217,8 +216,8 @@ static int mds_unlink_unpack(struct ptlrpc_request *req, int offset,
         struct mds_rec_unlink *rec;
         ENTRY;
 
-        rec = lustre_swab_reqbuf (req, offset, sizeof (*rec),
-                                  lustre_swab_mds_rec_unlink);
+        rec = lustre_swab_reqbuf(req, offset, sizeof (*rec),
+                                 lustre_swab_mds_rec_unlink);
         if (rec == NULL)
                 RETURN(-EFAULT);
 
@@ -232,11 +231,11 @@ static int mds_unlink_unpack(struct ptlrpc_request *req, int offset,
         r->ur_fid2 = &rec->ul_fid2;
         r->ur_time = rec->ul_time;
 
-        LASSERT_REQSWAB (req, offset + 1);
+        LASSERT_REQSWAB(req, offset + 1);
         r->ur_name = lustre_msg_string(req->rq_reqmsg, offset + 1, 0);
         if (r->ur_name == NULL)
                 RETURN(-EFAULT);
-        r->ur_namelen = req->rq_reqmsg->buflens[offset + 1];
+        r->ur_namelen = lustre_msg_buflen(req->rq_reqmsg, offset + 1);
         RETURN(0);
 }
 
@@ -246,8 +245,8 @@ static int mds_rename_unpack(struct ptlrpc_request *req, int offset,
         struct mds_rec_rename *rec;
         ENTRY;
 
-        rec = lustre_swab_reqbuf (req, offset, sizeof (*rec),
-                                  lustre_swab_mds_rec_rename);
+        rec = lustre_swab_reqbuf(req, offset, sizeof (*rec),
+                                 lustre_swab_mds_rec_rename);
         if (rec == NULL)
                 RETURN(-EFAULT);
 
@@ -264,13 +263,13 @@ static int mds_rename_unpack(struct ptlrpc_request *req, int offset,
         r->ur_name = lustre_msg_string(req->rq_reqmsg, offset + 1, 0);
         if (r->ur_name == NULL)
                 RETURN(-EFAULT);
-        r->ur_namelen = req->rq_reqmsg->buflens[offset + 1];
+        r->ur_namelen = lustre_msg_buflen(req->rq_reqmsg, offset + 1);
 
         LASSERT_REQSWAB (req, offset + 2);
         r->ur_tgt = lustre_msg_string(req->rq_reqmsg, offset + 2, 0);
         if (r->ur_tgt == NULL)
                 RETURN(-EFAULT);
-        r->ur_tgtlen = req->rq_reqmsg->buflens[offset + 2];
+        r->ur_tgtlen = lustre_msg_buflen(req->rq_reqmsg, offset + 2);
         RETURN(0);
 }
 
@@ -280,10 +279,10 @@ static int mds_open_unpack(struct ptlrpc_request *req, int offset,
         struct mds_rec_create *rec;
         ENTRY;
 
-        rec = lustre_swab_reqbuf (req, offset, sizeof (*rec),
-                                  lustre_swab_mds_rec_create);
+        rec = lustre_swab_reqbuf(req, offset, sizeof(*rec),
+                                 lustre_swab_mds_rec_create);
         if (rec == NULL)
-                RETURN (-EFAULT);
+                RETURN(-EFAULT);
 
         r->ur_uc.luc_fsuid = rec->cr_fsuid;
         r->ur_uc.luc_fsgid = rec->cr_fsgid;
@@ -297,18 +296,18 @@ static int mds_open_unpack(struct ptlrpc_request *req, int offset,
         r->ur_time = rec->cr_time;
         r->ur_flags = rec->cr_flags;
 
-        LASSERT_REQSWAB (req, offset + 1);
-        r->ur_name = lustre_msg_string (req->rq_reqmsg, offset + 1, 0);
+        LASSERT_REQSWAB(req, offset + 1);
+        r->ur_name = lustre_msg_string(req->rq_reqmsg, offset + 1, 0);
         if (r->ur_name == NULL)
-                RETURN (-EFAULT);
-        r->ur_namelen = req->rq_reqmsg->buflens[offset + 1];
+                RETURN(-EFAULT);
+        r->ur_namelen = lustre_msg_buflen(req->rq_reqmsg, offset + 1);
 
-        LASSERT_REQSWAB (req, offset + 2);
-        if (req->rq_reqmsg->bufcount > offset + 2) {
+        LASSERT_REQSWAB(req, offset + 2);
+        if (lustre_msg_bufcount(req->rq_reqmsg) > offset + 2) {
                 r->ur_eadata = lustre_msg_buf(req->rq_reqmsg, offset + 2, 0);
                 if (r->ur_eadata == NULL)
                         RETURN (-EFAULT);
-                r->ur_eadatalen = req->rq_reqmsg->buflens[offset + 2];
+                r->ur_eadatalen = lustre_msg_buflen(req->rq_reqmsg, offset + 2);
         }
         RETURN(0);
 }
@@ -335,13 +334,13 @@ int mds_update_unpack(struct ptlrpc_request *req, int offset,
         /* NB don't lustre_swab_reqbuf() here.  We're just taking a peek
          * and we want to leave it to the specific unpacker once we've
          * identified the message type */
-        opcodep = lustre_msg_buf (req->rq_reqmsg, offset, sizeof (*opcodep));
+        opcodep = lustre_msg_buf(req->rq_reqmsg, offset, sizeof (*opcodep));
         if (opcodep == NULL)
                 RETURN(-EFAULT);
 
         opcode = *opcodep;
-        if (lustre_msg_swabbed (req->rq_reqmsg))
-                __swab32s (&opcode);
+        if (lustre_msg_swabbed(req->rq_reqmsg))
+                __swab32s(&opcode);
 
         if (opcode >= REINT_MAX || mds_unpackers[opcode] == NULL) {
                 CERROR("Unexpected opcode %d\n", opcode);
index a3351ef..67403eb 100644 (file)
@@ -87,7 +87,7 @@ static int mds_llog_repl_cancel(struct llog_ctxt *ctxt, struct lov_stripe_md *ls
         RETURN(rc);
 }
 
-int mds_log_op_unlink(struct obd_device *obd, struct inode *inode,
+int mds_log_op_unlink(struct obd_device *obd, 
                       struct lov_mds_md *lmm, int lmm_size,
                       struct llog_cookie *logcookies, int cookies_size)
 {
@@ -101,7 +101,7 @@ int mds_log_op_unlink(struct obd_device *obd, struct inode *inode,
         if (IS_ERR(mds->mds_osc_obd))
                 RETURN(PTR_ERR(mds->mds_osc_obd));
 
-        rc = obd_unpackmd(mds->mds_osc_exp,  &lsm, lmm, lmm_size);
+        rc = obd_unpackmd(mds->mds_osc_exp, &lsm, lmm, lmm_size);
         if (rc < 0)
                 RETURN(rc);
         rc = obd_checkmd(mds->mds_osc_exp, obd->obd_self_export, lsm);
index 993afb8..d65b366 100644 (file)
@@ -263,7 +263,7 @@ static struct mds_file_data *mds_dentry_open(struct dentry *dentry,
                 GOTO(cleanup_dentry, error = -ENOMEM);
         }
 
-        body = lustre_msg_buf(req->rq_repmsg, 1, sizeof (*body));
+        body = lustre_msg_buf(req->rq_repmsg, DLM_REPLY_REC_OFF, sizeof(*body));
 
         if (flags & FMODE_WRITE) {
                 /* FIXME: in recovery, need to pass old epoch here */
@@ -312,11 +312,10 @@ static int mds_create_objects(struct ptlrpc_request *req, int offset,
 {
         struct inode *inode = dchild->d_inode;
         struct obd_trans_info oti = { 0 };
-        struct lov_stripe_md *lsm = NULL;
         struct lov_mds_md *lmm = NULL;
         int rc, lmm_size;
         struct mds_body *body;
-        struct obdo *oa;
+        struct obd_info oinfo = { { { 0 } } };
         void *lmm_buf;
         ENTRY;
 
@@ -326,7 +325,7 @@ static int mds_create_objects(struct ptlrpc_request *req, int offset,
             !(rec->ur_flags & FMODE_WRITE))
                 RETURN(0);
 
-        body = lustre_msg_buf(req->rq_repmsg, 1, sizeof(*body));
+        body = lustre_msg_buf(req->rq_repmsg, DLM_REPLY_REC_OFF, sizeof(*body));
 
         if (body->valid & OBD_MD_FLEASIZE)
                 RETURN(0);
@@ -360,29 +359,30 @@ static int mds_create_objects(struct ptlrpc_request *req, int offset,
                 mds_objids_from_lmm(*ids, lmm, &mds->mds_lov_desc);
 
                 rc = fsfilt_set_md(obd, inode, *handle, lmm, lmm_size, "lov");
+                if (rc)
+                        CERROR("open replay failed to set md:%d\n", rc);
                 lmm_buf = lustre_msg_buf(req->rq_repmsg, offset, lmm_size);
                 LASSERT(lmm_buf);
                 memcpy(lmm_buf, lmm, lmm_size);
-                if (rc)
-                        CERROR("open replay failed to set md:%d\n", rc);
+
                 RETURN(rc);
         }
 
         if (OBD_FAIL_CHECK_ONCE(OBD_FAIL_MDS_ALLOC_OBDO))
                 GOTO(out_ids, rc = -ENOMEM);
 
-        oa = obdo_alloc();
-        if (oa == NULL)
+        oinfo.oi_oa = obdo_alloc();
+        if (oinfo.oi_oa == NULL)
                 GOTO(out_ids, rc = -ENOMEM);
-        oa->o_uid = 0; /* must have 0 uid / gid on OST */
-        oa->o_gid = 0;
-        oa->o_mode = S_IFREG | 0600;
-        oa->o_id = inode->i_ino;
-        oa->o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLFLAGS |
+        oinfo.oi_oa->o_uid = 0; /* must have 0 uid / gid on OST */
+        oinfo.oi_oa->o_gid = 0;
+        oinfo.oi_oa->o_mode = S_IFREG | 0600;
+        oinfo.oi_oa->o_id = inode->i_ino;
+        oinfo.oi_oa->o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLFLAGS |
                 OBD_MD_FLMODE | OBD_MD_FLUID | OBD_MD_FLGID;
-        oa->o_size = 0;
+        oinfo.oi_oa->o_size = 0;
 
-        obdo_from_inode(oa, inode, OBD_MD_FLTYPE | OBD_MD_FLATIME |
+        obdo_from_inode(oinfo.oi_oa, inode, OBD_MD_FLTYPE | OBD_MD_FLATIME |
                         OBD_MD_FLMTIME | OBD_MD_FLCTIME);
 
         if (!(rec->ur_flags & MDS_OPEN_HAS_OBJS)) {
@@ -390,7 +390,7 @@ static int mds_create_objects(struct ptlrpc_request *req, int offset,
                 if (rec->ur_flags & MDS_OPEN_HAS_EA) {
                         rc = obd_iocontrol(OBD_IOC_LOV_SETSTRIPE,
                                            mds->mds_osc_exp,
-                                           0, &lsm, rec->ur_eadata);
+                                           0, &oinfo.oi_md, rec->ur_eadata);
                         if (rc)
                                 GOTO(out_oa, rc);
                 } else {
@@ -404,17 +404,18 @@ static int mds_create_objects(struct ptlrpc_request *req, int offset,
                         if (rc > 0)
                                 rc = obd_iocontrol(OBD_IOC_LOV_SETSTRIPE,
                                                    mds->mds_osc_exp,
-                                                   0, &lsm, lmm);
+                                                   0, &oinfo.oi_md, lmm);
                         OBD_FREE(lmm, mds->mds_max_mdsize);
                         if (rc)
                                 GOTO(out_oa, rc);
                 }
-                rc = obd_create(mds->mds_osc_exp, oa, &lsm, &oti);
+                rc = obd_create(mds->mds_osc_exp, oinfo.oi_oa, 
+                                &oinfo.oi_md, &oti);
                 if (rc) {
                         int level = D_ERROR;
                         if (rc == -ENOSPC)
                                 level = D_INODE;
-                        CDEBUG_EX(level, "error creating objects for "
+                        CDEBUG(level, "error creating objects for "
                                       "inode %lu: rc = %d\n",
                                inode->i_ino, rc);
                         if (rc > 0) {
@@ -426,28 +427,30 @@ static int mds_create_objects(struct ptlrpc_request *req, int offset,
                 }
         } else {
                 rc = obd_iocontrol(OBD_IOC_LOV_SETEA, mds->mds_osc_exp,
-                                   0, &lsm, rec->ur_eadata);
+                                   0, &oinfo.oi_md, rec->ur_eadata);
                 if (rc) {
                         GOTO(out_oa, rc);
                 }
-                lsm->lsm_object_id = oa->o_id;
+                oinfo.oi_md->lsm_object_id = oinfo.oi_oa->o_id;
         }
         if (inode->i_size) {
-                oa->o_size = inode->i_size;
-                obdo_from_inode(oa, inode, OBD_MD_FLTYPE | OBD_MD_FLATIME |
-                                OBD_MD_FLMTIME | OBD_MD_FLCTIME | OBD_MD_FLSIZE);
+                oinfo.oi_oa->o_size = inode->i_size;
+                obdo_from_inode(oinfo.oi_oa, inode, OBD_MD_FLTYPE | 
+                                OBD_MD_FLATIME | OBD_MD_FLMTIME | 
+                                OBD_MD_FLCTIME | OBD_MD_FLSIZE);
 
                 /* pack lustre id to OST */
-                oa->o_fid = body->fid1.id;
-                oa->o_generation = body->fid1.generation;
-                oa->o_valid |= OBD_MD_FLFID | OBD_MD_FLGENER;
+                oinfo.oi_oa->o_fid = body->fid1.id;
+                oinfo.oi_oa->o_generation = body->fid1.generation;
+                oinfo.oi_oa->o_valid |= OBD_MD_FLFID | OBD_MD_FLGENER;
 
-                rc = obd_setattr(mds->mds_osc_exp, oa, lsm, &oti);
+                rc = obd_setattr_rqset(mds->mds_osc_exp, &oinfo, &oti);
                 if (rc) {
                         CERROR("error setting attrs for inode %lu: rc %d\n",
                                inode->i_ino, rc);
                         if (rc > 0) {
-                                CERROR("obd_setattr returned bad rc %d\n", rc);
+                                CERROR("obd_setattr_async returned bad rc %d\n",
+                                       rc);
                                 rc = -EIO;
                         }
                         GOTO(out_oa, rc);
@@ -455,11 +458,11 @@ static int mds_create_objects(struct ptlrpc_request *req, int offset,
         }
 
         body->valid |= OBD_MD_FLBLKSZ | OBD_MD_FLEASIZE;
-        obdo_refresh_inode(inode, oa, OBD_MD_FLBLKSZ);
+        obdo_refresh_inode(inode, oinfo.oi_oa, OBD_MD_FLBLKSZ);
 
-        LASSERT(lsm && lsm->lsm_object_id);
+        LASSERT(oinfo.oi_md && oinfo.oi_md->lsm_object_id);
         lmm = NULL;
-        rc = obd_packmd(mds->mds_osc_exp, &lmm, lsm);
+        rc = obd_packmd(mds->mds_osc_exp, &lmm, oinfo.oi_md);
         if (rc < 0) {
                 CERROR("cannot pack lsm, err = %d\n", rc);
                 GOTO(out_oa, rc);
@@ -482,14 +485,14 @@ static int mds_create_objects(struct ptlrpc_request *req, int offset,
         obd_free_diskmd(mds->mds_osc_exp, &lmm);
  out_oa:
         oti_free_cookies(&oti);
-        obdo_free(oa);
+        obdo_free(oinfo.oi_oa);
  out_ids:
         if (rc) {
                 OBD_FREE(*ids, mds->mds_lov_desc.ld_tgt_count * sizeof(**ids));
                 *ids = NULL;
         }
-        if (lsm)
-                obd_free_memmd(mds->mds_osc_exp, &lsm);
+        if (oinfo.oi_md)
+                obd_free_memmd(mds->mds_osc_exp, &oinfo.oi_md);
         RETURN(rc);
 }
 
@@ -510,13 +513,13 @@ static void reconstruct_open(struct mds_update_record *rec, int offset,
         int put_child = 1;
         ENTRY;
 
-        LASSERT(offset == 2);                  /* only called via intent */
-        rep = lustre_msg_buf(req->rq_repmsg, 0, sizeof (*rep));
-        body = lustre_msg_buf(req->rq_repmsg, 1, sizeof (*body));
+        LASSERT(offset == DLM_INTENT_REC_OFF); /* only called via intent */
+        rep = lustre_msg_buf(req->rq_repmsg, DLM_LOCKREPLY_OFF, sizeof(*rep));
+        body = lustre_msg_buf(req->rq_repmsg, DLM_REPLY_REC_OFF, sizeof(*body));
 
         /* copy rc, transno and disp; steal locks */
         mds_req_from_mcd(req, mcd);
-        intent_set_disposition(rep, mcd->mcd_last_data);
+        intent_set_disposition(rep, le32_to_cpu(mcd->mcd_last_data));
 
         /* Only replay if create or open actually happened. */
         if (!intent_disposition(rep, DISP_OPEN_CREATE | DISP_OPEN_OPEN) ) {
@@ -545,8 +548,8 @@ static void reconstruct_open(struct mds_update_record *rec, int offset,
         mds_pack_inode2fid(&body->fid1, dchild->d_inode);
         mds_pack_inode2body(body, dchild->d_inode);
         if (S_ISREG(dchild->d_inode->i_mode)) {
-                rc = mds_pack_md(obd, req->rq_repmsg, 2, body,
-                                 dchild->d_inode, 1);
+                rc = mds_pack_md(obd, req->rq_repmsg, DLM_REPLY_REC_OFF + 1,
+                                 body, dchild->d_inode, 1);
 
                 if (rc)
                         LASSERT(rc == req->rq_status);
@@ -558,11 +561,12 @@ static void reconstruct_open(struct mds_update_record *rec, int offset,
         }
 
         if (!(rec->ur_flags & MDS_OPEN_JOIN_FILE))
-                lustre_shrink_reply(req, 2, body->eadatasize, 0);
+                lustre_shrink_reply(req, DLM_REPLY_REC_OFF + 1,
+                                    body->eadatasize, 0);
 
         if (req->rq_export->exp_connect_flags & OBD_CONNECT_ACL &&
             !(rec->ur_flags & MDS_OPEN_JOIN_FILE)) {
-                int acl_off = body->eadatasize ? 3 : 2;
+                int acl_off = DLM_REPLY_REC_OFF + (body->eadatasize ? 2 : 1);
 
                 rc = mds_pack_acl(med, dchild->d_inode, req->rq_repmsg,
                                   body, acl_off);
@@ -678,8 +682,8 @@ static int mds_finish_open(struct ptlrpc_request *req, struct dentry *dchild,
 
         if (S_ISREG(dchild->d_inode->i_mode) &&
             !(body->valid & OBD_MD_FLEASIZE)) {
-                rc = mds_pack_md(obd, req->rq_repmsg, 2, body,
-                                 dchild->d_inode, 0);
+                rc = mds_pack_md(obd, req->rq_repmsg, DLM_REPLY_REC_OFF + 1,
+                                 body, dchild->d_inode, 0);
                 if (rc) {
                         UNLOCK_INODE_MUTEX(dchild->d_inode);
                         RETURN(rc);
@@ -701,8 +705,8 @@ static int mds_finish_open(struct ptlrpc_request *req, struct dentry *dchild,
                 if (!(body->valid & OBD_MD_FLEASIZE) &&
                     !(body->valid & OBD_MD_FLMODEASIZE)) {
                         /* no EA: create objects */
-                        rc = mds_create_objects(req, 2, rec, mds, obd,
-                                                dchild, handle, &ids);
+                        rc = mds_create_objects(req, DLM_REPLY_REC_OFF + 1, rec,
+                                                mds, obd, dchild, handle, &ids);
                         if (rc) {
                                 CERROR("mds_create_objects: rc = %d\n", rc);
                                 UNLOCK_INODE_MUTEX(dchild->d_inode);
@@ -718,12 +722,13 @@ static int mds_finish_open(struct ptlrpc_request *req, struct dentry *dchild,
         }
         UNLOCK_INODE_MUTEX(dchild->d_inode);
 
-        if (!(rec->ur_flags & MDS_OPEN_JOIN_FILE))
-                lustre_shrink_reply(req, 2, body->eadatasize, 0);
+        if (rec && !(rec->ur_flags & MDS_OPEN_JOIN_FILE))
+                lustre_shrink_reply(req, DLM_REPLY_REC_OFF + 1,
+                                    body->eadatasize, 0);
 
         if (req->rq_export->exp_connect_flags & OBD_CONNECT_ACL &&
-            !(rec->ur_flags & MDS_OPEN_JOIN_FILE)) {
-                int acl_off = body->eadatasize ? 3 : 2;
+            rec && !(rec->ur_flags & MDS_OPEN_JOIN_FILE)) {
+                int acl_off = DLM_REPLY_REC_OFF + (body->eadatasize ? 2 : 1);
 
                 rc = mds_pack_acl(&req->rq_export->exp_mds_data,
                                   dchild->d_inode, req->rq_repmsg,
@@ -745,8 +750,9 @@ static int mds_finish_open(struct ptlrpc_request *req, struct dentry *dchild,
                 mds_lov_update_objids(obd, ids);
                 OBD_FREE(ids, sizeof(*ids) * mds->mds_lov_desc.ld_tgt_count);
         }
-        if (rc)
+        if (rc) /* coverity[deadcode] */
                 mds_mfd_unlink(mfd, 1);
+
         mds_mfd_put(mfd);
         RETURN(rc);
 }
@@ -801,22 +807,22 @@ static int mds_open_by_fid(struct ptlrpc_request *req, struct ll_fid *fid,
 int mds_pin(struct ptlrpc_request *req, int offset)
 {
         struct obd_device *obd = req->rq_export->exp_obd;
-        struct mds_body *request_body, *reply_body;
+        struct mds_body *reqbody, *repbody;
         struct lvfs_run_ctxt saved;
-        int rc, size = sizeof(*reply_body);
+        int rc, size[2] = { sizeof(struct ptlrpc_body), sizeof(*repbody) };
         ENTRY;
 
-        request_body = lustre_msg_buf(req->rq_reqmsg, offset,
-                                      sizeof(*request_body));
+        reqbody = lustre_msg_buf(req->rq_reqmsg, offset, sizeof(*reqbody));
 
-        rc = lustre_pack_reply(req, 1, &size, NULL);
+        rc = lustre_pack_reply(req, 2, size, NULL);
         if (rc)
                 RETURN(rc);
-        reply_body = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*reply_body));
+        repbody = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
+                                 sizeof(*repbody));
 
         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
-        rc = mds_open_by_fid(req, &request_body->fid1, reply_body,
-                             request_body->flags, NULL, NULL);
+        rc = mds_open_by_fid(req, &reqbody->fid1, repbody, reqbody->flags, NULL,
+                             NULL);
         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
 
         RETURN(rc);
@@ -831,18 +837,18 @@ int mds_lock_new_child(struct obd_device *obd, struct inode *inode,
 {
         struct ldlm_res_id child_res_id = { .name = { inode->i_ino, 0, 1, 0 } };
         struct lustre_handle lockh;
-        int lock_flags = 0;
+        int lock_flags = LDLM_FL_ATOMIC_CB;
         int rc;
 
         if (child_lockh == NULL)
                 child_lockh = &lockh;
 
-        rc = ldlm_cli_enqueue(NULL, NULL, obd->obd_namespace, child_res_id,
-                              LDLM_PLAIN, NULL, LCK_EX, &lock_flags,
-                              ldlm_blocking_ast, ldlm_completion_ast,
-                              NULL, NULL, NULL, 0, NULL, child_lockh);
+        rc = ldlm_cli_enqueue_local(obd->obd_namespace, child_res_id,
+                                    LDLM_PLAIN, NULL, LCK_EX, &lock_flags,
+                                    ldlm_blocking_ast, ldlm_completion_ast,
+                                    NULL, NULL, 0, NULL, child_lockh);
         if (rc != ELDLM_OK)
-                CERROR("ldlm_cli_enqueue: %d\n", rc);
+                CERROR("ldlm_cli_enqueue_local: %d\n", rc);
         else if (child_lockh == &lockh)
                 ldlm_lock_decref(child_lockh, LCK_EX);
 
@@ -864,16 +870,29 @@ int mds_open(struct mds_update_record *rec, int offset,
         int parent_mode = LCK_CR;
         void *handle = NULL;
         struct dentry_params dp;
-        unsigned int qcids[MAXQUOTAS] = {current->fsuid, current->fsgid};
-        unsigned int qpids[MAXQUOTAS] = {0, 0};
+        unsigned int qcids[MAXQUOTAS] = { current->fsuid, current->fsgid };
+        unsigned int qpids[MAXQUOTAS] = { 0, 0 };
+        int child_mode = LCK_CR;
+        /* Always returning LOOKUP lock if open succesful to guard
+           dentry on client. */
+        ldlm_policy_data_t policy = {.l_inodebits={MDS_INODELOCK_LOOKUP}};
+        struct ldlm_res_id child_res_id = { .name = {0}};
+        int lock_flags = 0;
         ENTRY;
 
+        OBD_FAIL_TIMEOUT(OBD_FAIL_MDS_PAUSE_OPEN | OBD_FAIL_ONCE,
+                         (obd_timeout + 1) / 4);
+
         CLASSERT(MAXQUOTAS < 4);
-        if (offset == 2) { /* intent */
-                rep = lustre_msg_buf(req->rq_repmsg, 0, sizeof (*rep));
-                body = lustre_msg_buf(req->rq_repmsg, 1, sizeof (*body));
-        } else if (offset == MDS_REQ_REC_OFF) { /* non-intent reint */
-                body = lustre_msg_buf(req->rq_repmsg, 0, sizeof (*body));
+        if (offset == DLM_INTENT_REC_OFF) { /* intent */
+                rep = lustre_msg_buf(req->rq_repmsg, DLM_LOCKREPLY_OFF,
+                                     sizeof(*rep));
+                body = lustre_msg_buf(req->rq_repmsg, DLM_REPLY_REC_OFF,
+                                      sizeof(*body));
+        } else if (offset == REQ_REC_OFF) { /* non-intent reint */
+                body = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
+                                      sizeof(*body));
+                LBUG(); /* XXX: not supported yet? */
         } else {
                 body = NULL;
                 LBUG();
@@ -884,7 +903,9 @@ int mds_open(struct mds_update_record *rec, int offset,
         /* Step 0: If we are passed a fid, then we assume the client already
          * opened this file and is only replaying the RPC, so we open the
          * inode by fid (at some large expense in security). */
-        if (lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY &&
+        /*XXX liblustre use mds_open_by_fid to implement LL_IOC_LOV_SETSTRIPE */
+        if (((lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY) ||
+             (req->rq_export->exp_libclient && rec->ur_flags&MDS_OPEN_HAS_EA))&&
             !(rec->ur_flags & MDS_OPEN_JOIN_FILE)) {
                 if (rec->ur_fid2->id == 0) {
                         struct ldlm_lock *lock = ldlm_handle2lock(child_lockh);
@@ -898,8 +919,13 @@ int mds_open(struct mds_update_record *rec, int offset,
 
                 rc = mds_open_by_fid(req, rec->ur_fid2, body, rec->ur_flags,
                                      rec, rep);
-                if (rc != -ENOENT)
+                if (rc != -ENOENT) {
+                        if (req->rq_export->exp_libclient &&
+                            rec->ur_flags & MDS_OPEN_HAS_EA)
+                                RETURN(ENOLCK);
+
                         RETURN(rc);
+                }
 
                 /* We didn't find the correct inode on disk either, so we
                  * need to re-create it via a regular replay. */
@@ -913,7 +939,8 @@ int mds_open(struct mds_update_record *rec, int offset,
                 RETURN(-EFAULT);
         }
 
-        LASSERT(offset == 2); /* If we got here, we must be called via intent */
+        /* If we got here, we must be called via intent */
+        LASSERT(offset == DLM_INTENT_REC_OFF);
 
         med = &req->rq_export->exp_mds_data;
         if (OBD_FAIL_CHECK(OBD_FAIL_MDS_OPEN_PACK)) {
@@ -1097,6 +1124,36 @@ found_child:
                 GOTO(cleanup, rc = -EAGAIN);
         }
 
+        /* Obtain OPEN lock as well */
+        policy.l_inodebits.bits |= MDS_INODELOCK_OPEN;
+
+        /* We cannot use acc_mode here, because it is zeroed in case of
+           creating a file, so we get wrong lockmode */
+        if (accmode(dchild->d_inode, rec->ur_flags) & MAY_WRITE)
+                child_mode = LCK_CW;
+        else if (accmode(dchild->d_inode, rec->ur_flags) & MAY_EXEC)
+                child_mode = LCK_PR;
+        else
+                child_mode = LCK_CR;
+
+        if (!(lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY) && 
+             (rec->ur_flags & MDS_OPEN_LOCK)) {
+                /* In case of replay we do not get a lock assuming that the
+                   caller has it already */
+                child_res_id.name[0] = dchild->d_inode->i_ino;
+                child_res_id.name[1] = dchild->d_inode->i_generation;
+
+                rc = ldlm_cli_enqueue_local(obd->obd_namespace, child_res_id,
+                                            LDLM_IBITS, &policy, child_mode, 
+                                            &lock_flags, ldlm_blocking_ast, 
+                                            ldlm_completion_ast, NULL, NULL,
+                                            0, NULL, child_lockh);
+                if (rc != ELDLM_OK)
+                        GOTO(cleanup, rc);
+
+                cleanup_phase = 3;
+        }
+
         if (!S_ISREG(dchild->d_inode->i_mode) &&
             !S_ISDIR(dchild->d_inode->i_mode) &&
             (req->rq_export->exp_connect_flags & OBD_CONNECT_NODEVOH)) {
@@ -1116,6 +1173,9 @@ found_child:
 
  cleanup_no_trans:
         switch (cleanup_phase) {
+        case 3:
+                if (rc)
+                        ldlm_lock_decref(child_lockh, child_mode);
         case 2:
                 if (rc && created) {
                         int err = vfs_unlink(dparent->d_inode, dchild);
@@ -1139,8 +1199,16 @@ found_child:
                 if (rc)
                         ldlm_lock_decref(&parent_lockh, parent_mode);
                 else
-                        ptlrpc_save_lock (req, &parent_lockh, parent_mode);
+                        ptlrpc_save_lock(req, &parent_lockh, parent_mode);
         }
+        /* If we have not taken the "open" lock, we may not return 0 here,
+           because caller expects 0 to mean "lock is taken", and it needs
+           nonzero return here for caller to return EDLM_LOCK_ABORTED to
+           client. Later caller should rewrite the return value back to zero
+           if it to be used any further
+         */
+        if ((cleanup_phase != 3) && !rc)
+                rc = ENOLCK;
 
         /* trigger dqacq on the owner of child and parent */
         lquota_adjust(quota_interface, obd, qcids, qpids, rc, FSFILT_OP_CREATE);
@@ -1175,7 +1243,7 @@ int mds_mfd_close(struct ptlrpc_request *req, int offset,struct obd_device *obd,
                 request_body = lustre_msg_buf(req->rq_reqmsg, offset,
                                               sizeof(*request_body));
         if (req && req->rq_repmsg != NULL)
-                reply_body = lustre_msg_buf(req->rq_repmsg, 0,
+                reply_body = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
                                             sizeof(*reply_body));
 
         fidlen = mds_fid2str(fidname, inode->i_ino, inode->i_generation);
@@ -1229,7 +1297,7 @@ int mds_mfd_close(struct ptlrpc_request *req, int offset,struct obd_device *obd,
                 }
 
                 if (req != NULL && req->rq_repmsg != NULL) {
-                        lmm = lustre_msg_buf(req->rq_repmsg, 1, 0);
+                        lmm = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF+1,0);
                         stripe_count = le32_to_cpu(lmm->lmm_stripe_count);
                 }
 
@@ -1243,10 +1311,11 @@ int mds_mfd_close(struct ptlrpc_request *req, int offset,struct obd_device *obd,
 
                 if (req != NULL && req->rq_repmsg != NULL &&
                     (reply_body->valid & OBD_MD_FLEASIZE) &&
-                    mds_log_op_unlink(obd, pending_child->d_inode, lmm,
-                                      req->rq_repmsg->buflens[1],
-                                      lustre_msg_buf(req->rq_repmsg, 2, 0),
-                                      req->rq_repmsg->buflens[2]) > 0) {
+                    mds_log_op_unlink(obd, lmm,
+                             lustre_msg_buflen(req->rq_repmsg, REPLY_REC_OFF+1),
+                             lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF+2, 0),
+                             lustre_msg_buflen(req->rq_repmsg, REPLY_REC_OFF+2))
+                             > 0) {
                         reply_body->valid |= OBD_MD_FLCOOKIE;
                 }
 
@@ -1303,8 +1372,11 @@ int mds_mfd_close(struct ptlrpc_request *req, int offset,struct obd_device *obd,
 
         if (iattr.ia_valid != 0) {
                 handle = fsfilt_start(obd, inode, FSFILT_OP_SETATTR, NULL);
-                if (IS_ERR(handle))
-                        GOTO(cleanup, rc = PTR_ERR(handle));
+                if (IS_ERR(handle)) {
+                        rc = PTR_ERR(handle);
+                        handle = NULL;
+                        GOTO(cleanup, rc);
+                }
                 rc = fsfilt_setattr(obd, mfd->mfd_dentry, handle, &iattr, 0);
                 if (rc)
                         CERROR("error in setattr(%s): rc %d\n", fidname, rc);
@@ -1345,12 +1417,13 @@ int mds_close(struct ptlrpc_request *req, int offset)
         struct mds_file_data *mfd;
         struct lvfs_run_ctxt saved;
         struct inode *inode;
-        int rc, repsize[3] = {sizeof(struct mds_body),
-                              obd->u.mds.mds_max_mdsize,
-                              obd->u.mds.mds_max_cookiesize};
+        int rc, repsize[4] = { sizeof(struct ptlrpc_body),
+                               sizeof(struct mds_body),
+                               obd->u.mds.mds_max_mdsize,
+                               obd->u.mds.mds_max_cookiesize };
         ENTRY;
 
-        rc = lustre_pack_reply(req, 3, repsize, NULL);
+        rc = lustre_pack_reply(req, 4, repsize, NULL);
         if (rc) {
                 CERROR("lustre_pack_reply: rc = %d\n", rc);
                 req->rq_status = rc;
@@ -1392,19 +1465,21 @@ int mds_close(struct ptlrpc_request *req, int offset)
         /* child orphan sem protects orphan_dec_test && is_orphan race */
         MDS_DOWN_WRITE_ORPHAN_SEM(inode); /* mds_mfd_close drops this */
         if (mds_inode_is_orphan(inode) && mds_orphan_open_count(inode) == 1) {
-                body = lustre_msg_buf(req->rq_repmsg, 0, sizeof (*body));
+                body = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
+                                      sizeof(*body));
                 LASSERT(body != NULL);
 
                 mds_pack_inode2fid(&body->fid1, inode);
                 mds_pack_inode2body(body, inode);
-                mds_pack_md(obd, req->rq_repmsg, 1,body,inode,MDS_PACK_MD_LOCK);
+                mds_pack_md(obd, req->rq_repmsg, REPLY_REC_OFF + 1, body, inode,
+                            MDS_PACK_MD_LOCK);
         }
 
         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
         req->rq_status = mds_mfd_close(req, offset, obd, mfd, 1);
         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
 
-        mds_shrink_reply(obd, req, body);
+        mds_shrink_reply(obd, req, body, REPLY_REC_OFF + 1);
         if (OBD_FAIL_CHECK(OBD_FAIL_MDS_CLOSE_PACK)) {
                 CERROR("test case OBD_FAIL_MDS_CLOSE_PACK\n");
                 req->rq_status = -ENOMEM;
@@ -1417,7 +1492,8 @@ int mds_close(struct ptlrpc_request *req, int offset)
 int mds_done_writing(struct ptlrpc_request *req, int offset)
 {
         struct mds_body *body;
-        int rc, size = sizeof(struct mds_body);
+        int rc, size[2] = { sizeof(struct ptlrpc_body),
+                            sizeof(struct mds_body) };
         ENTRY;
 
         MDS_CHECK_RESENT(req, mds_reconstruct_generic(req));
@@ -1430,7 +1506,7 @@ int mds_done_writing(struct ptlrpc_request *req, int offset)
                 RETURN(-EFAULT);
         }
 
-        rc = lustre_pack_reply(req, 1, &size, NULL);
+        rc = lustre_pack_reply(req, 2, size, NULL);
         if (rc) {
                 CERROR("lustre_pack_reply: rc = %d\n", rc);
                 req->rq_status = rc;
index fbc9c70..4e605a9 100644 (file)
@@ -141,7 +141,7 @@ int mds_finish_transno(struct mds_obd *mds, struct inode *inode, void *handle,
 
         off = med->med_lr_off;
 
-        transno = req->rq_reqmsg->transno;
+        transno = lustre_msg_get_transno(req->rq_reqmsg);
         if (rc != 0) {
                 if (transno != 0) {
                         CERROR("%s: replay %s transno "LPU64" failed: rc %d\n",
@@ -160,11 +160,20 @@ int mds_finish_transno(struct mds_obd *mds, struct inode *inode, void *handle,
                         mds->mds_last_transno = transno;
                 spin_unlock(&mds->mds_transno_lock);
         }
-        req->rq_repmsg->transno = req->rq_transno = transno;
-        mcd->mcd_last_transno = cpu_to_le64(transno);
-        mcd->mcd_last_xid = cpu_to_le64(req->rq_xid);
-        mcd->mcd_last_result = cpu_to_le32(rc);
-        mcd->mcd_last_data = cpu_to_le32(op_data);
+
+        req->rq_transno = transno;
+        lustre_msg_set_transno(req->rq_repmsg, transno);
+        if (lustre_msg_get_opc(req->rq_reqmsg) == MDS_CLOSE) {
+                mcd->mcd_last_close_transno = cpu_to_le64(transno);
+                mcd->mcd_last_close_xid = cpu_to_le64(req->rq_xid);
+                mcd->mcd_last_close_result = cpu_to_le32(rc);
+                mcd->mcd_last_close_data = cpu_to_le32(op_data);
+        } else {
+                mcd->mcd_last_transno = cpu_to_le64(transno);
+                mcd->mcd_last_xid = cpu_to_le64(req->rq_xid);
+                mcd->mcd_last_result = cpu_to_le32(rc);
+                mcd->mcd_last_data = cpu_to_le32(op_data);
+        }
 
         if (off <= 0) {
                 CERROR("client idx %d has offset %lld\n", med->med_lr_idx, off);
@@ -182,9 +191,9 @@ int mds_finish_transno(struct mds_obd *mds, struct inode *inode, void *handle,
                         rc = err;
         }
 
-        DEBUG_REQ_EX(log_pri, req,
-                     "wrote trans #"LPU64" rc %d client %s at idx %u: err = %d",
-                     transno, rc, mcd->mcd_uuid, med->med_lr_idx, err);
+        DEBUG_REQ(log_pri, req,
+                  "wrote trans #"LPU64" rc %d client %s at idx %u: err = %d",
+                   transno, rc, mcd->mcd_uuid, med->med_lr_idx, err);
 
         err = mds_lov_write_objids(obd);
         if (err) {
@@ -192,7 +201,7 @@ int mds_finish_transno(struct mds_obd *mds, struct inode *inode, void *handle,
                 if (rc == 0)
                         rc = err;
         }
-        CDEBUG_EX(log_pri, "wrote objids: err = %d\n", err);
+        CDEBUG(log_pri, "wrote objids: err = %d\n", err);
 
 commit:
         err = fsfilt_commit(obd, inode, handle, 0);
@@ -307,21 +316,22 @@ void mds_steal_ack_locks(struct ptlrpc_request *req)
         struct list_head          *tmp;
         struct ptlrpc_reply_state *oldrep;
         struct ptlrpc_service     *svc;
-        unsigned long              flags;
         int                        i;
 
         /* CAVEAT EMPTOR: spinlock order */
-        spin_lock_irqsave (&exp->exp_lock, flags);
+        spin_lock(&exp->exp_lock);
         list_for_each (tmp, &exp->exp_outstanding_replies) {
                 oldrep = list_entry(tmp, struct ptlrpc_reply_state,rs_exp_list);
 
                 if (oldrep->rs_xid != req->rq_xid)
                         continue;
 
-                if (oldrep->rs_msg.opc != req->rq_reqmsg->opc)
+                if (lustre_msg_get_opc(oldrep->rs_msg) !=
+                    lustre_msg_get_opc(req->rq_reqmsg))
                         CERROR ("Resent req xid "LPX64" has mismatched opc: "
                                 "new %d old %d\n", req->rq_xid,
-                                req->rq_reqmsg->opc, oldrep->rs_msg.opc);
+                                lustre_msg_get_opc(req->rq_reqmsg),
+                                lustre_msg_get_opc(oldrep->rs_msg));
 
                 svc = oldrep->rs_service;
                 spin_lock (&svc->srv_lock);
@@ -331,7 +341,8 @@ void mds_steal_ack_locks(struct ptlrpc_request *req)
                 CWARN("Stealing %d locks from rs %p x"LPD64".t"LPD64
                       " o%d NID %s\n",
                       oldrep->rs_nlocks, oldrep,
-                      oldrep->rs_xid, oldrep->rs_transno, oldrep->rs_msg.opc,
+                      oldrep->rs_xid, oldrep->rs_transno,
+                      lustre_msg_get_opc(oldrep->rs_msg),
                       libcfs_nid2str(exp->exp_connection->c_peer.nid));
 
                 for (i = 0; i < oldrep->rs_nlocks; i++)
@@ -346,15 +357,24 @@ void mds_steal_ack_locks(struct ptlrpc_request *req)
                 spin_unlock (&svc->srv_lock);
                 break;
         }
-        spin_unlock_irqrestore (&exp->exp_lock, flags);
+        spin_unlock(&exp->exp_lock);
 }
 
 void mds_req_from_mcd(struct ptlrpc_request *req, struct mds_client_data *mcd)
 {
+        if (lustre_msg_get_opc(req->rq_reqmsg) == MDS_CLOSE) {
+                req->rq_transno = le64_to_cpu(mcd->mcd_last_close_transno);
+                lustre_msg_set_transno(req->rq_repmsg, req->rq_transno);
+                req->rq_status = le32_to_cpu(mcd->mcd_last_close_result);
+                lustre_msg_set_status(req->rq_repmsg, req->rq_status);
+        } else {
+                req->rq_transno = le64_to_cpu(mcd->mcd_last_transno);
+                lustre_msg_set_transno(req->rq_repmsg, req->rq_transno);
+                req->rq_status = le32_to_cpu(mcd->mcd_last_result);
+                lustre_msg_set_status(req->rq_repmsg, req->rq_status);
+        }
         DEBUG_REQ(D_HA, req, "restoring transno "LPD64"/status %d",
-                  mcd->mcd_last_transno, mcd->mcd_last_result);
-        req->rq_repmsg->transno = req->rq_transno = mcd->mcd_last_transno;
-        req->rq_repmsg->status = req->rq_status = mcd->mcd_last_result;
+                  req->rq_transno, req->rq_status);
 
         mds_steal_ack_locks(req);
 }
@@ -375,7 +395,7 @@ static void reconstruct_reint_setattr(struct mds_update_record *rec,
                 return;
         }
 
-        body = lustre_msg_buf(req->rq_repmsg, 0, sizeof (*body));
+        body = lustre_msg_buf(req->rq_repmsg, offset, sizeof(*body));
         mds_pack_inode2fid(&body->fid1, de->d_inode);
         mds_pack_inode2body(body, de->d_inode);
 
@@ -395,9 +415,8 @@ int mds_osc_setattr_async(struct obd_device *obd, __u32 uid, __u32 gid,
                           struct llog_cookie *logcookies, __u64 id, __u32 gen)
 {
         struct mds_obd *mds = &obd->u.mds;
-        struct lov_stripe_md *lsm = NULL;
         struct obd_trans_info oti = { 0 };
-        struct obdo *oa = NULL;
+        struct obd_info oinfo = { { { 0 } } };
         int rc;
         ENTRY;
 
@@ -405,47 +424,47 @@ int mds_osc_setattr_async(struct obd_device *obd, __u32 uid, __u32 gid,
                 RETURN(0);
 
         /* first get memory EA */
-        oa = obdo_alloc();
-        if (!oa)
+        oinfo.oi_oa = obdo_alloc();
+        if (!oinfo.oi_oa)
                 RETURN(-ENOMEM);
 
         LASSERT(lmm);
 
-        rc = obd_unpackmd(mds->mds_osc_exp, &lsm, lmm, lmm_size);
+        rc = obd_unpackmd(mds->mds_osc_exp, &oinfo.oi_md, lmm, lmm_size);
         if (rc < 0) {
                 CERROR("Error unpack md %p for inode "LPU64"\n", lmm, id);
                 GOTO(out, rc);
         }
 
-        rc = obd_checkmd(mds->mds_osc_exp, obd->obd_self_export, lsm);
+        rc = obd_checkmd(mds->mds_osc_exp, obd->obd_self_export, oinfo.oi_md);
         if (rc) {
-                CERROR("Error revalidate lsm %p \n", lsm);
+                CERROR("Error revalidate lsm %p \n", oinfo.oi_md);
                 GOTO(out, rc);
         }
 
         /* then fill oa */
-        oa->o_id = lsm->lsm_object_id;
-        oa->o_uid = uid;
-        oa->o_gid = gid;
-        oa->o_valid = OBD_MD_FLID | OBD_MD_FLUID | OBD_MD_FLGID;
+        oinfo.oi_oa->o_uid = uid;
+        oinfo.oi_oa->o_gid = gid;
+        oinfo.oi_oa->o_valid |= OBD_MD_FLID | OBD_MD_FLUID | OBD_MD_FLGID;
+        oinfo.oi_oa->o_id = oinfo.oi_md->lsm_object_id;
         if (logcookies) {
-                oa->o_valid |= OBD_MD_FLCOOKIE;
+                oinfo.oi_oa->o_valid |= OBD_MD_FLCOOKIE;
                 oti.oti_logcookies = logcookies;
         }
 
-        oa->o_fid = id;
-        oa->o_generation = gen;
-        oa->o_valid |= OBD_MD_FLFID | OBD_MD_FLGENER;
+        oinfo.oi_oa->o_fid = id;
+        oinfo.oi_oa->o_generation = gen;
+        oinfo.oi_oa->o_valid |= OBD_MD_FLFID | OBD_MD_FLGENER;
 
-        /* do setattr from mds to ost asynchronously */
-        rc = obd_setattr_async(mds->mds_osc_exp, oa, lsm, &oti);
+        /* do async setattr from mds to ost not waiting for responses. */
+        rc = obd_setattr_async(mds->mds_osc_exp, &oinfo, &oti, NULL);
         if (rc)
                 CDEBUG(D_INODE, "mds to ost setattr objid 0x"LPX64
-                       " on ost error %d\n", lsm->lsm_object_id, rc);
+                       " on ost error %d\n", oinfo.oi_md->lsm_object_id, rc);
 out:
-        if (lsm)
-                obd_free_memmd(mds->mds_osc_exp, &lsm);
-        obdo_free(oa);
+        if (oinfo.oi_md)
+                obd_free_memmd(mds->mds_osc_exp, &oinfo.oi_md);
+        obdo_free(oinfo.oi_oa);
         RETURN(rc);
 }
 EXPORT_SYMBOL(mds_osc_setattr_async);
@@ -472,12 +491,13 @@ static int mds_reint_setattr(struct mds_update_record *rec, int offset,
         struct llog_cookie *logcookies = NULL;
         int lmm_size = 0, need_lock = 1, cookie_size = 0;
         int rc = 0, cleanup_phase = 0, err, locked = 0;
-        unsigned int qcids[MAXQUOTAS] = {0, 0};
-        unsigned int qpids[MAXQUOTAS] = {rec->ur_iattr.ia_uid,
-                                         rec->ur_iattr.ia_gid};
+        unsigned int qcids[MAXQUOTAS] = { 0, 0 };
+        unsigned int qpids[MAXQUOTAS] = { rec->ur_iattr.ia_uid, 
+                                          rec->ur_iattr.ia_gid };
         ENTRY;
 
-        LASSERT(offset == MDS_REQ_REC_OFF);
+        LASSERT(offset == REQ_REC_OFF);
+        offset = REPLY_REC_OFF;
 
         DEBUG_REQ(D_INODE, req, "setattr "LPU64"/%u %x", rec->ur_fid1->id,
                   rec->ur_fid1->generation, rec->ur_iattr.ia_valid);
@@ -551,7 +571,7 @@ static int mds_reint_setattr(struct mds_update_record *rec, int offset,
 
         if (rec->ur_iattr.ia_valid & ATTR_ATTR_FLAG) {  /* ioctl */
                 rc = fsfilt_iocontrol(obd, inode, NULL, EXT3_IOC_SETFLAGS,
-                                      (long)&rec->ur_iattr.ia_attr_flags);
+                                      (long)&rec->ur_flags);
         } else if (rec->ur_iattr.ia_valid) {            /* setattr */
                 rc = fsfilt_setattr(obd, de, handle, &rec->ur_iattr, 0);
                 /* journal chown/chgrp in llog, just like unlink */
@@ -583,10 +603,12 @@ static int mds_reint_setattr(struct mds_update_record *rec, int offset,
                  * values specified) then delete default striping from dir. */
                 if (S_ISDIR(inode->i_mode) &&
                     ((lum->lmm_stripe_size == 0 &&
-                      lum->lmm_stripe_offset == (typeof(lum->lmm_stripe_offset))(-1) &&
+                      lum->lmm_stripe_offset ==
+                      (typeof(lum->lmm_stripe_offset))(-1) &&
                       lum->lmm_stripe_count == 0) ||
                     /* lmm_stripe_size == -1 is deprecated in 1.4.6 */
-                    lum->lmm_stripe_size == (typeof(lum->lmm_stripe_size))(-1))){
+                    lum->lmm_stripe_size ==
+                    (typeof(lum->lmm_stripe_size))(-1))){
                         rc = fsfilt_set_md(obd, inode, handle, NULL, 0, "lov");
                         if (rc)
                                 GOTO(cleanup, rc);
@@ -606,7 +628,7 @@ static int mds_reint_setattr(struct mds_update_record *rec, int offset,
                 }
         }
 
-        body = lustre_msg_buf(req->rq_repmsg, 0, sizeof (*body));
+        body = lustre_msg_buf(req->rq_repmsg, offset, sizeof(*body));
         mds_pack_inode2fid(&body->fid1, inode);
         mds_pack_inode2body(body, inode);
 
@@ -700,9 +722,11 @@ static void reconstruct_reint_create(struct mds_update_record *rec, int offset,
         LASSERT(!IS_ERR(parent));
         child = ll_lookup_one_len(rec->ur_name, parent, rec->ur_namelen - 1);
         LASSERT(!IS_ERR(child));
-        body = lustre_msg_buf(req->rq_repmsg, offset, sizeof (*body));
+
+        body = lustre_msg_buf(req->rq_repmsg, offset, sizeof(*body));
         mds_pack_inode2fid(&body->fid1, child->d_inode);
         mds_pack_inode2body(body, child->d_inode);
+
         l_dput(parent);
         l_dput(child);
 }
@@ -720,12 +744,14 @@ static int mds_reint_create(struct mds_update_record *rec, int offset,
         struct lustre_handle lockh;
         int rc = 0, err, type = rec->ur_mode & S_IFMT, cleanup_phase = 0;
         int created = 0;
-        unsigned int qcids[MAXQUOTAS] = {current->fsuid, current->fsgid};
-        unsigned int qpids[MAXQUOTAS] = {0, 0};
+        unsigned int qcids[MAXQUOTAS] = { current->fsuid, current->fsgid };
+        unsigned int qpids[MAXQUOTAS] = { 0, 0 };
         struct dentry_params dp;
         ENTRY;
 
-        LASSERT(offset == MDS_REQ_REC_OFF);
+        LASSERT(offset == REQ_REC_OFF);
+        offset = REPLY_REC_OFF;
+
         LASSERT(!strcmp(req->rq_export->exp_obd->obd_type->typ_name,
                         LUSTRE_MDS_NAME));
 
@@ -883,7 +909,7 @@ static int mds_reint_create(struct mds_update_record *rec, int offset,
                                         rc);
                 }
 
-                body = lustre_msg_buf(req->rq_repmsg, offset, sizeof (*body));
+                body = lustre_msg_buf(req->rq_repmsg, offset, sizeof(*body));
                 mds_pack_inode2fid(&body->fid1, inode);
                 mds_pack_inode2body(body, inode);
         }
@@ -1012,11 +1038,12 @@ int enqueue_ordered_locks(struct obd_device *obd, struct ldlm_res_id *p1_res_id,
         CDEBUG(D_DLMTRACE, "lock order: "LPU64"/"LPU64"\n",
                res_id[0]->name[0], res_id[1]->name[0]);
 
-        flags = LDLM_FL_LOCAL_ONLY;
-        rc = ldlm_cli_enqueue(NULL, NULL, obd->obd_namespace, *res_id[0],
-                              LDLM_IBITS, policies[0], lock_modes[0], &flags,
-                              ldlm_blocking_ast, ldlm_completion_ast,
-                              NULL, NULL, NULL, 0, NULL, handles[0]);
+        flags = LDLM_FL_LOCAL_ONLY | LDLM_FL_ATOMIC_CB;
+        rc = ldlm_cli_enqueue_local(obd->obd_namespace, *res_id[0],
+                                    LDLM_IBITS, policies[0], lock_modes[0],
+                                    &flags, ldlm_blocking_ast, 
+                                    ldlm_completion_ast, NULL, NULL, 0, 
+                                    NULL, handles[0]);
         if (rc != ELDLM_OK)
                 RETURN(-EIO);
         ldlm_lock_dump_handle(D_OTHER, handles[0]);
@@ -1026,12 +1053,13 @@ int enqueue_ordered_locks(struct obd_device *obd, struct ldlm_res_id *p1_res_id,
                 memcpy(handles[1], handles[0], sizeof(*(handles[1])));
                 ldlm_lock_addref(handles[1], lock_modes[1]);
         } else if (res_id[1]->name[0] != 0) {
-                flags = LDLM_FL_LOCAL_ONLY;
-                rc = ldlm_cli_enqueue(NULL, NULL, obd->obd_namespace,
-                                      *res_id[1], LDLM_IBITS, policies[1],
-                                      lock_modes[1], &flags,
-                                      ldlm_blocking_ast, ldlm_completion_ast,
-                                      NULL, NULL, NULL, 0, NULL, handles[1]);
+                flags = LDLM_FL_LOCAL_ONLY | LDLM_FL_ATOMIC_CB;
+                rc = ldlm_cli_enqueue_local(obd->obd_namespace, *res_id[1],
+                                            LDLM_IBITS, policies[1],
+                                            lock_modes[1], &flags, 
+                                            ldlm_blocking_ast,
+                                            ldlm_completion_ast, NULL, NULL,
+                                            0, NULL, handles[1]);
                 if (rc != ELDLM_OK) {
                         ldlm_lock_decref(handles[0], lock_modes[0]);
                         RETURN(-EIO);
@@ -1120,7 +1148,7 @@ int enqueue_4ordered_locks(struct obd_device *obd,struct ldlm_res_id *p1_res_id,
 
         /* XXX we could send ASTs on all these locks first before blocking? */
         for (i = 0; i < 4; i++) {
-                flags = 0;
+                flags = LDLM_FL_ATOMIC_CB;
                 if (res_id[i]->name[0] == 0)
                         break;
                 if (i && res_eq(res_id[i], res_id[i-1])) {
@@ -1136,13 +1164,13 @@ int enqueue_4ordered_locks(struct obd_device *obd,struct ldlm_res_id *p1_res_id,
                         if (i < 3)
                                 try_to_aggregate_locks(res_id[i], policies[i],
                                                        res_id[i+1], policies[i+1]);
-                        rc = ldlm_cli_enqueue(NULL, NULL, obd->obd_namespace,
-                                              *res_id[i], LDLM_IBITS,
-                                              policies[i],
-                                              lock_modes[i], &flags,
-                                              ldlm_blocking_ast,
-                                              ldlm_completion_ast, NULL, NULL,
-                                              NULL, 0, NULL, dlm_handles[i]);
+                        rc = ldlm_cli_enqueue_local(obd->obd_namespace,
+                                                    *res_id[i], LDLM_IBITS,
+                                                    policies[i], lock_modes[i],
+                                                    &flags, ldlm_blocking_ast,
+                                                    ldlm_completion_ast, NULL, 
+                                                    NULL, 0, NULL, 
+                                                    dlm_handles[i]);
                         if (rc != ELDLM_OK)
                                 GOTO(out_err, rc = -EIO);
                         ldlm_lock_dump_handle(D_OTHER, dlm_handles[i]);
@@ -1212,7 +1240,7 @@ static int mds_verify_child(struct obd_device *obd,
         *dchildp = dchild = vchild;
 
         if (dchild->d_inode) {
-                int flags = 0;
+                int flags = LDLM_FL_ATOMIC_CB;
                 child_res_id->name[0] = dchild->d_inode->i_ino;
                 child_res_id->name[1] = dchild->d_inode->i_generation;
 
@@ -1227,11 +1255,12 @@ static int mds_verify_child(struct obd_device *obd,
                         GOTO(cleanup, rc = 1);
                 }
 
-                rc = ldlm_cli_enqueue(NULL, NULL, obd->obd_namespace,
-                                      *child_res_id, LDLM_IBITS, child_policy,
-                                      child_mode, &flags, ldlm_blocking_ast,
-                                      ldlm_completion_ast, NULL, NULL, NULL, 0,
-                                      NULL, child_lockh);
+                rc = ldlm_cli_enqueue_local(obd->obd_namespace, *child_res_id, 
+                                            LDLM_IBITS, child_policy, 
+                                            child_mode, &flags, 
+                                            ldlm_blocking_ast, 
+                                            ldlm_completion_ast, NULL, 
+                                            NULL, 0, NULL, child_lockh);
                 if (rc != ELDLM_OK)
                         GOTO(cleanup, rc = -EIO);
         } else {
@@ -1252,6 +1281,10 @@ cleanup:
         return rc;
 }
 
+#define INODE_CTIME_AGE (10)
+#define INODE_CTIME_OLD(inode) (LTIME_S(inode->i_ctime) +               \
+                                INODE_CTIME_AGE < CURRENT_SECONDS)
+
 int mds_get_parent_child_locked(struct obd_device *obd, struct mds_obd *mds,
                                 struct ll_fid *fid,
                                 struct lustre_handle *parent_lockh,
@@ -1309,6 +1342,16 @@ int mds_get_parent_child_locked(struct obd_device *obd, struct mds_obd *mds,
 
         child_res_id.name[0] = inode->i_ino;
         child_res_id.name[1] = inode->i_generation;
+
+        /* If we want a LCK_CR for a directory, and this directory has not been
+           changed for some time, we return not only a LOOKUP lock, but also an 
+           UPDATE lock to have negative dentry starts working for this dir.
+           Also we apply same logic to non-directories. If the file is rarely
+           changed - we return both locks and this might save us RPC on
+           later STAT. */
+        if ((child_mode & (LCK_CR|LCK_PR|LCK_CW)) && INODE_CTIME_OLD(inode))
+                child_policy.l_inodebits.bits |= MDS_INODELOCK_UPDATE;
+
         iput(inode);
 
 retry_locks:
@@ -1451,7 +1494,7 @@ int mds_get_cookie_size(struct obd_device *obd, struct lov_mds_md *lmm)
 }
 
 void mds_shrink_reply(struct obd_device *obd, struct ptlrpc_request *req,
-                      struct mds_body *body)
+                      struct mds_body *body, int md_off)
 {
         int cookie_size = 0, md_size = 0;
 
@@ -1461,15 +1504,15 @@ void mds_shrink_reply(struct obd_device *obd, struct ptlrpc_request *req,
         if (body && body->valid & OBD_MD_FLCOOKIE) {
                 LASSERT(body->valid & OBD_MD_FLEASIZE);
                 cookie_size = mds_get_cookie_size(obd, lustre_msg_buf(
-                                                  req->rq_repmsg, 1, 0));
+                                                  req->rq_repmsg, md_off, 0));
         }
 
         CDEBUG(D_INFO, "Shrink to md_size %d cookie_size %d \n", md_size,
                cookie_size);
-
-        lustre_shrink_reply(req, 1, md_size, 1);
-
-        lustre_shrink_reply(req, md_size? 2:1, cookie_size, 0);
+        lustre_shrink_reply(req, md_off, md_size, 1);
+        
+        lustre_shrink_reply(req, md_off + (md_size > 0), cookie_size, 0); 
 }
 
 static int mds_reint_unlink(struct mds_update_record *rec, int offset,
@@ -1484,11 +1527,12 @@ static int mds_reint_unlink(struct mds_update_record *rec, int offset,
         struct lustre_handle parent_lockh, child_lockh, child_reuse_lockh;
         void *handle = NULL;
         int rc = 0, cleanup_phase = 0;
-        unsigned int qcids [MAXQUOTAS] = {0, 0};
-        unsigned int qpids [MAXQUOTAS] = {0, 0};
+        unsigned int qcids[MAXQUOTAS] = { 0, 0 };
+        unsigned int qpids[MAXQUOTAS] = { 0, 0 };
         ENTRY;
 
-        LASSERT(offset == MDS_REQ_REC_OFF || offset == 2);
+        LASSERT(offset == REQ_REC_OFF); /*  || offset == DLM_INTENT_REC_OFF); */
+        offset = REPLY_REC_OFF;
 
         DEBUG_REQ(D_INODE, req, "parent ino "LPU64"/%u, child %s",
                   rec->ur_fid1->id, rec->ur_fid1->generation, rec->ur_name);
@@ -1551,10 +1595,10 @@ static int mds_reint_unlink(struct mds_update_record *rec, int offset,
         OBD_FAIL_WRITE(OBD_FAIL_MDS_REINT_UNLINK_WRITE, dparent->d_inode->i_sb);
 
         /* ldlm_reply in buf[0] if called via intent */
-        if (offset)
-                offset = 1;
+        if (offset == DLM_INTENT_REC_OFF)
+                offset = DLM_REPLY_REC_OFF;
 
-        body = lustre_msg_buf(req->rq_repmsg, offset, sizeof (*body));
+        body = lustre_msg_buf(req->rq_repmsg, offset, sizeof(*body));
         LASSERT(body != NULL);
 
         /* child orphan sem protects orphan_dec_test && is_orphan race */
@@ -1633,11 +1677,12 @@ static int mds_reint_unlink(struct mds_update_record *rec, int offset,
                 if (!(body->valid & OBD_MD_FLEASIZE)) {
                         body->valid |=(OBD_MD_FLSIZE | OBD_MD_FLBLOCKS |
                                        OBD_MD_FLATIME | OBD_MD_FLMTIME);
-                } else if (mds_log_op_unlink(obd, child_inode,
+                } else if (mds_log_op_unlink(obd,
                                 lustre_msg_buf(req->rq_repmsg, offset + 1, 0),
-                                        req->rq_repmsg->buflens[offset + 1],
+                                lustre_msg_buflen(req->rq_repmsg, offset + 1),
                                 lustre_msg_buf(req->rq_repmsg, offset + 2, 0),
-                                        req->rq_repmsg->buflens[offset+2]) > 0){
+                                lustre_msg_buflen(req->rq_repmsg, offset+2)) >
+                           0) {
                         body->valid |= OBD_MD_FLCOOKIE;
                 }
         }
@@ -1694,7 +1739,7 @@ cleanup:
         }
         req->rq_status = rc;
 
-        mds_shrink_reply(obd, req, body);
+        mds_shrink_reply(obd, req, body, REPLY_REC_OFF + 1);
 
         /* trigger dqrel on the owner of child and parent */
         lquota_adjust(quota_interface, obd, qcids, qpids, rc, FSFILT_OP_UNLINK);
@@ -1719,7 +1764,7 @@ static int mds_reint_link(struct mds_update_record *rec, int offset,
         int rc = 0, cleanup_phase = 0;
         ENTRY;
 
-        LASSERT(offset == MDS_REQ_REC_OFF);
+        LASSERT(offset == REQ_REC_OFF);
 
         DEBUG_REQ(D_INODE, req, "original "LPU64"/%u to "LPU64"/%u %s",
                   rec->ur_fid1->id, rec->ur_fid1->generation,
@@ -2057,11 +2102,12 @@ static int mds_reint_rename(struct mds_update_record *rec, int offset,
         struct lov_mds_md *lmm = NULL;
         int rc = 0, lock_count = 3, cleanup_phase = 0;
         void *handle = NULL;
-        unsigned int qcids[MAXQUOTAS] = {0, 0};
-        unsigned int qpids[4] = {0, 0, 0, 0};
+        unsigned int qcids[MAXQUOTAS] = { 0, 0 };
+        unsigned int qpids[4] = { 0, 0, 0, 0 };
         ENTRY;
 
-        LASSERT(offset == MDS_REQ_REC_OFF);
+        LASSERT(offset == REQ_REC_OFF);
+        offset = REPLY_REC_OFF;
 
         DEBUG_REQ(D_INODE, req, "parent "LPU64"/%u %s to "LPU64"/%u %s",
                   rec->ur_fid1->id, rec->ur_fid1->generation, rec->ur_name,
@@ -2118,7 +2164,7 @@ static int mds_reint_rename(struct mds_update_record *rec, int offset,
 
         /* if we are about to remove the target at first, pass the EA of
          * that inode to client to perform and cleanup on OST */
-        body = lustre_msg_buf(req->rq_repmsg, 0, sizeof (*body));
+        body = lustre_msg_buf(req->rq_repmsg, offset, sizeof(*body));
         LASSERT(body != NULL);
 
         /* child orphan sem protects orphan_dec_test && is_orphan race */
@@ -2134,8 +2180,8 @@ static int mds_reint_rename(struct mds_update_record *rec, int offset,
                 } else if (S_ISREG(new_inode->i_mode)) {
                         mds_pack_inode2fid(&body->fid1, new_inode);
                         mds_pack_inode2body(body, new_inode);
-                        mds_pack_md(obd, req->rq_repmsg, 1, body, new_inode,
-                                    MDS_PACK_MD_LOCK);
+                        mds_pack_md(obd, req->rq_repmsg, offset + 1, body,
+                                    new_inode, MDS_PACK_MD_LOCK);
                 }
         }
 
@@ -2150,7 +2196,7 @@ no_unlink:
                 GOTO(cleanup, rc = -EINVAL);
 #endif
 
-        lmm = lustre_msg_buf(req->rq_repmsg, 1, 0);
+        lmm = lustre_msg_buf(req->rq_repmsg, offset + 1, 0);
         handle = fsfilt_start_log(obd, de_tgtdir->d_inode, FSFILT_OP_RENAME,
                                   NULL, le32_to_cpu(lmm->lmm_stripe_count));
 
@@ -2177,11 +2223,16 @@ no_unlink:
                 if (!(body->valid & OBD_MD_FLEASIZE)) {
                         body->valid |= (OBD_MD_FLSIZE | OBD_MD_FLBLOCKS |
                                         OBD_MD_FLATIME | OBD_MD_FLMTIME);
-                } else if (mds_log_op_unlink(obd, new_inode,
-                                             lustre_msg_buf(req->rq_repmsg,1,0),
-                                             req->rq_repmsg->buflens[1],
-                                             lustre_msg_buf(req->rq_repmsg,2,0),
-                                             req->rq_repmsg->buflens[2]) > 0) {
+                } else if (mds_log_op_unlink(obd,
+                                             lustre_msg_buf(req->rq_repmsg,
+                                                            offset + 1, 0),
+                                             lustre_msg_buflen(req->rq_repmsg,
+                                                               offset + 1),
+                                             lustre_msg_buf(req->rq_repmsg,
+                                                            offset + 2, 0),
+                                             lustre_msg_buflen(req->rq_repmsg,
+                                                               offset + 2))
+                           > 0) {
                         body->valid |= OBD_MD_FLCOOKIE;
                 }
         }
index ed4539b..56aeb22 100644 (file)
@@ -45,7 +45,7 @@
 #include "mds_internal.h"
 
 static int mds_osc_destroy_orphan(struct obd_device *obd,
-                                  struct inode *inode,
+                                  umode_t mode,
                                   struct lov_mds_md *lmm,
                                   int lmm_size,
                                   struct llog_cookie *logcookies,
@@ -78,7 +78,7 @@ static int mds_osc_destroy_orphan(struct obd_device *obd,
         if (oa == NULL)
                 GOTO(out_free_memmd, rc = -ENOMEM);
         oa->o_id = lsm->lsm_object_id;
-        oa->o_mode = inode->i_mode & S_IFMT;
+        oa->o_mode = mode & S_IFMT;
         oa->o_valid = OBD_MD_FLID | OBD_MD_FLTYPE;
 
         if (log_unlink && logcookies) {
@@ -103,14 +103,16 @@ static int mds_unlink_orphan(struct obd_device *obd, struct dentry *dchild,
         struct llog_cookie *logcookies = NULL;
         int lmm_size, log_unlink = 0, cookie_size = 0;
         void *handle = NULL;
+        umode_t mode;
         int rc, err;
         ENTRY;
 
         LASSERT(mds->mds_osc_obd != NULL);
-
+        
         /* We don't need to do any of these other things for orhpan dirs,
          * especially not mds_get_md (may get a default LOV EA, bug 4554) */
-        if (S_ISDIR(inode->i_mode)) {
+        mode = inode->i_mode;
+        if (S_ISDIR(mode)) {
                 rc = vfs_rmdir(pending_dir, dchild);
                 if (rc)
                         CERROR("error %d unlinking dir %*s from PENDING\n",
@@ -145,7 +147,7 @@ static int mds_unlink_orphan(struct obd_device *obd, struct dentry *dchild,
                 OBD_ALLOC(logcookies, cookie_size);
                 if (logcookies == NULL)
                         rc = -ENOMEM;
-                else if (mds_log_op_unlink(obd, inode, lmm,lmm_size,logcookies,
+                else if (mds_log_op_unlink(obd, lmm,lmm_size,logcookies,
                                            cookie_size) > 0)
                         log_unlink = 1;
         }
@@ -156,7 +158,7 @@ static int mds_unlink_orphan(struct obd_device *obd, struct dentry *dchild,
                 if (!rc)
                         rc = err;
         } else if (!rc) {
-                rc = mds_osc_destroy_orphan(obd, inode, lmm, lmm_size,
+                rc = mds_osc_destroy_orphan(obd, mode, lmm, lmm_size,
                                             logcookies, log_unlink);
         }
 
index c3968ef..b60d429 100644 (file)
 #include <lustre_fsfilt.h>
 #include <lustre_ucache.h>
 
-#include "mds_internal.h"
+#include "mds_internal.h" 
+
+#ifndef XATTR_NAME_ACL_ACCESS
+#define XATTR_NAME_ACL_ACCESS   "system.posix_acl_access"
+#endif
 
 static int mds_getxattr_pack_msg(struct ptlrpc_request *req,
                                  struct dentry *de,
                                  struct mds_body *body)
 {
         struct inode *inode = de->d_inode;
-        int size[2] = {sizeof(*body)}, bufcnt = 1;
         char *xattr_name;
-        int rc = -EOPNOTSUPP, rc2;
+        int size[3] = { sizeof(struct ptlrpc_body), sizeof(*body) };
+        int bufcnt = 2, rc = -EOPNOTSUPP, rc2;
 
         if (inode == NULL)
                 return -ENOENT;
 
         if (body->valid & OBD_MD_FLXATTR) {
-                xattr_name = lustre_msg_string(req->rq_reqmsg, 1, 0);
+                xattr_name = lustre_msg_string(req->rq_reqmsg, REQ_REC_OFF+1,0);
                 if (!xattr_name) {
                         CERROR("can't extract xattr name\n");
                         return -EFAULT;
@@ -80,7 +84,7 @@ static int mds_getxattr_pack_msg(struct ptlrpc_request *req,
                 if (rc != -ENODATA && rc != -EOPNOTSUPP)
                         CWARN("get inode %lu EA size error: %d\n",
                               inode->i_ino, rc);
-                bufcnt = 0;
+                bufcnt = 1;
         } else {
                 size[bufcnt++] = min_t(int, body->eadatasize, rc);
         }
@@ -115,15 +119,16 @@ static int mds_getxattr_internal(struct obd_device *obd,
         if (inode == NULL)
                 GOTO(out, rc = -ENOENT);
 
-        repbody = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*repbody));
+        repbody = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
+                                 sizeof(*repbody));
         LASSERT(repbody != NULL);
 
-        buflen = lustre_msg_buflen(req->rq_repmsg, 1);
+        buflen = lustre_msg_buflen(req->rq_repmsg, REPLY_REC_OFF + 1);
         if (buflen)
-                buf = lustre_msg_buf(req->rq_repmsg, 1, buflen);
+                buf = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF + 1, buflen);
 
         if (reqbody->valid & OBD_MD_FLXATTR) {
-                xattr_name = lustre_msg_string(req->rq_reqmsg, 1, 0);
+                xattr_name = lustre_msg_string(req->rq_reqmsg, REQ_REC_OFF+1,0);
                 DEBUG_REQ(D_INODE, req, "getxattr %s\n", xattr_name);
 
                 if (inode->i_op && inode->i_op->getxattr) {
@@ -165,15 +170,16 @@ int mds_getxattr(struct ptlrpc_request *req)
         struct lvfs_run_ctxt saved;
         struct dentry *de;
         struct mds_body *body;
-        struct lvfs_ucred uc = {NULL,};
+        struct lvfs_ucred uc = { NULL, };
         int rc = 0;
         ENTRY;
 
-        body = lustre_swab_reqbuf(req, 0, sizeof(*body), lustre_swab_mds_body);
+        body = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*body),
+                                  lustre_swab_mds_body);
         if (body == NULL)
                 RETURN(-EFAULT);
 
-        rc = mds_init_ucred(&uc, req, 0);
+        rc = mds_init_ucred(&uc, req, REQ_REC_OFF);
         if (rc)
                 GOTO(out_ucred, rc);
 
@@ -219,7 +225,6 @@ int mds_setxattr_internal(struct ptlrpc_request *req, struct mds_body *body)
         __u64 lockpart;
         ENTRY;
 
-        body = lustre_msg_buf(req->rq_reqmsg, 0, sizeof (*body));
         LASSERT(body);
 
         DEBUG_REQ(D_INODE, req, "setxattr "LPU64"/%u",
@@ -230,7 +235,7 @@ int mds_setxattr_internal(struct ptlrpc_request *req, struct mds_body *body)
         lockpart = MDS_INODELOCK_UPDATE;
 
         /* various sanity check for xattr name */
-        xattr_name = lustre_msg_string(req->rq_reqmsg, 1, 0);
+        xattr_name = lustre_msg_string(req->rq_reqmsg, REQ_REC_OFF + 1, 0);
         if (!xattr_name) {
                 CERROR("can't extract xattr name\n");
                 GOTO(out, rc = -EPROTO);
@@ -270,15 +275,16 @@ int mds_setxattr_internal(struct ptlrpc_request *req, struct mds_body *body)
 
         if (body->valid & OBD_MD_FLXATTR) {
                 if (inode->i_op && inode->i_op->setxattr) {
-                        if (req->rq_reqmsg->bufcount < 3) {
+                        if (lustre_msg_bufcount(req->rq_reqmsg) < 4) {
                                 CERROR("no xattr data supplied\n");
                                 GOTO(out_trans, rc = -EFAULT);
                         }
 
-                        xattrlen = lustre_msg_buflen(req->rq_reqmsg, 2);
+                        xattrlen = lustre_msg_buflen(req->rq_reqmsg,
+                                                     REQ_REC_OFF + 2);
                         if (xattrlen)
-                                xattr = lustre_msg_buf(req->rq_reqmsg, 2,
-                                                       xattrlen);
+                                xattr = lustre_msg_buf(req->rq_reqmsg,
+                                                       REQ_REC_OFF+2, xattrlen);
 
                         LOCK_INODE_MUTEX(inode);
                         lock_24kernel();
@@ -324,24 +330,25 @@ int mds_setxattr(struct ptlrpc_request *req)
         struct obd_device *obd = req->rq_export->exp_obd;
         struct lvfs_run_ctxt saved;
         struct mds_body *body;
-        struct lvfs_ucred uc = {NULL,};
+        struct lvfs_ucred uc = { NULL, };
         int rc;
         ENTRY;
 
-        body = lustre_swab_reqbuf(req, 0, sizeof(*body), lustre_swab_mds_body);
+        body = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*body),
+                                  lustre_swab_mds_body);
         if (body == NULL)
                 RETURN(-EFAULT);
 
-        if (req->rq_reqmsg->bufcount < 2)
+        if (lustre_msg_bufcount(req->rq_reqmsg) < 3)
                 RETURN(-EFAULT);
 
-        rc = mds_init_ucred(&uc, req, 0);
+        rc = mds_init_ucred(&uc, req, REQ_REC_OFF);
         if (rc)
                 GOTO(out_ucred, rc);
 
         push_ctxt(&saved, &obd->obd_lvfs_ctxt, &uc);
 
-        rc = lustre_pack_reply(req, 0, NULL, NULL);
+        rc = lustre_pack_reply(req, 1, NULL, NULL);
         if (rc)
                 GOTO(out_pop, rc);
 
index 62cbf3e..380dbc3 100644 (file)
@@ -170,7 +170,7 @@ int mdt_client_free(const struct lu_context *ctxt,
         else if (rc >= 0)
                 rc = -EFAULT;
 
-        CDEBUG_EX(rc == 0 ? D_INFO : D_ERROR,
+        CDEBUG(rc == 0 ? D_INFO : D_ERROR,
                   "zeroing out client idx %u in %s rc %d\n",
                   med->med_lr_idx, LAST_RCVD, rc);
 
index ec5a67c..a837505 100644 (file)
@@ -324,7 +324,6 @@ static int mdt_getattr(struct mdt_thread_info *info)
         LASSERT(lu_object_assert_exists(&obj->mot_obj.mo_lu));
         ENTRY;
 
-
         req_capsule_set_size(&info->mti_pill, &RMF_MDT_MD,
                              RCL_SERVER, info->mti_mdt->mdt_max_mdsize);
 
@@ -337,7 +336,7 @@ static int mdt_getattr(struct mdt_thread_info *info)
         } else {
                 result = mdt_getattr_internal(info, obj);
         }
-        mdt_shrink_reply(info, 1);
+        mdt_shrink_reply(info, REPLY_REC_OFF + 1);
         RETURN(result);
 }
 
@@ -465,7 +464,7 @@ static int mdt_getattr_name(struct mdt_thread_info *info)
                 ldlm_lock_decref(&lhc->mlh_lh, lhc->mlh_mode);
                 lhc->mlh_lh.cookie = 0;
         }
-        mdt_shrink_reply(info, 1);
+        mdt_shrink_reply(info, REPLY_REC_OFF + 1);
         RETURN(rc);
 }
 
@@ -635,7 +634,7 @@ static int mdt_reint_internal(struct mdt_thread_info *info, __u32 op)
                         mcd = req->rq_export->exp_mdt_data.med_mcd;
                         if (mcd->mcd_last_xid == req->rq_xid) {
                                 mdt_reconstruct(info);
-                                RETURN(req->rq_repmsg->status);
+                                RETURN(lustre_msg_get_status(req->rq_repmsg));
                         } 
                         DEBUG_REQ(D_HA, req,
                                   "no reply for RESENT (xid "LPD64")",
@@ -864,11 +863,10 @@ int fid_lock(struct ldlm_namespace *ns, const struct lu_fid *f,
         LASSERT(lh != NULL);
         LASSERT(f != NULL);
 
-        /* FIXME: is that correct to have @flags=0 here? */
-        rc = ldlm_cli_enqueue(NULL, NULL, ns, *fid_build_res_name(f, res_id),
-                              LDLM_IBITS, policy, mode, &flags,
-                              ldlm_blocking_ast, ldlm_completion_ast, NULL,
-                              NULL, NULL, 0, NULL, lh);
+        rc = ldlm_cli_enqueue_local(ns, *fid_build_res_name(f, res_id), LDLM_IBITS, 
+                                    policy, mode, &flags, ldlm_blocking_ast, 
+                                    ldlm_completion_ast, NULL, NULL, 0, NULL,
+                                    lh);
         return rc == ELDLM_OK ? 0 : -EIO;
 }
 
@@ -1106,10 +1104,14 @@ static inline void mdt_finish_reply(struct mdt_thread_info *info, int rc)
                mdt->mdt_last_transno, exp->exp_obd->obd_last_committed);
 
         spin_lock(&mdt->mdt_transno_lock);
-        req->rq_repmsg->transno = req->rq_transno = info->mti_transno;
-        req->rq_repmsg->last_committed = exp->exp_obd->obd_last_committed;
+        req->rq_transno = info->mti_transno;
+        lustre_msg_set_transno(req->rq_repmsg, info->mti_transno);
+        
+        lustre_msg_set_last_committed(req->rq_repmsg, 
+                                      exp->exp_obd->obd_last_committed);
+        
         spin_unlock(&mdt->mdt_transno_lock);
-        req->rq_repmsg->last_xid = req->rq_xid;
+        lustre_msg_set_last_xid(req->rq_repmsg, req->rq_xid);
 }
 
 /*
@@ -1126,7 +1128,7 @@ static int mdt_req_handle(struct mdt_thread_info *info,
         ENTRY;
 
         LASSERT(h->mh_act != NULL);
-        LASSERT(h->mh_opc == req->rq_reqmsg->opc);
+        LASSERT(h->mh_opc == lustre_msg_get_opc(req->rq_reqmsg));
         LASSERT(current->journal_info == NULL);
 
         DEBUG_REQ(D_INODE, req, "%s", h->mh_name);
@@ -1226,7 +1228,7 @@ static void mdt_thread_info_init(struct ptlrpc_request *req,
 
         info->mti_fail_id = OBD_FAIL_MDS_ALL_REPLY_NET;
         info->mti_ctxt = req->rq_svc_thread->t_ctx;
-        info->mti_transno = req->rq_reqmsg->transno;
+        info->mti_transno = lustre_msg_get_transno(req->rq_reqmsg);
         /* it can be NULL while CONNECT */
         if (req->rq_export)
                 info->mti_mdt = mdt_dev(req->rq_export->exp_obd->obd_lu_dev);
@@ -1264,12 +1266,12 @@ static int mdt_recovery(struct ptlrpc_request *req)
 
         ENTRY;
 
-        if (req->rq_reqmsg->opc == MDS_CONNECT)
+        if (lustre_msg_get_opc(req->rq_reqmsg) == MDS_CONNECT)
                 RETURN(+1);
 
         if (req->rq_export == NULL) {
                 CERROR("operation %d on unconnected MDS from %s\n",
-                       req->rq_reqmsg->opc,
+                       lustre_msg_get_opc(req->rq_reqmsg),
                        libcfs_id2str(req->rq_peer));
                 req->rq_status = -ENOTCONN;
                 RETURN(-ENOTCONN);
@@ -1318,7 +1320,7 @@ static int mdt_reply(struct ptlrpc_request *req, int result,
         ENTRY;
 
         if (lustre_msg_get_flags(req->rq_reqmsg) & MSG_LAST_REPLAY) {
-                if (req->rq_reqmsg->opc != OBD_PING)
+                if (lustre_msg_get_opc(req->rq_reqmsg) != OBD_PING)
                         DEBUG_REQ(D_ERROR, req, "Unexpected MSG_LAST_REPLAY");
 
                 obd = req->rq_export != NULL ? req->rq_export->exp_obd : NULL;
@@ -1357,7 +1359,7 @@ static int mdt_handle0(struct ptlrpc_request *req, struct mdt_thread_info *info,
                 result = mdt_recovery(req);
                 switch (result) {
                 case +1:
-                        h = mdt_handler_find(msg->opc, supported);
+                        h = mdt_handler_find(lustre_msg_get_opc(msg), supported);
                         if (h != NULL)
                                 result = mdt_req_handle(info, h, req);
                         else {
@@ -1550,7 +1552,7 @@ static int mdt_intent_getattr(enum mdt_it_code opcode,
 
         ldlm_rep->lock_policy_res2 =
                 mdt_getattr_name_lock(info, lhc, child_bits, ldlm_rep);
-        mdt_shrink_reply(info, 2);
+        mdt_shrink_reply(info, DLM_REPLY_REC_OFF + 1);
 
         if (intent_disposition(ldlm_rep, DISP_LOOKUP_NEG))
                 ldlm_rep->lock_policy_res2 = 0;
@@ -1583,7 +1585,7 @@ static int mdt_intent_getattr(enum mdt_it_code opcode,
          */
 
         /* Fixup the lock to be given to the client */
-        l_lock(&new_lock->l_resource->lr_namespace->ns_lock);
+        lock_res_and_lock(new_lock);
         new_lock->l_readers = 0;
         new_lock->l_writers = 0;
 
@@ -1598,7 +1600,7 @@ static int mdt_intent_getattr(enum mdt_it_code opcode,
 
         new_lock->l_flags &= ~LDLM_FL_LOCAL;
 
-        l_unlock(&new_lock->l_resource->lr_namespace->ns_lock);
+        unlock_res_and_lock(new_lock);
         LDLM_LOCK_PUT(new_lock);
 
         RETURN(ELDLM_LOCK_REPLACED);
@@ -1738,7 +1740,7 @@ static int mdt_intent_policy(struct ldlm_namespace *ns,
         pill = &info->mti_pill;
         LASSERT(pill->rc_req == req);
 
-        if (req->rq_reqmsg->bufcount > MDS_REQ_INTENT_IT_OFF) {
+        if (req->rq_reqmsg->lm_bufcount > DLM_INTENT_IT_OFF) {
                 req_capsule_extend(pill, &RQF_LDLM_INTENT);
                 it = req_capsule_client_get(pill, &RMF_LDLM_INTENT);
                 if (it != NULL) {
@@ -2566,7 +2568,6 @@ static int mdt_obd_connect(const struct lu_context *ctx,
 
 static int mdt_obd_disconnect(struct obd_export *exp)
 {
-        unsigned long irqflags;
         int rc;
         ENTRY;
 
@@ -2949,6 +2950,12 @@ static struct mdt_opc_slice mdt_handlers[] = {
 
 static struct mdt_handler mdt_mds_readpage_ops[] = {
         DEF_MDT_HNDL_F(HABEO_CORPUS|HABEO_REFERO, READPAGE, mdt_readpage),
+
+        /*
+         * XXX: this is ugly and should be fixed one day, see mdc_close() for
+         * detailed comment. --umka
+         */
+        DEF_MDT_HNDL_F(HABEO_CORPUS             , CLOSE,    mdt_close),
 };
 
 static struct mdt_opc_slice mdt_readpage_handlers[] = {
index 6befc52..6f53189 100644 (file)
@@ -49,15 +49,15 @@ void mdt_dump_lmm(int level, struct lov_mds_md *lmm)
         __s16 stripe_count =
                 le16_to_cpu(((struct lov_user_md*)lmm)->lmm_stripe_count);
 
-        CDEBUG_EX(level, "objid "LPX64", magic 0x%08X, pattern %#X\n",
+        CDEBUG(level, "objid "LPX64", magic 0x%08X, pattern %#X\n",
                le64_to_cpu(lmm->lmm_object_id), le32_to_cpu(lmm->lmm_magic),
                le32_to_cpu(lmm->lmm_pattern));
-        CDEBUG_EX(level,"stripe_size=0x%x, stripe_count=0x%x\n",
+        CDEBUG(level,"stripe_size=0x%x, stripe_count=0x%x\n",
                le32_to_cpu(lmm->lmm_stripe_size),
                le32_to_cpu(lmm->lmm_stripe_count));
         LASSERT(stripe_count < (__s16)LOV_MAX_STRIPE_COUNT);
         for (i = 0, lod = lmm->lmm_objects; i < stripe_count; i++, lod++) {
-                CDEBUG_EX(level, "stripe %u idx %u subobj "LPX64"/"LPX64"\n",
+                CDEBUG(level, "stripe %u idx %u subobj "LPX64"/"LPX64"\n",
                        i, le32_to_cpu(lod->l_ost_idx),
                        le64_to_cpu(lod->l_object_gr),
                        le64_to_cpu(lod->l_object_id));
@@ -81,7 +81,7 @@ void mdt_shrink_reply(struct mdt_thread_info *info, int offset)
                        md_size, acl_size);
 
         lustre_shrink_reply(req, offset, md_size, 1);
-        lustre_shrink_reply(req, md_size? offset + 1: offset, acl_size, 0);
+        lustre_shrink_reply(req, md_size ? offset + 1: offset, acl_size, 0);
 }
 
 
index e0de245..11b15fc 100644 (file)
@@ -248,9 +248,9 @@ static int mdt_mfd_open(struct mdt_thread_info *info,
                 else
                         repbody->valid |= OBD_MD_FLEASIZE;
         }
-        /*FIXME: should determine the offset dynamicly,
-         *did not get ACL before shrink*/
-        mdt_shrink_reply(info, 2);
+        /* FIXME: should determine the offset dynamicly,
+         * did not get ACL before shrink. */
+        mdt_shrink_reply(info, DLM_REPLY_REC_OFF + 1);
 
         ldlm_rep = req_capsule_server_get(&info->mti_pill, &RMF_DLM_REP);
         intent_set_disposition(ldlm_rep, DISP_OPEN_OPEN);
@@ -552,7 +552,7 @@ int mdt_close(struct mdt_thread_info *info)
                 /* release reference on this object. */
                 mdt_object_put(info->mti_ctxt, o);
         }
-        mdt_shrink_reply(info, 1);
+        mdt_shrink_reply(info, REPLY_REC_OFF + 1);
         RETURN(rc);
 }
 
index 54a38b9..b988468 100644 (file)
@@ -459,9 +459,9 @@ int mdt_client_free(const struct lu_context *ctx,
         rc = mdt_write_last_rcvd(ctx, mdt, mcd, &off, NULL);
         mutex_up(&med->med_mcd_lock);
 
-        CDEBUG_EX(rc == 0 ? D_INFO : D_ERROR,
-                  "zeroing out client idx %u in %s rc %d\n",
-                  med->med_lr_idx, LAST_RCVD, rc);
+        CDEBUG(rc == 0 ? D_INFO : D_ERROR,
+               "zeroing out client idx %u in %s rc %d\n",
+               med->med_lr_idx, LAST_RCVD, rc);
 
         if (!test_and_clear_bit(med->med_lr_idx, mdt->mdt_client_bitmap)) {
                 CERROR("MDS client %u: bit already clear in bitmap!!\n",
@@ -660,8 +660,10 @@ static inline void mdt_req_from_mcd(struct ptlrpc_request *req,
 {
         DEBUG_REQ(D_HA, req, "restoring transno "LPD64"/status %d",
                   mcd->mcd_last_transno, mcd->mcd_last_result);
-        req->rq_repmsg->transno = req->rq_transno = mcd->mcd_last_transno;
-        req->rq_repmsg->status = req->rq_status = mcd->mcd_last_result;
+        req->rq_transno = mcd->mcd_last_transno;
+        req->rq_status = mcd->mcd_last_result;
+        lustre_msg_set_transno(req->rq_repmsg, req->rq_transno);
+        lustre_msg_set_status(req->rq_repmsg, req->rq_status);
         //mds_steal_ack_locks(req);
 }
 
index d9bd795..b67d355 100644 (file)
@@ -308,7 +308,7 @@ out_unlock_child:
         mdt_object_unlock_put(info, mc, lhc, rc);
 out_unlock_parent:
         mdt_object_unlock_put(info, mp, lhp, rc);
-        mdt_shrink_reply(info, 1);
+        mdt_shrink_reply(info, REPLY_REC_OFF + 1);
         return rc;
 }
 
index 2b3a807..b011e8c 100644 (file)
@@ -1,11 +1,18 @@
-# Copyright (C) 2001  Cluster File Systems, Inc.
+# Copyright (C) 2006  Cluster File Systems, Inc.
 #
 # This code is issued under the GNU General Public License.
 # See the file COPYING in this distribution
 
+if LIBLUSTRE
+noinst_LIBRARIES = libmgc.a
+libmgc_a_SOURCES = libmgc.c
+libmgc_a_CPPFLAGS = $(LLCPPFLAGS)
+libmgc_a_CFLAGS = $(LLCFLAGS)
+endif
+
 if MODULES
 modulefs_DATA = mgc$(KMODEXT)
 endif
 
 MOSTLYCLEANFILES := @MOSTLYCLEANFILES@ 
-DIST_SOURCES := $(mgc-objs:%.o=%.c)
+DIST_SOURCES := $(mgc-objs:%.o=%.c) libmgc.c
diff --git a/lustre/mgc/libmgc.c b/lustre/mgc/libmgc.c
new file mode 100644 (file)
index 0000000..a268422
--- /dev/null
@@ -0,0 +1,126 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ *  lustre/mgc/mgc_request.c
+ *  Lustre Management Client
+ *
+ *  Copyright (C) 2006 Cluster File Systems, Inc.
+ *   Author: Nathan Rutman <nathan@clusterfs.com>
+ *
+ *   This file is part of Lustre, http://www.lustre.org
+ *
+ *   Lustre is free software; you can redistribute it and/or
+ *   modify it under the terms of version 2 of the GNU General Public
+ *   License as published by the Free Software Foundation.
+ *
+ *   Lustre is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Lustre; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+/* Minimal MGC for liblustre */
+#ifndef EXPORT_SYMTAB
+# define EXPORT_SYMTAB
+#endif
+#define DEBUG_SUBSYSTEM S_MGC
+
+#include <liblustre.h>
+
+#include <obd_class.h>
+#include <lustre_dlm.h>
+#include <lustre_log.h>
+#include <lustre_fsfilt.h>
+#include <lustre_disk.h>
+
+
+static int mgc_cleanup(struct obd_device *obd)
+{
+        struct client_obd *cli = &obd->u.cli;
+        int rc;
+        ENTRY;
+
+        LASSERT(cli->cl_mgc_vfsmnt == NULL);
+        
+        ptlrpcd_decref();
+
+        rc = client_obd_cleanup(obd);
+        RETURN(rc);
+}
+
+static int mgc_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
+{
+        int rc;
+        ENTRY;
+
+        ptlrpcd_addref();
+
+        rc = client_obd_setup(obd, lcfg);
+        if (rc)
+                GOTO(err_decref, rc);
+
+        rc = obd_llog_init(obd, obd, 0, NULL);
+        if (rc) {
+                CERROR("failed to setup llogging subsystems\n");
+                GOTO(err_cleanup, rc);
+        }
+
+        RETURN(rc);
+
+err_cleanup:
+        client_obd_cleanup(obd);
+err_decref:
+        ptlrpcd_decref();
+        RETURN(rc);
+}
+
+static int mgc_llog_init(struct obd_device *obd, struct obd_device *tgt,
+                         int count, struct llog_catid *logid)
+{
+        struct llog_ctxt *ctxt;
+        int rc;
+        ENTRY;
+
+        rc = llog_setup(obd, LLOG_CONFIG_REPL_CTXT, tgt, 0, NULL,
+                        &llog_client_ops);
+        if (rc == 0) {
+                ctxt = llog_get_context(obd, LLOG_CONFIG_REPL_CTXT);
+                ctxt->loc_imp = obd->u.cli.cl_import;
+        }
+
+        RETURN(rc);
+}
+
+static int mgc_llog_finish(struct obd_device *obd, int count)
+{
+        int rc;
+        ENTRY;
+
+        rc = llog_cleanup(llog_get_context(obd, LLOG_CONFIG_REPL_CTXT));
+
+        RETURN(rc);
+}
+
+struct obd_ops mgc_obd_ops = {
+        .o_owner        = THIS_MODULE,
+        .o_setup        = mgc_setup,
+        .o_cleanup      = mgc_cleanup,
+        .o_add_conn     = client_import_add_conn,
+        .o_del_conn     = client_import_del_conn,
+        .o_connect      = client_connect_import,
+        .o_disconnect   = client_disconnect_export,
+        .o_llog_init    = mgc_llog_init,
+        .o_llog_finish  = mgc_llog_finish,
+};
+
+int __init mgc_init(void)
+{
+        return class_register_type(&mgc_obd_ops, NULL, 
+                                   NULL, LUSTRE_MGC_NAME, NULL);
+}
+
index a56c781..fe912bf 100644 (file)
@@ -70,7 +70,7 @@ int mgc_logname2resid(char *logname, struct ldlm_res_id *res_id)
         memcpy(&resname, logname, len);
 
         memset(res_id, 0, sizeof(*res_id));
-        /* FIXME are resid names swabbed across the wire? */
+        /* Always use the same endianness for the resid */
         res_id->name[0] = cpu_to_le64(resname);
         CDEBUG(D_MGC, "log %s to resid "LPX64"/"LPX64" (%.8s)\n", logname,
                res_id->name[0], res_id->name[1], (char *)&res_id->name[0]);
@@ -103,6 +103,7 @@ static void config_log_put(struct config_llog_data *cld)
                atomic_read(&cld->cld_refcount));
         if (atomic_dec_and_test(&cld->cld_refcount)) {
                 CDEBUG(D_MGC, "dropping config log %s\n", cld->cld_logname);
+                class_export_put(cld->cld_mgcexp);
                 OBD_FREE(cld->cld_logname, strlen(cld->cld_logname) + 1);
                 if (cld->cld_cfg.cfg_instance != NULL)
                         OBD_FREE(cld->cld_cfg.cfg_instance,
@@ -158,6 +159,7 @@ static int config_log_add(char *logname, struct config_llog_instance *cfg,
                           struct super_block *sb)
 {
         struct config_llog_data *cld;
+        struct lustre_sb_info *lsi = s2lsi(sb);
         int rc;
         ENTRY;
 
@@ -177,6 +179,10 @@ static int config_log_add(char *logname, struct config_llog_instance *cfg,
         cld->cld_cfg.cfg_flags = 0;
         cld->cld_cfg.cfg_sb = sb;
         atomic_set(&cld->cld_refcount, 1);
+        
+        /* Keep the mgc around until we are done */
+        cld->cld_mgcexp = class_export_get(lsi->lsi_mgc->obd_self_export);
+        
         if (cfg->cfg_instance != NULL) {
                 OBD_ALLOC(cld->cld_cfg.cfg_instance,
                           strlen(cfg->cfg_instance) + 1);
@@ -218,7 +224,8 @@ static int config_log_end(char *logname, struct config_llog_instance *cfg)
         RETURN(rc);
 }
 
-/* Failsafe */
+#if 0
+/* Failsafe FIXME remove this */
 static void config_log_end_all(void)
 {
         struct list_head *tmp, *n;
@@ -228,14 +235,14 @@ static void config_log_end_all(void)
         spin_lock(&config_list_lock);
         list_for_each_safe(tmp, n, &config_llog_list) {
                 cld = list_entry(tmp, struct config_llog_data, cld_list_chain);
-                CERROR("conflog failsafe %s\n", cld->cld_logname);
+                CERROR("\n\nconflog failsafe %s\n\n\n", cld->cld_logname);
                 list_del(&cld->cld_list_chain);
                 config_log_put(cld);
         }
         spin_unlock(&config_list_lock);
         EXIT;
 }
-
+#endif
 
 /********************** class fns **********************/
 
@@ -327,6 +334,7 @@ static int mgc_fs_cleanup(struct obd_device *obd)
                 fsfilt_put_ops(obd->obd_fsops);
 
         up(&cli->cl_mgc_sem);
+
         RETURN(rc);
 }
 
@@ -337,6 +345,7 @@ static int mgc_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
 
         switch (stage) {
         case OBD_CLEANUP_EARLY: 
+                break;
         case OBD_CLEANUP_EXPORTS:
                 break;
         case OBD_CLEANUP_SELF_EXP:
@@ -358,7 +367,11 @@ static int mgc_cleanup(struct obd_device *obd)
 
         LASSERT(cli->cl_mgc_vfsmnt == NULL);
         
-        config_log_end_all();
+        /* COMPAT_146 - old config logs may have added profiles we don't 
+           know about */
+        if (obd->obd_type->typ_refcnt <= 1) 
+                /* Only for the last mgc */
+                class_del_profiles();
 
         ptlrpcd_decref();
 
@@ -366,8 +379,6 @@ static int mgc_cleanup(struct obd_device *obd)
         RETURN(rc);
 }
 
-static struct obd_device *the_mgc;
-
 static int mgc_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
 {
         int rc;
@@ -385,7 +396,6 @@ static int mgc_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
                 GOTO(err_cleanup, rc);
         }
 
-        the_mgc = obd;
         RETURN(rc);
 
 err_cleanup:
@@ -427,21 +437,19 @@ static int mgc_async_requeue(void *data)
            the lock revocation to finish its setup, plus some random
            so everyone doesn't try to reconnect at once. */
         init_waitqueue_head(&waitq);
-        lwi = LWI_TIMEOUT(3 * HZ + (ll_rand() & 0x7f), NULL, NULL);
+        lwi = LWI_TIMEOUT(3 * HZ + (ll_rand() & 0xff), NULL, NULL);
         l_wait_event(waitq, 0, &lwi);
 
-        LASSERT(the_mgc);
-
-        class_export_get(the_mgc->obd_self_export);
 #if 0
         /* Re-send server info every time, in case MGS needs to regen its
            logs (for write_conf).  Do we need this?  It's extra RPCs for
            every server at every update.  Turning it off until I'm sure
            it's needed. */
+        /* Unsafe - we don't know that the lsi hasn't been destroyed */
         server_register_target(cld->cld_cfg.cfg_sb);
-#endif
-        rc = mgc_process_log(the_mgc, cld);
-        class_export_put(the_mgc->obd_self_export);
+#endif 
+
+        rc = mgc_process_log(cld->cld_mgcexp->exp_obd, cld);
 out:
         /* Whether we enqueued again or not in mgc_process_log,
            we're done with the ref from the old mgc_blocking_ast */
@@ -532,7 +540,6 @@ static int mgc_enqueue(struct obd_export *exp, struct lov_stripe_md *lsm,
                        struct lustre_handle *lockh)
 {
         struct config_llog_data *cld = (struct config_llog_data *)data;
-        struct obd_device *obd = class_exp2obd(exp);
         int rc;
         ENTRY;
 
@@ -546,10 +553,10 @@ static int mgc_enqueue(struct obd_export *exp, struct lov_stripe_md *lsm,
         /* We need a callback for every lockholder, so don't try to
            ldlm_lock_match (see rev 1.1.2.11.2.47) */
 
-        rc = ldlm_cli_enqueue(exp, NULL, obd->obd_namespace, cld->cld_resid,
-                              type, NULL, mode, flags,
+        rc = ldlm_cli_enqueue(exp, NULL, cld->cld_resid,
+                              type, NULL, mode, flags, 
                               mgc_blocking_ast, ldlm_completion_ast, NULL,
-                              data, NULL, 0, NULL, lockh);
+                              data, NULL, 0, NULL, lockh, 0);
 
         RETURN(rc);
 }
@@ -632,28 +639,29 @@ static int mgc_target_register(struct obd_export *exp,
 {
         struct ptlrpc_request *req;
         struct mgs_target_info *req_mti, *rep_mti;
-        int size = sizeof(*req_mti);
-        int rep_size = sizeof(*mti);
+        int size[] = { sizeof(struct ptlrpc_body), sizeof(*req_mti) };
+        int rep_size[] = { sizeof(struct ptlrpc_body), sizeof(*mti) };
         int rc;
         ENTRY;
 
         req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_MGS_VERSION,
-                              MGS_TARGET_REG, 1, &size, NULL);
+                              MGS_TARGET_REG, 2, size, NULL);
         if (!req)
                 RETURN(-ENOMEM);
 
-        req_mti = lustre_msg_buf(req->rq_reqmsg, 0, sizeof(*req_mti));
-        if (!req_mti)
+        req_mti = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, sizeof(*req_mti));
+        if (!req_mti) 
                 RETURN(-ENOMEM);
         memcpy(req_mti, mti, sizeof(*req_mti));
 
-        req->rq_replen = lustre_msg_size(1, &rep_size);
+        ptlrpc_req_set_repsize(req, 2, rep_size);
 
         CDEBUG(D_MGC, "register %s\n", mti->mti_svname);
 
         rc = ptlrpc_queue_wait(req);
         if (!rc) {
-                rep_mti = lustre_swab_repbuf(req, 0, sizeof(*rep_mti),
+                rep_mti = lustre_swab_repbuf(req, REPLY_REC_OFF,
+                                             sizeof(*rep_mti),
                                              lustre_swab_mgs_target_info);
                 memcpy(mti, rep_mti, sizeof(*rep_mti));
                 CDEBUG(D_MGC, "register %s got index = %d\n",
@@ -690,15 +698,20 @@ int mgc_set_info_async(struct obd_export *exp, obd_count keylen,
                         RETURN(-EINVAL);
                 value = *(int *)val;
                 imp->imp_initial_recov_bk = value > 0;
+                /* Even after the initial connection, give up all comms if 
+                   nobody answers the first time. */
+                imp->imp_recon_bk = 1;
+                CDEBUG(D_MGC, "InitRecov %s %d/%d:d%d:i%d:r%d:or%d:%s\n", 
+                       imp->imp_obd->obd_name, value, imp->imp_initial_recov,
+                       imp->imp_deactive, imp->imp_invalid, 
+                       imp->imp_replayable, imp->imp_obd->obd_replayable,
+                       ptlrpc_import_state_name(imp->imp_state));
+                /* Resurrect if we previously died */
                 if (imp->imp_invalid || value > 1) {
-                        /* Resurrect if we previously died */
-                        CDEBUG(D_MGC, "Reactivate %s %d:%d:%d:%s\n", 
-                               imp->imp_obd->obd_name, value,
-                               imp->imp_deactive, imp->imp_invalid, 
-                               ptlrpc_import_state_name(imp->imp_state));
-                        /* can't put this in obdclass, module loop with ptlrpc*/
-                        /* This seems to be necessary when restarting a
-                           combo mgs/mdt while the mgc is alive */
+                        /* Allow reconnect attempts */
+                        imp->imp_obd->obd_no_recov = 0;
+                        /* Force a new connect attempt */
+                        /* (can't put these in obdclass, module loop) */
                         ptlrpc_invalidate_import(imp);
                         /* Remove 'invalid' flag */
                         ptlrpc_activate_import(imp);
@@ -707,7 +720,7 @@ int mgc_set_info_async(struct obd_export *exp, obd_count keylen,
                 }
                 RETURN(0);
         }
-        /* Hack alert */
+        /* FIXME move this to mgc_process_config */
         if (KEY_IS("register_target")) {
                 struct mgs_target_info *mti;
                 if (vallen != sizeof(struct mgs_target_info))
@@ -753,16 +766,17 @@ static int mgc_import_event(struct obd_device *obd,
         CDEBUG(D_MGC, "import event %#x\n", event);
 
         switch (event) {
-        case IMP_EVENT_INVALIDATE: {
-                struct ldlm_namespace *ns = obd->obd_namespace;
-                ldlm_namespace_cleanup(ns, LDLM_FL_LOCAL_ONLY);
-                break;
-        }
         case IMP_EVENT_DISCON: 
                 /* MGC imports should not wait for recovery */
                 ptlrpc_invalidate_import(imp);
                 break;
         case IMP_EVENT_INACTIVE: 
+                break;
+        case IMP_EVENT_INVALIDATE: {
+                struct ldlm_namespace *ns = obd->obd_namespace;
+                ldlm_namespace_cleanup(ns, LDLM_FL_LOCAL_ONLY);
+                break;
+        }
         case IMP_EVENT_ACTIVE: 
         case IMP_EVENT_OCD:
                 break;
@@ -838,7 +852,6 @@ static int mgc_copy_handler(struct llog_handle *llh, struct llog_rec_hdr *rec,
 
         lcfg = (struct lustre_cfg *)cfg_buf;
 
-        /* FIXME we should always write to an empty log, so remove this check.*/
         /* append new records */
         if (rec->lrh_index >= llog_get_size(local_llh)) {
                 rc = llog_write_rec(local_llh, &local_rec, NULL, 0,
@@ -923,6 +936,8 @@ static int mgc_process_log(struct obd_device *mgc,
         if (cld->cld_stopping)
                 RETURN(0);
 
+        OBD_FAIL_TIMEOUT(OBD_FAIL_MGC_PROCESS_LOG, 20);
+
         lsi = s2lsi(cld->cld_cfg.cfg_sb);
 
         CDEBUG(D_MGC, "Process log %s:%s from %d\n", cld->cld_logname,
@@ -1012,6 +1027,7 @@ static int mgc_process_config(struct obd_device *obd, obd_count len, void *buf)
 
         switch(cmd = lcfg->lcfg_command) {
         case LCFG_LOV_ADD_OBD: {
+                /* Add any new target, not just osts */
                 struct mgs_target_info *mti;
 
                 if (LUSTRE_CFG_BUFLEN(lcfg, 1) !=
@@ -1025,6 +1041,7 @@ static int mgc_process_config(struct obd_device *obd, obd_count len, void *buf)
                 break;
         }
         case LCFG_LOV_DEL_OBD:
+                /* Remove target from the fs? */  
                 /* FIXME */
                 CERROR("lov_del_obd unimplemented\n");
                 rc = -ENOSYS;
@@ -1051,10 +1068,10 @@ static int mgc_process_config(struct obd_device *obd, obd_count len, void *buf)
                 }
 
                 /* COMPAT_146 */
-                /* For old logs, there was no start marker. */
-                /* FIXME only set this for old logs! */
-                cld->cld_cfg.cfg_flags |= CFG_F_MARKER;
-
+                /* FIXME only set this for old logs!  Right now this forces
+                   us to always skip the "inside markers" check */
+                cld->cld_cfg.cfg_flags |= CFG_F_COMPAT146;
+                
                 rc = mgc_process_log(obd, cld);
                 config_log_put(cld);
 
index ce489ae..aab8443 100644 (file)
@@ -114,7 +114,7 @@ int mgs_fs_setup(struct obd_device *obd, struct vfsmount *mnt)
         int rc;
         ENTRY;
 
-        // FIXME what's this?
+        /* FIXME what's this?  Do I need it? */
         rc = cleanup_group_info();
         if (rc)
                 RETURN(rc);
index 73f1793..9148e3b 100644 (file)
@@ -83,7 +83,6 @@ static int mgs_connect(const struct lu_context *ctx,
 
 static int mgs_disconnect(struct obd_export *exp)
 {
-        unsigned long irqflags;
         int rc;
         ENTRY;
 
@@ -95,7 +94,7 @@ static int mgs_disconnect(struct obd_export *exp)
         ldlm_cancel_locks_for_export(exp);
 
         /* complete all outstanding replies */
-        spin_lock_irqsave(&exp->exp_lock, irqflags);
+        spin_lock(&exp->exp_lock);
         while (!list_empty(&exp->exp_outstanding_replies)) {
                 struct ptlrpc_reply_state *rs =
                         list_entry(exp->exp_outstanding_replies.next,
@@ -107,7 +106,7 @@ static int mgs_disconnect(struct obd_export *exp)
                 ptlrpc_schedule_difficult_reply(rs);
                 spin_unlock(&svc->srv_lock);
         }
-        spin_unlock_irqrestore(&exp->exp_lock, irqflags);
+        spin_unlock(&exp->exp_lock);
 
         class_export_put(exp);
         RETURN(rc);
@@ -169,8 +168,8 @@ static int mgs_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
         if (rc)
                 GOTO(err_fs, rc);
 
-        /* Allow reconnect attempts */
-        obd->obd_replayable = 1;
+        /* No recovery for MGC's */
+        obd->obd_replayable = 0;
 
         /* Internal mgs setup */
         mgs_init_fsdb_list(obd);
@@ -253,7 +252,6 @@ static int mgs_ldlm_nsfree(void *data)
 static int mgs_cleanup(struct obd_device *obd)
 {
         struct mgs_obd *mgs = &obd->u.mgs;
-        lvfs_sbdev_type save_dev;
         ENTRY;
 
         ping_evictor_stop();
@@ -261,8 +259,6 @@ static int mgs_cleanup(struct obd_device *obd)
         if (mgs->mgs_sb == NULL)
                 RETURN(0);
 
-        save_dev = lvfs_sbdev(mgs->mgs_sb);
-
         ptlrpc_unregister_service(mgs->mgs_service);
 
         lprocfs_obd_cleanup(obd);
@@ -280,7 +276,6 @@ static int mgs_cleanup(struct obd_device *obd)
         cfs_kernel_thread(mgs_ldlm_nsfree, obd->obd_namespace,
                           CLONE_VM | CLONE_FILES);
 
-        lvfs_clear_rdonly(save_dev);
 
         fsfilt_put_ops(obd->obd_fsops);
 
@@ -297,12 +292,13 @@ static int mgs_get_cfg_lock(struct obd_device *obd, char *fsname,
         ENTRY;
 
         rc = mgc_logname2resid(fsname, &res_id);
-        if (!rc)
-                rc = ldlm_cli_enqueue(NULL, NULL, obd->obd_namespace, res_id,
-                                      LDLM_PLAIN, NULL, LCK_EX, &flags,
-                                      ldlm_blocking_ast, ldlm_completion_ast,
-                                      NULL, fsname, NULL, 0, NULL, lockh);
-        if (rc)
+        if (!rc) 
+                rc = ldlm_cli_enqueue_local(obd->obd_namespace, res_id,
+                                            LDLM_PLAIN, NULL, LCK_EX,
+                                            &flags, ldlm_blocking_ast,
+                                            ldlm_completion_ast, NULL,
+                                            fsname, 0, NULL, lockh);
+        if (rc) 
                 CERROR("can't take cfg lock for %s (%d)\n", fsname, rc);
 
         RETURN(rc);
@@ -315,7 +311,9 @@ static int mgs_put_cfg_lock(struct lustre_handle *lockh)
         RETURN(0);
 }
 
-/* rc=0 means ok */
+/* rc=0 means ok
+      1 means update
+     <0 means error */
 static int mgs_check_target(struct obd_device *obd, struct mgs_target_info *mti)
 {
         int rc;
@@ -323,9 +321,10 @@ static int mgs_check_target(struct obd_device *obd, struct mgs_target_info *mti)
 
         rc = mgs_check_index(obd, mti);
         if (rc == 0) {
-                LCONSOLE_ERROR("Index for %s has disappeared!  "
-                               "Regenerating this portion of the logs."
-                               "\n", mti->mti_svname);
+                LCONSOLE_ERROR("%s claims to have registered, but this MGS "
+                               "does not know about it.  Assuming the log was "
+                               "lost, will regenerate.\n",
+                               mti->mti_svname);
                 mti->mti_flags |= LDD_F_UPDATE;
                 rc = 1;
         } else if (rc == -1) {
@@ -342,7 +341,6 @@ static int mgs_check_target(struct obd_device *obd, struct mgs_target_info *mti)
                 rc = mgs_check_failnid(obd, mti);
         }
 
-
         RETURN(rc);
 }
 
@@ -352,11 +350,11 @@ static int mgs_handle_target_reg(struct ptlrpc_request *req)
         struct obd_device *obd = req->rq_export->exp_obd;
         struct lustre_handle lockh;
         struct mgs_target_info *mti, *rep_mti;
-        int rep_size = sizeof(*mti);
+        int rep_size[] = { sizeof(struct ptlrpc_body), sizeof(*mti) };
         int rc = 0, lockrc;
         ENTRY;
 
-        mti = lustre_swab_reqbuf(req, 0, sizeof(*mti),
+        mti = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*mti),
                                  lustre_swab_mgs_target_info);
 
         if (!(mti->mti_flags & (LDD_F_WRITECONF | LDD_F_UPGRADE14 |
@@ -366,8 +364,8 @@ static int mgs_handle_target_reg(struct ptlrpc_request *req)
                        mti->mti_svname, obd_export_nid2str(req->rq_export));
                 rc = mgs_check_target(obd, mti);
                 /* above will set appropriate mti flags */
-                if (!rc)
-                        /* Nothing wrong, don't revoke lock */
+                if (rc <= 0) 
+                        /* Nothing wrong, or fatal error */
                         GOTO(out_nolock, rc);
         }
 
@@ -386,16 +384,6 @@ static int mgs_handle_target_reg(struct ptlrpc_request *req)
 
         /* Log writing contention is handled by the fsdb_sem */
 
-        if (mti->mti_flags & LDD_F_WRITECONF) {
-                rc = mgs_erase_logs(obd, mti->mti_fsname);
-                mti->mti_flags |= LDD_F_UPDATE;
-                LCONSOLE_WARN("%s: Logs for fs %s were removed by user request."
-                              " All servers must re-register in order to "
-                              "regenerate the client log.\n",
-                              obd->obd_name, mti->mti_fsname);
-                mti->mti_flags &= ~LDD_F_WRITECONF;
-        }
-
         /* COMPAT_146 */
         if (mti->mti_flags & LDD_F_UPGRADE14) {
                 rc = mgs_upgrade_sv_14(obd, mti);
@@ -403,18 +391,38 @@ static int mgs_handle_target_reg(struct ptlrpc_request *req)
                         CERROR("Can't upgrade from 1.4 (%d)\n", rc);
                         GOTO(out, rc);
                 }
-
-                mti->mti_flags &= ~LDD_F_UPGRADE14;
-                /* Turn off the upgrade flag permanently */
+                
+                /* Turn off all other update-related flags; we're done. */
+                mti->mti_flags &= ~(LDD_F_UPGRADE14 | 
+                                    LDD_F_VIRGIN | LDD_F_UPDATE | 
+                                    LDD_F_NEED_INDEX | LDD_F_WRITECONF);
                 mti->mti_flags |= LDD_F_REWRITE_LDD;
+                goto out;
         }
         /* end COMPAT_146 */
 
+        if (mti->mti_flags & LDD_F_WRITECONF) {
+                if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
+                        rc = mgs_erase_logs(obd, mti->mti_fsname);
+                        LCONSOLE_WARN("%s: Logs for fs %s were removed by user "
+                                      "request.  All servers must be restarted "
+                                      "in order to regenerate the logs."
+                                      "\n", obd->obd_name, mti->mti_fsname);
+                } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
+                        rc = mgs_erase_log(obd, mti->mti_svname);
+                        LCONSOLE_WARN("%s: Regenerating %s log by user "
+                                      "request.\n",
+                                      obd->obd_name, mti->mti_svname);
+                }
+                mti->mti_flags |= LDD_F_UPDATE;
+        }
+
+
         if (mti->mti_flags & LDD_F_UPDATE) {
-                CDEBUG(D_MGS, "adding %s, index=%d\n", mti->mti_svname,
+                CDEBUG(D_MGS, "updating %s, index=%d\n", mti->mti_svname, 
                        mti->mti_stripe_index);
-
-                /* create the log for the new target
+                
+                /* create or update the target log 
                    and update the client/mdt logs */
                 rc = mgs_write_log_target(obd, mti);
                 if (rc) {
@@ -423,8 +431,8 @@ static int mgs_handle_target_reg(struct ptlrpc_request *req)
                         GOTO(out, rc);
                 }
 
-                mti->mti_flags &= ~(LDD_F_VIRGIN | LDD_F_UPDATE |
-                                    LDD_F_NEED_INDEX);
+                mti->mti_flags &= ~(LDD_F_VIRGIN | LDD_F_UPDATE | 
+                                    LDD_F_NEED_INDEX | LDD_F_WRITECONF);
                 mti->mti_flags |= LDD_F_REWRITE_LDD;
         }
 
@@ -435,36 +443,41 @@ out:
 out_nolock:
         CDEBUG(D_MGS, "replying with %s, index=%d, rc=%d\n", mti->mti_svname,
                mti->mti_stripe_index, rc);
-        lustre_pack_reply(req, 1, &rep_size, NULL);
+        lustre_pack_reply(req, 2, rep_size, NULL); 
         /* send back the whole mti in the reply */
-        rep_mti = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*rep_mti));
+        rep_mti = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
+                                 sizeof(*rep_mti));
         memcpy(rep_mti, mti, sizeof(*rep_mti));
+
+        /* Flush logs to disk */
+        fsfilt_sync(obd, obd->u.mgs.mgs_sb);
         RETURN(rc);
 }
 
 int mgs_handle(struct ptlrpc_request *req)
 {
         int fail = OBD_FAIL_MGS_ALL_REPLY_NET;
-        int rc = 0;
+        int opc, rc = 0;
         ENTRY;
 
         OBD_FAIL_RETURN(OBD_FAIL_MGS_ALL_REQUEST_NET | OBD_FAIL_ONCE, 0);
 
         LASSERT(current->journal_info == NULL);
-        if (req->rq_reqmsg->opc != MGS_CONNECT) {
+        opc = lustre_msg_get_opc(req->rq_reqmsg);
+        if (opc != MGS_CONNECT) {
                 if (req->rq_export == NULL) {
                         CERROR("lustre_mgs: operation %d on unconnected MGS\n",
-                               req->rq_reqmsg->opc);
+                               opc);
                         req->rq_status = -ENOTCONN;
                         GOTO(out, rc = -ENOTCONN);
                 }
         }
 
-        switch (req->rq_reqmsg->opc) {
+        switch (opc) {
         case MGS_CONNECT:
                 DEBUG_REQ(D_MGS, req, "connect");
                 rc = target_handle_connect(req, mgs_handle);
-                if (!rc && (req->rq_reqmsg->conn_cnt > 1))
+                if (!rc && (lustre_msg_get_conn_cnt(req->rq_reqmsg) > 1))
                         /* Make clients trying to reconnect after a MGS restart
                            happy; also requires obd_replayable */
                         lustre_msg_add_op_flags(req->rq_repmsg,
@@ -533,9 +546,11 @@ int mgs_handle(struct ptlrpc_request *req)
         }
 
         LASSERT(current->journal_info == NULL);
-
-        CDEBUG_EX(D_CONFIG | (rc?D_ERROR:0), "MGS handle cmd=%d rc=%d\n",
-               req->rq_reqmsg->opc, rc);
+       
+        if (rc) 
+                CDEBUG(D_CONFIG | D_ERROR, "MGS handle cmd=%d rc=%d\n", opc, rc);
+        else
+                CDEBUG(D_CONFIG, "MGS handle cmd=%d rc=%d\n", opc, rc);
 
  out:
         target_send_reply(req, rc, fail);
@@ -569,11 +584,9 @@ int mgs_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
                 struct lustre_handle lockh;
                 struct lustre_cfg *lcfg;
                 struct llog_rec_hdr rec;
-                char fsname[32], *devname;
+                char fsname[MTI_NAME_MAXLEN];
                 int lockrc;
 
-                CERROR("MGS param\n");
-
                 rec.lrh_len = llog_data_len(data->ioc_plen1);
 
                 if (data->ioc_type == LUSTRE_CFG_TYPE) {
@@ -593,24 +606,7 @@ int mgs_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
                 if (lcfg->lcfg_bufcount < 1)
                         GOTO(out_free, rc = -EINVAL);
 
-                /* Extract fsname */
-                memset(fsname, 0, sizeof(fsname));
-                devname = lustre_cfg_string(lcfg, 0);
-                if (devname) {
-                        char *ptr = strchr(devname, '-');
-                        if (!ptr) {
-                                /* assume devname is the fsname */
-                                strncpy(fsname, devname, sizeof(fsname));
-                        } else {
-                                strncpy(fsname, devname, ptr - devname);
-                        }
-                        CDEBUG(D_MGS, "set param on fs %s device %s\n",
-                               fsname, devname);
-                } else {
-                        CDEBUG(D_MGS, "set global param\n");
-                }
-
-                rc = mgs_setparam(obd, fsname, lcfg);
+                rc = mgs_setparam(obd, lcfg, fsname);
                 if (rc) {
                         CERROR("setparam err %d\n", rc);
                         GOTO(out_free, rc);
@@ -620,7 +616,7 @@ int mgs_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
                    someone was already reading while we were updating the logs,
                    so we don't really need to hold the lock while we're
                    writing (above). */
-                if (fsname) {
+                if (fsname[0]) {
                         lockrc = mgs_get_cfg_lock(obd, fsname, &lockh);
                         if (lockrc != ELDLM_OK)
                                 CERROR("lock error %d for fs %s\n", lockrc,
@@ -628,6 +624,7 @@ int mgs_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
                         else
                                 mgs_put_cfg_lock(&lockh);
                 }
+
 out_free:
                 OBD_FREE(lcfg, data->ioc_plen1);
                 RETURN(rc);
index 688055c..e0f271b 100644 (file)
 #define MGS_SERVICE_WATCHDOG_TIMEOUT (obd_timeout * 10)
 
 /* mgs_llog.c */
-#define FSDB_EMPTY 0x0001
+#define FSDB_EMPTY      0x0001
+#define FSDB_OLDLOG14   0x0002  /* log starts in old (1.4) style */
+
 
 struct fs_db {
         char              fsdb_name[8];
-        struct list_head  fsdb_list;
+        struct list_head  fsdb_list;           /* list of databases */
         struct semaphore  fsdb_sem;
-        void*             fsdb_ost_index_map;
-        void*             fsdb_mdt_index_map;
+        void             *fsdb_ost_index_map;  /* bitmap of used indicies */
+        void             *fsdb_mdt_index_map;  /* bitmap of used indicies */
+        /* COMPAT_146 these items must be recorded out of the old client log */
+        char             *fsdb_clilov;         /* COMPAT_146 client lov name */
+        char             *fsdb_clilmv;
+        char             *fsdb_mdtlov;         /* COMPAT_146 mds lov name */
+        char             *fsdb_mdtlmv;
+        char             *fsdb_mdc;            /* COMPAT_146 mdc name */
+        /* end COMPAT_146 */
         __u32             fsdb_flags;
         __u32             fsdb_gen;
 };
@@ -38,12 +47,14 @@ int mgs_check_index(struct obd_device *obd, struct mgs_target_info *mti);
 int mgs_check_failnid(struct obd_device *obd, struct mgs_target_info *mti);
 int mgs_write_log_target(struct obd_device *obd, struct mgs_target_info *mti);
 int mgs_upgrade_sv_14(struct obd_device *obd, struct mgs_target_info *mti);
+int mgs_erase_log(struct obd_device *obd, char *name);
 int mgs_erase_logs(struct obd_device *obd, char *fsname);
-int mgs_setparam(struct obd_device *obd, char *fsname, struct lustre_cfg *lcfg);
+int mgs_setparam(struct obd_device *obd, struct lustre_cfg *lcfg, char *fsname);
 
 /* mgs_fs.c */
 int mgs_fs_setup(struct obd_device *obd, struct vfsmount *mnt);
 int mgs_fs_cleanup(struct obd_device *obddev);
 
+#define strsuf(buf, suffix) (strcmp((buf)+strlen(buf)-strlen(suffix), (suffix)))
 
 #endif
index bf04996..6fbe5fb 100644 (file)
@@ -27,7 +27,7 @@
 #define EXPORT_SYMTAB
 #endif
 #define DEBUG_SUBSYSTEM S_MGS
-#define D_MGS D_CONFIG/*|D_WARNING*/
+#define D_MGS D_CONFIG /*|D_WARNING*/
 
 #ifdef __KERNEL__
 #include <linux/module.h>
@@ -44,6 +44,7 @@
 #include <lustre_fsfilt.h>
 #include <lustre_disk.h>
 #include <lustre_param.h>
+#include <lustre_ver.h>
 #include "mgs_internal.h"
 
 /********************** Class fns ********************/
@@ -86,13 +87,32 @@ out_pop:
 
 /******************** DB functions *********************/
 
+static inline int name_create(char **newname, char *prefix, char *suffix)
+{
+        LASSERT(newname);
+        OBD_ALLOC(*newname, strlen(prefix) + strlen(suffix) + 1);
+        if (!*newname) 
+                return -ENOMEM;
+        sprintf(*newname, "%s%s", prefix, suffix);
+        return 0;
+}
+
+static inline void name_destroy(char *name)
+{        
+        if (name)
+                OBD_FREE(name, strlen(name) + 1);
+}
+
 /* from the (client) config log, figure out:
         1. which ost's/mdt's are configured (by index)
         2. what the last config step is
+        3. COMPAT_146 lov name
+        4. COMPAT_146 mdt lov name
+        5. COMPAT_146 mdc name 
 */
-/* FIXME is it better to have a separate db file, instead of parsing the info
-   out of the client log? */
-static int mgs_fsdb_handler(struct llog_handle *llh, struct llog_rec_hdr *rec,
+/* It might be better to have a separate db file, instead of parsing the info
+   out of the client log.  This is slow and potentially error-prone. */
+static int mgs_fsdb_handler(struct llog_handle *llh, struct llog_rec_hdr *rec, 
                             void *data)
 {
         struct fs_db *fsdb = (struct fs_db *)data;
@@ -147,6 +167,44 @@ static int mgs_fsdb_handler(struct llog_handle *llh, struct llog_rec_hdr *rec,
                 set_bit(index, fsdb->fsdb_mdt_index_map);
         }
 
+        /* COMPAT_146 */
+        /* figure out the old LOV name. fsdb_gen = 0 means old log */
+        if ((fsdb->fsdb_gen == 0) && (lcfg->lcfg_command == LCFG_ATTACH) &&
+            (strcmp(lustre_cfg_string(lcfg, 1), LUSTRE_LOV_NAME) == 0)) {
+                fsdb->fsdb_flags |= FSDB_OLDLOG14;
+                name_destroy(fsdb->fsdb_clilov);
+                rc = name_create(&fsdb->fsdb_clilov, 
+                                 lustre_cfg_string(lcfg, 0), "");
+                if (rc) 
+                        RETURN(rc);
+                CDEBUG(D_MGS, "client lov name is %s\n", fsdb->fsdb_clilov);
+        }
+
+        /* figure out the old MDT lov name from the MDT uuid */
+        if ((fsdb->fsdb_gen == 0) && (lcfg->lcfg_command == LCFG_SETUP) &&
+            (strncmp(lustre_cfg_string(lcfg, 0), "MDC_", 4) == 0)) {
+                char *ptr;
+                fsdb->fsdb_flags |= FSDB_OLDLOG14;
+                ptr = strstr(lustre_cfg_string(lcfg, 1), "_UUID");
+                if (!ptr) {
+                        CERROR("Can't parse MDT uuid %s\n", 
+                               lustre_cfg_string(lcfg, 1));
+                        RETURN(-EINVAL);
+                }
+                *ptr = '\0';
+                name_destroy(fsdb->fsdb_mdtlov);
+                rc = name_create(&fsdb->fsdb_mdtlov, 
+                                 "lov_", lustre_cfg_string(lcfg, 1));
+                if (rc) 
+                        RETURN(rc);
+                rc = name_create(&fsdb->fsdb_mdc, 
+                                 lustre_cfg_string(lcfg, 0), "");
+                if (rc) 
+                        RETURN(rc);
+                CDEBUG(D_MGS, "MDT lov name is %s\n", fsdb->fsdb_mdtlov);
+        }
+        /* end COMPAT_146 */
+
         /* Keep track of the latest marker step */
         if (lcfg->lcfg_command == LCFG_MARKER) {
                 struct cfg_marker *marker;
@@ -181,7 +239,7 @@ static int mgs_get_fsdb_from_llog(struct obd_device *obd, char *logname,
                 fsdb->fsdb_flags |= FSDB_EMPTY;
 
         rc = llog_process(loghandle, mgs_fsdb_handler, (void *)fsdb, NULL);
-        CDEBUG(D_MGS, "get_db = %d\n", rc);
+        CDEBUG(D_INFO, "get_db = %d\n", rc);
 out_close:
         rc2 = llog_close(loghandle);
         if (!rc)
@@ -238,6 +296,7 @@ static struct fs_db *mgs_new_fsdb(struct obd_device *obd, char *fsname)
 {
         struct mgs_obd *mgs = &obd->u.mgs;
         struct fs_db *fsdb;
+        int rc;
         ENTRY;
 
         OBD_ALLOC_PTR(fsdb);
@@ -252,6 +311,20 @@ static struct fs_db *mgs_new_fsdb(struct obd_device *obd, char *fsname)
         }
 
         strncpy(fsdb->fsdb_name, fsname, sizeof(fsdb->fsdb_name));
+        rc = name_create(&fsdb->fsdb_mdtlov, fsname, "-mdtlov");
+        if (rc) 
+                GOTO(err, rc);
+        rc = name_create(&fsdb->fsdb_mdtlmv, fsname, "-mdtlmv");
+        if (rc) 
+                GOTO(err, rc);
+        rc = name_create(&fsdb->fsdb_clilov, fsname, "-clilov");
+        if (rc) 
+                GOTO(err, rc);
+
+        rc = name_create(&fsdb->fsdb_clilmv, fsname, "-clilmv");
+        if (rc) 
+                GOTO(err, rc);
+
         sema_init(&fsdb->fsdb_sem, 1);
         list_add(&fsdb->fsdb_list, &mgs->mgs_fs_db_list);
 
@@ -261,6 +334,10 @@ err:
                 OBD_FREE(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
         if (fsdb->fsdb_mdt_index_map)
                 OBD_FREE(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
+        name_destroy(fsdb->fsdb_clilov);
+        name_destroy(fsdb->fsdb_clilmv);
+        name_destroy(fsdb->fsdb_mdtlov); 
+        name_destroy(fsdb->fsdb_mdtlmv); 
         OBD_FREE_PTR(fsdb);
         RETURN(NULL);
 }
@@ -272,6 +349,11 @@ static void mgs_free_fsdb(struct fs_db *fsdb)
         list_del(&fsdb->fsdb_list);
         OBD_FREE(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
         OBD_FREE(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
+        name_destroy(fsdb->fsdb_clilov); 
+        name_destroy(fsdb->fsdb_clilmv); 
+        name_destroy(fsdb->fsdb_mdtlov); 
+        name_destroy(fsdb->fsdb_mdtlmv); 
+        name_destroy(fsdb->fsdb_mdc); 
         OBD_FREE_PTR(fsdb);
 }
 
@@ -296,24 +378,7 @@ int mgs_cleanup_fsdb_list(struct obd_device *obd)
         return 0;
 }
 
-static inline int name_create(char *prefix, char *suffix, char **newname)
-{
-        LASSERT(newname);
-        OBD_ALLOC(*newname, strlen(prefix) + strlen(suffix) + 1);
-        if (!*newname)
-                return -ENOMEM;
-        sprintf(*newname, "%s%s", prefix, suffix);
-        return 0;
-}
-
-static inline void name_destroy(char *name)
-{
-        if (name)
-                OBD_FREE(name, strlen(name) + 1);
-}
-
-
-static int mgs_find_or_make_fsdb(struct obd_device *obd, char *name,
+static int mgs_find_or_make_fsdb(struct obd_device *obd, char *name, 
                                struct fs_db **dbh)
 {
         struct mgs_obd *mgs = &obd->u.mgs;
@@ -336,8 +401,7 @@ static int mgs_find_or_make_fsdb(struct obd_device *obd, char *name,
                 return -ENOMEM;
 
         /* populate the db from the client llog */
-        name_create(name, "-client", &cliname);
-        down(&fsdb->fsdb_sem);
+        name_create(&cliname, name, "-client");
         rc = mgs_get_fsdb_from_llog(obd, cliname, fsdb);
         up(&fsdb->fsdb_sem);
         name_destroy(cliname);
@@ -385,7 +449,10 @@ int mgs_check_index(struct obd_device *obd, struct mgs_target_info *mti)
         RETURN(0);
 }
 
-
+/* Return codes:
+        0  newly marked as in use
+        <0 err
+        +EALREADY for update of an old index */
 int mgs_set_index(struct obd_device *obd, struct mgs_target_info *mti)
 {
         struct fs_db *fsdb;
@@ -438,7 +505,7 @@ int mgs_set_index(struct obd_device *obd, struct mgs_target_info *mti)
                                        mti->mti_svname, mti->mti_stripe_index);
                         RETURN(-EADDRINUSE);
                 } else {
-                        CERROR("Server %s updating index %d\n",
+                        CDEBUG(D_MGS, "Server %s updating index %d\n",
                                mti->mti_svname, mti->mti_stripe_index);
                         RETURN(EALREADY);
                 }
@@ -464,8 +531,10 @@ static int record_lcfg(struct obd_device *obd, struct llog_handle *llh,
         struct llog_rec_hdr    rec;
         int buflen, rc;
 
-        LASSERT(llh);
-        LASSERT(llh->lgh_ctxt);
+        if (!lcfg || !llh) 
+                return -ENOMEM;
+
+        LASSERT(llh->lgh_ctxt);        
 
         buflen = lustre_cfg_len(lcfg->lcfg_bufcount,
                                 lcfg->lcfg_buflens);
@@ -476,10 +545,8 @@ static int record_lcfg(struct obd_device *obd, struct llog_handle *llh,
         /* idx = -1 means append */
         rc = llog_write_rec(llh, &rec, NULL, 0, (void *)lcfg, -1);
         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
-        if (rc) {
+        if (rc) 
                 CERROR("failed %d\n", rc);
-        }
-        LASSERT(!rc);
         return rc;
 }
 
@@ -505,6 +572,8 @@ static int record_base(struct obd_device *obd, struct llog_handle *llh,
                 lustre_cfg_bufs_set_string(&bufs, 4, s4);
 
         lcfg = lustre_cfg_new(cmd, &bufs);
+        if (!lcfg) 
+                return -ENOMEM;
         lcfg->lcfg_nid = nid;
 
         rc = record_lcfg(obd, llh, lcfg);
@@ -558,7 +627,8 @@ static int record_lov_setup(struct obd_device *obd, struct llog_handle *llh,
         lustre_cfg_bufs_reset(&bufs, devname);
         lustre_cfg_bufs_set(&bufs, 1, desc, sizeof(*desc));
         lcfg = lustre_cfg_new(LCFG_SETUP, &bufs);
-
+        if (!lcfg) 
+                return -ENOMEM;
         rc = record_lcfg(obd, llh, lcfg);
 
         lustre_cfg_free(lcfg);
@@ -623,15 +693,17 @@ static int record_marker(struct obd_device *obd, struct llog_handle *llh,
                 fsdb->fsdb_gen++;
         marker.cm_step = fsdb->fsdb_gen;
         marker.cm_flags = flags;
-        strncpy(marker.cm_svname, svname, sizeof(marker.cm_svname));
-        strncpy(marker.cm_comment, comment, sizeof(marker.cm_comment));
+        marker.cm_vers = LUSTRE_VERSION_CODE;
+        strncpy(marker.cm_svname, svname, sizeof(marker.cm_svname)); 
+        strncpy(marker.cm_comment, comment, sizeof(marker.cm_comment)); 
         do_gettimeofday(&tv);
         marker.cm_createtime = tv.tv_sec;
         marker.cm_canceltime = 0;
         lustre_cfg_bufs_reset(&bufs, NULL);
         lustre_cfg_bufs_set(&bufs, 1, &marker, sizeof(marker));
         lcfg = lustre_cfg_new(LCFG_MARKER, &bufs);
-
+        if (!lcfg) 
+                return -ENOMEM;
         rc = record_lcfg(obd, llh, lcfg);
 
         lustre_cfg_free(lcfg);
@@ -687,8 +759,6 @@ static int mgs_log_is_empty(struct obd_device *obd, char *name)
         struct llog_handle *llh;
         int rc = 0;
 
-        /* FIXME cache the empty state in the db */
-
         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
         rc = llog_create(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT),
                          &llh, NULL, name);
@@ -713,9 +783,16 @@ static int mgs_write_log_direct(struct obd_device *obd, struct fs_db *fsdb,
         int rc;
         ENTRY;
 
+        if (!lcfg) 
+                RETURN(-ENOMEM);
+
         rc = record_start_log(obd, &llh, logname);
-        rc = record_marker(obd, llh, fsdb, CM_START, obdname, "param");
+        if (rc) 
+                RETURN(rc);
 
+        /* FIXME These should be a single journal transaction */
+        rc = record_marker(obd, llh, fsdb, CM_START, obdname, "param"); 
+        
         rc = record_lcfg(obd, llh, lcfg);
 
         rc = record_marker(obd, llh, fsdb, CM_END, obdname, "param");
@@ -726,24 +803,29 @@ static int mgs_write_log_direct(struct obd_device *obd, struct fs_db *fsdb,
 
 /* write the lcfg in all logs for the given fs */
 int mgs_write_log_direct_all(struct obd_device *obd, struct fs_db *fsdb,
-                          char *fsname, struct lustre_cfg *lcfg)
+                           struct mgs_target_info *mti, struct lustre_cfg *lcfg)
 {
         struct mgs_obd *mgs = &obd->u.mgs;
         struct list_head dentry_list;
         struct l_linux_dirent *dirent, *n;
+        char *fsname = mti->mti_fsname;
         char *logname;
-        int rc, len = strlen(fsname);
+        int rc = 0, len = strlen(fsname);
         ENTRY;
-
-        /* We need to set params for any future logs
-           as well. FIXME Append this file to every new log. */
-        name_create(fsname, "-params", &logname);
+        
+        /* We need to set params for any future logs 
+           as well. FIXME Append this file to every new log. 
+           Actually, we should store as params (text), not llogs.  Or
+           in a database. */
+        name_create(&logname, fsname, "-params");
         if (mgs_log_is_empty(obd, logname)) {
                 struct llog_handle *llh = NULL;
                 rc = record_start_log(obd, &llh, logname);
-                rc = record_end_log(obd, &llh);
+                record_end_log(obd, &llh);
         }
         name_destroy(logname);
+        if (rc) 
+                RETURN(rc);
 
         /* Find all the logs in the CONFIGS directory */
         rc = class_dentry_readdir(obd, mgs->mgs_configs_dir,
@@ -759,7 +841,10 @@ int mgs_write_log_direct_all(struct obd_device *obd, struct fs_db *fsdb,
                 if (strncmp(fsname, dirent->lld_name, len) == 0) {
                         CDEBUG(D_MGS, "Changing log %s\n", dirent->lld_name);
                         rc = mgs_write_log_direct(obd, fsdb, dirent->lld_name,
-                                                  dirent->lld_name, lcfg);
+                                                  mti->mti_svname, lcfg);
+                        if (rc)
+                                CERROR("err %d writing log %s\n", rc, 
+                                       dirent->lld_name);
                 }
                 OBD_FREE(dirent, sizeof(*dirent));
         }
@@ -774,7 +859,7 @@ struct temp_comp
         struct obd_device *comp_obd;
 };
 
-static int mgs_write_log_mdc_to_mds(struct obd_device *, struct fs_db *,
+static int mgs_write_log_mdc_to_mdt(struct obd_device *, struct fs_db *,
                                     struct mgs_target_info *, char *);
 
 static int mgs_steal_llog_handler(struct llog_handle *llh,
@@ -861,50 +946,6 @@ static int mgs_steal_llog_handler(struct llog_handle *llh,
         if (got_an_osc_or_mdc == 0 || last_step < 0)
                 RETURN(rc);
         
-#if 0
-
-        if (lcfg->lcfg_command == LCFG_ATTACH) {
-                char *name;
-                char *type;
-                char *uuid;
-                char *dash;
-                name = lustre_cfg_string(lcfg, 0);
-                type = lustre_cfg_string(lcfg, 1);
-                name_create(lustre_cfg_string(lcfg, 2),"",&uuid);
-                dash =  strchr(uuid, '-');
-                *(++dash)='m';
-                *(++dash)='d';
-                *(++dash)='t';
-                rc = record_start_log(obd, &mdt_llh, mti->mti_svname);
-                rc = record_attach(obd, mdt_llh, name, type, uuid);
-                rc = record_end_log(obd, &mdt_llh);
-                name_destroy(uuid);
-                RETURN(rc);
-        }
-
-        if (lcfg->lcfg_command == LCFG_LOV_ADD_OBD) {
-                char *name;
-                char *uuid;
-                char *index;
-                char *gen;
-                char *dash;
-
-                LASSERT(got_an_osc_or_mdc == 1);
-                name_create(lustre_cfg_string(lcfg, 0),"",&name);
-                uuid = lustre_cfg_string(lcfg, 1);
-                index = lustre_cfg_string(lcfg, 2);
-                gen = lustre_cfg_string(lcfg, 3);
-                dash =  strchr(name, '-');
-                *(++dash)='m';
-                *(++dash)='d';
-                *(++dash)='t';
-
-                rc = record_start_log(obd, &mdt_llh, mti->mti_svname);
-                rc = record_lov_add(obd,mdt_llh,name,uuid,index,gen);
-                rc = record_end_log(obd, &mdt_llh);
-                RETURN(rc);
-        }
-#endif
         if (lcfg->lcfg_command == LCFG_ADD_UUID) {
                 uint64_t nodenid;
                 nodenid = lcfg->lcfg_nid;
@@ -934,7 +975,7 @@ static int mgs_steal_llog_handler(struct llog_handle *llh,
                        strlen(mti->mti_fsname));
                 tmti->mti_stripe_index = index;
                 
-                mgs_write_log_mdc_to_mds(obd, fsdb, tmti, mti->mti_svname);
+                mgs_write_log_mdc_to_mdt(obd, fsdb, tmti, mti->mti_svname);
                 memset(tmti, 0, sizeof(*tmti));
                 RETURN(rc);
         }
@@ -1054,12 +1095,15 @@ static int mgs_write_log_lov(struct obd_device *obd, struct fs_db *fsdb,
         /* This should always be the first entry in a log.
         rc = mgs_clear_log(obd, logname); */
         rc = record_start_log(obd, &llh, logname);
-        rc = record_marker(obd, llh, fsdb, CM_START, lovname, "lov setup");
+        if (rc) 
+                GOTO(out, rc);
+        /* FIXME these should be a single journal transaction */
+        rc = record_marker(obd, llh, fsdb, CM_START, lovname, "lov setup"); 
         rc = record_attach(obd, llh, lovname, "lov", uuid);
         rc = record_lov_setup(obd, llh, lovname, lovdesc);
         rc = record_marker(obd, llh, fsdb, CM_END, lovname, "lov setup");
         rc = record_end_log(obd, &llh);
-
+out:        
         OBD_FREE(lovdesc, sizeof(*lovdesc));
         RETURN(rc);
 }
@@ -1090,9 +1134,9 @@ static int mgs_write_log_failnids(struct obd_device *obd,
                         if (failnodeuuid == NULL) {
                                 /* We don't know the failover node name,
                                    so just use the first nid as the uuid */
-                                rc = name_create(libcfs_nid2str(nid), "",
-                                                 &failnodeuuid);
-                                if (rc)
+                                rc = name_create(&failnodeuuid,
+                                                 libcfs_nid2str(nid), "");
+                                if (rc) 
                                         return rc;
                         }
                         CDEBUG(D_MGS, "add nid %s for failover uuid %s, "
@@ -1113,35 +1157,39 @@ static int mgs_write_log_failnids(struct obd_device *obd,
 
 /***************************************BEGIN PROTO****************************/
 static int mgs_write_log_mdc_to_lmv(struct obd_device *obd, struct fs_db *fsdb,
-                             struct mgs_target_info *mti,
-                             char *logname, char *lmvname)
+                                    struct mgs_target_info *mti,
+                                    char *logname, char *lmvname)
 {
         struct llog_handle *llh = NULL;
-        char *nodeuuid, *mdcname, *mdcuuid, *lmvuuid;
+        char *mdcname, *nodeuuid, *mdcuuid, *lmvuuid;
         char index[5];
         int i, rc;
-
         ENTRY;
+        
         if (mgs_log_is_empty(obd, logname)) {
-                //This should not happen!
-                RETURN (-EINVAL);
+                CERROR("log is empty! Logical error\n");
+                RETURN(-EINVAL);
         }
 
         CDEBUG(D_MGS, "adding mdc for %s to log %s:lmv(%s)\n",
                mti->mti_svname, logname, lmvname);
 
-        name_create(libcfs_nid2str(mti->mti_nids[0]), "", &nodeuuid);
-        name_create(mti->mti_svname, "-mdc", &mdcname);
-        name_create(mdcname, "_UUID", &mdcuuid);
-        name_create(lmvname, "_UUID", &lmvuuid);
+        name_create(&nodeuuid, libcfs_nid2str(mti->mti_nids[0]), "");
+        name_create(&mdcname, mti->mti_svname, "-mdc");
+        name_create(&mdcuuid, mdcname, "_UUID");
+        name_create(&lmvuuid, lmvname, "_UUID");
 
         rc = record_start_log(obd, &llh, logname);
         rc = record_marker(obd, llh, fsdb, CM_START, mti->mti_svname,
                            "add mdc");
+
         for (i = 0; i < mti->mti_nid_count; i++) {
-                CDEBUG(D_MGS, "add nid %s for mdt\n", libcfs_nid2str(mti->mti_nids[i]));
+                CDEBUG(D_MGS, "add nid %s for mdt\n", 
+                       libcfs_nid2str(mti->mti_nids[i]));
+                       
                 rc = record_add_uuid(obd, llh, mti->mti_nids[i], nodeuuid);
         }
+
         rc = record_attach(obd, llh, mdcname, LUSTRE_MDC_NAME, lmvuuid);
         rc = record_setup(obd, llh, mdcname, mti->mti_uuid, nodeuuid, 0, 0);
         rc = mgs_write_log_failnids(obd, mti, llh, mdcname);
@@ -1159,7 +1207,7 @@ static int mgs_write_log_mdc_to_lmv(struct obd_device *obd, struct fs_db *fsdb,
 }
 
 /* add new mdc to already existent MDS */
-static int mgs_write_log_mdc_to_mds(struct obd_device *obd, struct fs_db *fsdb,
+static int mgs_write_log_mdc_to_mdt(struct obd_device *obd, struct fs_db *fsdb,
                                     struct mgs_target_info *mti, char *logname)
 {
         struct llog_handle *llh = NULL;
@@ -1170,17 +1218,17 @@ static int mgs_write_log_mdc_to_mds(struct obd_device *obd, struct fs_db *fsdb,
 
         ENTRY;
         if (mgs_log_is_empty(obd, mti->mti_svname)) {
-                //This should not happen!
+                CERROR("log is empty! Logical error\n");
                 RETURN (-EINVAL);
         }
 
         CDEBUG(D_MGS, "adding mdc index %d to %s\n", idx, logname);
 
-        name_create(libcfs_nid2str(mti->mti_nids[0]), "", &nodeuuid);
+        name_create(&nodeuuid, libcfs_nid2str(mti->mti_nids[0]), "");
         snprintf(index, sizeof(index), "-mdc%04x", idx);
-        name_create(logname, index, &mdcname);
-        name_create(mdcname, "_UUID", &mdcuuid);
-        name_create(logname, "_UUID", &mdtuuid);
+        name_create(&mdcname, logname, index);
+        name_create(&mdcuuid, mdcname, "_UUID");
+        name_create(&mdtuuid, logname, "_UUID");
 
         rc = record_start_log(obd, &llh, logname);
         rc = record_marker(obd, llh, fsdb, CM_START, mti->mti_svname, "add mdc");
@@ -1210,98 +1258,165 @@ static int mgs_write_log_mdt0(struct obd_device *obd, struct fs_db *fsdb,
 {
         char *log = mti->mti_svname;
         struct llog_handle *llh = NULL;
-        char *uuid, *lovname, *lmvname;
+        char *uuid;
         char mdt_index[5];
         int rc = 0;
         ENTRY;
 
-        CDEBUG(D_MGS, "writing new mdt %s\n", log);
-
         OBD_ALLOC(uuid, sizeof(struct obd_uuid));
         if (uuid == NULL)
                 RETURN(-ENOMEM);
 
-        name_create(log, "-mdtlov", &lovname);
-        name_create(log, "-mdtlmv", &lmvname);
         if (mgs_log_is_empty(obd, log)) {
-                rc = mgs_write_log_lov(obd, fsdb, mti, log, lovname);
+                rc = mgs_write_log_lov(obd, fsdb, mti, mti->mti_svname,
+                                       fsdb->fsdb_mdtlov);
         } 
 
         sprintf(uuid, "%s_UUID", log);
         sprintf(mdt_index,"%d",mti->mti_stripe_index);
+        
         /* add MDT itself */
         rc = record_start_log(obd, &llh, log);
+        if (rc) 
+                RETURN(rc);
+        
+        /* FIXME this whole fn should be a single journal transaction */
         rc = record_marker(obd, llh, fsdb, CM_START, log, "add mdt");
         rc = record_attach(obd, llh, log, LUSTRE_MDT0_NAME, uuid);
-        /*FIXME: lmvname maybe not right now*/
-        rc = record_mount_opt(obd, llh, log, lovname, lmvname);
-        rc = record_setup(obd, llh, log, uuid, mdt_index, lovname, 0);
+        
+        rc = record_mount_opt(obd, llh, log, fsdb->fsdb_mdtlov, 
+                              fsdb->fsdb_mdtlmv);
+        
+        rc = record_setup(obd, llh, mti->mti_svname, uuid, mdt_index, 
+                          fsdb->fsdb_mdtlov, 0);
+        
         rc = record_marker(obd, llh, fsdb, CM_END, log, "add mdt");
         rc = record_end_log(obd, &llh);
         
-        name_destroy(lovname);
-
         OBD_FREE(uuid, sizeof(*uuid));
         RETURN(rc);
 }
 
 /* envelope method for all layers log */
-static int mgs_write_log_mds(struct obd_device *obd, struct fs_db *fsdb,
+static int mgs_write_log_mdt(struct obd_device *obd, struct fs_db *fsdb,
                               struct mgs_target_info *mti)
 {
+        char *cliname, *mdcname, *mdcuuid, *nodeuuid;
         struct llog_handle *llh = NULL;
-        char *cliname, *lovname, *lmvname;
-        int rc, i = 0;
+        struct temp_comp comp = { 0 };
         char mdt_index[9];
-        struct temp_comp comp;
+        int rc, i = 0;
         ENTRY;
 
-        CDEBUG(D_MGS, "writing new mds %s\n", mti->mti_svname);
-
-        /* Make up our own uuid */
-        snprintf(mti->mti_uuid, sizeof(mti->mti_uuid), "%s_UUID", mti->mti_svname);        
+        CDEBUG(D_MGS, "writing new mdt %s\n", mti->mti_svname);
+
+        /* COMPAT_146 */
+        if (mti->mti_flags & LDD_F_UPGRADE14) {
+                /* We're starting with an old uuid.  Assume old name for lov
+                   as well since the lov entry already exists in the log. */
+                CDEBUG(D_MGS, "old mds uuid %s\n", mti->mti_uuid);
+                if (strncmp(mti->mti_uuid, fsdb->fsdb_mdtlov + 4, 
+                            strlen(fsdb->fsdb_mdtlov) - 4) != 0) {
+                        CERROR("old mds uuid %s doesn't match log %s (%s)\n",
+                               mti->mti_uuid, fsdb->fsdb_mdtlov, 
+                               fsdb->fsdb_mdtlov + 4);
+                        RETURN(-EINVAL);
+                }
+        }
+        /* end COMPAT_146 */
+        
+        if (mti->mti_uuid[0] == '\0') {
+                /* Make up our own uuid */
+                snprintf(mti->mti_uuid, sizeof(mti->mti_uuid),
+                         "%s_UUID", mti->mti_svname);
+        }
 
         /* add mdt */
         rc = mgs_write_log_mdt0(obd, fsdb, mti);
         
         /* Append the mdt info to the client log */
-        name_create(mti->mti_fsname, "-client", &cliname);
-        name_create(mti->mti_fsname, "-clilov", &lovname);
-        name_create(mti->mti_fsname, "-clilmv", &lmvname);
-        if (mgs_log_is_empty(obd, cliname)) {
+        name_create(&cliname, mti->mti_fsname, "-client");
+        
+        if (mgs_log_is_empty(obd, cliname)) { 
                 /* Start client log */
-                rc = mgs_write_log_lov(obd, fsdb, mti, cliname, lovname);
-                rc = mgs_write_log_lmv(obd, fsdb, mti, cliname, lmvname);
+                rc = mgs_write_log_lov(obd, fsdb, mti, cliname, 
+                                       fsdb->fsdb_clilov);
+                rc = mgs_write_log_lmv(obd, fsdb, mti, cliname, 
+                                       fsdb->fsdb_clilmv);
         }
 
-        /* copy client info about lov/lmv */
-        //comp.comp_obd = obd;
-        comp.comp_mti = mti;
-        comp.comp_fsdb = fsdb;
-        rc = mgs_steal_llog_for_mdt_from_client(obd, cliname, &comp);
+        /* add mountopts */
+        name_create(&nodeuuid, libcfs_nid2str(mti->mti_nids[0]),/*"_UUID"*/"");
+        name_create(&mdcname, mti->mti_svname, "-mdc");
+        name_create(&mdcuuid, mdcname, "_UUID");
+        
+        /* 
+        #09 L add_uuid nid=uml1@tcp(0x20000c0a80201) 0:  1:uml1_UUID
+        #10 L attach   0:MDC_uml1_mdsA_MNT_client  1:mdc  2:1d834_MNT_client_03f
+        #11 L setup    0:MDC_uml1_mdsA_MNT_client  1:mdsA_UUID  2:uml1_UUID
+        #12 L add_uuid nid=uml2@tcp(0x20000c0a80202) 0:  1:uml2_UUID
+        #13 L add_conn 0:MDC_uml1_mdsA_MNT_client  1:uml2_UUID
+        #14 L mount_option 0:  1:client  2:lov1  3:MDC_uml1_mdsA_MNT_client
+        */
+        
+        /* COMPAT_146 */
+        if (mti->mti_flags & LDD_F_UPGRADE14) { 
+                rc = record_start_log(obd, &llh, cliname);
+                if (rc) 
+                        GOTO(out, rc);
+        
+                rc = record_marker(obd, llh, fsdb, CM_START, 
+                                   mti->mti_svname,"add mdc");
+                                   
+                /* Old client log already has MDC entry, but needs mount opt 
+                   for new client name (lustre-client) */
+                /* FIXME Old MDT log already has an old mount opt 
+                   which we should remove (currently handled by
+                   class_del_profiles()) */
+                rc = record_mount_opt(obd, llh, cliname, fsdb->fsdb_clilov,
+                                      fsdb->fsdb_mdc);
+                /* end COMPAT_146 */
+                
+                rc = record_marker(obd, llh, fsdb, CM_END, 
+                                   mti->mti_svname, "add mdc");
+        } else {
+                /* copy client info about lov/lmv */
+                comp.comp_mti = mti;
+                comp.comp_fsdb = fsdb;
+                
+                rc = mgs_steal_llog_for_mdt_from_client(obd, cliname, 
+                                                        &comp);
 
-        rc = mgs_write_log_mdc_to_lmv(obd, fsdb, mti, cliname, lmvname);
+                rc = mgs_write_log_mdc_to_lmv(obd, fsdb, mti, cliname, 
+                                              fsdb->fsdb_clilmv);
 
-        /* add mountopts */
-        rc = record_start_log(obd, &llh, cliname);
-        rc = record_marker(obd, llh, fsdb, CM_START, cliname,"mount opts");
-        rc = record_mount_opt(obd, llh, cliname, lovname, lmvname);
-        rc = record_marker(obd, llh, fsdb, CM_END, cliname, "mount opts"); 
+                rc = record_start_log(obd, &llh, cliname);
+                if (rc) 
+                        GOTO(out, rc);
+        
+                rc = record_marker(obd, llh, fsdb, CM_START, cliname, 
+                                   "mount opts");
+                rc = record_mount_opt(obd, llh, cliname, fsdb->fsdb_clilov,
+                                      fsdb->fsdb_clilmv);
+                rc = record_marker(obd, llh, fsdb, CM_END, cliname, 
+                                   "mount opts"); 
+        }
+                           
         rc = record_end_log(obd, &llh);
-
-        name_destroy(lmvname);        
-        name_destroy(lovname);
+out:
+        name_destroy(mdcuuid);
+        name_destroy(mdcname);
+        name_destroy(nodeuuid);
         name_destroy(cliname);
         
-        //for_all_existing_mdt except current one
+        // for_all_existing_mdt except current one
         for (i = 0; i < INDEX_MAP_SIZE * 8; i++){
                 char *mdtname;
-                if (/*i != mti->mti_stripe_index &&*/  
-                    test_bit(i,  fsdb->fsdb_mdt_index_map)) {
+                if (test_bit(i,  fsdb->fsdb_mdt_index_map)) {
                         sprintf(mdt_index,"-MDT%04x",i);
                         
-                        name_create(mti->mti_fsname, mdt_index, &mdtname);
-                        rc = mgs_write_log_mdc_to_mds(obd, fsdb, mti, mdtname);
+                        name_create(&mdtname, mti->mti_fsname, mdt_index);
+                        rc = mgs_write_log_mdc_to_mdt(obd, fsdb, mti, mdtname);
                         name_destroy(mdtname);
                 }
         }
@@ -1330,10 +1445,10 @@ static int mgs_write_log_osc_to_lov(struct obd_device *obd, struct fs_db *fsdb,
         }
   
 
-        name_create(libcfs_nid2str(mti->mti_nids[0]), "", &nodeuuid);
-        name_create(mti->mti_svname, "-osc", &oscname);
-        name_create(oscname, "_UUID", &oscuuid);
-        name_create(lovname, "_UUID", &lovuuid);
+        name_create(&nodeuuid, libcfs_nid2str(mti->mti_nids[0]), "");
+        name_create(&oscname, mti->mti_svname, "-osc");
+        name_create(&oscuuid, oscname, "_UUID");
+        name_create(&lovuuid, lovname, "_UUID");
 
         /*
         #03 L add_uuid nid=uml1@tcp(0x20000c0a80201) 0:  1:uml1_UUID
@@ -1346,7 +1461,11 @@ static int mgs_write_log_osc_to_lov(struct obd_device *obd, struct fs_db *fsdb,
         #07 L add_conn 0:OSC_uml1_ost1_MNT_client  1:uml2_UUID
         #08 L lov_modify_tgts add 0:lov1  1:ost1_UUID  2(index):0  3(gen):1
         */
+        
         rc = record_start_log(obd, &llh, logname);
+        if (rc) 
+                GOTO(out, rc);
+        /* FIXME these should be a single journal transaction */
         rc = record_marker(obd, llh, fsdb, CM_START | flags, mti->mti_svname,
                            "add osc"); 
         for (i = 0; i < mti->mti_nid_count; i++) {
@@ -1361,7 +1480,7 @@ static int mgs_write_log_osc_to_lov(struct obd_device *obd, struct fs_db *fsdb,
         rc = record_marker(obd, llh, fsdb, CM_END | flags, mti->mti_svname,
                            "add osc"); 
         rc = record_end_log(obd, &llh);
-        
+out:        
         name_destroy(lovuuid);
         name_destroy(oscuuid);
         name_destroy(oscname);
@@ -1374,9 +1493,9 @@ static int mgs_write_log_ost(struct obd_device *obd, struct fs_db *fsdb,
 {
         struct llog_handle *llh = NULL;
         char *logname, *lovname;
-        int i, rc, flags = 0;
         char mdt_index[9];
-
+        char *ptr = mti->mti_params;
+        int rc, flags = 0, failout = 0, i;
         ENTRY;
         
         CDEBUG(D_MGS, "writing new ost %s\n", mti->mti_svname);
@@ -1384,34 +1503,34 @@ static int mgs_write_log_ost(struct obd_device *obd, struct fs_db *fsdb,
         /* The ost startup log */
 
         /* If the ost log already exists, that means that someone reformatted
-           the ost and it called target_add again.
-           FIXME check and warn here, maybe inc config ver #?  Or abort, 
-           and claim there's already a server with that name?  Maybe need 
-           another flag to say it's okay to rewrite. 
-           Heck, what do we do about the client and mds logs? We better
-           abort. */
+           the ost and it called target_add again. */
         if (!mgs_log_is_empty(obd, mti->mti_svname)) {
                 LCONSOLE_ERROR("The config log for %s already exists, yet the "
                                "server claims it never registered.  It may have"
                                " been reformatted, or the index changed. Use "
                                " tunefs.lustre --writeconf to regenerate "
                                " all logs.\n", mti->mti_svname);
-                return -EALREADY;
+                RETURN(-EALREADY);
         }
         /*
         attach obdfilter ost1 ost1_UUID
         setup /dev/loop2 ldiskfs f|n errors=remount-ro,user_xattr
         */
+        if (class_find_param(ptr, PARAM_FAILMODE, &ptr) == 0) 
+                failout = (strncmp(ptr, "failout", 7) == 0);
         rc = record_start_log(obd, &llh, mti->mti_svname);
+        if (rc) 
+                RETURN(rc);
+        /* FIXME these should be a single journal transaction */
         rc = record_marker(obd, llh, fsdb, CM_START, mti->mti_svname,"add ost"); 
         if (*mti->mti_uuid == '\0') 
                 snprintf(mti->mti_uuid, sizeof(mti->mti_uuid),
                          "%s_UUID", mti->mti_svname);
         rc = record_attach(obd, llh, mti->mti_svname,
                            "obdfilter"/*LUSTRE_OST_NAME*/, mti->mti_uuid);
-        rc = record_setup(obd,llh,mti->mti_svname,
-                          "dev"/*ignored*/,"type"/*ignored*/,
-                          "f", 0/*options*/);
+        rc = record_setup(obd, llh, mti->mti_svname,
+                          "dev"/*ignored*/, "type"/*ignored*/,
+                          failout ? "n" : "f", 0/*options*/);
         rc = record_marker(obd, llh, fsdb, CM_END, mti->mti_svname, "add ost"); 
         rc = record_end_log(obd, &llh);
 
@@ -1424,13 +1543,14 @@ static int mgs_write_log_ost(struct obd_device *obd, struct fs_db *fsdb,
                    entry. Let's do a fake one for fun. */
                 flags = CM_SKIP | CM_UPGRADE146;
 
-        //for_all_existing_mdt{
+        // for_all_existing_mdt
         for (i = 0; i < INDEX_MAP_SIZE * 8; i++){
                  if (test_bit(i,  fsdb->fsdb_mdt_index_map)) {
                         sprintf(mdt_index,"-MDT%04x",i);
-                        name_create(mti->mti_fsname, mdt_index, &logname);
-                        name_create(logname, "-mdtlov", &lovname);
-                        mgs_write_log_osc_to_lov(obd, fsdb, mti, logname, lovname, flags);
+                        name_create(&logname, mti->mti_fsname, mdt_index);
+                        name_create(&lovname, logname, "-mdtlov");
+                        mgs_write_log_osc_to_lov(obd, fsdb, mti, logname, 
+                                                 fsdb->fsdb_mdtlov, flags);
                         name_destroy(logname);
                         name_destroy(lovname);
                 }
@@ -1438,10 +1558,8 @@ static int mgs_write_log_ost(struct obd_device *obd, struct fs_db *fsdb,
         //END PROTO
     
         /* Append ost info to the client log */
-        name_create(mti->mti_fsname, "-client", &logname);
-        name_create(mti->mti_fsname, "-clilov", &lovname);
-        mgs_write_log_osc_to_lov(obd, fsdb, mti, logname, lovname, 0);
-        name_destroy(lovname);
+        name_create(&logname, mti->mti_fsname, "-client");
+        mgs_write_log_osc_to_lov(obd, fsdb, mti, logname, fsdb->fsdb_clilov, 0);
         name_destroy(logname);
         
         RETURN(rc);
@@ -1469,34 +1587,39 @@ static int mgs_write_log_add_failnid(struct obd_device *obd, struct fs_db *fsdb,
 
         /* Create mdc/osc client name (e.g. lustre-OST0001-osc) */
         if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
-                name_create(mti->mti_svname, "-mdc", &cliname);
+                name_create(&cliname, mti->mti_svname, "-mdc");
         } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
-                name_create(mti->mti_svname, "-osc", &cliname);
+                name_create(&cliname, mti->mti_svname, "-osc");
         } else {
                 RETURN(-EINVAL);
         }
         
         /* Add failover nids to client log */
-        name_create(mti->mti_fsname, "-client", &logname);
+        name_create(&logname, mti->mti_fsname, "-client");
         rc = record_start_log(obd, &llh, logname);
-        rc = record_marker(obd, llh, fsdb, CM_START, mti->mti_svname,
-                           "add failnid");
-        rc = mgs_write_log_failnids(obd, mti, llh, cliname);
-        rc = record_marker(obd, llh, fsdb, CM_END, mti->mti_svname,
-                           "add failnid"); 
-        rc = record_end_log(obd, &llh);
-        name_destroy(logname);
-
-        if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
-                /* Add OST failover nids to the MDT log as well */
-                name_create(mti->mti_fsname, "-MDT0000", &logname);
-                rc = record_start_log(obd, &llh, logname);
+        if (!rc) { 
+                /* FIXME this fn should be a single journal transaction */
                 rc = record_marker(obd, llh, fsdb, CM_START, mti->mti_svname,
                                    "add failnid");
                 rc = mgs_write_log_failnids(obd, mti, llh, cliname);
                 rc = record_marker(obd, llh, fsdb, CM_END, mti->mti_svname,
                                    "add failnid"); 
                 rc = record_end_log(obd, &llh);
+        }
+        name_destroy(logname);
+
+        if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
+                /* Add OST failover nids to the MDT log as well */
+                name_create(&logname, mti->mti_fsname, "-MDT0000");
+                rc = record_start_log(obd, &llh, logname);
+                if (!rc) {
+                        rc = record_marker(obd, llh, fsdb, CM_START, 
+                                           mti->mti_svname, "add failnid");
+                        rc = mgs_write_log_failnids(obd, mti, llh, cliname);
+                        rc = record_marker(obd, llh, fsdb, CM_END, 
+                                           mti->mti_svname, "add failnid"); 
+                        rc = record_end_log(obd, &llh);
+                }
                 name_destroy(logname);
         }
 
@@ -1509,64 +1632,73 @@ static int mgs_write_log_params(struct obd_device *obd, struct fs_db *fsdb,
 {
         struct lustre_cfg_bufs bufs;
         struct lustre_cfg *lcfg;
+        char *logname;
         char *ptr = mti->mti_params;
-        char *endptr;
-        char *end = mti->mti_params + sizeof(mti->mti_params);
-        int rc = 0, len;
+        char *endptr, *tmp;
+        int rc = 0;
         ENTRY;
 
         if (!mti->mti_params) 
                 RETURN(0);
 
-        while (ptr < end) {
+        /* FIXME we should cancel out old settings of the same parameters,
+           and skip settings that are the same as old values */
+
+        /* For various parameter settings, we have to figure out which logs
+           care about them (e.g. both mdt and client for lov settings) */
+        while (ptr) {
                 while (*ptr == ' ') 
                         ptr++;
-                if (*ptr == '\0' || (ptr >= end))
+                if (*ptr == '\0')
                         break;
                 endptr = strchr(ptr, ' ');
-                if (endptr)
-                        len = endptr - ptr;
-                else
-                        len = strlen(ptr);
-                CDEBUG(D_MGS, "next param '%.*s'\n", len, ptr);
+                if (endptr) 
+                        *endptr = '\0';
+                CDEBUG(D_MGS, "next param '%s'\n", ptr);
+
+                /* The params are stored in MOUNT_DATA_FILE and modified 
+                   via tunefs.lustre */
+
+                /* Processed in lustre_start_mgc */
+                if (class_match_param(ptr, PARAM_MGSNODE, NULL) == 0) 
+                        GOTO(end_while, rc);
 
-                if (class_match_param(ptr, PARAM_MGSNODE, &endptr) == 0) 
+                /* Processed in mgs_write_log_ost */
+                if (class_match_param(ptr, PARAM_FAILMODE, NULL) == 0) 
                         GOTO(end_while, rc);
 
-                if (class_match_param(ptr, PARAM_FAILNODE, &endptr) == 0) {
+                if (class_match_param(ptr, PARAM_FAILNODE, NULL) == 0) {
                         /* Add a failover nidlist */
                         rc = 0;
                         /* We already processed failovers params for new
                            targets in mgs_write_log_target */
-                        if (mti->mti_flags & MTI_F_IOCTL) {
+                        if (mti->mti_flags & LDD_F_PARAM_FNID) {
                                 CDEBUG(D_MGS, "Adding failnode\n");
                                 rc = mgs_write_log_add_failnid(obd, fsdb, mti);
                         }
                         GOTO(end_while, rc);
                 }
 
-                if (class_match_param(ptr, PARAM_OBD_TIMEOUT, &endptr) == 0) {
+                if (class_match_param(ptr, PARAM_SYS_TIMEOUT, &tmp) == 0) {
                         /* Change obd timeout */
                         int timeout;
-                        timeout = simple_strtoul(endptr, &endptr, 0);
+                        timeout = simple_strtoul(tmp, NULL, 0);
 
                         CDEBUG(D_MGS, "obd timeout %d\n", timeout);
                         lustre_cfg_bufs_reset(&bufs, NULL);
                         lcfg = lustre_cfg_new(LCFG_SET_TIMEOUT, &bufs);
                         lcfg->lcfg_num = timeout;
                         /* modify all servers and clients */
-                        rc = mgs_write_log_direct_all(obd, fsdb, mti->mti_fsname,
-                                                   lcfg); 
+                        rc = mgs_write_log_direct_all(obd, fsdb, mti, lcfg); 
                         lustre_cfg_free(lcfg);
                         GOTO(end_while, rc);
                 }
 
-                if (class_match_param(ptr, PARAM_DEFAULT_STRIPE, &endptr) == 0){
+                if (class_match_param(ptr, PARAM_LOV, NULL) == 0) {
                         /* Change lov default stripe params */
-                        char *lovname, *logname;
                         CDEBUG(D_MGS, "lov param %s\n", ptr);
                         if (!(mti->mti_flags & LDD_F_SV_TYPE_MDT)) {
-                                LCONSOLE_ERROR("Default stripe params must be "
+                                LCONSOLE_ERROR("LOV params must be "
                                                "set on the MDT, not %s. "
                                                "Ignoring.\n",
                                                mti->mti_svname);
@@ -1574,43 +1706,87 @@ static int mgs_write_log_params(struct obd_device *obd, struct fs_db *fsdb,
                         }
 
                         /* Modify mdtlov */
-                        name_create(mti->mti_fsname, "-mdtlov", &lovname);
-                        if (mgs_log_is_empty(obd, mti->mti_svname)) {
-                                name_destroy(lovname);
+                        if (mgs_log_is_empty(obd, mti->mti_svname))
                                 GOTO(end_while, rc = -ENODEV);
-                        }
-                        lustre_cfg_bufs_reset(&bufs, lovname);
-                        lustre_cfg_bufs_set(&bufs, 1, ptr, len);
+                        lustre_cfg_bufs_reset(&bufs, fsdb->fsdb_mdtlov);
+                        lustre_cfg_bufs_set_string(&bufs, 1, ptr);
                         lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
                         rc = mgs_write_log_direct(obd, fsdb, mti->mti_svname, 
-                                                  lovname, lcfg);
+                                                  fsdb->fsdb_mdtlov, lcfg);
                         lustre_cfg_free(lcfg);
-                        name_destroy(lovname);
                         if (rc) 
                                 GOTO(end_while, rc);
 
                         /* Modify clilov */
-                        name_create(mti->mti_fsname, "-client", &logname);
-                        name_create(mti->mti_fsname, "-clilov", &lovname);
-                        lustre_cfg_bufs_reset(&bufs, lovname);
-                        lustre_cfg_bufs_set(&bufs, 1, ptr, len);
+                        name_create(&logname, mti->mti_fsname, "-client");
+                        lustre_cfg_bufs_reset(&bufs, fsdb->fsdb_clilov);
+                        lustre_cfg_bufs_set_string(&bufs, 1, ptr);
                         lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
                         rc = mgs_write_log_direct(obd, fsdb, logname,
-                                                  lovname, lcfg);
+                                                  fsdb->fsdb_clilov, lcfg);
                         lustre_cfg_free(lcfg);
-                        name_destroy(lovname);
                         name_destroy(logname);
                         GOTO(end_while, rc);
                 }
 
-                LCONSOLE_WARN("Ignoring unrecognized param '%.*s'\n", len, ptr);
+                /* All osc., mdc. params in proc */
+                if ((class_match_param(ptr, PARAM_OSC, NULL) == 0) || 
+                    (class_match_param(ptr, PARAM_MDC, NULL) == 0) ||
+                    (class_match_param(ptr, PARAM_LLITE, NULL) == 0)) {
+                        char ctype[8];
+                        char *cname;
+                        if (memcmp(ptr, PARAM_LLITE, strlen(PARAM_LLITE)) == 0)
+                                sprintf(ctype, "-client");
+                        else
+                                sprintf(ctype, "-%.3s", ptr);
+                        CDEBUG(D_MGS, "%s param %s\n", ctype + 1, ptr);
+                        /* Generate osc/mdc name */
+                        if (strsuf(mti->mti_svname, ctype) == 0) 
+                                name_create(&cname, mti->mti_svname, "");
+                        else
+                                name_create(&cname, mti->mti_svname, ctype);
+                        /* Modify client */
+                        name_create(&logname, mti->mti_fsname, "-client");
+                        lustre_cfg_bufs_reset(&bufs, cname);
+                        lustre_cfg_bufs_set_string(&bufs, 1, ptr);
+                        lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
+                        rc = mgs_write_log_direct(obd, fsdb, logname,
+                                                  cname, lcfg);
+                        lustre_cfg_free(lcfg);
+                        name_destroy(logname);
+                        name_destroy(cname);
+                        GOTO(end_while, rc);
+                }
+
+                /* All mdt., ost. params in proc */
+                if ((class_match_param(ptr, PARAM_MDT, NULL) == 0) || 
+                    (class_match_param(ptr, PARAM_OST, NULL) == 0)) {
+                        CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
+                        if (mgs_log_is_empty(obd, mti->mti_svname))
+                                GOTO(end_while, rc = -ENODEV);
+                        lustre_cfg_bufs_reset(&bufs, mti->mti_svname);
+                        lustre_cfg_bufs_set_string(&bufs, 1, ptr);
+                        lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
+                        rc = mgs_write_log_direct(obd, fsdb, mti->mti_svname,
+                                                  mti->mti_svname, lcfg);
+                        lustre_cfg_free(lcfg);
+                        GOTO(end_while, rc);
+                }
+
+                LCONSOLE_WARN("Ignoring unrecognized param '%s'\n", ptr);
 
 end_while:
                 if (rc) {
-                        CERROR("err %d on param '%.*s\n", rc, len, ptr);
+                        CERROR("err %d on param '%s\n", rc, ptr);
                         break;
                 }
-                ptr += len;
+                
+                if (!endptr)
+                        /* last param */
+                        break;
+                 
+                *endptr = ' ';
+                ptr = endptr + 1;
         }
 
         RETURN(rc);
@@ -1634,17 +1810,10 @@ int mgs_check_failnid(struct obd_device *obd, struct mgs_target_info *mti)
                 RETURN(-ENOENT);
 
         CDEBUG(D_MGS, "Checking for new failnids for %s\n", mti->mti_svname);
-        // FIXME check logs
-        /* FIXME we need a real database lookup.  Create on-disk db of known 
-           size, lookup by index */
-        /* Check each nid, or check only nid0 and add all if nid0 is missing?
-           What if someone adds a net to a node? Better check everything. */
-        /* if nid 0 is missing, mgs_write_log_add_failnid.
-           if just one nid is missing, add uuid for nodeuuid[nid0]).
-        */
 
-        /* Hey, we can just check mti->params to see if we're already in
-           the failover list */
+        /* FIXME We can just check mti->params to see if we're already in
+           the failover list.  Modify mti->params for rewriting back at 
+           server_register_target(). */
         
         down(&fsdb->fsdb_sem);
         rc = mgs_write_log_add_failnid(obd, fsdb, mti);
@@ -1667,10 +1836,31 @@ int mgs_write_log_target(struct obd_device *obd,
                 CERROR("Can't get index (%d)\n", rc);
                 RETURN(rc);
         }
-        if (rc == EALREADY) {
-                // FIXME mark old log sections as invalid, add new.
-                CERROR("updates not yet implemented\n");
-                RETURN(-EALREADY);
+
+        /* COMPAT_146 */
+        if (mti->mti_flags & LDD_F_UPGRADE14) {
+                if (rc == EALREADY) {
+                        CDEBUG(D_MGS, "Found index %d for %s 1.4 log, upgrading\n",
+                               mti->mti_stripe_index, mti->mti_svname);
+                } else {
+                        LCONSOLE_ERROR("Failed to find %s in the old client "
+                                       "log\n", mti->mti_svname);
+                        /* Not in client log?  Upgrade anyhow...*/
+                        /* RETURN(-EINVAL); */
+                }
+                /* end COMPAT_146 */
+        } else {
+                if (rc == EALREADY) {
+                        /* Update a target entry in the logs */
+                        LCONSOLE_WARN("Found index %d for %s, updating log\n", 
+                                      mti->mti_stripe_index, mti->mti_svname);
+                        /* FIXME mark old log sections as invalid, 
+                           inc config ver #, add new log sections.
+                           Make sure to update client and mds logs too
+                           if needed */
+                        /* in the mean time, assume all logs were lost
+                           (writeconf), and recreate this one */
+                }
         }
 
         rc = mgs_find_or_make_fsdb(obd, mti->mti_fsname, &fsdb); 
@@ -1681,19 +1871,28 @@ int mgs_write_log_target(struct obd_device *obd,
 
         down(&fsdb->fsdb_sem);
 
-        if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
-                rc = mgs_write_log_mds(obd, fsdb, mti);
-        } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
-                rc = mgs_write_log_ost(obd, fsdb, mti);
+        if (mti->mti_flags & 
+            (LDD_F_VIRGIN | LDD_F_UPGRADE14 | LDD_F_WRITECONF)) {
+                /* Generate a log from scratch */
+                if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
+                        rc = mgs_write_log_mdt(obd, fsdb, mti);
+                } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
+                        rc = mgs_write_log_ost(obd, fsdb, mti);
+                } else {
+                        CERROR("Unknown target type %#x, can't create log for "
+                               "%s\n", mti->mti_flags, mti->mti_svname);
+                }
+                if (rc) {
+                        CERROR("Can't write logs for %s (%d)\n",
+                               mti->mti_svname, rc);
+                        GOTO(out_up, rc);
+                }
         } else {
-                CERROR("Unknown target type %#x, can't create log for %s\n",
-                       mti->mti_flags, mti->mti_svname);
+                /* Just update the params from tunefs in mgs_write_log_params */
+                CDEBUG(D_MGS, "Update params for %s\n", mti->mti_svname);
+                mti->mti_flags |= LDD_F_PARAM_FNID;
         }
-        if (rc) {
-                CERROR("Can't write logs for %s (%d)\n", mti->mti_svname, rc);
-                GOTO(out_up, rc);
-        }
-
+        
         rc = mgs_write_log_params(obd, fsdb, mti);
 
 out_up:
@@ -1701,107 +1900,25 @@ out_up:
         RETURN(rc);
 }
 
-
 /* COMPAT_146 */
-/***************** upgrade pre-mountconf logs to mountconf *****************/
-
-#if 0
-int mgs_upgrade_logs_14(struct obd_device *obd, struct fs_db *fsdb, 
-                        struct mgs_target_info *mti)
-{
-        int rc = 0;
-        ENTRY;
-
-        CDEBUG(D_MGS, "Upgrading old logs for %s\n", mti->mti_fsname);
-
-        /* If we get here, we know: 
-                the client log fsname-client exists
-                the logs have not been updated
-           so
-        1. parse the old client log (client log name?) to find out UUIDs for
-           all servers
-        2. regen all ost logs: servers will get new
-           name based on index, but will keep their old uuids.
-        3. append mdt startup to the end of the mdt log
-        4. append marker to old client log signifying we did the upgrade
-        ?  translate mds/client logs to new names?
-                  2 UP mdt MDS MDS_uuid 3
-                  3 UP lov lov_mdsA 47d06_lov_mdsA_61f31f85bc 4
-                  4 UP osc OSC_uml1_ost1_mdsA 47d06_lov_mdsA_61f31f85bc 4
-                  5 UP osc OSC_uml1_ost2_mdsA 47d06_lov_mdsA_61f31f85bc 4
-                  6 UP mds lustre-MDT0000 mdsA_UUID 3
-                to
-        ?  update server uuids?
-        */
-
-        
-        /* old mdt log: 
-        old osc's were part of old lov,
-        mount opt connects mdt to lov
-        so need to use old lov name.
-        old client logs starts old mdc and lov,
-        so need to use old lov,mdc names in mount opt - but new client name 
-        *-client instead of just "client" */
-
-
-        if ((mti->mti_flags & LDD_F_SV_TYPE_MDT)) {
-                CDEBUG(D_MGS, "Upgrade MDT\n");
-                if (mgs_log_is_empty(obd, mti->mti_svname)) {
-                        CERROR("The MDT log %s is missing.\n", mti->mti_svname);
-                        RETURN(-ENOENT);
-                }
-                /* Append the MDT startup sequence to the old log 
-                   (lconf used to start the MDT directly) */
-                rc = mgs_write_log_mdt(obd, fsdb, mti);
-                if (rc) 
-                        RETURN(rc);
-
-                /* this would be for trying to update an old client log */
-                struct llog_handle *llh = NULL;
-                char *cliname;
-                CDEBUG(D_MGS, "Upgrade client\n");
-
-                name_create(mti->mti_fsname, "-client", &cliname);
-
-                rc = record_start_log(obd, &llh, cliname);
-                rc = record_marker(obd, llh, fsdb, CM_START, "client",
-                                   "upgrade from 1.4"); 
-                /* FIXME find the old lovname and mdcname from old log */
-                /* old: mount_option 0:  1:client  2:lov1  3:MDC_uml1_mdsA_MNT_client */
-                /* new: mount_option 0:  1:lustre-client  2:lustre-clilov  3:lustre-MDT0000-mdc */
-                rc = record_mount_opt(obd, llh, cliname, "lov1", 
-                                      "MDC_uml1_mdsA_MNT_client");
-                rc = record_marker(obd, llh, fsdb, CM_END, "client", 
-                                   "upgrade to 1.6"); 
-                rc = record_end_log(obd, &llh);
-                name_destroy(cliname);
-        }
-        
-        if ((mti->mti_flags & LDD_F_SV_TYPE_OST)) {
-                CDEBUG(D_MGS, "Upgrade OST\n");
-                /* A regular new ost log, but don't update client or MDT logs */
-                rc = mgs_write_log_ost(obd, fsdb, mti);
-        }
-
-        RETURN(rc);
-}
-#endif        
-
-/* first connect of upgraded servers */ 
+/* upgrade pre-mountconf logs to mountconf at first connect */ 
 int mgs_upgrade_sv_14(struct obd_device *obd, struct mgs_target_info *mti)
 {
         struct fs_db *fsdb;
         int rc = 0;
         ENTRY;
 
-        /* Create client and ost log normally, as servers register.
-         That way logs are modern (except have old uuids (from last_rcvd))
-         - Old clients can continue to use upgraded OSTs
-         - New clients will only start with upgraded OSTs
-         - MDT won't know about old OSTs, only upgraded, so we need the old
-           MDT log in order for old clients to work. (Old clients connect to
-           the MDT, not the MGS, for their logs, and will therefore receive
-           the old client log from the MDT /LOGS dir.) */ 
+        /* Create ost log normally, as servers register.  Servers 
+           register with their old uuids (from last_rcvd), so old
+           (MDT and client) logs should work.
+         - new MDT won't know about old OSTs, only the ones that have 
+           registered, so we need the old MDT log to get the LOV right 
+           in order for old clients to work. 
+         - Old clients connect to the MDT, not the MGS, for their logs, and 
+           will therefore receive the old client log from the MDT /LOGS dir. 
+         - Old clients can continue to use and connect to old or new OSTs
+         - New clients will contact the MGS for their log 
+        */
 
         CDEBUG(D_MGS, "upgrading server %s from pre-1.6\n", 
                mti->mti_svname); 
@@ -1811,11 +1928,14 @@ int mgs_upgrade_sv_14(struct obd_device *obd, struct mgs_target_info *mti)
         if (rc) 
                 RETURN(rc);
 
-        if (fsdb->fsdb_flags & FSDB_EMPTY)
-                /* First server to upgrade sees this */
-                CWARN("info: missing client log\n");
+        if (fsdb->fsdb_flags & FSDB_EMPTY) {
+                LCONSOLE_ERROR("The old client log %s-client is missing.  Was "
+                               "tunefs.lustre successful?\n",
+                               mti->mti_fsname);
+                RETURN(-ENOENT);
+        }
 
-        if (!(fsdb->fsdb_flags & FSDB_EMPTY) && (fsdb->fsdb_gen == 0)) {
+        if (fsdb->fsdb_gen == 0) {
                 /* There were no markers in the client log, meaning we have 
                    not updated the logs for this fs */
                 CWARN("info: found old, unupdated client log\n");
@@ -1829,14 +1949,12 @@ int mgs_upgrade_sv_14(struct obd_device *obd, struct mgs_target_info *mti)
                 RETURN(-ENOENT);
         }
 
-        /* FIXME Old MDT log already has an old mount opt 
-           which we should drop */
         rc = mgs_write_log_target(obd, mti);
         RETURN(rc);
 }
 /* end COMPAT_146 */
 
-static int mgs_clear_log(struct obd_device *obd, char *name)
+int mgs_erase_log(struct obd_device *obd, char *name)
 {
         struct lvfs_run_ctxt saved;
         struct llog_handle *llh;
@@ -1887,7 +2005,7 @@ int mgs_erase_logs(struct obd_device *obd, char *fsname)
                 list_del(&dirent->lld_list);
                 if (strncmp(fsname, dirent->lld_name, len) == 0) {
                         CDEBUG(D_MGS, "Removing log %s\n", dirent->lld_name);
-                        mgs_clear_log(obd, dirent->lld_name);
+                        mgs_erase_log(obd, dirent->lld_name);
                 }
                 OBD_FREE(dirent, sizeof(*dirent));
         }
@@ -1920,11 +2038,12 @@ static void print_lustre_cfg(struct lustre_cfg *lcfg)
 }
 
 /* Set a permanent (config log) param for a target or fs */
-int mgs_setparam(struct obd_device *obd, char *fsname, struct lustre_cfg *lcfg)
+int mgs_setparam(struct obd_device *obd, struct lustre_cfg *lcfg, char *fsname)
 {
         struct fs_db *fsdb;
         struct mgs_target_info *mti;
-        char *devname;
+        char *devname, *param;
+        char *ptr;
         int rc = 0;
         ENTRY;
 
@@ -1932,14 +2051,33 @@ int mgs_setparam(struct obd_device *obd, char *fsname, struct lustre_cfg *lcfg)
         
         /* lustre, lustre-mdtlov, lustre-client, lustre-MDT0000 */
         devname = lustre_cfg_string(lcfg, 0);
-
-        if (devname == NULL) {
-                /* Global setting across all fs's? */
-                LCONSOLE_ERROR("Global settings not implemented yet!\n");
+        param = lustre_cfg_string(lcfg, 1);
+        if (!devname) {
+                /* Assume device name embedded in param:
+                   lustre-OST0000.osc.max_dirty_mb=32 */
+                ptr = strchr(param, '.');
+                if (ptr) {
+                        devname = param;
+                        *ptr = 0;
+                        param = ptr + 1;
+                }
+        }
+        if (!devname) {
+                LCONSOLE_ERROR("No target specified: %s\n", param);
                 RETURN(-ENOSYS);
         }
-        
-        CDEBUG(D_MGS, "target: %s\n", devname);
+
+        /* Extract fsname */
+        ptr = strchr(devname, '-');
+        memset(fsname, 0, MTI_NAME_MAXLEN);
+        if (!ptr) {
+                /* assume devname is the fsname */
+                strncpy(fsname, devname, MTI_NAME_MAXLEN);
+        } else {  
+                strncpy(fsname, devname, ptr - devname);
+        }
+        fsname[MTI_NAME_MAXLEN] = 0;
+        CDEBUG(D_MGS, "setparam on fs %s device %s\n", fsname, devname);
 
         rc = mgs_find_or_make_fsdb(obd, fsname, &fsdb); 
         if (rc) 
@@ -1953,14 +2091,14 @@ int mgs_setparam(struct obd_device *obd, char *fsname, struct lustre_cfg *lcfg)
         OBD_ALLOC_PTR(mti);
         if (!mti) 
                 GOTO(out, rc = -ENOMEM);
-        strcpy(mti->mti_fsname, fsname);
-        strcpy(mti->mti_svname, devname);
+        strncpy(mti->mti_fsname, fsname, MTI_NAME_MAXLEN);
+        strncpy(mti->mti_svname, devname, MTI_NAME_MAXLEN);
         rc = server_name2index(devname, &mti->mti_stripe_index, NULL);
         if (rc < 0) 
-                GOTO(out, rc);
-        mti->mti_flags = rc | MTI_F_IOCTL;
-        strncpy(mti->mti_params, lustre_cfg_string(lcfg, 1), 
-                sizeof(mti->mti_params));
+                /* Not a valid server, may be only fsname */
+                rc = 0;
+        mti->mti_flags = rc | LDD_F_PARAM_FNID;
+        strncpy(mti->mti_params, param, sizeof(mti->mti_params));
 
         down(&fsdb->fsdb_sem);
         rc = mgs_write_log_params(obd, fsdb, mti); 
index 061c3a5..36f49d4 100644 (file)
@@ -51,9 +51,9 @@
 atomic_t libcfs_kmemory = {0};
 #endif
 
-struct obd_device obd_dev[MAX_OBD_DEVICES];
+struct obd_device *obd_devs[MAX_OBD_DEVICES];
 struct list_head obd_types;
-spinlock_t obd_dev_lock;
+spinlock_t obd_dev_lock = SPIN_LOCK_UNLOCKED;
 #ifndef __KERNEL__
 atomic_t obd_memory;
 int obd_memmax;
@@ -68,6 +68,7 @@ unsigned int obd_health_check_timeout = 120; /* seconds */
 char obd_lustre_upcall[128] = "DEFAULT"; /* or NONE or /full/path/to/upcall  */
 
 cfs_waitq_t obd_race_waitq;
+int obd_race_state;
 
 #ifdef __KERNEL__
 unsigned int obd_print_fail_loc(void)
@@ -113,7 +114,7 @@ static inline void obd_conn2data(struct obd_ioctl_data *data,
         data->ioc_cookie = conn->cookie;
 }
 
-int class_resolve_dev_name(uint32_t len, char *name)
+int class_resolve_dev_name(uint32_t len, const char *name)
 {
         int rc;
         int dev;
@@ -159,7 +160,7 @@ int class_handle_ioctl(unsigned int cmd, unsigned long arg)
                 return 0;
         }
 
-        CDEBUG(D_IOCTL, "cmd = %x, obd = %p\n", cmd, obd);
+        CDEBUG(D_IOCTL, "cmd = %x\n", cmd);
         if (obd_ioctl_getdata(&buf, &len, (void *)arg)) {
                 CERROR("OBD ioctl: data error\n");
                 GOTO(out, err = -EINVAL);
@@ -280,11 +281,9 @@ int class_handle_ioctl(unsigned int cmd, unsigned long arg)
                         CERROR("ioctl buffer too small to hold version\n");
                         GOTO(out, err = -EINVAL);
                 }
-
-                if (index >= MAX_OBD_DEVICES)
-                        GOTO(out, err = -ENOENT);
-                obd = &obd_dev[index];
-                if (!obd->obd_type)
+                                
+                obd = class_num2obd(index);
+                if (!obd)
                         GOTO(out, err = -ENOENT);
 
                 if (obd->obd_stopping)
@@ -307,12 +306,19 @@ int class_handle_ioctl(unsigned int cmd, unsigned long arg)
 
         }
 
-        if (data->ioc_dev >= MAX_OBD_DEVICES) {
+        if (data->ioc_dev >= class_devno_max()) {
                 CERROR("OBD ioctl: No device\n");
                 GOTO(out, err = -EINVAL);
         }
-        obd = &obd_dev[data->ioc_dev];
-        if (!(obd && obd->obd_set_up) || obd->obd_stopping) {
+
+        obd = class_num2obd(data->ioc_dev);
+        if (obd == NULL) {
+                CERROR("OBD ioctl : No Device %d\n", data->ioc_dev);
+                GOTO(out, err = -EINVAL);
+        }
+        LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
+
+        if (!obd->obd_set_up || obd->obd_stopping) {
                 CERROR("OBD ioctl: device not setup %d \n", data->ioc_dev);
                 GOTO(out, err = -EINVAL);
         }
@@ -371,10 +377,11 @@ extern cfs_psdev_t obd_psdev;
 void *obd_psdev = NULL;
 #endif
 
-EXPORT_SYMBOL(obd_dev);
+EXPORT_SYMBOL(obd_devs);
 EXPORT_SYMBOL(obd_fail_loc);
 EXPORT_SYMBOL(obd_print_fail_loc);
 EXPORT_SYMBOL(obd_race_waitq);
+EXPORT_SYMBOL(obd_race_state);
 EXPORT_SYMBOL(obd_dump_on_timeout);
 EXPORT_SYMBOL(obd_timeout);
 EXPORT_SYMBOL(ldlm_timeout);
@@ -386,14 +393,12 @@ EXPORT_SYMBOL(proc_lustre_root);
 
 EXPORT_SYMBOL(class_register_type);
 EXPORT_SYMBOL(class_unregister_type);
-EXPORT_SYMBOL(class_search_type);
 EXPORT_SYMBOL(class_get_type);
 EXPORT_SYMBOL(class_put_type);
 EXPORT_SYMBOL(class_name2dev);
 EXPORT_SYMBOL(class_name2obd);
 EXPORT_SYMBOL(class_uuid2dev);
 EXPORT_SYMBOL(class_uuid2obd);
-EXPORT_SYMBOL(class_obd_list);
 EXPORT_SYMBOL(class_find_client_obd);
 EXPORT_SYMBOL(class_find_client_notype);
 EXPORT_SYMBOL(class_devices_in_group);
@@ -403,6 +408,7 @@ EXPORT_SYMBOL(class_conn2obd);
 EXPORT_SYMBOL(class_exp2cliimp);
 EXPORT_SYMBOL(class_conn2cliimp);
 EXPORT_SYMBOL(class_disconnect);
+EXPORT_SYMBOL(class_num2obd);
 
 /* uuid.c */
 EXPORT_SYMBOL(class_generate_random_uuid);
@@ -418,7 +424,9 @@ EXPORT_SYMBOL(class_incref);
 EXPORT_SYMBOL(class_decref);
 EXPORT_SYMBOL(class_get_profile);
 EXPORT_SYMBOL(class_del_profile);
+EXPORT_SYMBOL(class_del_profiles);
 EXPORT_SYMBOL(class_process_config);
+EXPORT_SYMBOL(class_process_proc_param);
 EXPORT_SYMBOL(class_config_parse_llog);
 EXPORT_SYMBOL(class_config_dump_llog);
 EXPORT_SYMBOL(class_attach);
@@ -516,15 +524,16 @@ int init_obdclass(void)
 #endif
 {
         int i, err;
-        struct obd_device *obd;
 #ifdef __KERNEL__
         int lustre_register_fs(void);
 
-        printk(KERN_INFO "Lustre: OBD class driver Build Version: "
-               BUILD_VERSION", info@clusterfs.com\n");
+        printk(KERN_INFO "Lustre: OBD class driver, info@clusterfs.com\n");
+        printk(KERN_INFO "        Lustre Version: "LUSTRE_VERSION_STRING"\n");
+        printk(KERN_INFO "        Build Version: "BUILD_VERSION"\n");
 #else
-        CDEBUG(D_INFO, "Lustre: OBD class driver Build Version: "
-               BUILD_VERSION", info@clusterfs.com\n");
+        CDEBUG(D_INFO, "Lustre: OBD class driver, info@clusterfs.com\n");
+        CDEBUG(D_INFO, "        Lustre Version: "LUSTRE_VERSION_STRING"\n");
+        CDEBUG(D_INFO, "        Build Version: "BUILD_VERSION"\n");
 #endif
 
         spin_lock_init(&obd_types_lock);
@@ -550,8 +559,8 @@ int init_obdclass(void)
         }
 
         /* This struct is already zerod for us (static global) */
-        for (i = 0, obd = obd_dev; i < MAX_OBD_DEVICES; i++, obd++)
-                obd->obd_minor = i;
+        for (i = 0; i < class_devno_max(); i++)
+                obd_devs[i] = NULL;
 
         err = obd_init_caches();
         if (err)
@@ -579,11 +588,12 @@ static void cleanup_obdclass(void)
         lustre_unregister_fs();
 
         cfs_psdev_deregister(&obd_psdev);
-        for (i = 0; i < MAX_OBD_DEVICES; i++) {
-                struct obd_device *obd = &obd_dev[i];
-                if (obd->obd_type && obd->obd_set_up &&
+        for (i = 0; i < class_devno_max(); i++) {
+                struct obd_device *obd = class_num2obd(i);
+                if (obd && obd->obd_set_up &&
                     OBT(obd) && OBP(obd, detach)) {
                         /* XXX should this call generic detach otherwise? */
+                        LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
                         OBP(obd, detach)(obd);
                 }
         }
@@ -603,5 +613,5 @@ MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
 MODULE_DESCRIPTION("Lustre Class Driver Build Version: " BUILD_VERSION);
 MODULE_LICENSE("GPL");
 
-cfs_module(obdclass, "1.0.0", init_obdclass, cleanup_obdclass);
+cfs_module(obdclass, LUSTRE_VERSION_STRING, init_obdclass, cleanup_obdclass);
 #endif
index 763606b..7d3d313 100644 (file)
@@ -102,7 +102,7 @@ int dump_obdo(struct obdo *oa)
 
 void dump_lsm(int level, struct lov_stripe_md *lsm)
 {
-        CDEBUG_EX(level, "lsm %p, objid "LPX64", maxbytes "LPX64", magic 0x%08X, "
+        CDEBUG(level, "lsm %p, objid "LPX64", maxbytes "LPX64", magic 0x%08X, "
                "stripe_size %u, stripe_count %u\n", lsm,
                lsm->lsm_object_id, lsm->lsm_maxbytes, lsm->lsm_magic,
                lsm->lsm_stripe_size, lsm->lsm_stripe_count);
index 4930dc1..d2a3864 100644 (file)
 extern struct list_head obd_types;
 spinlock_t obd_types_lock;
 
-cfs_mem_cache_t *obdo_cachep = NULL;
+cfs_mem_cache_t *obd_device_cachep;
+cfs_mem_cache_t *obdo_cachep;
 EXPORT_SYMBOL(obdo_cachep);
-cfs_mem_cache_t *import_cachep = NULL;
+cfs_mem_cache_t *import_cachep;
 
 int (*ptlrpc_put_connection_superhack)(struct ptlrpc_connection *c);
 
@@ -46,6 +47,27 @@ int (*ptlrpc_put_connection_superhack)(struct ptlrpc_connection *c);
  * support functions: we could use inter-module communication, but this
  * is more portable to other OS's
  */
+static struct obd_device *obd_device_alloc(void)
+{
+        struct obd_device *obd;
+
+        OBD_SLAB_ALLOC(obd, obd_device_cachep, SLAB_KERNEL, sizeof(*obd));
+        if (obd != NULL) {
+                obd->obd_magic = OBD_DEVICE_MAGIC;
+        }
+        return obd;
+}
+EXPORT_SYMBOL(obd_device_alloc);
+
+static void obd_device_free(struct obd_device *obd)
+{
+        LASSERT(obd != NULL);
+        LASSERTF(obd->obd_magic == OBD_DEVICE_MAGIC, "obd %p obd_magic %08x != %08x\n", 
+                 obd, obd->obd_magic, OBD_DEVICE_MAGIC);
+        OBD_SLAB_FREE(obd, obd_device_cachep, sizeof(*obd));
+}
+EXPORT_SYMBOL(obd_device_free);
+
 struct obd_type *class_search_type(const char *name)
 {
         struct list_head *tmp;
@@ -80,15 +102,22 @@ struct obd_type *class_get_type(const char *name)
                 }
         }
 #endif
-        if (type)
+        if (type) {
+                spin_lock(&type->obd_type_lock);
+                type->typ_refcnt++;
                 try_module_get(type->typ_dt_ops->o_owner);
+                spin_unlock(&type->obd_type_lock);
+        }
         return type;
 }
 
 void class_put_type(struct obd_type *type)
 {
         LASSERT(type);
+        spin_lock(&type->obd_type_lock);
+        type->typ_refcnt--;
         module_put(type->typ_dt_ops->o_owner);
+        spin_unlock(&type->obd_type_lock);
 }
 
 #define CLASS_MAX_NAME 1024
@@ -127,6 +156,7 @@ int class_register_type(struct obd_ops *dt_ops, struct md_ops *md_ops,
         if (md_ops)
                 *(type->typ_md_ops) = *md_ops;
         strcpy(type->typ_name, name);
+        spin_lock_init(&type->obd_type_lock);
 
 #ifdef LPROCFS
         type->typ_procroot = lprocfs_register(type->typ_name, proc_lustre_root,
@@ -200,48 +230,90 @@ int class_unregister_type(const char *name)
         RETURN(0);
 } /* class_unregister_type */
 
-struct obd_device *class_newdev(struct obd_type *type, char *name)
+struct obd_device *class_newdev(const char *type_name, const char *name)
 {
         struct obd_device *result = NULL;
+        struct obd_type *type = NULL;
         int i;
+        int new_obd_minor = 0;
+
+        if (strlen(name) > MAX_OBD_NAME) {
+                CERROR("name/uuid must be < %u bytes long\n",MAX_OBD_NAME);
+                RETURN(ERR_PTR(-EINVAL));
+        }
+
+        type = class_get_type(type_name); 
+        if (type == NULL){
+                CERROR("OBD: unknown type: %s\n", type_name);
+                RETURN(ERR_PTR(-ENODEV));
+        }
 
         spin_lock(&obd_dev_lock);
-        for (i = 0 ; i < MAX_OBD_DEVICES; i++) {
-                struct obd_device *obd = &obd_dev[i];
-                if (obd->obd_name && (strcmp(name, obd->obd_name) == 0)) {
+        for (i = 0 ; i < class_devno_max(); i++) {
+                struct obd_device *obd = class_num2obd(i);
+                if (obd && obd->obd_name && (strcmp(name, obd->obd_name) == 0)) {
                         CERROR("Device %s already exists, won't add\n", name);
                         if (result) {
-                                result->obd_type = NULL;
-                                result->obd_name = NULL;
-                                result = NULL;
+                                LASSERTF(result->obd_magic == OBD_DEVICE_MAGIC,
+                                         "%p obd_magic %08x != %08x\n",
+                                         result, result->obd_magic, OBD_DEVICE_MAGIC);
+                                LASSERTF(result->obd_minor == new_obd_minor,
+                                         "%p obd_minor %d != %d\n",
+                                         result, result->obd_minor, new_obd_minor);
+
+                                obd_devs[result->obd_minor] = NULL;
+                                result->obd_name[0]='\0';
+                                obd_device_free(result);
                         }
+                        result = ERR_PTR(-EEXIST);
                         break;
                 }
-                if (!result && !obd->obd_type) {
-                        LASSERT(obd->obd_minor == i);
-                        memset(obd, 0, sizeof(*obd));
+                if (!result && !obd) {
+                        obd = obd_device_alloc();
+
+                        if(obd == NULL)
+                                GOTO(out,result = ERR_PTR(-ENOMEM));
+
+                        LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
                         obd->obd_minor = i;
+                        new_obd_minor = i;
                         obd->obd_type = type;
-                        obd->obd_name = name;
+                        memcpy(obd->obd_name, name, strlen(name));
+
                         CDEBUG(D_IOCTL, "Adding new device %s (%p)\n",
                                obd->obd_name, obd);
                         result = obd;
+                        obd_devs[i] = result;
+                        obd = NULL;
                 }
         }
         spin_unlock(&obd_dev_lock);
+out :
+        if (IS_ERR(result)) {
+                class_put_type(type);
+        }
         return result;
 }
 
 void class_release_dev(struct obd_device *obd)
 {
-        int minor = obd->obd_minor;
+        struct obd_type *obd_type = obd->obd_type;
+
+        LASSERTF(obd->obd_magic == OBD_DEVICE_MAGIC, "%p obd_magic %08x != %08x\n",
+                 obd, obd->obd_magic, OBD_DEVICE_MAGIC);
+        LASSERTF(obd == obd_devs[obd->obd_minor], "obd %p != obd_devs[%d] %p\n",
+                 obd, obd->obd_minor, obd_devs[obd->obd_minor]);
+        LASSERT(obd_type != NULL);
+
+        CDEBUG(D_INFO, "Release obd device %s obd_type name =%s\n",
+               obd->obd_name,obd->obd_type->typ_name);
 
         spin_lock(&obd_dev_lock);
-        memset(obd, 0x5a, sizeof(*obd));
-        obd->obd_type = NULL;
-        obd->obd_minor = minor;
-        obd->obd_name = NULL;
+        obd_devs[obd->obd_minor] = NULL;
+        obd_device_free(obd);
         spin_unlock(&obd_dev_lock);
+
+        class_put_type(obd_type);
 }
 
 int class_name2dev(const char *name)
@@ -252,11 +324,12 @@ int class_name2dev(const char *name)
                 return -1;
 
         spin_lock(&obd_dev_lock);
-        for (i = 0; i < MAX_OBD_DEVICES; i++) {
-                struct obd_device *obd = &obd_dev[i];
-                if (obd->obd_name && strcmp(name, obd->obd_name) == 0) {
+        for (i = 0; i < class_devno_max(); i++) {
+                struct obd_device *obd = class_num2obd(i);
+                if (obd && obd->obd_name && strcmp(name, obd->obd_name) == 0) {
                         /* Make sure we finished attaching before we give
                            out any references */
+                        LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
                         if (obd->obd_attached) {
                                 spin_unlock(&obd_dev_lock);
                                 return i;
@@ -272,9 +345,10 @@ int class_name2dev(const char *name)
 struct obd_device *class_name2obd(const char *name)
 {
         int dev = class_name2dev(name);
-        if (dev < 0)
+
+        if (dev < 0 || dev > class_devno_max())
                 return NULL;
-        return &obd_dev[dev];
+        return class_num2obd(dev);
 }
 
 int class_uuid2dev(struct obd_uuid *uuid)
@@ -282,9 +356,10 @@ int class_uuid2dev(struct obd_uuid *uuid)
         int i;
 
         spin_lock(&obd_dev_lock);
-        for (i = 0; i < MAX_OBD_DEVICES; i++) {
-                struct obd_device *obd = &obd_dev[i];
-                if (obd_uuid_equals(uuid, &obd->obd_uuid)) {
+        for (i = 0; i < class_devno_max(); i++) {
+                struct obd_device *obd = class_num2obd(i);
+                if (obd && obd_uuid_equals(uuid, &obd->obd_uuid)) {
+                        LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
                         spin_unlock(&obd_dev_lock);
                         return i;
                 }
@@ -299,7 +374,28 @@ struct obd_device *class_uuid2obd(struct obd_uuid *uuid)
         int dev = class_uuid2dev(uuid);
         if (dev < 0)
                 return NULL;
-        return &obd_dev[dev];
+        return class_num2obd(dev);
+}
+
+struct obd_device *class_num2obd(int num)
+{
+        struct obd_device *obd = NULL;
+
+        if (num < class_devno_max()) {
+                obd = obd_devs[num];
+                if (obd == NULL) {
+                        return NULL;
+                }
+
+                LASSERTF(obd->obd_magic == OBD_DEVICE_MAGIC,
+                         "%p obd_magic %08x != %08x\n",
+                         obd, obd->obd_magic, OBD_DEVICE_MAGIC);
+                LASSERTF(obd->obd_minor == num,
+                         "%p obd_minor %0d != %0d\n",
+                         obd, obd->obd_minor, num);
+        }
+
+        return obd;
 }
 
 void class_obd_list(void)
@@ -308,9 +404,9 @@ void class_obd_list(void)
         int i;
 
         spin_lock(&obd_dev_lock);
-        for (i = 0; i < MAX_OBD_DEVICES; i++) {
-                struct obd_device *obd = &obd_dev[i];
-                if (obd->obd_type == NULL)
+        for (i = 0; i < class_devno_max(); i++) {
+                struct obd_device *obd = class_num2obd(i);
+                if (obd == NULL)
                         continue;
                 if (obd->obd_stopping)
                         status = "ST";
@@ -339,9 +435,9 @@ struct obd_device * class_find_client_obd(struct obd_uuid *tgt_uuid,
         int i;
 
         spin_lock(&obd_dev_lock);
-        for (i = 0; i < MAX_OBD_DEVICES; i++) {
-                struct obd_device *obd = &obd_dev[i];
-                if (obd->obd_type == NULL)
+        for (i = 0; i < class_devno_max(); i++) {
+                struct obd_device *obd = class_num2obd(i);
+                if (obd == NULL)
                         continue;
                 if ((strncmp(obd->obd_type->typ_name, typ_name,
                              strlen(typ_name)) == 0)) {
@@ -381,15 +477,15 @@ struct obd_device * class_devices_in_group(struct obd_uuid *grp_uuid, int *next)
 
         if (next == NULL)
                 i = 0;
-        else if (*next >= 0 && *next < MAX_OBD_DEVICES)
+        else if (*next >= 0 && *next < class_devno_max())
                 i = *next;
         else
                 return NULL;
 
         spin_lock(&obd_dev_lock);
-        for (; i < MAX_OBD_DEVICES; i++) {
-                struct obd_device *obd = &obd_dev[i];
-                if (obd->obd_type == NULL)
+        for (; i < class_devno_max(); i++) {
+                struct obd_device *obd = class_num2obd(i);
+                if (obd == NULL)
                         continue;
                 if (obd_uuid_equals(grp_uuid, &obd->obd_uuid)) {
                         if (next != NULL)
@@ -409,6 +505,11 @@ void obd_cleanup_caches(void)
         int rc;
 
         ENTRY;
+        if (obd_device_cachep) {
+                rc = cfs_mem_cache_destroy(obd_device_cachep);
+                LASSERTF(rc == 0, "Cannot destropy ll_obd_device_cache: rc %d\n", rc);
+                obd_device_cachep = NULL;
+        }
         if (obdo_cachep) {
                 rc = cfs_mem_cache_destroy(obdo_cachep);
                 LASSERTF(rc == 0, "Cannot destory ll_obdo_cache\n");
@@ -426,6 +527,12 @@ int obd_init_caches(void)
 {
         ENTRY;
 
+        LASSERT(obd_device_cachep == NULL);
+        obd_device_cachep = cfs_mem_cache_create("ll_obd_dev_cache",
+                                              sizeof(struct obd_device), 0, 0);
+        if (!obd_device_cachep)
+                GOTO(out, -ENOMEM);
+
         LASSERT(obdo_cachep == NULL);
         obdo_cachep = cfs_mem_cache_create("ll_obdo_cache", sizeof(struct obdo),
                                         0, 0);
@@ -549,6 +656,7 @@ struct obd_export *class_new_export(struct obd_device *obd,
         CFS_INIT_LIST_HEAD(&export->exp_outstanding_replies);
         /* XXX this should be in LDLM init */
         CFS_INIT_LIST_HEAD(&export->exp_ldlm_data.led_held_locks);
+        spin_lock_init(&export->exp_ldlm_data.led_lock);
 
         CFS_INIT_LIST_HEAD(&export->exp_handle.h_link);
         class_handle_hash(&export->exp_handle, export_handle_addref);
@@ -661,6 +769,7 @@ struct obd_import *class_new_import(struct obd_device *obd)
         CFS_INIT_LIST_HEAD(&imp->imp_sending_list);
         CFS_INIT_LIST_HEAD(&imp->imp_delayed_list);
         spin_lock_init(&imp->imp_lock);
+        imp->imp_last_success_conn = 0;
         imp->imp_state = LUSTRE_IMP_NEW;
         imp->imp_obd = class_incref(obd);
         cfs_waitq_init(&imp->imp_recovery_waitq);
@@ -672,6 +781,10 @@ struct obd_import *class_new_import(struct obd_device *obd)
         CFS_INIT_LIST_HEAD(&imp->imp_handle.h_link);
         class_handle_hash(&imp->imp_handle, import_handle_addref);
 
+        /* the default magic is V1, will be used in connect RPC, and
+         * then adjusted according to the flags in request/reply. */
+        imp->imp_msg_magic = LUSTRE_MSG_MAGIC_V1;
+
         return imp;
 }
 EXPORT_SYMBOL(class_new_import);
@@ -879,27 +992,32 @@ void oig_release(struct obd_io_group *oig)
 }
 EXPORT_SYMBOL(oig_release);
 
-void oig_add_one(struct obd_io_group *oig, struct oig_callback_context *occ)
+int oig_add_one(struct obd_io_group *oig, struct oig_callback_context *occ)
 {
-        unsigned long flags;
+        int rc = 0;
         CDEBUG(D_CACHE, "oig %p ready to roll\n", oig);
-        spin_lock_irqsave(&oig->oig_lock, flags);
-        oig->oig_pending++;
-        if (occ != NULL)
-                list_add_tail(&occ->occ_oig_item, &oig->oig_occ_list);
-        spin_unlock_irqrestore(&oig->oig_lock, flags);
+        spin_lock(&oig->oig_lock);
+        if (oig->oig_rc) {
+                rc = oig->oig_rc;
+        } else {
+                oig->oig_pending++;
+                if (occ != NULL)
+                        list_add_tail(&occ->occ_oig_item, &oig->oig_occ_list);
+        }
+        spin_unlock(&oig->oig_lock);
         oig_grab(oig);
+
+        return 0;
 }
 EXPORT_SYMBOL(oig_add_one);
 
 void oig_complete_one(struct obd_io_group *oig,
                       struct oig_callback_context *occ, int rc)
 {
-        unsigned long flags;
         cfs_waitq_t *wake = NULL;
         int old_rc;
 
-        spin_lock_irqsave(&oig->oig_lock, flags);
+        spin_lock(&oig->oig_lock);
 
         if (occ != NULL)
                 list_del_init(&occ->occ_oig_item);
@@ -911,7 +1029,7 @@ void oig_complete_one(struct obd_io_group *oig,
         if (--oig->oig_pending <= 0)
                 wake = &oig->oig_waitq;
 
-        spin_unlock_irqrestore(&oig->oig_lock, flags);
+        spin_unlock(&oig->oig_lock);
 
         CDEBUG(D_CACHE, "oig %p completed, rc %d -> %d via %d, %d now "
                         "pending (racey)\n", oig, old_rc, oig->oig_rc, rc,
@@ -924,12 +1042,11 @@ EXPORT_SYMBOL(oig_complete_one);
 
 static int oig_done(struct obd_io_group *oig)
 {
-        unsigned long flags;
         int rc = 0;
-        spin_lock_irqsave(&oig->oig_lock, flags);
+        spin_lock(&oig->oig_lock);
         if (oig->oig_pending <= 0)
                 rc = 1;
-        spin_unlock_irqrestore(&oig->oig_lock, flags);
+        spin_unlock(&oig->oig_lock);
         return rc;
 }
 
@@ -937,9 +1054,8 @@ static void interrupted_oig(void *data)
 {
         struct obd_io_group *oig = data;
         struct oig_callback_context *occ;
-        unsigned long flags;
 
-        spin_lock_irqsave(&oig->oig_lock, flags);
+        spin_lock(&oig->oig_lock);
         /* We need to restart the processing each time we drop the lock, as
          * it is possible other threads called oig_complete_one() to remove
          * an entry elsewhere in the list while we dropped lock.  We need to
@@ -950,12 +1066,12 @@ restart:
                 if (occ->interrupted)
                         continue;
                 occ->interrupted = 1;
-                spin_unlock_irqrestore(&oig->oig_lock, flags);
+                spin_unlock(&oig->oig_lock);
                 occ->occ_interrupted(occ);
-                spin_lock_irqsave(&oig->oig_lock, flags);
+                spin_lock(&oig->oig_lock);
                 goto restart;
         }
-        spin_unlock_irqrestore(&oig->oig_lock, flags);
+        spin_unlock(&oig->oig_lock);
 }
 
 int oig_wait(struct obd_io_group *oig)
@@ -986,12 +1102,11 @@ EXPORT_SYMBOL(oig_wait);
 void class_fail_export(struct obd_export *exp)
 {
         int rc, already_failed;
-        unsigned long flags;
 
-        spin_lock_irqsave(&exp->exp_lock, flags);
+        spin_lock(&exp->exp_lock);
         already_failed = exp->exp_failed;
         exp->exp_failed = 1;
-        spin_unlock_irqrestore(&exp->exp_lock, flags);
+        spin_unlock(&exp->exp_lock);
 
         if (already_failed) {
                 CDEBUG(D_HA, "disconnecting dead export %p/%s; skipping\n",
index 517035c..6eb062b 100644 (file)
@@ -163,37 +163,37 @@ extern struct cfs_psdev_ops          obd_psdev_ops;
 /*  opening /dev/obd */
 static int obd_class_open(struct inode * inode, struct file * file)
 {
-       if (obd_psdev_ops.p_open != NULL)
-               return obd_psdev_ops.p_open(0, NULL);
-       return -EPERM;
+        if (obd_psdev_ops.p_open != NULL)
+                return obd_psdev_ops.p_open(0, NULL);
+        return -EPERM;
 }
 
 /*  closing /dev/obd */
 static int obd_class_release(struct inode * inode, struct file * file)
 {
-       if (obd_psdev_ops.p_close != NULL)
-               return obd_psdev_ops.p_close(0, NULL);
-       return -EPERM;
+        if (obd_psdev_ops.p_close != NULL)
+                return obd_psdev_ops.p_close(0, NULL);
+        return -EPERM;
 }
 
 /* to control /dev/obd */
 static int obd_class_ioctl(struct inode *inode, struct file *filp,
-                          unsigned int cmd, unsigned long arg)
+                           unsigned int cmd, unsigned long arg)
 {
-       int err = 0;
-       ENTRY;
+        int err = 0;
+        ENTRY;
 
-       if (current->fsuid != 0)
-               RETURN(err = -EACCES);
-       if ((cmd & 0xffffff00) == ((int)'T') << 8) /* ignore all tty ioctls */
-               RETURN(err = -ENOTTY);
+        if (current->fsuid != 0)
+                RETURN(err = -EACCES);
+        if ((cmd & 0xffffff00) == ((int)'T') << 8) /* ignore all tty ioctls */
+                RETURN(err = -ENOTTY);
 
-       if (obd_psdev_ops.p_ioctl != NULL)
-               err = obd_psdev_ops.p_ioctl(NULL, cmd, (void *)arg);
-       else
-               err = -EPERM;
+        if (obd_psdev_ops.p_ioctl != NULL)
+                err = obd_psdev_ops.p_ioctl(NULL, cmd, (void *)arg);
+        else
+                err = -EPERM;
 
-       RETURN(err);
+        RETURN(err);
 }
 
 /* declare character device */
@@ -225,7 +225,11 @@ int obd_proc_read_kernel_version(char *page, char **start, off_t off, int count,
                                  int *eof, void *data)
 {
         *eof = 1;
+#ifdef LUSTRE_KERNEL_VERSION
         return snprintf(page, count, "%u\n", LUSTRE_KERNEL_VERSION);
+#else
+        return snprintf(page, count, "%u\n", "patchless");
+#endif
 }
 
 int obd_proc_read_pinger(char *page, char **start, off_t off, int count,
@@ -251,11 +255,15 @@ static int obd_proc_read_health(char *page, char **start, off_t off,
                 rc += snprintf(page + rc, count - rc, "LBUG\n");
 
         spin_lock(&obd_dev_lock);
-        for (i = 0; i < MAX_OBD_DEVICES; i++) {
+        for (i = 0; i < class_devno_max(); i++) {
                 struct obd_device *obd;
 
-                obd = &obd_dev[i];
-                if (obd->obd_type == NULL)
+                obd = class_num2obd(i);
+                if (obd == NULL)
+                        continue;
+
+                LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
+                if (obd->obd_stopping)
                         continue;
 
                 class_incref(obd);
@@ -318,9 +326,10 @@ struct lprocfs_vars lprocfs_base[] = {
 #ifdef __KERNEL__
 static void *obd_device_list_seq_start(struct seq_file *p, loff_t*pos)
 {
-        if (*pos >= MAX_OBD_DEVICES)
+        if (*pos >= class_devno_max())
                 return NULL;
-        return &obd_dev[*pos];
+
+        return pos;
 }
 
 static void obd_device_list_seq_stop(struct seq_file *p, void *v)
@@ -328,21 +337,24 @@ static void obd_device_list_seq_stop(struct seq_file *p, void *v)
 }
 
 static void *obd_device_list_seq_next(struct seq_file *p, void *v, loff_t *pos)
-{
+{      
         ++*pos;
-        if (*pos >= MAX_OBD_DEVICES)
+        if (*pos >= class_devno_max())
                 return NULL;
-        return &obd_dev[*pos];
+
+        return pos;
 }
 
 static int obd_device_list_seq_show(struct seq_file *p, void *v)
 {
-        struct obd_device *obd = (struct obd_device *)v;
-        int index = obd - &obd_dev[0];
+        int index = *(int*)v;
+        struct obd_device *obd = class_num2obd(index);
         char *status;
 
-        if (!obd->obd_type)
+        if (obd == NULL)
                 return 0;
+
+        LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
         if (obd->obd_stopping)
                 status = "ST";
         else if (obd->obd_set_up)
@@ -431,6 +443,7 @@ int class_procfs_clean(void)
 /* Check that we're building against the appropriate version of the Lustre
  * kernel patch */
 #include <linux/lustre_version.h>
+#ifdef LUSTRE_KERNEL_VERSION
 #define LUSTRE_MIN_VERSION 37
 #define LUSTRE_MAX_VERSION 47
 #if (LUSTRE_KERNEL_VERSION < LUSTRE_MIN_VERSION)
@@ -439,3 +452,4 @@ int class_procfs_clean(void)
 # error Cannot continue: Your Lustre sources are older than the kernel patch
 #endif
 #endif
+#endif
index b5db22d..a92977c 100644 (file)
@@ -207,10 +207,16 @@ void obdo_refresh_inode(struct inode *dst, struct obdo *src, obd_flag valid)
 
         if (valid & OBD_MD_FLATIME && src->o_atime > LTIME_S(dst->i_atime))
                 LTIME_S(dst->i_atime) = src->o_atime;
-        if (valid & OBD_MD_FLMTIME && src->o_mtime > LTIME_S(dst->i_mtime))
-                LTIME_S(dst->i_mtime) = src->o_mtime;
-        if (valid & OBD_MD_FLCTIME && src->o_ctime > LTIME_S(dst->i_ctime))
+        
+        /* mtime is always updated with ctime, but can be set in past.
+           As write and utime(2) may happen within 1 second, and utime's
+           mtime has a priority over write's one, leave mtime from mds 
+           for the same ctimes. */
+        if (valid & OBD_MD_FLCTIME && src->o_ctime > LTIME_S(dst->i_ctime)) {
                 LTIME_S(dst->i_ctime) = src->o_ctime;
+                if (valid & OBD_MD_FLMTIME)
+                        LTIME_S(dst->i_mtime) = src->o_mtime;
+        }
         if (valid & OBD_MD_FLSIZE) 
                 dst->i_size = src->o_size;
         /* optimum IO size */
index 9bdea74..bc8afc6 100644 (file)
@@ -119,7 +119,14 @@ static int llog_check_cb(struct llog_handle *handle, struct llog_rec_hdr *rec,
                 }
                 if (handle->lgh_ctxt == NULL)
                         RETURN(-EOPNOTSUPP);
-                llog_cat_id2handle(handle, &log_handle, &lir->lid_id);
+                rc = llog_cat_id2handle(handle, &log_handle, &lir->lid_id);
+                if (rc) {
+                        CDEBUG(D_IOCTL,
+                               "cannot find log #"LPX64"#"LPX64"#%08x\n",
+                               lir->lid_id.lgl_oid, lir->lid_id.lgl_ogr,
+                               lir->lid_id.lgl_ogen);
+                        RETURN(rc);
+                }
                 rc = llog_process(log_handle, llog_check_cb, NULL, NULL);
                 llog_close(log_handle);
         } else {
index faa9328..460cd4b 100644 (file)
@@ -709,9 +709,10 @@ int llog_get_cat_list(struct obd_device *obd, struct obd_device *disk_obd,
         int rc;
         int size = sizeof(*idarray) * count;
         loff_t off = 0;
+        ENTRY;
 
         if (!count) 
-                return (0);
+                RETURN(0);
 
         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
         file = filp_open(name, O_RDWR | O_CREAT | O_LARGEFILE, 0700);
@@ -737,11 +738,12 @@ int llog_get_cat_list(struct obd_device *obd, struct obd_device *disk_obd,
                 GOTO(out, rc);
         }
 
+        EXIT;
  out:
         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
         if (file && !IS_ERR(file))
                 rc = filp_close(file, 0);
-        RETURN(rc);
+        return rc;
 }
 EXPORT_SYMBOL(llog_get_cat_list);
 
index a1829bc..3912558 100644 (file)
@@ -72,19 +72,20 @@ int llog_setup(struct obd_device *obd, int index, struct obd_device *disk_obd,
                 RETURN(-EFAULT);
 
         if (obd->obd_llog_ctxt[index]) {
-        /* During an mds_lov_add_ost, we try to tear down and resetup llogs.
-           But the mdt teardown does not flow down to the lov/osc's as the 
-           setup does, because the lov/osc must clean up only when they are
-           done, not when the mdt is done. So instead, we just assume that
-           if the lov llogs are already set up then we must cleanup first. */
+                /* mds_lov_update_mds might call here multiple times. So if the
+                   llog is already set up then don't to do it again. */
                 CDEBUG(D_CONFIG, "obd %s ctxt %d already set up\n", 
                        obd->obd_name, index);
-                llog_cleanup(obd->obd_llog_ctxt[index]);
+                ctxt = obd->obd_llog_ctxt[index];
+                LASSERT(ctxt->loc_obd == obd);
+                LASSERT(ctxt->loc_exp == disk_obd->obd_self_export);
+                LASSERT(ctxt->loc_logops == op);
+                GOTO(out, rc = 0);
         }
-
+        
         OBD_ALLOC(ctxt, sizeof(*ctxt));
         if (!ctxt)
-                RETURN(-ENOMEM);
+                GOTO(out, rc = -ENOMEM);
 
         obd->obd_llog_ctxt[index] = ctxt;
         ctxt->loc_obd = obd;
@@ -95,7 +96,14 @@ int llog_setup(struct obd_device *obd, int index, struct obd_device *disk_obd,
 
         if (op->lop_setup)
                 rc = op->lop_setup(obd, index, disk_obd, count, logid);
-
+        
+        if (rc) {
+                obd->obd_llog_ctxt[index] = NULL;
+                class_export_put(ctxt->loc_exp);
+                OBD_FREE(ctxt, sizeof(*ctxt));
+        }
+        
+out:
         RETURN(rc);
 }
 EXPORT_SYMBOL(llog_setup);
@@ -241,10 +249,6 @@ int llog_obd_origin_setup(struct obd_device *obd, int index,
         if (rc)
                 CERROR("llog_process with cat_cancel_cb failed: %d\n", rc);
  out:
-        if (ctxt && rc) {
-                obd->obd_llog_ctxt[index] = NULL;
-                OBD_FREE(ctxt, sizeof(*ctxt));
-        }
         RETURN(rc);
 }
 EXPORT_SYMBOL(llog_obd_origin_setup);
@@ -317,9 +321,14 @@ int llog_cat_initialize(struct obd_device *obd, int count)
         int rc;
         ENTRY;
 
+        /* We don't want multiple mdt threads here at once */
+        mutex_down(&obd->obd_dev_sem);
+
         OBD_ALLOC(idarray, size);
-        if (!idarray)
+        if (!idarray) {
+                mutex_up(&obd->obd_dev_sem);
                 RETURN(-ENOMEM);
+        }
 
         rc = llog_get_cat_list(obd, obd, name, count, idarray);
         if (rc) {
@@ -341,6 +350,7 @@ int llog_cat_initialize(struct obd_device *obd, int count)
 
  out:
         OBD_FREE(idarray, size);
+        mutex_up(&obd->obd_dev_sem);
         RETURN(rc);
 }
 EXPORT_SYMBOL(llog_cat_initialize);
index 88488e9..f4d8a50 100644 (file)
@@ -58,6 +58,27 @@ struct proc_dir_entry *lprocfs_srch(struct proc_dir_entry *head,
 
 /* lprocfs API calls */
 
+/* Function that emulates snprintf but also has the side effect of advancing
+   the page pointer for the next write into the buffer, incrementing the total
+   length written to the buffer, and decrementing the size left in the
+   buffer. */
+static int lprocfs_obd_snprintf(char **page, int end, int *len,
+                                const char *format, ...)
+{
+        va_list list;
+        int n;
+
+        if (*len >= end)
+                return 0;
+
+        va_start(list, format);
+        n = vsnprintf(*page, end - *len, format, list);
+        va_end(list);
+
+        *page += n; *len += n;
+        return n;
+}
+
 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
                      void *data)
 {
@@ -230,7 +251,7 @@ int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
                        int *eof, void *data)
 {
         struct obd_statfs osfs;
-        int rc = obd_statfs(data, &osfs, jiffies - HZ);
+        int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ);
         if (!rc) {
                 *eof = 1;
                 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
@@ -242,7 +263,7 @@ int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
                            int *eof, void *data)
 {
         struct obd_statfs osfs;
-        int rc = obd_statfs(data, &osfs, jiffies - HZ);
+        int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ);
         if (!rc) {
                 __u32 blk_size = osfs.os_bsize >> 10;
                 __u64 result = osfs.os_blocks;
@@ -260,7 +281,7 @@ int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
                           int *eof, void *data)
 {
         struct obd_statfs osfs;
-        int rc = obd_statfs(data, &osfs, jiffies - HZ);
+        int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ);
         if (!rc) {
                 __u32 blk_size = osfs.os_bsize >> 10;
                 __u64 result = osfs.os_bfree;
@@ -278,7 +299,7 @@ int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
                            int *eof, void *data)
 {
         struct obd_statfs osfs;
-        int rc = obd_statfs(data, &osfs, jiffies - HZ);
+        int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ);
         if (!rc) {
                 __u32 blk_size = osfs.os_bsize >> 10;
                 __u64 result = osfs.os_bavail;
@@ -296,7 +317,7 @@ int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
                           int *eof, void *data)
 {
         struct obd_statfs osfs;
-        int rc = obd_statfs(data, &osfs, jiffies - HZ);
+        int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ);
         if (!rc) {
                 *eof = 1;
                 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
@@ -309,7 +330,7 @@ int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
                          int *eof, void *data)
 {
         struct obd_statfs osfs;
-        int rc = obd_statfs(data, &osfs, jiffies - HZ);
+        int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ);
         if (!rc) {
                 *eof = 1;
                 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
@@ -361,7 +382,7 @@ static const char *obd_connect_names[] = {
         "initial_transno",
         "inode_bit_locks",
         "join_file",
-        "",
+        "getattr_by_fid",
         "no_oh_for_devices",
         NULL
 };
@@ -416,7 +437,7 @@ int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
         int rc = 0;
 
         LASSERT(obd != NULL);
-        LASSERT(obd->obd_type != NULL);
+        LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
         LASSERT(obd->obd_type->typ_procroot != NULL);
 
         obd->obd_proc_entry = lprocfs_register(obd->obd_name,
@@ -479,12 +500,27 @@ void lprocfs_free_stats(struct lprocfs_stats *stats)
         OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_online_cpus()]));
 }
 
-/* Reset counter under lock */
-int lprocfs_counter_write(struct file *file, const char *buffer,
-                          unsigned long count, void *data)
+static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
+                                       size_t len, loff_t *off)
 {
-        /* not supported */
-        return 0;
+        struct seq_file *seq = file->private_data;
+        struct lprocfs_stats *stats = seq->private;
+        struct lprocfs_counter *percpu_cntr;
+        int i,j;
+
+        for (i = 0; i < num_online_cpus(); i++) {
+                for (j = 0; j < stats->ls_num; j++) {        
+                        percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
+                        atomic_inc(&percpu_cntr->lc_cntl.la_entry);
+                        percpu_cntr->lc_count = 0;
+                        percpu_cntr->lc_sum = 0;
+                        percpu_cntr->lc_min = ~(__u64)0;
+                        percpu_cntr->lc_max = 0;
+                        percpu_cntr->lc_sumsquare = 0;
+                        atomic_inc(&percpu_cntr->lc_cntl.la_exit);
+                }
+        }
+        return len;
 }
 
 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
@@ -593,6 +629,7 @@ struct file_operations lprocfs_stats_seq_fops = {
         .owner   = THIS_MODULE,
         .open    = lprocfs_stats_seq_open,
         .read    = seq_read,
+        .write   = lprocfs_stats_seq_write,
         .llseek  = seq_lseek,
         .release = seq_release,
 };
@@ -608,7 +645,6 @@ int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
                 return -ENOMEM;
         entry->proc_fops = &lprocfs_stats_seq_fops;
         entry->data = (void *)stats;
-        entry->write_proc = lprocfs_counter_write;
         return 0;
 }
 
@@ -622,7 +658,10 @@ void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
         for (i = 0; i < num_online_cpus(); i++) {
                 c = &(stats->ls_percpu[i]->lp_cntr[index]);
                 c->lc_config = conf;
+                c->lc_count = 0;
+                c->lc_sum = 0;
                 c->lc_min = ~(__u64)0;
+                c->lc_max = 0;
                 c->lc_name = name;
                 c->lc_units = units;
         }
@@ -646,8 +685,8 @@ int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
         LASSERT(obd->obd_proc_entry != NULL);
         LASSERT(obd->obd_cntr_base == 0);
 
-        num_stats = 1 + OBD_COUNTER_OFFSET(quotactl) +
-                num_private_stats;
+        num_stats = (sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
+                num_private_stats - 1 /* o_owner */;
         stats = lprocfs_alloc_stats(num_stats);
         if (stats == NULL)
                 return -ENOMEM;
@@ -672,6 +711,7 @@ int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
+        LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, checkmd);
@@ -708,6 +748,7 @@ int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, san_preprw);
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
+        LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
@@ -717,6 +758,7 @@ int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
+        LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
 
         for (i = num_private_stats; i < num_stats; i++) {
                 /* If this LBUGs, it is likely that an obd
@@ -724,12 +766,9 @@ int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
                  * <obd.h>, and that the corresponding line item
                  * LPROCFS_OBD_OP_INIT(.., .., opname)
                  * is missing from the list above. */
-                if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
-                        CERROR("Missing obd_stat initializer obd_op "
-                               "operation at offset %d. Aborting.\n",
-                               i - num_private_stats);
-                        LBUG();
-                }
+                LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
+                         "Missing obd_stat initializer obd_op "
+                         "operation at offset %d.\n", i - num_private_stats);
         }
         rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
         if (rc < 0) {
@@ -832,7 +871,13 @@ void lprocfs_free_md_stats(struct obd_device *obd)
 int lprocfs_write_helper(const char *buffer, unsigned long count,
                          int *val)
 {
-        char kernbuf[20], *end;
+        return lprocfs_write_frac_helper(buffer, count, val, 1);
+}
+
+int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
+                              int *val, int mult)
+{
+        char kernbuf[20], *end, *pbuf;
 
         if (count > (sizeof(kernbuf) - 1))
                 return -EINVAL;
@@ -841,33 +886,131 @@ int lprocfs_write_helper(const char *buffer, unsigned long count,
                 return -EFAULT;
 
         kernbuf[count] = '\0';
+        pbuf = kernbuf;
+        if (*pbuf == '-') {
+                mult = -mult;
+                pbuf++;
+        }
 
-        *val = simple_strtol(kernbuf, &end, 0);
-        if (kernbuf == end)
+        *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
+        if (pbuf == end)
                 return -EINVAL;
 
+        if (end != NULL && *end == '.') {
+                int temp_val, pow = 1;
+                int i;
+
+                pbuf = end + 1;
+                if (strlen(pbuf) > 5)
+                        pbuf[5] = '\0'; /*only allow 5bits fractional*/
+
+                temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
+
+                if (pbuf < end) {
+                        for (i = 0; i < (end - pbuf); i++)
+                                pow *= 10;
+
+                        *val += temp_val / pow;
+                }
+        }
         return 0;
 }
 
+int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val, int mult)
+{
+        long decimal_val,frac_val;
+        int prtn;
+
+        if (count < 10)
+                return -EINVAL;
+
+        decimal_val =val / mult;
+        prtn = snprintf(buffer, count, "%ld", decimal_val);
+        frac_val = val % mult;
+
+        if (prtn < (count - 4) && frac_val > 0) {
+                long temp_frac;
+                int i, temp_mult = 1, frac_bits = 0;
+
+                temp_frac = frac_val * 10;
+                buffer[prtn++] = '.';
+                while (frac_bits < 2 && (temp_frac / mult) < 1 ) { /*only reserved 2bits fraction*/
+                        buffer[prtn++] ='0';
+                        temp_frac *= 10;
+                        frac_bits++;
+                }
+                /*
+                  Need to think these cases :
+                        1. #echo x.00 > /proc/xxx       output result : x
+                        2. #echo x.0x > /proc/xxx       output result : x.0x
+                        3. #echo x.x0 > /proc/xxx       output result : x.x
+                        4. #echo x.xx > /proc/xxx       output result : x.xx
+                        Only reserved 2bits fraction.       
+                 */
+                for (i = 0; i < (5 - prtn); i++)
+                        temp_mult *= 10;
+
+                frac_bits = min((int)count - prtn, 3 - frac_bits);
+                prtn += snprintf(buffer + prtn, frac_bits, "%ld", frac_val * temp_mult / mult);
+
+                prtn--;
+                while(buffer[prtn] < '1' || buffer[prtn] > '9') {
+                        prtn--;
+                        if (buffer[prtn] == '.') {
+                                prtn--;
+                                break;
+                        }
+                }
+                prtn++;
+        }
+        buffer[prtn++] ='\n';
+        return prtn;
+}
+
 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
 {
-        char kernbuf[22], *end;
+        return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
+}
 
-        if (count > (sizeof(kernbuf) - 1))
+int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
+                              __u64 *val, int mult)
+{
+        char kernbuf[22], *end, *pbuf;
+
+        if (count > (sizeof(kernbuf) - 1) )
                 return -EINVAL;
 
         if (copy_from_user(kernbuf, buffer, count))
                 return -EFAULT;
 
         kernbuf[count] = '\0';
+        pbuf = kernbuf;
+        if (*pbuf == '-') {
+                mult = -mult;
+                pbuf++;
+        }
 
-        if (kernbuf[0] == '-')
-                *val = -simple_strtoull(kernbuf + 1, &end, 0);
-        else
-                *val = simple_strtoull(kernbuf, &end, 0);
-        if (kernbuf == end)
+        *val = simple_strtoull(pbuf, &end, 10) * mult;
+        if (pbuf == end)
                 return -EINVAL;
 
+        if (end != NULL && *end == '.') {
+                int temp_val;
+                int i, pow = 1;
+
+                pbuf = end + 1;
+                if (strlen(pbuf) > 10)
+                        pbuf[10] = '\0';
+
+                temp_val = (int)simple_strtoull(pbuf, &end, 10) * mult;
+
+                if (pbuf < end) {
+                        for (i = 0; i < (end - pbuf); i++)
+                                pow *= 10;
+
+                        *val += (__u64)(temp_val / pow);
+                }
+        }
         return 0;
 }
 
@@ -889,14 +1032,12 @@ EXPORT_SYMBOL(lprocfs_obd_seq_create);
 
 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
 {
-        unsigned long flags;
-
         if (value >= OBD_HIST_MAX)
                 value = OBD_HIST_MAX - 1;
 
-        spin_lock_irqsave(&oh->oh_lock, flags);
+        spin_lock(&oh->oh_lock);
         oh->oh_buckets[value]++;
-        spin_unlock_irqrestore(&oh->oh_lock, flags);
+        spin_unlock(&oh->oh_lock);
 }
 EXPORT_SYMBOL(lprocfs_oh_tally);
 
@@ -924,81 +1065,111 @@ EXPORT_SYMBOL(lprocfs_oh_sum);
 
 void lprocfs_oh_clear(struct obd_histogram *oh)
 {
-        unsigned long flags;
-        spin_lock_irqsave(&oh->oh_lock, flags);
+        spin_lock(&oh->oh_lock);
         memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
-        spin_unlock_irqrestore(&oh->oh_lock, flags);
+        spin_unlock(&oh->oh_lock);
 }
 EXPORT_SYMBOL(lprocfs_oh_clear);
 
 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
-                                          int count, int *eof, void *data)
+                                   int count, int *eof, void *data)
 {
         struct obd_device *obd = data;
-        int len = 0, n,
-                connected = obd->obd_connected_clients,
-                max_recoverable = obd->obd_max_recoverable_clients,
-                recoverable = obd->obd_recoverable_clients,
-                completed = max_recoverable - recoverable,
-                queue_len = obd->obd_requests_queued_for_recovery,
-                replayed = obd->obd_replayed_requests;
-        __u64 next_transno = obd->obd_next_recovery_transno;
+        int len = 0, size;
 
         LASSERT(obd != NULL);
-        *eof = 1;
+        LASSERT(count >= 0);
+
+        /* Set start of user data returned to
+           page + off since the user may have
+           requested to read much smaller than
+           what we need to read */
+        *start = page + off;
+
+        /* We know we are allocated a page here.
+           Also we know that this function will
+           not need to write more than a page
+           so we can truncate at PAGE_SIZE.  */
+        size = min(count + (int)off + 1, (int)PAGE_SIZE);
+
+        /* Initialize the page */
+        memset(page, 0, size);
+
+        if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
+                goto out;
 
-        n = snprintf(page, count, "status: ");
-        page += n; len += n; count -= n;
         if (obd->obd_max_recoverable_clients == 0) {
-                n = snprintf(page, count, "INACTIVE\n");
-                return len + n;
+                lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n");
+                goto fclose;
         }
 
         /* sampled unlocked, but really... */
         if (obd->obd_recovering == 0) {
-                n = snprintf(page, count, "COMPLETE\n");
-                page += n; len += n; count -= n;
-
-                n = snprintf(page, count, "recovery_start: %lu\n",
-                             obd->obd_recovery_start);
-                page += n; len += n; count -= n;
-                n = snprintf(page, count, "recovery_end: %lu\n",
-                             obd->obd_recovery_end);
-                page += n; len += n; count -= n;
-                n = snprintf(page, count, "recovered_clients: %d\n",
-                             completed);
-                page += n; len += n; count -= n;
-                n = snprintf(page, count, "unrecovered_clients: %d\n",
-                             obd->obd_recoverable_clients);
-                page += n; len += n; count -= n;
-                n = snprintf(page, count, "last_transno: "LPD64"\n",
-                             next_transno - 1);
-                page += n; len += n; count -= n;
-                n = snprintf(page, count, "replayed_requests: %d\n", replayed);
-                return len + n;
+                if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
+                        goto out;
+
+                if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
+                    obd->obd_recovery_start) <= 0)
+                        goto out;
+
+                if (lprocfs_obd_snprintf(&page, size, &len, "recovery_end: %lu\n",
+                    obd->obd_recovery_end) <= 0)
+                        goto out;
+
+                /* Number of clients have have completed recovery */
+                if (lprocfs_obd_snprintf(&page, size, &len, "recovered_clients: %d\n",
+                    obd->obd_max_recoverable_clients - obd->obd_recoverable_clients) <= 0)
+                        goto out;
+
+                if (lprocfs_obd_snprintf(&page, size, &len, "unrecovered_clients: %d\n",
+                    obd->obd_recoverable_clients) <= 0)
+                        goto out;
+
+                if (lprocfs_obd_snprintf(&page, size, &len, "last_transno: "LPD64"\n",
+                    obd->obd_next_recovery_transno - 1) <= 0)
+                        goto out;
+
+                lprocfs_obd_snprintf(&page, size, &len, "replayed_requests: %d\n", obd->obd_replayed_requests);
+                goto fclose;
         }
 
-        n = snprintf(page, count, "RECOVERING\n");
-        page += n; len += n; count -= n;
-        n = snprintf(page, count, "recovery_start: %lu\n",
-                     obd->obd_recovery_start);
-        page += n; len += n; count -= n;
-        n = snprintf(page, count, "time remaining: %lu\n",
-                     CURRENT_SECONDS >= obd->obd_recovery_end ? 0 : 
-                     obd->obd_recovery_end - CURRENT_SECONDS);
-        page += n; len += n; count -= n;
-        n = snprintf(page, count, "connected_clients: %d/%d\n",
-                     connected, max_recoverable);
-        page += n; len += n; count -= n;
-        n = snprintf(page, count, "completed_clients: %d/%d\n",
-                     completed, max_recoverable);
-        page += n; len += n; count -= n;
-        n = snprintf(page, count, "replayed_requests: %d/??\n", replayed);
-        page += n; len += n; count -= n;
-        n = snprintf(page, count, "queued_requests: %d\n", queue_len);
-        page += n; len += n; count -= n;
-        n = snprintf(page, count, "next_transno: "LPD64"\n", next_transno);
-        return len + n;
+        if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
+                goto out;
+
+        if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
+            obd->obd_recovery_start) <= 0)
+                goto out;
+
+        if (lprocfs_obd_snprintf(&page, size, &len, "time remaining: %lu\n",
+                                 CURRENT_SECONDS >= obd->obd_recovery_end ? 0 :
+                                 obd->obd_recovery_end - CURRENT_SECONDS) <= 0)
+                goto out;
+
+        if(lprocfs_obd_snprintf(&page, size, &len, "connected_clients: %d/%d\n",
+                                obd->obd_connected_clients,
+                                obd->obd_max_recoverable_clients) <= 0)
+                goto out;
+
+        /* Number of clients have have completed recovery */
+        if (lprocfs_obd_snprintf(&page, size, &len, "completed_clients: %d/%d\n",
+                                 obd->obd_max_recoverable_clients - obd->obd_recoverable_clients,
+                                 obd->obd_max_recoverable_clients) <= 0)
+                goto out;
+
+        if (lprocfs_obd_snprintf(&page, size, &len, "replayed_requests: %d/??\n",
+                                 obd->obd_replayed_requests) <= 0)
+                goto out;
+
+        if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
+                                 obd->obd_requests_queued_for_recovery) <= 0)
+                goto out;
+
+        lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n", obd->obd_next_recovery_transno);
+
+fclose:
+        *eof = 1;
+out:
+        return min(count, len - (int)off);
 }
 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
 
@@ -1032,5 +1203,8 @@ EXPORT_SYMBOL(lprocfs_rd_filestotal);
 EXPORT_SYMBOL(lprocfs_rd_filesfree);
 
 EXPORT_SYMBOL(lprocfs_write_helper);
+EXPORT_SYMBOL(lprocfs_write_frac_helper);
+EXPORT_SYMBOL(lprocfs_read_frac_helper);
 EXPORT_SYMBOL(lprocfs_write_u64_helper);
+EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
 #endif /* LPROCFS*/
index 862fe2b..e3340fb 100644 (file)
@@ -320,8 +320,8 @@ int lu_cdebug_printer(const struct lu_context *ctx,
         vsnprintf(key->lck_area + used,
                   ARRAY_SIZE(key->lck_area) - used, format, args);
         if (complete) {
-                libcfs_debug_msg(info->lpi_subsys, info->lpi_mask,
-                                 info->lpi_file, info->lpi_fn,
+                libcfs_debug_msg(NULL, info->lpi_subsys, info->lpi_mask,
+                                 (char *)info->lpi_file, info->lpi_fn,
                                  info->lpi_line, "%s", key->lck_area);
                 key->lck_area[0] = 0;
         }
index c1665cb..c3ea051 100644 (file)
 #include <lustre_log.h>
 #include <lprocfs_status.h>
 #include <libcfs/list.h>
+#include <lustre_param.h>
 
+/*********** string parsing utils *********/
+
+/* returns 0 if we find this key in the buffer, else 1 */
+int class_find_param(char *buf, char *key, char **valp)
+{
+        char *ptr;
+
+        if (!buf) 
+                return 1;
+
+        if ((ptr = strstr(buf, key)) == NULL) 
+                return 1;
+
+        if (valp) 
+                *valp = ptr + strlen(key);
+        
+        return 0;
+}
+
+/* returns 0 if this is the first key in the buffer, else 1.
+   valp points to first char after key. */
+int class_match_param(char *buf, char *key, char **valp)
+{
+        if (!buf) 
+                return 1;
+
+        if (memcmp(buf, key, strlen(key)) != 0) 
+                return 1;
+
+        if (valp) 
+                *valp = buf + strlen(key);
+        
+        return 0;
+}
+
+/* 0 is good nid, 
+   1 not found
+   < 0 error
+   endh is set to next separator */
+int class_parse_nid(char *buf, lnet_nid_t *nid, char **endh)
+{
+        char tmp, *endp;
+
+        if (!buf) 
+                return 1;
+        while (*buf == ',' || *buf == ':') 
+                buf++;
+        if (*buf == ' ' || *buf == '/' || *buf == '\0') 
+                return 1;
+
+        /* nid separators or end of nids */
+        endp = strpbrk(buf, ",: /");
+        if (endp == NULL) 
+                endp = buf + strlen(buf);
+
+        tmp = *endp;
+        *endp = '\0';
+        *nid = libcfs_str2nid(buf);
+        if (*nid == LNET_NID_ANY) {
+                LCONSOLE_ERROR("Can't parse NID '%s'\n", buf);
+                *endp = tmp;
+                return -EINVAL;
+        }
+        *endp = tmp;
+
+        if (endh) 
+                *endh = endp;
+        CDEBUG(D_INFO, "Nid %s\n", libcfs_nid2str(*nid));
+        return 0;
+}
+
+EXPORT_SYMBOL(class_find_param);
+EXPORT_SYMBOL(class_match_param);
+EXPORT_SYMBOL(class_parse_nid);
 
 /********************** class fns **********************/
 
  */
 int class_attach(struct lustre_cfg *lcfg)
 {
-        struct obd_type *type;
         struct obd_device *obd = NULL;
-        char *typename, *name, *namecopy, *uuid;
-        int rc, len, cleanup_phase = 0;
+        char *typename, *name, *uuid;
+        int rc, len;
         ENTRY;
 
         if (!LUSTRE_CFG_BUFLEN(lcfg, 1)) {
@@ -92,34 +166,31 @@ int class_attach(struct lustre_cfg *lcfg)
                 }
         }
 
-        /* find the type */
-        type = class_get_type(typename);
-        if (!type) {
-                CERROR("OBD: unknown type: %s\n", typename);
-                RETURN(-ENODEV);
-        }
-        cleanup_phase = 1;  /* class_put_type */
-
-        len = strlen(name) + 1;
-        OBD_ALLOC(namecopy, len);
-        if (!namecopy)
-                GOTO(out, rc = -ENOMEM);
-        memcpy(namecopy, name, len);
-        cleanup_phase = 2; /* free obd_name */
-
-        obd = class_newdev(type, namecopy);
-        if (obd == NULL) {
+        obd = class_newdev(typename, name);
+        if (IS_ERR(obd)) {
                 /* Already exists or out of obds */
-                CERROR("Can't create device %s\n", name);
-                GOTO(out, rc = -EEXIST);
+                rc = PTR_ERR(obd);
+                obd = NULL;
+                CERROR("Cannot create device %s of type %s : %d\n",
+                       name, typename, rc);
+                GOTO(out, rc);
         }
-        cleanup_phase = 3;  /* class_release_dev */
+        LASSERTF(obd != NULL, "Cannot get obd device %s of type %s\n",
+                 name, typename);
+        LASSERTF(obd->obd_magic == OBD_DEVICE_MAGIC, 
+                 "obd %p obd_magic %08X != %08X\n",
+                 obd, obd->obd_magic, OBD_DEVICE_MAGIC);
+        LASSERTF(strncmp(obd->obd_name, name, strlen(name)) == 0, "%p obd_name %s != %s\n",
+                 obd, obd->obd_name, name);
 
         CFS_INIT_LIST_HEAD(&obd->obd_exports);
         CFS_INIT_LIST_HEAD(&obd->obd_exports_timed);
         spin_lock_init(&obd->obd_dev_lock);
+        sema_init(&obd->obd_dev_sem, 1);
         spin_lock_init(&obd->obd_osfs_lock);
-        obd->obd_osfs_age = cfs_time_shift(-1000);
+        /* obd->obd_osfs_age must be set to a value in the distant
+         * past to guarantee a fresh statfs is fetched on mount. */
+        obd->obd_osfs_age = cfs_time_shift_64(-1000);
 
         /* XXX belongs in setup not attach  */
         /* recovery data */
@@ -148,21 +219,17 @@ int class_attach(struct lustre_cfg *lcfg)
         }
 
         /* Detach drops this */
+        spin_lock(&obd->obd_dev_lock);
         atomic_set(&obd->obd_refcount, 1);
+        spin_unlock(&obd->obd_dev_lock);
 
         obd->obd_attached = 1;
-        type->typ_refcnt++;
         CDEBUG(D_IOCTL, "OBD: dev %d attached type %s with refcount %d\n",
                obd->obd_minor, typename, atomic_read(&obd->obd_refcount));
         RETURN(0);
  out:
-        switch (cleanup_phase) {
-        case 3:
+        if (obd != NULL) {
                 class_release_dev(obd);
-        case 2:
-                OBD_FREE(namecopy, strlen(namecopy) + 1);
-        case 1:
-                class_put_type(type);
         }
         return rc;
 }
@@ -173,7 +240,11 @@ int class_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
         struct obd_export *exp;
         ENTRY;
 
-        LASSERT(obd == (obd_dev + obd->obd_minor));
+        LASSERT(obd != NULL);
+        LASSERTF(obd == class_num2obd(obd->obd_minor), "obd %p != obd_devs[%d] %p\n", 
+                 obd, obd->obd_minor, class_num2obd(obd->obd_minor));
+        LASSERTF(obd->obd_magic == OBD_DEVICE_MAGIC, "obd %p obd_magic %08x != %08x\n", 
+                 obd, obd->obd_magic, OBD_DEVICE_MAGIC);
 
         /* have we attached a type to this device? */
         if (!obd->obd_attached) {
@@ -211,7 +282,6 @@ int class_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
         if (err)
                 GOTO(err_exp, err);
 
-        obd->obd_type->typ_refcnt++;
         obd->obd_set_up = 1;
         spin_lock(&obd->obd_dev_lock);
         /* cleanup drops this */
@@ -231,32 +301,6 @@ err_exp:
         RETURN(err);
 }
 
-static int __class_detach(struct obd_device *obd)
-{
-        int err = 0;
-        ENTRY;
-
-        CDEBUG(D_CONFIG, "destroying obd %d (%s)\n",
-               obd->obd_minor, obd->obd_name);
-
-        if (OBP(obd, detach))
-                err = OBP(obd,detach)(obd);
-
-        if (obd->obd_name) {
-                OBD_FREE(obd->obd_name, strlen(obd->obd_name)+1);
-                obd->obd_name = NULL;
-        } else {
-                CERROR("device %d: no name at detach\n", obd->obd_minor);
-        }
-
-        LASSERT(OBT(obd));
-        /* Attach took type refcount */
-        obd->obd_type->typ_refcnt--;
-        class_put_type(obd->obd_type);
-        class_release_dev(obd);
-        RETURN(err);
-}
-
 int class_detach(struct obd_device *obd, struct lustre_cfg *lcfg)
 {
         ENTRY;
@@ -365,8 +409,11 @@ int class_cleanup(struct obd_device *obd, struct lustre_cfg *lcfg)
                         dump_exports(obd);
                         GOTO(out, err = -EBUSY);
                 }
+                /* refcounf - 3 might be the number of real exports 
+                   (excluding self export). But class_incref is called
+                   by other things as well, so don't count on it. */
                 CDEBUG(D_IOCTL, "%s: forcing exports to disconnect: %d\n",
-                       obd->obd_name, atomic_read(&obd->obd_refcount) - 1);
+                       obd->obd_name, atomic_read(&obd->obd_refcount) - 3);
                 dump_exports(obd);
                 class_disconnect_exports(obd);
         }
@@ -382,7 +429,6 @@ int class_cleanup(struct obd_device *obd, struct lustre_cfg *lcfg)
 
         class_decref(obd);
         obd->obd_set_up = 0;
-        obd->obd_type->typ_refcnt--;
 
         RETURN(0);
 out:
@@ -442,9 +488,12 @@ void class_decref(struct obd_device *obd)
                                 CERROR("Cleanup %s returned %d\n",
                                        obd->obd_name, err);
                 }
-                err = __class_detach(obd);
-                if (err)
-                        CERROR("Detach returned %d\n", err);
+                if (OBP(obd, detach)) {
+                        err = OBP(obd,detach)(obd);
+                        if (err)
+                                CERROR("Detach returned %d\n", err);
+                }
+                class_release_dev(obd);
         }
 }
 
@@ -529,8 +578,10 @@ int class_add_profile(int proflen, char *prof, int osclen, char *osc,
 {
         struct lustre_profile *lprof;
         int err = 0;
-
         ENTRY;
+
+        CDEBUG(D_CONFIG, "Add profile %s\n", prof);
+
         OBD_ALLOC(lprof, sizeof(*lprof));
         if (lprof == NULL)
                 RETURN(-ENOMEM);
@@ -543,27 +594,27 @@ int class_add_profile(int proflen, char *prof, int osclen, char *osc,
         memcpy(lprof->lp_profile, prof, proflen);
 
         LASSERT(osclen == (strlen(osc) + 1));
-        OBD_ALLOC(lprof->lp_osc, osclen);
-        if (lprof->lp_osc == NULL)
+        OBD_ALLOC(lprof->lp_dt, osclen);
+        if (lprof->lp_dt == NULL)
                 GOTO(out, err = -ENOMEM);
-        memcpy(lprof->lp_osc, osc, osclen);
+        memcpy(lprof->lp_dt, osc, osclen);
 
         if (mdclen > 0) {
                 LASSERT(mdclen == (strlen(mdc) + 1));
-                OBD_ALLOC(lprof->lp_mdc, mdclen);
-                if (lprof->lp_mdc == NULL)
+                OBD_ALLOC(lprof->lp_md, mdclen);
+                if (lprof->lp_md == NULL)
                         GOTO(out, err = -ENOMEM);
-                memcpy(lprof->lp_mdc, mdc, mdclen);
+                memcpy(lprof->lp_md, mdc, mdclen);
         }
 
         list_add(&lprof->lp_list, &lustre_profile_list);
         RETURN(err);
 
 out:
-        if (lprof->lp_mdc)
-                OBD_FREE(lprof->lp_mdc, mdclen);
-        if (lprof->lp_osc)
-                OBD_FREE(lprof->lp_osc, osclen);
+        if (lprof->lp_md)
+                OBD_FREE(lprof->lp_md, mdclen);
+        if (lprof->lp_dt)
+                OBD_FREE(lprof->lp_dt, osclen);
         if (lprof->lp_profile)
                 OBD_FREE(lprof->lp_profile, proflen);
         OBD_FREE(lprof, sizeof(*lprof));        
@@ -573,18 +624,49 @@ out:
 void class_del_profile(const char *prof)
 {
         struct lustre_profile *lprof;
+        ENTRY;
+
+        CDEBUG(D_CONFIG, "Del profile %s\n", prof);
 
         lprof = class_get_profile(prof);
         if (lprof) {
                 list_del(&lprof->lp_list);
                 OBD_FREE(lprof->lp_profile, strlen(lprof->lp_profile) + 1);
-                OBD_FREE(lprof->lp_osc, strlen(lprof->lp_osc) + 1);
-                if (lprof->lp_mdc)
-                        OBD_FREE(lprof->lp_mdc, strlen(lprof->lp_mdc) + 1);
+                OBD_FREE(lprof->lp_dt, strlen(lprof->lp_dt) + 1);
+                if (lprof->lp_md)
+                        OBD_FREE(lprof->lp_md, strlen(lprof->lp_md) + 1);
+                OBD_FREE(lprof, sizeof *lprof);
+        }
+        EXIT;
+}
+
+/* COMPAT_146 */
+void class_del_profiles(void)
+{
+        struct lustre_profile *lprof, *n;
+        ENTRY;
+
+        list_for_each_entry_safe(lprof, n, &lustre_profile_list, lp_list) {
+                list_del(&lprof->lp_list);
+                OBD_FREE(lprof->lp_profile, strlen(lprof->lp_profile) + 1);
+                OBD_FREE(lprof->lp_dt, strlen(lprof->lp_dt) + 1);
+                if (lprof->lp_md)
+                        OBD_FREE(lprof->lp_md, strlen(lprof->lp_md) + 1);
                 OBD_FREE(lprof, sizeof *lprof);
         }
+        EXIT;
 }
 
+/* We can't call ll_process_config directly because it lives in a module that
+   must be loaded after this one. */
+static int (*client_process_config)(struct lustre_cfg *lcfg) = NULL;
+
+void lustre_register_client_process_config(int (*cpc)(struct lustre_cfg *lcfg))
+{
+        client_process_config = cpc;
+}
+EXPORT_SYMBOL(lustre_register_client_process_config);
+
 int class_process_config(struct lustre_cfg *lcfg)
 {
         struct obd_device *obd;
@@ -640,8 +722,6 @@ int class_process_config(struct lustre_cfg *lcfg)
                 CDEBUG(D_IOCTL, "changing lustre timeout from %d to %d\n",
                        obd_timeout, lcfg->lcfg_num);
                 obd_timeout = max(lcfg->lcfg_num, 1U);
-                if (ldlm_timeout >= obd_timeout)
-                        ldlm_timeout = max(obd_timeout / 3, 1U);
                 GOTO(out, err = 0);
         }
         case LCFG_SET_UPCALL: {
@@ -660,6 +740,17 @@ int class_process_config(struct lustre_cfg *lcfg)
                        marker->cm_flags, marker->cm_svname, marker->cm_comment);
                 GOTO(out, err = 0);
         }
+        case LCFG_PARAM: {
+                /* llite has no obd */
+                if ((class_match_param(lustre_cfg_string(lcfg, 1), 
+                                      PARAM_LLITE, 0) == 0) &&
+                    client_process_config) {
+                        err = (*client_process_config)(lcfg);
+                        GOTO(out, err);
+                }
+                /* Fall through */
+                break;
+        }
         }
 
         /* Commands that require a device */
@@ -702,14 +793,78 @@ int class_process_config(struct lustre_cfg *lcfg)
         }
         }
 out:
-        if ((err == -ENOSYS || err == -EINVAL) &&
-            !(lcfg->lcfg_command & LCFG_REQUIRED)) {
-                CWARN("Skipping optional command %#x\n", lcfg->lcfg_command);
+        if ((err < 0) && !(lcfg->lcfg_command & LCFG_REQUIRED)) {
+                CWARN("Ignoring error %d on optional command %#x\n", err, 
+                      lcfg->lcfg_command);
                 err = 0;
         }
         return err;
 }
 
+int class_process_proc_param(char *prefix, struct lprocfs_vars *lvars, 
+                             struct lustre_cfg *lcfg, void *data)
+{
+        struct lprocfs_vars *var;
+        char *key, *sval;
+        int i, vallen;
+        int matched = 0, j = 0;
+        int rc = 0;
+        ENTRY;
+
+        if (lcfg->lcfg_command != LCFG_PARAM) {
+                CERROR("Unknown command: %d\n", lcfg->lcfg_command);
+                RETURN(-EINVAL);
+        }
+
+        /* e.g. tunefs.lustre --param mdt.group_upcall=foo /r/tmp/lustre-mdt
+           or   lctl conf_param lustre-MDT0000.mdt.group_upcall=bar
+           or   lctl conf_param lustre-OST0000.osc.max_dirty_mb=36 */
+        for (i = 1; i < lcfg->lcfg_bufcount; i++) {
+                key = lustre_cfg_buf(lcfg, i);
+                /* Strip off prefix */
+                class_match_param(key, prefix, &key);
+                sval = strchr(key, '=');
+                if (!sval || (*(sval + 1) == 0)) {
+                        CERROR("Can't parse param %s\n", key);
+                        rc = -EINVAL;
+                        /* continue parsing other params */
+                        continue;
+                }
+                sval++;
+                vallen = strlen(sval);
+                matched = 0;
+                j = 0;
+                /* Search proc entries */
+                while (lvars[j].name) {
+                        var = &lvars[j];
+                        if (class_match_param(key, (char *)var->name, 0) == 0) {
+                                matched++;
+                                rc = -EROFS;
+                                if (var->write_fptr) 
+                                        rc = (var->write_fptr)(NULL, sval,
+                                                               vallen, data);
+                                if (rc < 0) 
+                                        CERROR("writing proc entry %s err %d\n", 
+                                               var->name, rc);
+                                break;
+                        }
+                        j++;
+                }    
+                if (!matched) {
+                        CERROR("Unknown param %s\n", key);
+                        rc = -EINVAL;
+                        /* continue parsing other params */
+                } else {
+                        LCONSOLE_INFO("%s: set %s to %s\n", prefix,
+                                      key, sval);
+                }
+        }
+        
+        if (rc > 0) 
+                rc = 0;
+        RETURN(rc);
+}
+
 int class_config_dump_handler(struct llog_handle * handle,
                               struct llog_rec_hdr *rec, void *data);
 
@@ -749,8 +904,8 @@ static int class_config_llog_handler(struct llog_handle * handle,
                 /* Figure out config state info */
                 if (lcfg->lcfg_command == LCFG_MARKER) {
                         struct cfg_marker *marker = lustre_cfg_buf(lcfg, 1);
-                        CDEBUG(D_CONFIG, "Marker, cfg_flg=%#x\n",
-                               clli->cfg_flags);
+                        CDEBUG(D_CONFIG, "Marker, inst_flg=%#x mark_flg=%#x\n",
+                               clli->cfg_flags, marker->cm_flags);
                         if (marker->cm_flags & CM_START) {
                                 /* all previous flags off */
                                 clli->cfg_flags = CFG_F_MARKER;
@@ -768,17 +923,17 @@ static int class_config_llog_handler(struct llog_handle * handle,
                                 clli->cfg_flags = 0;
                         }
                 }
-                /* A config command without a start marker before it is
-                   illegal (1.4.6. compat must set it artificially) */
-                if (!(clli->cfg_flags & CFG_F_MARKER) && 
+                /* A config command without a start marker before it is 
+                   illegal (post 146) */
+                if (!(clli->cfg_flags & CFG_F_COMPAT146) &&
+                    !(clli->cfg_flags & CFG_F_MARKER) && 
                     (lcfg->lcfg_command != LCFG_MARKER)) {
                         CWARN("Config not inside markers, ignoring! (%#x)\n", 
                               clli->cfg_flags);
                         clli->cfg_flags |= CFG_F_SKIP;
                 }
                 if (clli->cfg_flags & CFG_F_SKIP) {
-                        // FIXME warning
-                        CDEBUG(D_CONFIG|D_WARNING, "skipping %#x\n",
+                        CDEBUG(D_CONFIG, "skipping %#x\n",
                                clli->cfg_flags);
                         rc = 0;
                         /* No processing! */
@@ -792,7 +947,8 @@ static int class_config_llog_handler(struct llog_handle * handle,
 
                 lustre_cfg_bufs_init(&bufs, lcfg);
 
-                if (clli && clli->cfg_instance && LUSTRE_CFG_BUFLEN(lcfg, 0) > 0){
+                if (clli && clli->cfg_instance && 
+                    LUSTRE_CFG_BUFLEN(lcfg, 0) > 0){
                         inst = 1;
                         inst_len = LUSTRE_CFG_BUFLEN(lcfg, 0) +
                                 strlen(clli->cfg_instance) + 1;
@@ -881,8 +1037,7 @@ int class_config_parse_llog(struct llog_ctxt *ctxt, char *name,
 
         rc = llog_process(llh, class_config_llog_handler, cfg, &cd);
 
-        /* FIXME remove warning */
-        CDEBUG(D_CONFIG|D_WARNING, "Processed log %s gen %d-%d (rc=%d)\n", name, 
+        CDEBUG(D_CONFIG, "Processed log %s gen %d-%d (rc=%d)\n", name, 
                cd.first_idx + 1, cd.last_idx, rc);
         if (cfg)
                 cfg->cfg_last_idx = cd.last_idx;
index 50777cd..7d41ed3 100644 (file)
@@ -25,7 +25,7 @@
 
 
 #define DEBUG_SUBSYSTEM S_MGMT
-#define D_MOUNT D_SUPER|D_CONFIG /*|D_WARNING */
+#define D_MOUNT D_SUPER|D_CONFIG /*|D_WARNING */ 
 #define PRINT_CMD LCONSOLE
 #define PRINT_MASK D_SUPER
 
 
 static int (*client_fill_super)(struct super_block *sb) = NULL;
 
-/*********** string parsing utils *********/
-
-/* returns 0 if we find this key in the buffer, else 1 */
-int class_find_param(char *buf, char *key, char **valp)
-{
-        char *ptr;
-
-        if (!buf)
-                return 1;
-
-        if ((ptr = strstr(buf, key)) == NULL)
-                return 1;
-
-        if (valp)
-                *valp = ptr + strlen(key);
-
-        return 0;
-}
-
-/* returns 0 if this is the first key in the buffer, else 1 */
-int class_match_param(char *buf, char *key, char **valp)
-{
-        if (!buf)
-                return 1;
-
-        if (memcmp(buf, key, strlen(key)) != 0)
-                return 1;
-
-        if (valp)
-                *valp = buf + strlen(key);
-
-        return 0;
-}
-
-/* 0 is good nid,
-   1 not found
-   < 0 error
-   endh is set to next separator */
-int class_parse_nid(char *buf, lnet_nid_t *nid, char **endh)
-{
-        char tmp, *endp;
-
-        if (!buf)
-                return 1;
-        while (*buf == ',' || *buf == ':')
-                buf++;
-        if (*buf == ' ' || *buf == '/' || *buf == '\0')
-                return 1;
-
-        /* nid separators or end of nids */
-        endp = strpbrk(buf, ",: /");
-        if (endp == NULL)
-                endp = buf + strlen(buf);
-
-        tmp = *endp;
-        *endp = '\0';
-        *nid = libcfs_str2nid(buf);
-        if (*nid == LNET_NID_ANY) {
-                LCONSOLE_ERROR("Can't parse NID '%s'\n", buf);
-                *endp = tmp;
-                return -EINVAL;
-        }
-        *endp = tmp;
-
-        if (endh)
-                *endh = endp;
-        CDEBUG(D_MOUNT, "Nid %s\n", libcfs_nid2str(*nid));
-        return 0;
-}
-
 /*********** mount lookup *********/
 
 DECLARE_MUTEX(lustre_mount_info_lock);
@@ -201,38 +131,7 @@ static int server_deregister_mount(const char *name)
         RETURN(0);
 }
 
-/* Deregister anyone referencing the mnt. Everyone should have
-   put_mount in *_cleanup, but this is a catch-all in case of err... */
-/* FIXME this should be removed from lustre_free_lsi, which may be called
-   from server_put_mount _before_ it gets to server_deregister_mount.
-   Leave it here for now for the error message it shows... */
-static void server_deregister_mount_all(struct vfsmount *mnt)
-{
-        struct list_head *tmp, *n;
-        struct lustre_mount_info *lmi;
-        ENTRY;
-
-        if (!mnt) {
-                EXIT;
-                return;
-        }
-
-        //down(&lustre_mount_info_lock);
-        list_for_each_safe(tmp, n, &server_mount_info_list) {
-                lmi = list_entry(tmp, struct lustre_mount_info, lmi_list_chain);
-                if (lmi->lmi_mnt == mnt) {
-                        CERROR("Mount %p still referenced by %s\n", mnt,
-                               lmi->lmi_name);
-                        //OBD_FREE(lmi->lmi_name, strlen(lmi->lmi_name) + 1);
-                        //list_del(&lmi->lmi_list_chain);
-                        //OBD_FREE(lmi, sizeof(*lmi));
-                }
-        }
-        //up(&lustre_mount_info_lock);
-        EXIT;
-}
-
-/* obd's look up a registered mount using their name. This is just
+/* obd's look up a registered mount using their obdname. This is just
    for initial obd setup to find the mount struct.  It should not be
    called every time you want to mntget. */
 struct lustre_mount_info *server_get_mount(const char *name)
@@ -461,7 +360,14 @@ int lustre_process_log(struct super_block *sb, char *logname,
         rc = obd_process_config(mgc, sizeof(*lcfg), lcfg);
         lustre_cfg_free(lcfg);
 
-        if (rc)
+        if (rc == -EINVAL) 
+                LCONSOLE_ERROR("%s: The configuration '%s' could not be read "
+                               "from the MGS (%d).  Make sure this client and "
+                               "the MGS are running compatible versions of "
+                               "Lustre.\n",
+                               mgc->obd_name, logname, rc);
+
+        if (rc) 
                 LCONSOLE_ERROR("%s: The configuration '%s' could not be read "
                                "from the MGS (%d).  This may be the result of "
                                "communication errors between this node and "
@@ -499,8 +405,8 @@ int lustre_end_log(struct super_block *sb, char *logname,
 
 /**************** obd start *******************/
 
-static int do_lcfg(char *cfgname, lnet_nid_t nid, int cmd,
-                   char *s1, char *s2, char *s3, char *s4)
+int do_lcfg(char *cfgname, lnet_nid_t nid, int cmd,
+            char *s1, char *s2, char *s3, char *s4)
 {
         struct lustre_cfg_bufs bufs;
         struct lustre_cfg    * lcfg = NULL;
@@ -613,27 +519,57 @@ static int lustre_start_mgc(struct super_block *sb)
         struct obd_uuid *uuid;
         class_uuid_t uuidc;
         lnet_nid_t nid;
-        char niduuid[10];
+        char *mgcname, *niduuid;
         char *ptr;
         int recov_bk = 0;
-        int rc = 0, i = 0, j;
+        int rc = 0, i = 0, j, len;
         ENTRY;
 
         LASSERT(lsi->lsi_lmd);
+        
+        /* Find the first non-lo MGS nid for our MGC name */
+        if (lsi->lsi_flags & LSI_SERVER) {
+                ptr = lsi->lsi_ldd->ldd_params;
+                /* Use mgsnode= nids */
+                if ((class_find_param(ptr, PARAM_MGSNODE, &ptr) == 0) &&
+                    (class_parse_nid(ptr, &nid, &ptr) == 0)) {
+                        i++;
+                } else if (IS_MGS(lsi->lsi_ldd)) {
+                        lnet_process_id_t id;
+                        while ((rc = LNetGetId(i++, &id)) != -ENOENT) {
+                                if (LNET_NETTYP(LNET_NIDNET(id.nid)) == LOLND) 
+                                        continue;
+                                nid = id.nid;
+                                i++;
+                                break;
+                        }
+                }
+        } else { /* client */
+                /* Use nids from mount line: uml1,1@elan:uml2,2@elan:/lustre */
+                ptr = lsi->lsi_lmd->lmd_dev;
+                if (class_parse_nid(ptr, &nid, &ptr) == 0) 
+                        i++;
+        }
+        if (i == 0) {
+                CERROR("No valid MGS nids found.\n");
+                RETURN(-EINVAL);
+        }
+
+        len = strlen(LUSTRE_MGC_OBDNAME) + strlen(libcfs_nid2str(nid)) + 1;
+        OBD_ALLOC(mgcname, len);
+        OBD_ALLOC(niduuid, len + 2);
+        if (!mgcname || !niduuid) 
+                GOTO(out_free, rc = -ENOMEM);
+        sprintf(mgcname, "%s%s", LUSTRE_MGC_OBDNAME, libcfs_nid2str(nid));
 
-        obd = class_name2obd(LUSTRE_MGC_OBDNAME);
+        obd = class_name2obd(mgcname);
         if (obd) {
+                /* Re-using an existing MGC */
                 atomic_inc(&obd->u.cli.cl_mgc_refcount);
-                /* FIXME There's only one MGC, but users could give different
-                   MGS nids on the mount line.  So now do we add new MGS uuids
-                   or not?  If there's truly one MGS per site, the MGS uuids
-                   _should_ all be the same. Maybe check here?
-                */
-
                 /* If we are restarting the MGS, don't try to keep the MGC's
                    old connection, or registration will fail. */
                 if ((lsi->lsi_flags & LSI_SERVER) && IS_MGS(lsi->lsi_ldd)) {
-                        CDEBUG(D_MOUNT|D_ERROR, "New MGS with live MGC\n");
+                        CDEBUG(D_MOUNT, "New MGS with live MGC\n");
                         recov_bk = 1;
                 }
 
@@ -642,7 +578,7 @@ static int lustre_start_mgc(struct super_block *sb)
                    (using its local copy of the log), but we do want to connect
                    if at all possible. */
                 recov_bk++;
-                CDEBUG(D_MOUNT, "Set MGS reconnect %d\n", recov_bk);
+                CDEBUG(D_MOUNT, "%s: Set MGC reconnect %d\n", mgcname,recov_bk);
                 rc = obd_set_info_async(obd->obd_self_export,
                                         strlen(KEY_INIT_RECOV_BACKUP),
                                         KEY_INIT_RECOV_BACKUP,
@@ -650,44 +586,47 @@ static int lustre_start_mgc(struct super_block *sb)
                 GOTO(out, rc = 0);
         }
 
-        CDEBUG(D_MOUNT, "Start MGC '%s'\n", LUSTRE_MGC_OBDNAME);
+        CDEBUG(D_MOUNT, "Start MGC '%s'\n", mgcname);
 
         /* Add the primary nids for the MGS */
+        i = 0;
+        sprintf(niduuid, "%s%x", mgcname, i);
         if (lsi->lsi_flags & LSI_SERVER) {
                 ptr = lsi->lsi_ldd->ldd_params;
                 if (IS_MGS(lsi->lsi_ldd)) {
                         /* Use local nids (including LO) */
                         lnet_process_id_t id;
                         while ((rc = LNetGetId(i++, &id)) != -ENOENT) {
-                                rc = do_lcfg(LUSTRE_MGC_OBDNAME, id.nid,
-                                             LCFG_ADD_UUID, "mgsnid0", 0,0,0);
+                                rc = do_lcfg(mgcname, id.nid,
+                                             LCFG_ADD_UUID, niduuid, 0,0,0);
                         }
                 } else {
                         /* Use mgsnode= nids */
                         if (class_find_param(ptr, PARAM_MGSNODE, &ptr) != 0) {
                                 CERROR("No MGS nids given.\n");
-                                RETURN(-EINVAL);
+                                GOTO(out_free, rc = -EINVAL);
                         }
                         while (class_parse_nid(ptr, &nid, &ptr) == 0) {
-                                rc = do_lcfg(LUSTRE_MGC_OBDNAME, nid,
-                                             LCFG_ADD_UUID, "mgsnid0", 0,0,0);
+                                rc = do_lcfg(mgcname, nid,
+                                             LCFG_ADD_UUID, niduuid, 0,0,0);
                                 i++;
                         }
                 }
         } else { /* client */
-                /* use nids from mount line: uml1,1@elan:uml2,2@elan:/lustre */
+                /* Use nids from mount line: uml1,1@elan:uml2,2@elan:/lustre */
                 ptr = lsi->lsi_lmd->lmd_dev;
                 while (class_parse_nid(ptr, &nid, &ptr) == 0) {
-                        rc = do_lcfg(LUSTRE_MGC_OBDNAME, nid,
-                                     LCFG_ADD_UUID, "mgsnid0", 0,0,0);
+                        rc = do_lcfg(mgcname, nid,
+                                     LCFG_ADD_UUID, niduuid, 0,0,0);
                         i++;
-                        if (*ptr == ':')
+                        /* Stop at the first failover nid */
+                        if (*ptr == ':') 
                                 break;
                 }
         }
         if (i == 0) {
                 CERROR("No valid MGS nids found.\n");
-                RETURN(-EINVAL);
+                GOTO(out_free, rc = -EINVAL);
         }
         lsi->lsi_lmd->lmd_mgs_failnodes = 1;
 
@@ -697,29 +636,29 @@ static int lustre_start_mgc(struct super_block *sb)
         class_uuid_unparse(uuidc, uuid);
 
         /* Start the MGC */
-        rc = lustre_start_simple(LUSTRE_MGC_OBDNAME, LUSTRE_MGC_NAME,
+        rc = lustre_start_simple(mgcname, LUSTRE_MGC_NAME, 
                                  (char *)uuid->uuid, LUSTRE_MGS_OBDNAME,
-                                 "mgsnid0");
+                                 niduuid);
         OBD_FREE_PTR(uuid);
-        if (rc)
-                RETURN(rc);
-
+        if (rc) 
+                GOTO(out_free, rc);
+        
         /* Add any failover MGS nids */
         i = 1;
         while ((*ptr == ':' ||
                 class_find_param(ptr, PARAM_MGSNODE, &ptr) == 0)) {
                 /* New failover node */
-                sprintf(niduuid, "mgsnid%d", i);
+                sprintf(niduuid, "%s%x", mgcname, i);
                 j = 0;
                 while (class_parse_nid(ptr, &nid, &ptr) == 0) {
                         j++;
-                        rc = do_lcfg(LUSTRE_MGC_OBDNAME, nid,
+                        rc = do_lcfg(mgcname, nid,
                                      LCFG_ADD_UUID, niduuid, 0,0,0);
                         if (*ptr == ':')
                                 break;
                 }
                 if (j > 0) {
-                        rc = do_lcfg(LUSTRE_MGC_OBDNAME, 0, LCFG_ADD_CONN,
+                        rc = do_lcfg(mgcname, 0, LCFG_ADD_CONN,
                                      niduuid, 0, 0, 0);
                         i++;
                 } else {
@@ -728,11 +667,11 @@ static int lustre_start_mgc(struct super_block *sb)
                 }
         }
         lsi->lsi_lmd->lmd_mgs_failnodes = i;
-
-        obd = class_name2obd(LUSTRE_MGC_OBDNAME);
+        
+        obd = class_name2obd(mgcname);
         if (!obd) {
-                CERROR("Can't find mgcobd %s\n", LUSTRE_MGC_OBDNAME);
-                RETURN(-ENOTCONN);
+                CERROR("Can't find mgcobd %s\n", mgcname);
+                GOTO(out_free, rc = -ENOTCONN);
         }
 
         /* Try all connections, but only once. */
@@ -744,10 +683,6 @@ static int lustre_start_mgc(struct super_block *sb)
         if (rc)
                 /* nonfatal */
                 CERROR("can't set %s %d\n", KEY_INIT_RECOV_BACKUP, rc);
-
-        /* FIXME add ACL support? */
-        //ocd.ocd_connect_flags = OBD_CONNECT_ACL;
-
         /* We connect to the MGS at setup, and don't disconnect until cleanup */
         rc = obd_connect(NULL, &mgc_conn, obd, &(obd->obd_uuid), &ocd);
         if (rc) {
@@ -766,6 +701,11 @@ out:
         /* Keep the mgc info in the sb. Note that many lsi's can point
            to the same mgc.*/
         lsi->lsi_mgc = obd;
+out_free:
+        if (mgcname) 
+                OBD_FREE(mgcname, len);
+        if (niduuid) 
+                OBD_FREE(niduuid, len + 2);
         RETURN(rc);
 }
 
@@ -773,8 +713,8 @@ static int lustre_stop_mgc(struct super_block *sb)
 {
         struct lustre_sb_info *lsi = s2lsi(sb);
         struct obd_device *obd;
-        char niduuid[10];
-        int i, rc;
+        char *niduuid, *ptr = 0;
+        int i, rc, len;
         ENTRY;
 
         if (!lsi)
@@ -802,20 +742,33 @@ static int lustre_stop_mgc(struct super_block *sb)
         if (obd->u.cli.cl_mgc_mgsexp)
                 obd_disconnect(obd->u.cli.cl_mgc_mgsexp);
 
+        /* Save the obdname for cleaning the nid uuids, which are 
+           obdnameXX */
+        len = strlen(obd->obd_name) + 5;
+        OBD_ALLOC(niduuid, len);
+        if (niduuid) {
+                strcpy(niduuid, obd->obd_name);
+                ptr = niduuid + strlen(niduuid);
+        }
+
         rc = class_manual_cleanup(obd);
-        if (rc)
+        if (rc) 
                 RETURN(rc);
 
+        /* Clean the nid uuids */
+        if (!niduuid) 
+                RETURN(-ENOMEM);
         for (i = 0; i < lsi->lsi_lmd->lmd_mgs_failnodes; i++) {
-                sprintf(niduuid, "mgsnid%d", i);
-                rc = do_lcfg(obd->obd_name, 0, LCFG_DEL_UUID,
+                sprintf(ptr, "%x", i);
+                rc = do_lcfg(LUSTRE_MGC_OBDNAME, 0, LCFG_DEL_UUID, 
                              niduuid, 0, 0, 0);
                 if (rc)
                         CERROR("del MDC UUID %s failed: rc = %d\n",
                                niduuid, rc);
         }
+        OBD_FREE(niduuid, len);
         /* class_import_put will get rid of the additional connections */
-
+        
         RETURN(0);
 }
 
@@ -864,12 +817,14 @@ static int server_stop_servers(int lddflags, int lsiflags)
         /* Either an MDT or an OST or neither  */
 
         /* if this was an MDT, and there are no more MDT's, clean up the MDS */
-        if ((lddflags & LDD_F_SV_TYPE_MDT) && (obd = class_name2obd("MDS"))) {
-                //FIXME pre-rename, should eventually be LUSTRE_MDT_NAME
+        if ((lddflags & LDD_F_SV_TYPE_MDT) && 
+            (obd = class_name2obd(LUSTRE_MDS_OBDNAME))) {
+                /*FIXME pre-rename, should eventually be LUSTRE_MDT_NAME*/
                 type = class_search_type(LUSTRE_MDS_NAME);
         }
         /* if this was an OST, and there are no more OST's, clean up the OSS */
-        if ((lddflags & LDD_F_SV_TYPE_OST) && (obd = class_name2obd("OSS"))) {
+        if ((lddflags & LDD_F_SV_TYPE_OST) &&
+            (obd = class_name2obd(LUSTRE_OSS_OBDNAME))) {
                 type = class_search_type(LUSTRE_OST_NAME);
         }
 
@@ -925,6 +880,7 @@ static int server_sb2mti(struct super_block *sb, struct mgs_target_info *mti)
                 }
         }
 
+        mti->mti_lustre_ver = LUSTRE_VERSION_CODE;
         mti->mti_config_ver = 0;
         mti->mti_flags = ldd->ldd_flags;
         mti->mti_stripe_index = ldd->ldd_svindex;
@@ -967,7 +923,7 @@ int server_register_target(struct super_block *sb)
                mti->mti_flags);
 
         /* Register the target */
-        /* FIXME use mdc_process_config instead */
+        /* FIXME use mgc_process_config instead */
         rc = obd_set_info_async(mgc->u.cli.cl_mgc_mgsexp,
                                 strlen("register_target"), "register_target",
                                 sizeof(*mti), mti, NULL);
@@ -999,6 +955,9 @@ int server_register_target(struct super_block *sb)
                 label = fsfilt_get_label(mgc, lsi->lsi_srv_mnt->mnt_sb);
                 if (label)
                         CDEBUG(D_MOUNT, "Disk label changed to %s\n", label);
+                
+                /* Flush the new ldd to disk */
+                fsfilt_sync(mgc, lsi->lsi_srv_mnt->mnt_sb);
         }
 
 out:
@@ -1018,17 +977,37 @@ static int server_start_targets(struct super_block *sb, struct vfsmount *mnt)
 
         CDEBUG(D_MOUNT, "starting target %s\n", lsi->lsi_ldd->ldd_svname);
 
+#if 0
+        /* If we're an MDT, make sure the global MDS is running */
+        if (lsi->lsi_ldd->ldd_flags & LDD_F_SV_TYPE_MDT) {
+                /* make sure the MDS is started */
+                obd = class_name2obd(LUSTRE_MDS_OBDNAME);
+                if (!obd) {
+                        rc = lustre_start_simple(LUSTRE_MDS_OBDNAME, 
+                    /* FIXME pre-rename, should eventually be LUSTRE_MDS_NAME */
+                                                 LUSTRE_MDT_NAME, 
+                                                 LUSTRE_MDS_OBDNAME"_uuid",
+                                                 0, 0);
+                        if (rc) {
+                                CERROR("failed to start MDS: %d\n", rc);
+                                RETURN(rc);
+                        }
+                }
+        }
+#endif
         /* If we're an MDT, make sure the global MDS is running */
         if (lsi->lsi_ldd->ldd_flags & LDD_F_SV_TYPE_MDT) {
                 /* make sure (what will be called) the MDS is started */
-                obd = class_name2obd("MDS");
+                obd = class_name2obd(LUSTRE_MDS_OBDNAME);
                 if (!obd) {
-                        //FIXME pre-rename, should eventually be LUSTRE_MDS_NAME
-                        rc = lustre_start_simple("MDS", LUSTRE_MDS_NAME,
-                                                 "MDS_uuid", 0, 0);
+                        // FIXME pre-rename, should eventually be LUSTRE_MDS_NAME
+                        rc = lustre_start_simple(LUSTRE_MDS_OBDNAME, 
+                                                 LUSTRE_MDS_NAME,
+                                                 LUSTRE_MDS_OBDNAME"_uuid", 
+                                                 0, 0);
                         if (rc) {
                                 CERROR("failed to start MDS: %d\n", rc);
-                                GOTO(out_servers, rc);
+                                RETURN(rc);
                         }
                 }
         }
@@ -1036,20 +1015,24 @@ static int server_start_targets(struct super_block *sb, struct vfsmount *mnt)
         /* If we're an OST, make sure the global OSS is running */
         if (lsi->lsi_ldd->ldd_flags & LDD_F_SV_TYPE_OST) {
                 /* make sure OSS is started */
-                obd = class_name2obd("OSS");
+                obd = class_name2obd(LUSTRE_OSS_OBDNAME);
                 if (!obd) {
-                        rc = lustre_start_simple("OSS", LUSTRE_OSS_NAME,
-                                                 "OSS_uuid", 0, 0);
+                        rc = lustre_start_simple(LUSTRE_OSS_OBDNAME, 
+                                                 LUSTRE_OSS_NAME,
+                                                 LUSTRE_OSS_OBDNAME"_uuid", 
+                                                 0, 0);
                         if (rc) {
                                 CERROR("failed to start OSS: %d\n", rc);
-                                GOTO(out_servers, rc);
+                                RETURN(rc);
                         }
                 }
         }
 
         /* Set the mgc fs to our server disk.  This allows the MGC
            to read and write configs locally. */
-        server_mgc_set_fs(lsi->lsi_mgc, sb);
+        rc = server_mgc_set_fs(lsi->lsi_mgc, sb);
+        if (rc)
+                RETURN(rc);
 
         /* Register with MGS */
         rc = server_register_target(sb);
@@ -1061,14 +1044,20 @@ static int server_start_targets(struct super_block *sb, struct vfsmount *mnt)
                         LCONSOLE_ERROR("Communication error with the MGS.  Is "
                                        "the MGS running?\n");
                 }
-                GOTO(out, rc);
+                GOTO(out_mgc, rc);
+        }
+        if (rc == -EINVAL) {
+                LCONSOLE_ERROR("The MGS is refusing to allow this server (%s) "
+                               "to start.  Please see messages on the MGS node."
+                               "\n", lsi->lsi_ldd->ldd_svname);
+                GOTO(out_mgc, rc);
         }
 
         /* Let the target look up the mount using the target's name
            (we can't pass the sb or mnt through class_process_config.) */
         rc = server_register_mount(lsi->lsi_ldd->ldd_svname, sb, mnt);
-        if (rc)
-                GOTO(out, rc);
+        if (rc) 
+                GOTO(out_mgc, rc);
 
         /* Start targets using the llog named for the target */
         memset(&cfg, 0, sizeof(cfg));
@@ -1076,20 +1065,28 @@ static int server_start_targets(struct super_block *sb, struct vfsmount *mnt)
         if (rc) {
                 CERROR("failed to start server %s: %d\n",
                        lsi->lsi_ldd->ldd_svname, rc);
-                GOTO(out, rc);
+                GOTO(out_mgc, rc);
         }
 
-        if (!class_name2obd(lsi->lsi_ldd->ldd_svname)) {
-                CERROR("no server named %s was started\n",
-                       lsi->lsi_ldd->ldd_svname);
-                rc = -ENXIO;
-        }
-
-out:
+out_mgc:
         /* Release the mgc fs for others to use */
         server_mgc_clear_fs(lsi->lsi_mgc);
 
-out_servers:
+        if (!rc) {
+                obd = class_name2obd(lsi->lsi_ldd->ldd_svname);
+                if (!obd) {
+                        CERROR("no server named %s was started\n",
+                               lsi->lsi_ldd->ldd_svname);
+                        RETURN(-ENXIO);
+                }
+
+                if ((lsi->lsi_lmd->lmd_flags & LMD_FLG_ABORT_RECOV) &&
+                    (OBP(obd, iocontrol))) {
+                        obd_iocontrol(OBD_IOC_ABORT_RECOVERY, 
+                                      obd->obd_self_export, 0, NULL, NULL);
+                }
+        }
+        
         RETURN(rc);
 }
 
@@ -1153,15 +1150,14 @@ static int lustre_free_lsi(struct super_block *sb)
         }
 
         LASSERT(lsi->lsi_llsbi == NULL);
-
-        server_deregister_mount_all(lsi->lsi_srv_mnt);
-
         OBD_FREE(lsi, sizeof(*lsi));
         s2lsi_nocast(sb) = NULL;
 
         RETURN(0);
 }
-
+           
+/* The lsi has one reference for every server that is using the disk - 
+   e.g. MDT, MGS, and potentially MGC */
 static int lustre_put_lsi(struct super_block *sb)
 {
         struct lustre_sb_info *lsi = s2lsi(sb);
@@ -1201,17 +1197,17 @@ static struct vfsmount *server_kernel_mount(struct super_block *sb)
            Note ext3/ldiskfs can't be mounted ro. */
         s_flags = sb->s_flags;
 
-        /* Pre-mount ext3 to read the MOUNT_DATA_FILE */
-        CDEBUG(D_MOUNT, "Pre-mount ext3 %s\n", lmd->lmd_dev);
-        mnt = do_kern_mount("ext3", s_flags, lmd->lmd_dev, 0);
+        /* Pre-mount ldiskfs to read the MOUNT_DATA_FILE */
+        CDEBUG(D_MOUNT, "Pre-mount ldiskfs %s\n", lmd->lmd_dev);
+        mnt = do_kern_mount("ldiskfs", s_flags, lmd->lmd_dev, 0);
         if (IS_ERR(mnt)) {
                 rc = PTR_ERR(mnt);
-                CERROR("premount ext3 failed (%d), trying ldiskfs\n", rc);
-                /* If ext3 fails (bec. of mballoc, extents), try ldiskfs */
-                mnt = do_kern_mount("ldiskfs", s_flags, lmd->lmd_dev, 0);
+                CERROR("premount ldiskfs failed (%d), trying ext3\n", rc);
+                /* If ldisk fails, try ext3 */
+                mnt = do_kern_mount("ext3", s_flags, lmd->lmd_dev, 0);
                 if (IS_ERR(mnt)) {
                         rc = PTR_ERR(mnt);
-                        CERROR("premount ldiskfs failed: rc = %d\n", rc);
+                        CERROR("premount ext3 failed: rc = %d\n", rc);
                         GOTO(out_free, rc);
                 }
         }
@@ -1277,20 +1273,23 @@ static void server_wait_finished(struct vfsmount *mnt)
 {
         wait_queue_head_t   waitq;
         struct l_wait_info  lwi;
-        int                 retries = 10;
-
+        int                 retries = 120;
+        
         init_waitqueue_head(&waitq);
 
-        while ((atomic_read(&mnt->mnt_count) > 0) && retries--) {
-                CWARN("Mount still busy with %d refs\n",
-                       atomic_read(&mnt->mnt_count));
+        while ((atomic_read(&mnt->mnt_count) > 1) && (retries > 0)) {
+                LCONSOLE_WARN("Mount still busy with %d refs, waiting for "
+                              "%d secs...\n",
+                              atomic_read(&mnt->mnt_count), retries);
 
                 /* Wait for a bit */
-                lwi = LWI_TIMEOUT(2 * HZ, NULL, NULL);
+                retries -= 5;
+                lwi = LWI_TIMEOUT(5 * HZ, NULL, NULL);
                 l_wait_event(waitq, 0, &lwi);
         }
-        if (atomic_read(&mnt->mnt_count)) {
-                CERROR("Mount is still busy, giving up.\n");
+        if (atomic_read(&mnt->mnt_count) > 1) {
+                CERROR("Mount %p is still busy (%d refs), giving up.\n",
+                       mnt, atomic_read(&mnt->mnt_count));
         }
 }
 
@@ -1299,6 +1298,7 @@ static void server_put_super(struct super_block *sb)
         struct lustre_sb_info *lsi = s2lsi(sb);
         struct obd_device     *obd;
         struct vfsmount       *mnt = lsi->lsi_srv_mnt;
+        lvfs_sbdev_type        save_dev;
         char *tmpname;
         int tmpname_sz;
         int lddflags = lsi->lsi_ldd->ldd_flags;
@@ -1327,8 +1327,7 @@ static void server_put_super(struct super_block *sb)
                         if (lsi->lsi_flags & LSI_UMOUNT_FAILOVER)
                                 obd->obd_fail = 1;
                         /* We can't seem to give an error return code
-                           to .put_super, so we better make sure we clean up!
-                           FIXME is there a way to get around this? */
+                           to .put_super, so we better make sure we clean up! */
                         obd->obd_force = 1;
                         class_manual_cleanup(obd);
                 } else {
@@ -1346,17 +1345,22 @@ static void server_put_super(struct super_block *sb)
                 server_stop_mgs(sb);
         }
 
-        /* clean the mgc and sb */
-        rc = lustre_common_put_super(sb);
-        // FIXME how do I return a failure?
+        save_dev = lvfs_sbdev(sb);
 
-        /* drop the One True Mount */
-        unlock_mntput(mnt);
+        /* Clean the mgc and sb */
+        rc = lustre_common_put_super(sb);
+        /* FIXME how can I report a failure to umount? */ 
 
         /* Wait for the targets to really clean up - can't exit (and let the
            sb get destroyed) while the mount is still in use */
         server_wait_finished(mnt);
-
+        
+        /* drop the One True Mount */
+        unlock_mntput(mnt);
+#ifndef LUSTRE_PATCHLESS
+        lvfs_clear_rdonly(save_dev);
+#endif
+        
         /* Stop the servers (MDS, OSS) if no longer needed.  We must wait
            until the target is really gone so that our type refcount check
            is right. */
@@ -1464,6 +1468,7 @@ static int server_fill_super(struct super_block *sb)
                 rc = PTR_ERR(mnt);
                 CERROR("Unable to mount device %s: %d\n",
                       lsi->lsi_lmd->lmd_dev, rc);
+                lustre_put_lsi(sb);
                 GOTO(out, rc);
         }
         lsi->lsi_srv_mnt = mnt;
@@ -1510,8 +1515,8 @@ static int server_fill_super(struct super_block *sb)
            call s_p_s if so.
            Probably should start client from new thread so we can return.
            Client will not finish until all servers are connected.
-           Note - MGMT-only server does NOT get a client, since there is no
-           lustre fs associated - the MGMT is for all lustre fs's */
+           Note - MGS-only server does NOT get a client, since there is no
+           lustre fs associated - the MGS is for all lustre fs's */
         }
 
         rc = server_fill_super_common(sb);
@@ -1535,10 +1540,8 @@ int server_name2index(char *svname, __u32 *idx, char **endptr)
         unsigned long index;
         int rc;
         char *dash = strchr(svname, '-');
-        if (!dash) {
-                CERROR("Can't understand server name %s\n", svname);
+        if (!dash) 
                 return(-EINVAL);
-        }
 
         if (strncmp(dash + 1, "MDT", 3) == 0)
                 rc = LDD_F_SV_TYPE_MDT;
@@ -1561,7 +1564,8 @@ int lustre_common_put_super(struct super_block *sb)
         ENTRY;
 
         CDEBUG(D_MOUNT, "dropping sb %p\n", sb);
-
+        
+        /* Drop a ref to the MGC */
         rc = lustre_stop_mgc(sb);
         if (rc && (rc != -ENOENT)) {
                 if (rc != -EBUSY) {
@@ -1572,6 +1576,7 @@ int lustre_common_put_super(struct super_block *sb)
                    needs the mgc.  Let him clean it up. */
                 CDEBUG(D_MOUNT, "MGC still in use\n");
         }
+        /* Drop a ref to the mounted disk */
         lustre_put_lsi(sb);
         RETURN(rc);
 }
@@ -1603,7 +1608,8 @@ int lustre_check_exclusion(struct super_block *sb, char *svname)
         ENTRY;
 
         rc = server_name2index(svname, &index, NULL);
-        if (rc != LDD_F_SV_TYPE_OST)
+        if (rc != LDD_F_SV_TYPE_OST) 
+                /* Only exclude OSTs */
                 RETURN(0);
 
         CDEBUG(D_MOUNT, "Check exclusion %s (%d) in %d of %s\n", svname,
@@ -1636,7 +1642,7 @@ static int lmd_make_exclusion(struct lustre_mount_data *lmd, char *ptr)
                 s1++;
                 rc = server_name2index(s1, &index, &s2);
                 if (rc < 0) {
-                        CERROR("Can't parse %s\n", s1);
+                        CERROR("Can't parse server name '%s'\n", s1);
                         break;
                 }
                 if (rc == LDD_F_SV_TYPE_OST)
@@ -1693,31 +1699,32 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd)
         }
         lmd->lmd_magic = LMD_MAGIC;
 
-        /* Default flags */
-        lmd->lmd_flags |= LMD_FLG_RECOVER;
+        /* Set default flags here */
 
         s1 = options;
         while (*s1) {
+                int clear = 0;
                 /* Skip whitespace and extra commas */
                 while (*s1 == ' ' || *s1 == ',')
                         s1++;
 
                 /* Client options are parsed in ll_options: eg. flock,
                    user_xattr, acl */
-
-                if (strncmp(s1, "recov", 5) == 0)
-                        /* FIXME do something with the RECOVER flag - see lconf */
-                        lmd->lmd_flags |= LMD_FLG_RECOVER;
-                else if (strncmp(s1, "norecov", 7) == 0)
-                        lmd->lmd_flags &= ~LMD_FLG_RECOVER;
-                else if (strncmp(s1, "nosvc", 5) == 0)
+                
+                /* Parse non-ldiskfs options here. Rather than modifying
+                   ldiskfs, we just zero these out here */
+                if (strncmp(s1, "abort_recov", 11) == 0) {
+                        lmd->lmd_flags |= LMD_FLG_ABORT_RECOV;
+                        clear++;
+                } else if (strncmp(s1, "nosvc", 5) == 0) {
                         lmd->lmd_flags |= LMD_FLG_NOSVC;
-
+                        clear++;
                 /* ost exclusion list */
-                else if (strncmp(s1, "exclude=", 8) == 0) {
+                else if (strncmp(s1, "exclude=", 8) == 0) {
                         rc = lmd_make_exclusion(lmd, s1 + 7);
                         if (rc)
                                 goto invalid;
+                        clear++;
                 }
 
                 /* Linux 2.4 doesn't pass the device, so we stuck it at the
@@ -1726,15 +1733,22 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd)
                         devname = s1 + 7;
                         /* terminate options right before device.  device
                            must be the last one. */
-                        *s1 = 0;
+                        *s1 = '\0';
                         break;
                 }
 
                 /* Find next opt */
                 s2 = strchr(s1, ',');
-                if (s2 == NULL)
+                if (s2 == NULL) {
+                        if (clear) 
+                                *s1 = '\0';
                         break;
-                s1 = s2 + 1;
+                }
+                s2++;
+                if (clear) 
+                        memmove(s1, s2, strlen(s2) + 1);
+                else
+                        s1 = s2;
         }
 
         if (!devname) {
@@ -1809,7 +1823,7 @@ static int lustre_fill_super(struct super_block *sb, void *data, int silent)
                 CDEBUG(D_MOUNT, "Mounting client %s\n", lmd->lmd_profile);
                 if (!client_fill_super) {
                         LCONSOLE_ERROR("Nothing registered for client mount!"
-                               " Is llite module loaded?\n");
+                               " Is the 'lustre' module loaded?\n");
                         rc = -ENODEV;
                 } else {
                         rc = lustre_start_mgc(sb);
@@ -1832,8 +1846,8 @@ static int lustre_fill_super(struct super_block *sb, void *data, int silent)
 
 out:
         if (rc){
-                CERROR("Unable to mount %s\n",
-                       s2lsi(sb) ? lmd->lmd_dev : "");
+                CERROR("Unable to mount %s (%d)\n", 
+                       s2lsi(sb) ? lmd->lmd_dev : "", rc);
         } else {
                 LCONSOLE_WARN("mount %s complete\n", lmd->lmd_dev);
         }
@@ -1852,6 +1866,7 @@ void lustre_register_client_fill_super(int (*cfs)(struct super_block *sb))
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
 /* 2.5 and later */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))
 struct super_block * lustre_get_sb(struct file_system_type *fs_type,
                                int flags, const char *devname, void * data)
 {
@@ -1860,6 +1875,17 @@ struct super_block * lustre_get_sb(struct file_system_type *fs_type,
            but 2.4 doesn't get devname.  So we do it in mount_lustre.c */
         return get_sb_nodev(fs_type, flags, data, lustre_fill_super);
 }
+#else
+int lustre_get_sb(struct file_system_type *fs_type,
+                               int flags, const char *devname, void * data,
+                               struct vfsmount *mnt)
+{
+        /* calls back in fill super */
+        /* we could append devname= onto options (*data) here, 
+           but 2.4 doesn't get devname.  So we do it in mount_lustre.c */
+        return get_sb_nodev(fs_type, flags, data, lustre_fill_super, mnt);
+}
+#endif
 
 struct file_system_type lustre_fs_type = {
         .owner        = THIS_MODULE,
@@ -1910,8 +1936,6 @@ EXPORT_SYMBOL(server_put_mount);
 EXPORT_SYMBOL(server_register_target);
 EXPORT_SYMBOL(server_name2index);
 EXPORT_SYMBOL(server_mti_print);
-EXPORT_SYMBOL(class_find_param);
-EXPORT_SYMBOL(class_match_param);
-EXPORT_SYMBOL(class_parse_nid);
+EXPORT_SYMBOL(do_lcfg);
 
 
index e0e55b7..547ae26 100644 (file)
@@ -59,14 +59,12 @@ static int echo_connect(const struct lu_context *ctx,
 
 static int echo_disconnect(struct obd_export *exp)
 {
-        unsigned long irqflags;
-
         LASSERT (exp != NULL);
 
         ldlm_cancel_locks_for_export(exp);
 
         /* complete all outstanding replies */
-        spin_lock_irqsave(&exp->exp_lock, irqflags);
+        spin_lock(&exp->exp_lock);
         while (!list_empty(&exp->exp_outstanding_replies)) {
                 struct ptlrpc_reply_state *rs =
                         list_entry(exp->exp_outstanding_replies.next,
@@ -78,7 +76,7 @@ static int echo_disconnect(struct obd_export *exp)
                 ptlrpc_schedule_difficult_reply(rs);
                 spin_unlock(&svc->srv_lock);
         }
-        spin_unlock_irqrestore(&exp->exp_lock, irqflags);
+        spin_unlock(&exp->exp_lock);
 
         return class_disconnect(exp);
 }
@@ -156,11 +154,10 @@ int echo_destroy(struct obd_export *exp, struct obdo *oa,
         RETURN(0);
 }
 
-static int echo_getattr(struct obd_export *exp, struct obdo *oa,
-                        struct lov_stripe_md *md)
+static int echo_getattr(struct obd_export *exp, struct obd_info *oinfo)
 {
         struct obd_device *obd = class_exp2obd(exp);
-        obd_id id = oa->o_id;
+        obd_id id = oinfo->oi_oa->o_id;
 
         ENTRY;
         if (!obd) {
@@ -169,19 +166,20 @@ static int echo_getattr(struct obd_export *exp, struct obdo *oa,
                 RETURN(-EINVAL);
         }
 
-        if (!(oa->o_valid & OBD_MD_FLID)) {
-                CERROR("obdo missing FLID valid flag: "LPX64"\n", oa->o_valid);
+        if (!(oinfo->oi_oa->o_valid & OBD_MD_FLID)) {
+                CERROR("obdo missing FLID valid flag: "LPX64"\n", 
+                       oinfo->oi_oa->o_valid);
                 RETURN(-EINVAL);
         }
 
-        obdo_cpy_md(oa, &obd->u.echo.eo_oa, oa->o_valid);
-        oa->o_id = id;
+        obdo_cpy_md(oinfo->oi_oa, &obd->u.echo.eo_oa, oinfo->oi_oa->o_valid);
+        oinfo->oi_oa->o_id = id;
 
         RETURN(0);
 }
 
-static int echo_setattr(struct obd_export *exp, struct obdo *oa,
-                        struct lov_stripe_md *md, struct obd_trans_info *oti)
+static int echo_setattr(struct obd_export *exp, struct obd_info *oinfo,
+                        struct obd_trans_info *oti)
 {
         struct obd_device *obd = class_exp2obd(exp);
 
@@ -192,14 +190,15 @@ static int echo_setattr(struct obd_export *exp, struct obdo *oa,
                 RETURN(-EINVAL);
         }
 
-        if (!(oa->o_valid & OBD_MD_FLID)) {
-                CERROR("obdo missing FLID valid flag: "LPX64"\n", oa->o_valid);
+        if (!(oinfo->oi_oa->o_valid & OBD_MD_FLID)) {
+                CERROR("obdo missing FLID valid flag: "LPX64"\n", 
+                       oinfo->oi_oa->o_valid);
                 RETURN(-EINVAL);
         }
 
-        memcpy(&obd->u.echo.eo_oa, oa, sizeof(*oa));
+        memcpy(&obd->u.echo.eo_oa, oinfo->oi_oa, sizeof(*oinfo->oi_oa));
 
-        if (oa->o_id & 4) {
+        if (oinfo->oi_oa->o_id & 4) {
                 /* Save lock to force ACKed reply */
                 ldlm_lock_addref (&obd->u.echo.eo_nl_lock, LCK_NL);
                 oti->oti_ack_locks[0].mode = LCK_NL;
@@ -473,10 +472,10 @@ static int echo_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
                 RETURN(-ENOMEM);
         }
 
-        rc = ldlm_cli_enqueue(NULL, NULL, obd->obd_namespace, res_id,
-                              LDLM_PLAIN, NULL, LCK_NL, &lock_flags,
-                              NULL, ldlm_completion_ast, NULL, NULL,
-                              NULL, 0, NULL, &obd->u.echo.eo_nl_lock);
+        rc = ldlm_cli_enqueue_local(obd->obd_namespace, res_id, LDLM_PLAIN, 
+                                    NULL, LCK_NL, &lock_flags, NULL, 
+                                    ldlm_completion_ast, NULL, NULL, 
+                                    0, NULL, &obd->u.echo.eo_nl_lock);
         LASSERT (rc == ELDLM_OK);
 
         lprocfs_init_vars(echo, &lvars);
index 198cd25..c1a170a 100644 (file)
@@ -493,6 +493,7 @@ static int echo_client_kbrw(struct obd_device *obd, int rw, struct obdo *oa,
                             obd_size count, struct obd_trans_info *oti)
 {
         struct echo_client_obd *ec = &obd->u.echo_client;
+        struct obd_info         oinfo = { { { 0 } } };
         obd_count               npages;
         struct brw_page        *pga;
         struct brw_page        *pgp;
@@ -543,7 +544,9 @@ static int echo_client_kbrw(struct obd_device *obd, int rw, struct obdo *oa,
                                                      oa->o_id, off, pgp->count);
         }
 
-        rc = obd_brw(rw, ec->ec_exp, oa, lsm, npages, pga, oti);
+        oinfo.oi_oa = oa;
+        oinfo.oi_md = lsm;
+        rc = obd_brw(rw, ec->ec_exp, &oinfo, npages, pga, oti);
 
  out:
         if (rc != 0 || rw != OBD_BRW_READ)
@@ -574,6 +577,7 @@ static int echo_client_ubrw(struct obd_device *obd, int rw,
                             struct obd_trans_info *oti)
 {
         struct echo_client_obd *ec = &obd->u.echo_client;
+        struct obd_info         oinfo = { { { 0 } } };
         obd_count               npages;
         struct brw_page        *pga;
         struct brw_page        *pgp;
@@ -582,8 +586,7 @@ static int echo_client_ubrw(struct obd_device *obd, int rw,
         int                     i;
         int                     rc;
 
-        LASSERT (rw == OBD_BRW_WRITE ||
-                 rw == OBD_BRW_READ);
+        LASSERT (rw == OBD_BRW_WRITE || rw == OBD_BRW_READ);
 
         /* NB: for now, only whole pages, page aligned */
 
@@ -621,7 +624,9 @@ static int echo_client_ubrw(struct obd_device *obd, int rw,
                 pgp->flag = 0;
         }
 
-        rc = obd_brw(rw, ec->ec_exp, oa, lsm, npages, pga, oti);
+        oinfo.oi_oa = oa;
+        oinfo.oi_md = lsm;
+        rc = obd_brw(rw, ec->ec_exp, &oinfo, npages, pga, oti);
 
         //        if (rw == OBD_BRW_READ)
         //                mark_dirty_kiobuf (kiobuf, count);
@@ -676,12 +681,12 @@ struct echo_async_state {
 
 static int eas_should_wake(struct echo_async_state *eas)
 {
-        unsigned long flags;
         int rc = 0;
-        spin_lock_irqsave(&eas->eas_lock, flags);
+
+        spin_lock(&eas->eas_lock);
         if (eas->eas_rc == 0 && !list_empty(&eas->eas_avail))
             rc = 1;
-        spin_unlock_irqrestore(&eas->eas_lock, flags);
+        spin_unlock(&eas->eas_lock);
         return rc;
 };
 
@@ -704,11 +709,10 @@ static void ec_ap_fill_obdo(void *data, int cmd, struct obdo *oa)
         memcpy(oa, &eap->eap_eas->eas_oa, sizeof(*oa));
 }
 
-static void ec_ap_completion(void *data, int cmd, struct obdo *oa, int rc)
+static int ec_ap_completion(void *data, int cmd, struct obdo *oa, int rc)
 {
         struct echo_async_page *eap = EAP_FROM_COOKIE(data);
         struct echo_async_state *eas;
-        unsigned long flags;
 
         eas = eap->eap_eas;
 
@@ -720,13 +724,14 @@ static void ec_ap_completion(void *data, int cmd, struct obdo *oa, int rc)
                                              eas->eas_oa.o_id, eap->eap_off,
                                              CFS_PAGE_SIZE);
 
-        spin_lock_irqsave(&eas->eas_lock, flags);
+        spin_lock(&eas->eas_lock);
         if (rc && !eas->eas_rc)
                 eas->eas_rc = rc;
         eas->eas_in_flight--;
         list_add(&eap->eap_item, &eas->eas_avail);
         cfs_waitq_signal(&eas->eas_waitq);
-        spin_unlock_irqrestore(&eas->eas_lock, flags);
+        spin_unlock(&eas->eas_lock);
+        return 0;
 }
 
 static struct obd_async_page_ops ec_async_page_ops = {
@@ -745,7 +750,6 @@ static int echo_client_async_page(struct obd_export *exp, int rw,
         struct echo_async_page *eap;
         struct echo_async_state eas;
         int rc = 0;
-        unsigned long flags;
         struct echo_async_page **aps = NULL;
 
         ENTRY;
@@ -806,15 +810,15 @@ static int echo_client_async_page(struct obd_export *exp, int rw,
         }
 
         /* first we spin queueing io and being woken by its completion */
-        spin_lock_irqsave(&eas.eas_lock, flags);
+        spin_lock(&eas.eas_lock);
         for(;;) {
                 int rc;
 
                 /* sleep until we have a page to send */
-                spin_unlock_irqrestore(&eas.eas_lock, flags);
-                rc = wait_event_interruptible(eas.eas_waitq,
+                spin_unlock(&eas.eas_lock);
+                rc = wait_event_interruptible(eas.eas_waitq, 
                                               eas_should_wake(&eas));
-                spin_lock_irqsave(&eas.eas_lock, flags);
+                spin_lock(&eas.eas_lock);
                 if (rc && !eas.eas_rc)
                         eas.eas_rc = rc;
                 if (eas.eas_rc)
@@ -824,7 +828,7 @@ static int echo_client_async_page(struct obd_export *exp, int rw,
                 eap = list_entry(eas.eas_avail.next, struct echo_async_page,
                                  eap_item);
                 list_del(&eap->eap_item);
-                spin_unlock_irqrestore(&eas.eas_lock, flags);
+                spin_unlock(&eas.eas_lock);
 
                 /* unbind the eap from its old page offset */
                 if (eap->eap_cookie != NULL) {
@@ -840,7 +844,7 @@ static int echo_client_async_page(struct obd_export *exp, int rw,
                                          eap->eap_off, &ec_async_page_ops,
                                          eap, &eap->eap_cookie);
                 if (rc) {
-                        spin_lock_irqsave(&eas.eas_lock, flags);
+                        spin_lock(&eas.eas_lock);
                         eas.eas_rc = rc;
                         break;
                 }
@@ -857,7 +861,7 @@ static int echo_client_async_page(struct obd_export *exp, int rw,
                                         rw, 0, CFS_PAGE_SIZE, 0,
                                         ASYNC_READY | ASYNC_URGENT |
                                         ASYNC_COUNT_STABLE);
-                spin_lock_irqsave(&eas.eas_lock, flags);
+                spin_lock(&eas.eas_lock);
                 if (rc && !eas.eas_rc) {
                         eas.eas_rc = rc;
                         break;
@@ -871,12 +875,12 @@ static int echo_client_async_page(struct obd_export *exp, int rw,
 
         /* now we just spin waiting for all the rpcs to complete */
         while(eas.eas_in_flight) {
-                spin_unlock_irqrestore(&eas.eas_lock, flags);
-                wait_event_interruptible(eas.eas_waitq,
+                spin_unlock(&eas.eas_lock);
+                wait_event_interruptible(eas.eas_waitq, 
                                          eas.eas_in_flight == 0);
-                spin_lock_irqsave(&eas.eas_lock, flags);
+                spin_lock(&eas.eas_lock);
         }
-        spin_unlock_irqrestore(&eas.eas_lock, flags);
+        spin_unlock(&eas.eas_lock);
 
 out:
         if (aps != NULL) {
@@ -1083,9 +1087,10 @@ echo_client_enqueue(struct obd_export *exp, struct obdo *oa,
         struct obd_device      *obd = exp->exp_obd;
         struct echo_client_obd *ec = &obd->u.echo_client;
         struct lustre_handle   *ulh = obdo_handle (oa);
+        struct obd_enqueue_info einfo = { 0 };
+        struct obd_info oinfo = { { { 0 } } };
         struct ec_object       *eco;
         struct ec_lock         *ecl;
-        int                     flags;
         int                     rc;
 
         if (!(mode == LCK_PR || mode == LCK_PW))
@@ -1110,11 +1115,17 @@ echo_client_enqueue(struct obd_export *exp, struct obdo *oa,
         ecl->ecl_policy.l_extent.end =
                 (nob == 0) ? ((obd_off) -1) : (offset + nob - 1);
 
-        flags = 0;
-        rc = obd_enqueue(ec->ec_exp, eco->eco_lsm, LDLM_EXTENT,
-                         &ecl->ecl_policy, mode, &flags, echo_ldlm_callback,
-                         ldlm_completion_ast, NULL, eco, sizeof(struct ost_lvb),
-                         lustre_swab_ost_lvb, &ecl->ecl_lock_handle);
+        einfo.ei_type = LDLM_EXTENT;
+        einfo.ei_mode = mode;
+        einfo.ei_cb_bl = echo_ldlm_callback;
+        einfo.ei_cb_cp = ldlm_completion_ast;
+        einfo.ei_cb_gl = NULL;
+        einfo.ei_cbdata = eco;
+
+        oinfo.oi_policy = ecl->ecl_policy;
+        oinfo.oi_lockh = &ecl->ecl_lock_handle;
+        oinfo.oi_md = eco->eco_lsm;
+        rc = obd_enqueue(ec->ec_exp, &oinfo, &einfo);
         if (rc != 0)
                 goto failed_1;
 
@@ -1230,8 +1241,10 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp,
         case OBD_IOC_GETATTR:
                 rc = echo_get_object (&eco, obd, &data->ioc_obdo1);
                 if (rc == 0) {
-                        rc = obd_getattr(ec->ec_exp, &data->ioc_obdo1,
-                                         eco->eco_lsm);
+                        struct obd_info oinfo = { { { 0 } } };
+                        oinfo.oi_md = eco->eco_lsm;
+                        oinfo.oi_oa = &data->ioc_obdo1;
+                        rc = obd_getattr(ec->ec_exp, &oinfo);
                         echo_put_object(eco);
                 }
                 GOTO(out, rc);
@@ -1242,8 +1255,11 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp,
 
                 rc = echo_get_object (&eco, obd, &data->ioc_obdo1);
                 if (rc == 0) {
-                        rc = obd_setattr(ec->ec_exp, &data->ioc_obdo1,
-                                         eco->eco_lsm, NULL);
+                        struct obd_info oinfo = { { { 0 } } };
+                        oinfo.oi_oa = &data->ioc_obdo1;
+                        oinfo.oi_md = eco->eco_lsm;
+
+                        rc = obd_setattr(ec->ec_exp, &oinfo, NULL);
                         echo_put_object(eco);
                 }
                 GOTO(out, rc);
index 4daebaa..4bdc262 100644 (file)
 #include <lustre_disk.h>
 #include <lustre_quota.h>
 #include <lustre_ver.h>
+#include <linux/slab.h>
+#include <lustre_param.h>
 
 #include "filter_internal.h"
 
 static struct lvfs_callback_ops filter_lvfs_ops;
+kmem_cache_t *ll_fmd_cachep;
 
 static void filter_commit_cb(struct obd_device *obd, __u64 transno,
                              void *cb_data, int error)
@@ -124,7 +127,7 @@ int filter_finish_transno(struct obd_export *exp, struct obd_trans_info *oti,
                         rc = err;
         }
 
-        CDEBUG_EX(log_pri, "wrote trans "LPU64" for client %s at #%d: err = %d\n",
+        CDEBUG(log_pri, "wrote trans "LPU64" for client %s at #%d: err = %d\n",
                last_rcvd, fcd->fcd_uuid, fed->fed_lr_idx, err);
 
         RETURN(rc);
@@ -279,7 +282,7 @@ static int filter_client_free(struct obd_export *exp)
                                                   filter->fo_fsd, 1);
                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
 
-                CDEBUG_EX(rc == 0 ? D_INFO : D_ERROR,
+                CDEBUG(rc == 0 ? D_INFO : D_ERROR,
                        "zeroing out client %s at idx %u (%llu) in %s rc %d\n",
                        fed->fed_fcd->fcd_uuid, fed->fed_lr_idx, fed->fed_lr_off,
                        LAST_RCVD, rc);
@@ -299,9 +302,181 @@ free:
         return 0;
 }
 
+/* drop fmd reference, free it if last ref. must be called with fed_lock held.*/
+static inline void filter_fmd_put_nolock(struct filter_export_data *fed,
+                                         struct filter_mod_data *fmd)
+{
+        LASSERT_SPIN_LOCKED(&fed->fed_lock);
+        if (--fmd->fmd_refcount == 0) {
+                /* XXX when we have persistent reservations and the handle
+                 * is stored herein we need to drop it here. */
+                fed->fed_mod_count--;
+                list_del(&fmd->fmd_list);
+                OBD_SLAB_FREE(fmd, ll_fmd_cachep, sizeof(*fmd));
+        }
+}
+
+/* drop fmd reference, free it if last ref */
+void filter_fmd_put(struct obd_export *exp, struct filter_mod_data *fmd)
+{
+        struct filter_export_data *fed;
+
+        if (fmd == NULL)
+                return;
+
+        fed = &exp->exp_filter_data;
+        spin_lock(&fed->fed_lock);
+        filter_fmd_put_nolock(fed, fmd); /* caller reference */
+        spin_unlock(&fed->fed_lock);
+}
+
+/* expire entries from the end of the list if there are too many
+ * or they are too old */
+static void filter_fmd_expire_nolock(struct filter_obd *filter,
+                                     struct filter_export_data *fed,
+                                     struct filter_mod_data *keep)
+{
+        struct filter_mod_data *fmd, *tmp;
+
+        list_for_each_entry_safe(fmd, tmp, &fed->fed_mod_list, fmd_list) {
+                if (fmd == keep)
+                        break;
+
+                if (time_before(jiffies, fmd->fmd_expire) &&
+                    fed->fed_mod_count < filter->fo_fmd_max_num)
+                        break;
+
+                list_del_init(&fmd->fmd_list);
+                filter_fmd_put_nolock(fed, fmd); /* list reference */
+        }
+}
+
+void filter_fmd_expire(struct obd_export *exp)
+{
+        spin_lock(&exp->exp_filter_data.fed_lock);
+        filter_fmd_expire_nolock(&exp->exp_obd->u.filter,
+                                 &exp->exp_filter_data, NULL);
+        spin_unlock(&exp->exp_filter_data.fed_lock);
+}
+
+/* find specified objid, group in export fmd list.
+ * caller must hold fed_lock and take fmd reference itself */
+static struct filter_mod_data *filter_fmd_find_nolock(struct filter_obd *filter,
+                                                struct filter_export_data *fed,
+                                                obd_id objid, obd_gr group)
+{
+        struct filter_mod_data *found = NULL, *fmd;
+
+        LASSERT_SPIN_LOCKED(&fed->fed_lock);
+
+        list_for_each_entry_reverse(fmd, &fed->fed_mod_list, fmd_list) {
+                if (fmd->fmd_id == objid && fmd->fmd_gr == group) {
+                        found = fmd;
+                        list_del(&fmd->fmd_list);
+                        list_add_tail(&fmd->fmd_list, &fed->fed_mod_list);
+                        fmd->fmd_expire = jiffies + filter->fo_fmd_max_age;
+                        break;
+                }
+        }
+
+        filter_fmd_expire_nolock(filter, fed, found);
+
+        return found;
+}
+
+/* Find fmd based on objid and group, or return NULL if not found. */
+struct filter_mod_data *filter_fmd_find(struct obd_export *exp,
+                                        obd_id objid, obd_gr group)
+{
+        struct filter_mod_data *fmd;
+
+        spin_lock(&exp->exp_filter_data.fed_lock);
+        fmd = filter_fmd_find_nolock(&exp->exp_obd->u.filter,
+                                     &exp->exp_filter_data, objid, group);
+        if (fmd)
+                fmd->fmd_refcount++;    /* caller reference */
+        spin_unlock(&exp->exp_filter_data.fed_lock);
+
+        return fmd;
+}
+
+/* Find fmd based on objid and group, or create a new one if none is found.
+ * It is possible for this function to return NULL under memory pressure,
+ * or if objid = 0 is passed (which will only cause old entries to expire).
+ * Currently this is not fatal because any fmd state is transient and
+ * may also be freed when it gets sufficiently old. */
+struct filter_mod_data *filter_fmd_get(struct obd_export *exp,
+                                       obd_id objid, obd_gr group)
+{
+        struct filter_export_data *fed = &exp->exp_filter_data;
+        struct filter_mod_data *found = NULL, *fmd_new = NULL;
+
+        OBD_SLAB_ALLOC(fmd_new, ll_fmd_cachep, SLAB_NOFS, sizeof(*fmd_new));
+
+        spin_lock(&fed->fed_lock);
+        found = filter_fmd_find_nolock(&exp->exp_obd->u.filter,fed,objid,group);
+        if (fmd_new) {
+                if (found == NULL) {
+                        list_add_tail(&fmd_new->fmd_list, &fed->fed_mod_list);
+                        fmd_new->fmd_id = objid;
+                        fmd_new->fmd_gr = group;
+                        fmd_new->fmd_refcount++;   /* list reference */
+                        found = fmd_new;
+                        fed->fed_mod_count++;
+                } else {
+                        OBD_SLAB_FREE(fmd_new, ll_fmd_cachep, sizeof(*fmd_new));
+                }
+        }
+        if (found) {
+                found->fmd_refcount++;          /* caller reference */
+                found->fmd_expire = jiffies +
+                        exp->exp_obd->u.filter.fo_fmd_max_age;
+        }
+
+        spin_unlock(&fed->fed_lock);
+
+        return found;
+}
+
+#if DO_FMD_DROP
+/* drop fmd list reference so it will disappear when last reference is put.
+ * This isn't so critical because it would in fact only affect the one client
+ * that is doing the unlink and at worst we have an stale entry referencing
+ * an object that should never be used again. */
+static void filter_fmd_drop(struct obd_export *exp, obd_id objid, obd_gr group)
+{
+        struct filter_mod_data *found = NULL;
+
+        spin_lock(&exp->exp_filter_data.fed_lock);
+        found = filter_fmd_find_nolock(&exp->exp_filter_data, objid, group);
+        if (found) {
+                list_del_init(&found->fmd_list);
+                filter_fmd_put_nolock(&exp->exp_filter_data, found);
+        }
+        spin_unlock(&exp->exp_filter_data.fed_lock);
+}
+#else
+#define filter_fmd_drop(exp, objid, group)
+#endif
+
+/* remove all entries from fmd list */
+static void filter_fmd_cleanup(struct obd_export *exp)
+{
+        struct filter_export_data *fed = &exp->exp_filter_data;
+        struct filter_mod_data *fmd = NULL, *tmp;
+
+        spin_lock(&fed->fed_lock);
+        list_for_each_entry_safe(fmd, tmp, &fed->fed_mod_list, fmd_list) {
+                list_del_init(&fmd->fmd_list);
+                filter_fmd_put_nolock(fed, fmd);
+        }
+        spin_unlock(&fed->fed_lock);
+}
+
 static int filter_init_export(struct obd_export *exp)
 {
         spin_lock_init(&exp->exp_filter_data.fed_lock);
+        INIT_LIST_HEAD(&exp->exp_filter_data.fed_mod_list);
         exp->exp_connecting = 1;
 
         return 0;
@@ -330,6 +505,7 @@ int filter_update_server_data(struct obd_device *obd, struct file *filp,
         CDEBUG(D_INODE, "server last_mount: "LPU64"\n",
                le64_to_cpu(fsd->lsd_mount_count));
 
+        fsd->lsd_compat14 = fsd->lsd_last_transno;
         rc = fsfilt_write_record(obd, filp, fsd, sizeof(*fsd), &off,force_sync);
         if (rc)
                 CERROR("error writing lr_server_data: rc = %d\n", rc);
@@ -422,6 +598,12 @@ static int filter_init_server_data(struct obd_device *obd, struct file * filp)
                 }
                 mount_count = le64_to_cpu(fsd->lsd_mount_count);
                 filter->fo_subdir_count = le16_to_cpu(fsd->lsd_subdir_count);
+                /* COMPAT_146 */
+                /* Assume old last_rcvd format unless I_C_LR is set */
+                if (!(fsd->lsd_feature_incompat & 
+                      cpu_to_le32(OBD_INCOMPAT_COMMON_LR)))
+                        fsd->lsd_last_transno = fsd->lsd_compat14;
+                /* end COMPAT_146 */
         }
 
         if (fsd->lsd_feature_incompat & ~cpu_to_le32(FILTER_INCOMPAT_SUPP)) {
@@ -438,7 +620,7 @@ static int filter_init_server_data(struct obd_device *obd, struct file * filp)
                 GOTO(err_fsd, rc = -EINVAL);
         }
 
-        CDEBUG(D_INODE, "%s: server last_rcvd : "LPU64"\n",
+        CDEBUG(D_INODE, "%s: server last_transno : "LPU64"\n",
                obd->obd_name, le64_to_cpu(fsd->lsd_last_transno));
         CDEBUG(D_INODE, "%s: server mount_count: "LPU64"\n",
                obd->obd_name, mount_count + 1);
@@ -499,28 +681,35 @@ static int filter_init_server_data(struct obd_device *obd, struct file * filp)
                 CDEBUG(D_HA, "RCVRNG CLIENT uuid: %s idx: %d lr: "LPU64
                        " srv lr: "LPU64"\n", fcd->fcd_uuid, cl_idx,
                        last_rcvd, le64_to_cpu(fsd->lsd_last_transno));
-                if (IS_ERR(exp))
-                        GOTO(err_client, rc = PTR_ERR(exp));
-
-                fed = &exp->exp_filter_data;
-                fed->fed_fcd = fcd;
-                rc = filter_client_add(obd, filter, fed, cl_idx);
-                LASSERTF(rc == 0, "rc = %d\n", rc); /* can't fail existing */
-
-
-                fcd = NULL;
-                exp->exp_replay_needed = 1;
-                exp->exp_connecting = 0;
-                obd->obd_recoverable_clients++;
-                obd->obd_max_recoverable_clients++;
-                class_export_put(exp);
+                if (IS_ERR(exp)) {
+                        if (PTR_ERR(exp) == -EALREADY) {
+                                /* export already exists, zero out this one */
+                                CERROR("Zeroing out duplicate export due to "
+                                       "bug 10479.\n");
+                                fcd->fcd_uuid[0] = '\0';
+                        } else {
+                                GOTO(err_client, rc = PTR_ERR(exp));
+                        }
+                } else {
+                        fed = &exp->exp_filter_data;
+                        fed->fed_fcd = fcd;
+                        rc = filter_client_add(obd, filter, fed, cl_idx);
+                        LASSERTF(rc == 0, "rc = %d\n", rc); /* can't fail existing */
+
+                        fcd = NULL;
+                        exp->exp_replay_needed = 1;
+                        exp->exp_connecting = 0;
+                        obd->obd_recoverable_clients++;
+                        obd->obd_max_recoverable_clients++;
+                        class_export_put(exp);
+                }
 
+                /* Need to check last_rcvd even for duplicated exports. */
                 CDEBUG(D_OTHER, "client at idx %d has last_rcvd = "LPU64"\n",
                        cl_idx, last_rcvd);
 
                 if (last_rcvd > le64_to_cpu(fsd->lsd_last_transno))
                         fsd->lsd_last_transno = cpu_to_le64(last_rcvd);
-
         }
 
         if (fcd)
@@ -880,32 +1069,22 @@ static void filter_post(struct obd_device *obd)
         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
 }
 
-static void filter_set_last_id(struct filter_obd *filter, struct obdo *oa,
-                               obd_id id)
+static void filter_set_last_id(struct filter_obd *filter,
+                               obd_id id, obd_gr group)
 {
-        obd_gr group = 0;
         LASSERT(filter->fo_fsd != NULL);
-
-        if (oa != NULL) {
-                LASSERT(oa->o_gr <= FILTER_GROUPS);
-                group = oa->o_gr;
-        }
+        LASSERT(group <= FILTER_GROUPS);
 
         spin_lock(&filter->fo_objidlock);
         filter->fo_last_objids[group] = id;
         spin_unlock(&filter->fo_objidlock);
 }
 
-__u64 filter_last_id(struct filter_obd *filter, struct obdo *oa)
+obd_id filter_last_id(struct filter_obd *filter, obd_gr group)
 {
         obd_id id;
-        obd_gr group = 0;
         LASSERT(filter->fo_fsd != NULL);
-
-        if (oa != NULL) {
-                LASSERT(oa->o_gr <= FILTER_GROUPS);
-                group = oa->o_gr;
-        }
+        LASSERT(group <= FILTER_GROUPS);
 
         /* FIXME: object groups */
         spin_lock(&filter->fo_objidlock);
@@ -945,7 +1124,7 @@ struct dentry *filter_parent_lock(struct obd_device *obd, obd_gr group,
                 return dparent;
 
         rc = filter_lock_dentry(obd, dparent);
-        fsfilt_check_slow(now, obd_timeout, "parent lock");
+        fsfilt_check_slow(obd, now, obd_timeout, "parent lock");
         return rc ? ERR_PTR(rc) : dparent;
 }
 
@@ -1026,10 +1205,10 @@ static int filter_prepare_destroy(struct obd_device *obd, obd_id objid)
         ENTRY;
         /* Tell the clients that the object is gone now and that they should
          * throw away any cached pages. */
-        rc = ldlm_cli_enqueue(NULL, NULL, obd->obd_namespace, res_id,
-                              LDLM_EXTENT, &policy, LCK_PW,
-                              &flags, ldlm_blocking_ast, ldlm_completion_ast,
-                              NULL, NULL, NULL, 0, NULL, &lockh);
+        rc = ldlm_cli_enqueue_local(obd->obd_namespace, res_id, LDLM_EXTENT, 
+                                    &policy, LCK_PW, &flags, ldlm_blocking_ast, 
+                                    ldlm_completion_ast, NULL, NULL, 0, NULL, 
+                                    &lockh);
 
         /* We only care about the side-effects, just drop the lock. */
         if (rc == ELDLM_OK)
@@ -1050,12 +1229,13 @@ int filter_vfs_unlink(struct inode *dir, struct dentry *dentry)
 
         /* don't need dir->i_zombie for 2.4, it is for rename/unlink of dir
          * itself we already hold dir->i_mutex for child create/unlink ops */
+        LASSERT(dentry->d_inode != NULL);
         LASSERT(TRYLOCK_INODE_MUTEX(dir) == 0);
         LASSERT(TRYLOCK_INODE_MUTEX(dentry->d_inode) == 0);
 
 
         /* may_delete() */
-        if (!dentry->d_inode || dentry->d_parent->d_inode != dir)
+        if (/*!dentry->d_inode ||*/dentry->d_parent->d_inode != dir)
                 GOTO(out, rc = -ENOENT);
 
         rc = ll_permission(dir, MAY_WRITE | MAY_EXEC, NULL);
@@ -1095,7 +1275,7 @@ out:
  * Caller must hold child i_mutex, we drop it always.
  * Caller is also required to ensure that dchild->d_inode exists. */
 static int filter_destroy_internal(struct obd_device *obd, obd_id objid,
-                                   struct dentry *dparent,
+                                   obd_gr group, struct dentry *dparent,
                                    struct dentry *dchild)
 {
         struct inode *inode = dchild->d_inode;
@@ -1128,22 +1308,25 @@ static int filter_intent_policy(struct ldlm_namespace *ns,
         struct ldlm_reply *rep;
         struct list_head *tmp;
         ldlm_error_t err;
-        int tmpflags = 0, rc, repsize[2] = {sizeof(*rep), sizeof(*reply_lvb)};
-        int only_liblustre = 0;
+        int rc, tmpflags = 0, only_liblustre = 0;
+        int repsize[3] = { [MSG_PTLRPC_BODY_OFF] = sizeof(struct ptlrpc_body),
+                           [DLM_LOCKREPLY_OFF]   = sizeof(*rep),
+                           [DLM_REPLY_REC_OFF]   = sizeof(*reply_lvb) };
         ENTRY;
 
         policy = ldlm_get_processing_policy(res);
         LASSERT(policy != NULL);
         LASSERT(req != NULL);
 
-        rc = lustre_pack_reply(req, 2, repsize, NULL);
+        rc = lustre_pack_reply(req, 3, repsize, NULL);
         if (rc)
                 RETURN(req->rq_status = rc);
 
-        rep = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*rep));
+        rep = lustre_msg_buf(req->rq_repmsg, DLM_LOCKREPLY_OFF, sizeof(*rep));
         LASSERT(rep != NULL);
 
-        reply_lvb = lustre_msg_buf(req->rq_repmsg, 1, sizeof(*reply_lvb));
+        reply_lvb = lustre_msg_buf(req->rq_repmsg, DLM_REPLY_REC_OFF,
+                                   sizeof(*reply_lvb));
         LASSERT(reply_lvb != NULL);
 
         //fixup_handle_for_resent_req(req, lock, &lockh);
@@ -1156,25 +1339,25 @@ static int filter_intent_policy(struct ldlm_namespace *ns,
         lock->l_req_mode = LCK_PR;
 
         LASSERT(ns == res->lr_namespace);
-        l_lock(&ns->ns_lock);
-
-        res->lr_tmp = &rpc_list;
-        rc = policy(lock, &tmpflags, 0, &err);
-        res->lr_tmp = NULL;
+        lock_res(res);
+        rc = policy(lock, &tmpflags, 0, &err, &rpc_list);
+        check_res_locked(res);
 
         /* FIXME: we should change the policy function slightly, to not make
          * this list at all, since we just turn around and free it */
         while (!list_empty(&rpc_list)) {
-                struct ldlm_ast_work *w =
-                        list_entry(rpc_list.next, struct ldlm_ast_work, w_list);
-                list_del(&w->w_list);
-                LDLM_LOCK_PUT(w->w_lock);
-                OBD_FREE(w, sizeof(*w));
+                struct ldlm_lock *wlock =
+                        list_entry(rpc_list.next, struct ldlm_lock, l_cp_ast);
+                LASSERT((lock->l_flags & LDLM_FL_AST_SENT) == 0);
+                LASSERT(lock->l_flags & LDLM_FL_CP_REQD);
+                lock->l_flags &= ~LDLM_FL_CP_REQD;
+                list_del_init(&wlock->l_cp_ast);
+                LDLM_LOCK_PUT(wlock);
         }
 
         /* The lock met with no resistance; we're finished. */
         if (rc == LDLM_ITER_CONTINUE) {
-                l_unlock(&ns->ns_lock);
+                unlock_res(res);
                 /*
                  * do not grant locks to the liblustre clients: they cannot
                  * handle ASTs robustly.
@@ -1190,11 +1373,9 @@ static int filter_intent_policy(struct ldlm_namespace *ns,
          * policy nicely created a list of all PW locks for us.  We will choose
          * the highest of those which are larger than the size in the LVB, if
          * any, and perform a glimpse callback. */
-        down(&res->lr_lvb_sem);
         res_lvb = res->lr_lvb_data;
         LASSERT(res_lvb != NULL);
         *reply_lvb = *res_lvb;
-        up(&res->lr_lvb_sem);
 
         list_for_each(tmp, &res->lr_granted) {
                 struct ldlm_lock *tmplock =
@@ -1233,7 +1414,7 @@ static int filter_intent_policy(struct ldlm_namespace *ns,
                 LDLM_LOCK_PUT(l);
                 l = LDLM_LOCK_GET(tmplock);
         }
-        l_unlock(&ns->ns_lock);
+        unlock_res(res);
 
         /* There were no PW locks beyond the size in the LVB; finished. */
         if (l == NULL) {
@@ -1278,9 +1459,9 @@ static int filter_intent_policy(struct ldlm_namespace *ns,
         if (rc != 0 && ns->ns_lvbo && ns->ns_lvbo->lvbo_update)
                 ns->ns_lvbo->lvbo_update(res, NULL, 0, 1);
 
-        down(&res->lr_lvb_sem);
+        lock_res(res);
         *reply_lvb = *res_lvb;
-        up(&res->lr_lvb_sem);
+        unlock_res(res);
 
  out:
         LDLM_LOCK_PUT(l);
@@ -1468,7 +1649,6 @@ int filter_common_setup(struct obd_device *obd, struct lustre_cfg* lcfg,
         sema_init(&filter->fo_create_lock, 1);
         spin_lock_init(&filter->fo_translock);
         spin_lock_init(&filter->fo_objidlock);
-        spin_lock_init(&filter->fo_stats_lock);
         INIT_LIST_HEAD(&filter->fo_export_list);
         sema_init(&filter->fo_alloc_lock, 1);
         spin_lock_init(&filter->fo_r_pages.oh_lock);
@@ -1483,7 +1663,11 @@ int filter_common_setup(struct obd_device *obd, struct lustre_cfg* lcfg,
         spin_lock_init(&filter->fo_w_discont_blocks.oh_lock);
         spin_lock_init(&filter->fo_r_disk_iosize.oh_lock);
         spin_lock_init(&filter->fo_w_disk_iosize.oh_lock);
+        spin_lock_init(&filter->fo_r_dio_frags.oh_lock);
+        spin_lock_init(&filter->fo_w_dio_frags.oh_lock);
         filter->fo_readcache_max_filesize = FILTER_MAX_CACHE_SIZE;
+        filter->fo_fmd_max_num = FILTER_FMD_MAX_NUM_DEFAULT;
+        filter->fo_fmd_max_age = FILTER_FMD_MAX_AGE_DEFAULT;
 
         sprintf(ns_name, "filter-%s", obd->obd_uuid.uuid);
         obd->obd_namespace = ldlm_namespace_new(ns_name, LDLM_NAMESPACE_SERVER);
@@ -1716,14 +1900,14 @@ static int filter_cleanup(struct obd_device *obd)
                 unlock_kernel();
                 must_relock++;
         }
-
-        if (must_put)
+        
+        if (must_put) {
                 /* In case we didn't mount with lustre_get_mount -- old method*/
                 mntput(filter->fo_vfsmnt);
+                lvfs_clear_rdonly(save_dev);
+        }
         obd->u.obt.obt_sb = NULL;
 
-        lvfs_clear_rdonly(save_dev);
-
         if (must_relock)
                 lock_kernel();
 
@@ -1743,10 +1927,10 @@ static int filter_connect_internal(struct obd_export *exp,
                 RETURN(0);
 
         CDEBUG(D_RPCTRACE, "%s: cli %s/%p ocd_connect_flags: "LPX64
-               " ocd_version: %x ocd_grant: %d\n",
+               " ocd_version: %x ocd_grant: %d ocd_index: %u\n",
                exp->exp_obd->obd_name, exp->exp_client_uuid.uuid, exp,
                data->ocd_connect_flags, data->ocd_version,
-               data->ocd_grant);
+               data->ocd_grant, data->ocd_index);
 
         data->ocd_connect_flags &= OST_CONNECT_SUPPORTED;
         exp->exp_connect_flags = data->ocd_connect_flags;
@@ -1762,7 +1946,7 @@ static int filter_connect_internal(struct obd_export *exp,
                 spin_unlock(&exp->exp_obd->obd_osfs_lock);
 
                 CDEBUG(D_CACHE, "%s: cli %s/%p ocd_grant: %d want: "
-                       "%lld left: %lld\n", exp->exp_obd->obd_name,
+                       LPU64" left: "LPU64"\n", exp->exp_obd->obd_name,
                        exp->exp_client_uuid.uuid, exp,
                        data->ocd_grant, want, left);
         }
@@ -1788,6 +1972,14 @@ static int filter_connect_internal(struct obd_export *exp,
                         RETURN(-EBADF);
                 }
         }
+
+        if (OBD_FAIL_CHECK(OBD_FAIL_OST_BRW_SIZE)) {
+                data->ocd_brw_size = 65536;
+        } else if (data->ocd_connect_flags & OBD_CONNECT_BRW_SIZE) {
+                data->ocd_brw_size = min(data->ocd_brw_size,
+                                         (__u32)(PTLRPC_MAX_BRW_PAGES << PAGE_SHIFT));
+        }
+
         /* FIXME: Do the same with the MDS UUID and fsd_peeruuid.
          * FIXME: We don't strictly need the COMPAT flag for that,
          * FIXME: as fsd_peeruuid[0] will tell us if that is set.
@@ -1835,8 +2027,6 @@ static int filter_connect(const struct lu_context *ctx,
 
         fed = &exp->exp_filter_data;
 
-        spin_lock_init(&fed->fed_lock);
-
         rc = filter_connect_internal(exp, data);
         if (rc)
                 GOTO(cleanup, rc);
@@ -1998,6 +2188,7 @@ static int filter_destroy_export(struct obd_export *exp)
                 fsfilt_sync(exp->exp_obd, exp->exp_obd->u.obt.obt_sb);
 
         filter_grant_discard(exp);
+        filter_fmd_cleanup(exp);
 
         if (!(exp->exp_flags & OBD_OPT_FORCE))
                 filter_grant_sanity_check(exp->exp_obd, __FUNCTION__);
@@ -2022,7 +2213,8 @@ static int filter_disconnect(struct obd_export *exp)
 
         /* Disconnect early so that clients can't keep using export */
         rc = class_disconnect(exp);
-        ldlm_cancel_locks_for_export(exp);
+        if (exp->exp_obd->obd_namespace != NULL)
+                ldlm_cancel_locks_for_export(exp);
 
         fsfilt_sync(obd, obd->u.obt.obt_sb);
 
@@ -2036,16 +2228,22 @@ static int filter_disconnect(struct obd_export *exp)
         RETURN(rc);
 }
 
+static int filter_ping(struct obd_export *exp)
+{
+        filter_fmd_expire(exp);
+
+        return 0;
+}
+
 struct dentry *__filter_oa2dentry(struct obd_device *obd, struct obdo *oa,
                                   const char *what, int quiet)
 {
         struct dentry *dchild = NULL;
-        obd_gr group = 0;
 
-        if (oa->o_valid & OBD_MD_FLGROUP)
-                group = oa->o_gr;
+        if (!(oa->o_valid & OBD_MD_FLGROUP))
+                oa->o_gr = 0;
 
-        dchild = filter_fid2dentry(obd, NULL, group, oa->o_id);
+        dchild = filter_fid2dentry(obd, NULL, oa->o_gr, oa->o_id);
 
         if (IS_ERR(dchild)) {
                 CERROR("%s error looking up object: "LPU64"\n",
@@ -2064,8 +2262,7 @@ struct dentry *__filter_oa2dentry(struct obd_device *obd, struct obdo *oa,
         return dchild;
 }
 
-static int filter_getattr(struct obd_export *exp, struct obdo *oa,
-                          struct lov_stripe_md *md)
+static int filter_getattr(struct obd_export *exp, struct obd_info *oinfo)
 {
         struct dentry *dentry = NULL;
         struct obd_device *obd;
@@ -2078,13 +2275,13 @@ static int filter_getattr(struct obd_export *exp, struct obdo *oa,
                 RETURN(-EINVAL);
         }
 
-        dentry = filter_oa2dentry(obd, oa);
+        dentry = filter_oa2dentry(obd, oinfo->oi_oa);
         if (IS_ERR(dentry))
                 RETURN(PTR_ERR(dentry));
 
         /* Limit the valid bits in the return data to what we actually use */
-        oa->o_valid = OBD_MD_FLID;
-        obdo_from_inode(oa, dentry->d_inode, FILTER_VALID_FLAGS);
+        oinfo->oi_oa->o_valid = OBD_MD_FLID;
+        obdo_from_inode(oinfo->oi_oa, dentry->d_inode, FILTER_VALID_FLAGS);
 
         f_dput(dentry);
         RETURN(rc);
@@ -2101,10 +2298,9 @@ int filter_update_fidea(struct obd_export *exp, struct inode *inode,
 
         if (oa->o_valid & OBD_MD_FLFID) {
                 struct filter_fid ff;
-                obd_gr group = 0;
 
-                if (oa->o_valid & OBD_MD_FLGROUP)
-                        group = oa->o_gr;
+                if (!(oa->o_valid & OBD_MD_FLGROUP))
+                        oa->o_gr = 0;
 
                 /* packing fid and converting it to LE for storing into EA.
                  * Here ->o_stripe_idx should be filled by LOV and rest of
@@ -2113,11 +2309,11 @@ int filter_update_fidea(struct obd_export *exp, struct inode *inode,
                 ff.ff_fid.f_type = cpu_to_le32(oa->o_stripe_idx);
                 ff.ff_fid.generation = cpu_to_le32(oa->o_generation);
                 ff.ff_objid = cpu_to_le64(oa->o_id);
-                ff.ff_group = cpu_to_le64(group);
+                ff.ff_group = cpu_to_le64(oa->o_gr);
 
                 CDEBUG(D_INODE, "storing filter fid EA ("LPU64"/%u/%u"
                        LPU64"/"LPU64")\n", oa->o_fid, oa->o_stripe_idx,
-                       oa->o_generation, oa->o_id, group);
+                       oa->o_generation, oa->o_id, oa->o_gr);
 
                 rc = fsfilt_set_md(obd, inode, handle, &ff, sizeof(ff), "fid");
                 if (rc)
@@ -2212,17 +2408,13 @@ int filter_setattr_internal(struct obd_export *exp, struct dentry *dentry,
                                       EXT3_IOC_SETFLAGS, (long)&oa->o_flags);
         } else {
                 rc = fsfilt_setattr(exp->exp_obd, dentry, handle, &iattr, 1);
-                if (fcc != NULL)
+                if (fcc != NULL) {
                         /* set cancel cookie callback function */
-                        fsfilt_add_journal_cb(exp->exp_obd, 0, oti ?
-                                              oti->oti_handle : handle,
+                        fsfilt_add_journal_cb(exp->exp_obd, 0, handle,
                                               filter_cancel_cookies_cb,
                                               fcc);
-        }
-
-        if (locked) {
-                UNLOCK_INODE_MUTEX(inode);
-                locked = 0;
+                        fcc = NULL;
+                }
         }
 
         rc = filter_finish_transno(exp, oti, rc);
@@ -2233,28 +2425,46 @@ int filter_setattr_internal(struct obd_export *exp, struct dentry *dentry,
                 if (!rc)
                         rc = err;
         }
+
+        if (locked) {
+                /* Let's flush truncated page on disk immediately, then we can
+                 * avoid need to search for page aliases before directio writes
+                 * and this sort of stuff at expense of somewhat slower
+                 * truncates not on a page boundary. I believe this is the only
+                 * place in filter code that can lead to pages getting to
+                 * pagecache so far. */
+                filter_clear_truncated_page(inode);
+                UNLOCK_INODE_MUTEX(inode);
+                locked = 0;
+        }
+
         EXIT;
 out_unlock:
         if (locked)
                 UNLOCK_INODE_MUTEX(inode);
 
+        if (fcc)
+                OBD_FREE(fcc, sizeof(*fcc));
+
         /* trigger quota release */
         if (ia_valid & (ATTR_SIZE | ATTR_UID | ATTR_GID)) {
                 unsigned int cur_ids[MAXQUOTAS] = {oa->o_uid, oa->o_gid};
                 int rc2 = lquota_adjust(quota_interface, exp->exp_obd, cur_ids,
                                         orig_ids, rc, FSFILT_OP_SETATTR);
-                CDEBUG_EX(rc2 ? D_ERROR : D_QUOTA,
+
+                CDEBUG(rc2 ? D_ERROR : D_QUOTA,
                        "filter adjust qunit. (rc:%d)\n", rc2);
         }
         return rc;
 }
 
 /* this is called from filter_truncate() until we have filter_punch() */
-int filter_setattr(struct obd_export *exp, struct obdo *oa,
-                   struct lov_stripe_md *md, struct obd_trans_info *oti)
+int filter_setattr(struct obd_export *exp, struct obd_info *oinfo,
+                   struct obd_trans_info *oti)
 {
-        struct ldlm_res_id res_id = { .name = { oa->o_id } };
+        struct ldlm_res_id res_id = { .name = { oinfo->oi_oa->o_id } };
         struct ldlm_valblock_ops *ns_lvbo;
+        struct filter_mod_data *fmd;
         struct lvfs_run_ctxt saved;
         struct filter_obd *filter;
         struct ldlm_resource *res;
@@ -2262,7 +2472,7 @@ int filter_setattr(struct obd_export *exp, struct obdo *oa,
         int rc;
         ENTRY;
 
-        dentry = __filter_oa2dentry(exp->exp_obd, oa,
+        dentry = __filter_oa2dentry(exp->exp_obd, oinfo->oi_oa,
                                     __FUNCTION__, 1);
         if (IS_ERR(dentry))
                 RETURN(PTR_ERR(dentry));
@@ -2271,8 +2481,16 @@ int filter_setattr(struct obd_export *exp, struct obdo *oa,
         push_ctxt(&saved, &exp->exp_obd->obd_lvfs_ctxt, NULL);
         lock_kernel();
 
+        if (oinfo->oi_oa->o_valid &
+            (OBD_MD_FLMTIME | OBD_MD_FLATIME | OBD_MD_FLCTIME)) {
+                fmd = filter_fmd_get(exp,oinfo->oi_oa->o_id,oinfo->oi_oa->o_gr);
+                if (fmd && fmd->fmd_mactime_xid < oti->oti_xid)
+                        fmd->fmd_mactime_xid = oti->oti_xid;
+                filter_fmd_put(exp, fmd);
+        }
+
         /* setting objects attributes (including owner/group) */
-        rc = filter_setattr_internal(exp, dentry, oa, oti);
+        rc = filter_setattr_internal(exp, dentry, oinfo->oi_oa, oti);
         if (rc)
                 GOTO(out_unlock, rc);
 
@@ -2286,10 +2504,10 @@ int filter_setattr(struct obd_export *exp, struct obdo *oa,
                 ldlm_resource_putref(res);
         }
 
-        oa->o_valid = OBD_MD_FLID;
+        oinfo->oi_oa->o_valid = OBD_MD_FLID;
 
         /* Quota release need uid/gid info */
-        obdo_from_inode(oa, dentry->d_inode,
+        obdo_from_inode(oinfo->oi_oa, dentry->d_inode,
                         FILTER_VALID_FLAGS | OBD_MD_FLUID | OBD_MD_FLGID);
 
         EXIT;
@@ -2350,13 +2568,17 @@ static int filter_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp,
         RETURN(lsm_size);
 }
 
-static void filter_destroy_precreated(struct obd_export *exp, struct obdo *oa,
+/* caller must hold fo_create_lock */
+static int filter_destroy_precreated(struct obd_export *exp, struct obdo *oa,
                                       struct filter_obd *filter)
 {
         struct obdo doa; /* XXX obdo on stack */
-        __u64 last, id;
+        obd_id last, id;
+        int rc;
         ENTRY;
+
         LASSERT(oa);
+        LASSERT(down_trylock(&filter->fo_create_lock) != 0);
 
         memset(&doa, 0, sizeof(doa));
         if (oa->o_valid & OBD_MD_FLGROUP) {
@@ -2367,81 +2589,109 @@ static void filter_destroy_precreated(struct obd_export *exp, struct obdo *oa,
         }
         doa.o_mode = S_IFREG;
 
-        filter->fo_destroy_in_progress = 1;
-        down(&filter->fo_create_lock);
         if (!filter->fo_destroy_in_progress) {
                 CERROR("%s: destroy_in_progress already cleared\n",
                         exp->exp_obd->obd_name);
-                up(&filter->fo_create_lock);
-                EXIT;
-                return;
+                RETURN(0);
         }
 
-        last = filter_last_id(filter, &doa);
+        last = filter_last_id(filter, doa.o_gr);
         CWARN("%s: deleting orphan objects from "LPU64" to "LPU64"\n",
                exp->exp_obd->obd_name, oa->o_id + 1, last);
-        for (id = oa->o_id + 1; id <= last; id++) {
+        for (id = last; id > oa->o_id; id--) {
                 doa.o_id = id;
-                filter_destroy(exp, &doa, NULL, NULL, NULL);
+                rc = filter_destroy(exp, &doa, NULL, NULL, NULL);
+                if (rc && rc != -ENOENT) /* this is pretty fatal... */
+                        CEMERG("error destroying precreate objid "LPU64": %d\n",
+                               id, rc);
+                filter_set_last_id(filter, id - 1, doa.o_gr);
+                /* update last_id on disk periodically so that if we restart
+                 * we don't need to re-scan all of the just-deleted objects. */
+                if ((id & 511) == 0)
+                        filter_update_last_objid(exp->exp_obd, doa.o_gr, 0);
         }
 
         CDEBUG(D_HA, "%s: after destroy: set last_objids["LPU64"] = "LPU64"\n",
                exp->exp_obd->obd_name, doa.o_gr, oa->o_id);
 
-        spin_lock(&filter->fo_objidlock);
-        filter->fo_last_objids[doa.o_gr] = oa->o_id;
-        spin_unlock(&filter->fo_objidlock);
-
+        rc = filter_update_last_objid(exp->exp_obd, doa.o_gr, 1);
         filter->fo_destroy_in_progress = 0;
-        up(&filter->fo_create_lock);
 
-        EXIT;
+        RETURN(0);
 }
 
+static int filter_precreate(struct obd_device *obd, struct obdo *oa,
+                            obd_gr group, int *num);
 /* returns a negative error or a nonnegative number of files to create */
-static int filter_should_precreate(struct obd_export *exp, struct obdo *oa,
-                                   obd_gr group)
+static int filter_handle_precreate(struct obd_export *exp, struct obdo *oa,
+                                   obd_gr group, struct obd_trans_info *oti)
 {
         struct obd_device *obd = exp->exp_obd;
         struct filter_obd *filter = &obd->u.filter;
         int diff, rc;
         ENTRY;
 
-        diff = oa->o_id - filter_last_id(filter, oa);
-        CDEBUG(D_INFO, "filter_last_id() = "LPU64" -> diff = %d\n",
-               filter_last_id(filter, oa), diff);
-
         /* delete orphans request */
-        if ((oa->o_valid & OBD_MD_FLFLAGS) &&
-            (oa->o_flags & OBD_FL_DELORPHAN)) {
-                if (diff >= 0)
-                        RETURN(diff);
+        if ((oa->o_valid & OBD_MD_FLFLAGS) && (oa->o_flags & OBD_FL_DELORPHAN)){
+                /* This causes inflight precreates to abort and drop lock */
+                filter->fo_destroy_in_progress = 1;
+                down(&filter->fo_create_lock);
+                diff = oa->o_id - filter_last_id(filter, group);
+                CDEBUG(D_HA, "filter_last_id() = "LPU64" -> diff = %d\n",
+                       filter_last_id(filter, group), diff);
+
                 if (-diff > OST_MAX_PRECREATE) {
                         CERROR("%s: ignoring bogus orphan destroy request: "
                                "obdid "LPU64" last_id "LPU64"\n", obd->obd_name,
-                               oa->o_id, filter_last_id(filter, oa));
-                        RETURN(-EINVAL);
+                               oa->o_id, filter_last_id(filter, group));
+                        /* FIXME: should reset precreate_next_id on MDS */
+                        GOTO(out, rc = -EINVAL);
+                }
+                if (diff < 0) {
+                        rc = filter_destroy_precreated(exp, oa, filter);
+                        if (rc)
+                                CERROR("%s: unable to write lastobjid, but "
+                                       "orphans were deleted\n", obd->obd_name);
+                        GOTO(out, rc);
+                } else {
+                        /*XXX used by MDS for the first time! */
+                        filter->fo_destroy_in_progress = 0;
                 }
-                filter_destroy_precreated(exp, oa, filter);
-                rc = filter_update_last_objid(obd, group, 0);
-                if (rc)
-                        CERROR("%s: unable to write lastobjid, but orphans"
-                               "were deleted\n", obd->obd_name);
-                RETURN(0);
         } else {
+                down(&filter->fo_create_lock);
+                if (oti->oti_conn_cnt < exp->exp_conn_cnt) {
+                        CERROR("%s: dropping old precreate request\n",
+                               obd->obd_name);
+                        GOTO(out, rc = 0);
+                }
                 /* only precreate if group == 0 and o_id is specfied */
-                if (!(oa->o_valid & OBD_FL_DELORPHAN) &&
-                    (group != 0 || oa->o_id == 0))
-                        RETURN(1);
+                if (group != 0 || oa->o_id == 0)
+                        diff = 1;
+                else
+                        diff = oa->o_id - filter_last_id(filter, group);
+                CDEBUG(D_HA, "filter_last_id() = "LPU64" -> diff = %d\n",
+                       filter_last_id(filter, group), diff);
 
                 LASSERTF(diff >= 0,"%s: "LPU64" - "LPU64" = %d\n",obd->obd_name,
-                         oa->o_id, filter_last_id(filter, oa), diff);
-                RETURN(diff);
+                         oa->o_id, filter_last_id(filter, group), diff);
         }
+
+        if (diff > 0) {
+                oa->o_id = filter_last_id(&obd->u.filter, group);
+                rc = filter_precreate(obd, oa, group, &diff);
+                oa->o_id = filter_last_id(&obd->u.filter, group);
+                oa->o_valid = OBD_MD_FLID;
+                GOTO(out, rc);
+        }
+        /* else diff == 0 */
+        GOTO(out, rc = 0);
+out:
+        up(&filter->fo_create_lock);
+        return rc;
 }
 
 static int filter_statfs(struct obd_device *obd, struct obd_statfs *osfs,
-                         unsigned long max_age)
+                         __u64 max_age)
 {
         struct filter_obd *filter = &obd->u.filter;
         int blockbits = obd->u.obt.obt_sb->s_blocksize_bits;
@@ -2484,6 +2734,8 @@ static int filter_statfs(struct obd_device *obd, struct obd_statfs *osfs,
  * thread 2: gets id (x + 1) from filter_next_id
  * thread 2: creates object (x + 1)
  * thread 1: tries to create object x, gets -ENOSPC
+ *
+ * Caller must hold fo_create_lock
  */
 static int filter_precreate(struct obd_device *obd, struct obdo *oa,
                             obd_gr group, int *num)
@@ -2493,12 +2745,14 @@ static int filter_precreate(struct obd_device *obd, struct obdo *oa,
         struct obd_statfs *osfs;
         int err = 0, rc = 0, recreate_obj = 0, i;
         unsigned long enough_time = jiffies + (obd_timeout * HZ) / 4;
-        __u64 next_id;
+        obd_id next_id;
         void *handle = NULL;
         ENTRY;
 
         filter = &obd->u.filter;
 
+        LASSERT(down_trylock(&filter->fo_create_lock) != 0);
+
         if ((oa->o_valid & OBD_MD_FLFLAGS) &&
             (oa->o_flags & OBD_FL_RECREATE_OBJS)) {
                 recreate_obj = 1;
@@ -2506,7 +2760,7 @@ static int filter_precreate(struct obd_device *obd, struct obdo *oa,
                 OBD_ALLOC(osfs, sizeof(*osfs));
                 if (osfs == NULL)
                         RETURN(-ENOMEM);
-                rc = filter_statfs(obd, osfs, jiffies - HZ);
+                rc = filter_statfs(obd, osfs, cfs_time_current_64() - HZ);
                 if (rc == 0 && osfs->os_bavail < (osfs->os_blocks >> 10)) {
                         CDEBUG(D_HA, "OST out of space! avail "LPU64"\n",
                                osfs->os_bavail <<
@@ -2515,29 +2769,27 @@ static int filter_precreate(struct obd_device *obd, struct obdo *oa,
                         rc = -ENOSPC;
                 }
                 OBD_FREE(osfs, sizeof(*osfs));
-                if (rc) {
+                if (rc)
                         RETURN(rc);
-                }
         }
 
         CDEBUG(D_HA, "%s: precreating %d objects in group "LPU64" at "LPU64"\n",
                obd->obd_name, *num, group, oa->o_id);
 
-        down(&filter->fo_create_lock);
-
         for (i = 0; i < *num && err == 0; i++) {
                 int cleanup_phase = 0;
 
                 if (filter->fo_destroy_in_progress) {
                         CWARN("%s: precreate aborted by destroy\n",
                               obd->obd_name);
+                        rc = -EAGAIN;
                         break;
                 }
 
                 if (recreate_obj) {
                         __u64 last_id;
                         next_id = oa->o_id;
-                        last_id = filter_last_id(filter, oa);
+                        last_id = filter_last_id(filter, group);
                         if (next_id > last_id) {
                                 CERROR("Error: Trying to recreate obj greater"
                                        "than last id "LPD64" > "LPD64"\n",
@@ -2545,7 +2797,7 @@ static int filter_precreate(struct obd_device *obd, struct obdo *oa,
                                 GOTO(cleanup, rc = -EINVAL);
                         }
                 } else
-                        next_id = filter_last_id(filter, oa) + 1;
+                        next_id = filter_last_id(filter, group) + 1;
 
                 CDEBUG(D_INFO, "precreate objid "LPU64"\n", next_id);
 
@@ -2595,7 +2847,7 @@ static int filter_precreate(struct obd_device *obd, struct obdo *oa,
                 }
 
                 if (!recreate_obj) {
-                        filter_set_last_id(filter, oa, next_id);
+                        filter_set_last_id(filter, next_id, group);
                         err = filter_update_last_objid(obd, group, 0);
                         if (err)
                                 CERROR("unable to write lastobjid "
@@ -2629,11 +2881,12 @@ static int filter_precreate(struct obd_device *obd, struct obdo *oa,
         }
         *num = i;
 
-        up(&filter->fo_create_lock);
-
         CDEBUG(D_HA, "%s: created %d objects for group "LPU64": "LPU64"\n",
                obd->obd_name, i, group, filter->fo_last_objids[group]);
 
+        CDEBUG(D_HA, "%s: filter_precreate() created %d objects: rc %d\n",
+               obd->obd_name, i, rc);
+
         RETURN(rc);
 }
 
@@ -2643,15 +2896,14 @@ static int filter_create(struct obd_export *exp, struct obdo *oa,
         struct obd_device *obd = NULL;
         struct lvfs_run_ctxt saved;
         struct lov_stripe_md *lsm = NULL;
-        obd_gr group = 0;
         int rc = 0, diff;
         ENTRY;
 
-        if (oa->o_valid & OBD_MD_FLGROUP)
-                group = oa->o_gr;
+        if (!(oa->o_valid & OBD_MD_FLGROUP))
+                oa->o_gr = 0;
 
         CDEBUG(D_INFO, "filter_create(od->o_gr="LPU64",od->o_id="LPU64")\n",
-               group, oa->o_id);
+               oa->o_gr, oa->o_id);
         if (ea != NULL) {
                 lsm = *ea;
                 if (lsm == NULL) {
@@ -2666,22 +2918,21 @@ static int filter_create(struct obd_export *exp, struct obdo *oa,
 
         if ((oa->o_valid & OBD_MD_FLFLAGS) &&
             (oa->o_flags & OBD_FL_RECREATE_OBJS)) {
-                if (oa->o_id > filter_last_id(&obd->u.filter, oa)) {
+                if (oa->o_id > filter_last_id(&obd->u.filter, oa->o_gr)) {
                         CERROR("recreate objid "LPU64" > last id "LPU64"\n",
-                               oa->o_id, filter_last_id(&obd->u.filter, oa));
+                               oa->o_id, filter_last_id(&obd->u.filter,
+                                                        oa->o_gr));
                         rc = -EINVAL;
                 } else {
+                        struct filter_obd *filter = &obd->u.filter;
+
                         diff = 1;
-                        rc = filter_precreate(obd, oa, group, &diff);
+                        down(&filter->fo_create_lock);
+                        rc = filter_precreate(obd, oa, oa->o_gr, &diff);
+                        up(&filter->fo_create_lock);
                 }
         } else {
-                diff = filter_should_precreate(exp, oa, group);
-                if (diff > 0) {
-                        oa->o_id = filter_last_id(&obd->u.filter, oa);
-                        rc = filter_precreate(obd, oa, group, &diff);
-                        oa->o_id = filter_last_id(&obd->u.filter, oa);
-                        oa->o_valid = OBD_MD_FLID;
-                }
+                rc = filter_handle_precreate(exp, oa, oa->o_gr, oti);
         }
 
         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
@@ -2711,12 +2962,11 @@ int filter_destroy(struct obd_export *exp, struct obdo *oa,
         void *handle = NULL;
         struct llog_cookie *fcc = NULL;
         int rc, rc2, cleanup_phase = 0;
-        obd_gr group = 0;
         struct iattr iattr;
         ENTRY;
 
-        if (oa->o_valid & OBD_MD_FLGROUP)
-                group = oa->o_gr;
+        if (!(oa->o_valid & OBD_MD_FLGROUP))
+                oa->o_gr = 0;
 
         obd = exp->exp_obd;
         filter = &obd->u.filter;
@@ -2724,7 +2974,7 @@ int filter_destroy(struct obd_export *exp, struct obdo *oa,
         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
         cleanup_phase = 1;
 
-        dchild = filter_fid2dentry(obd, NULL, group, oa->o_id);
+        dchild = filter_fid2dentry(obd, NULL, oa->o_gr, oa->o_id);
         if (IS_ERR(dchild))
                 GOTO(cleanup, rc = PTR_ERR(dchild));
         cleanup_phase = 2;
@@ -2737,6 +2987,7 @@ int filter_destroy(struct obd_export *exp, struct obdo *oa,
                         fcc = obdo_logcookie(oa);
                         llog_cancel(llog_get_context(obd, fcc->lgc_subsys + 1),
                                     NULL, 1, fcc, 0);
+                        fcc = NULL; /* we didn't allocate fcc, don't free it */
                 }
                 GOTO(cleanup, rc = -ENOENT);
         }
@@ -2779,7 +3030,7 @@ int filter_destroy(struct obd_export *exp, struct obdo *oa,
          * here, and not while truncating above.  That avoids holding the
          * parent lock for a long time during truncate, which can block other
          * threads from doing anything to objects in that directory. bug 7171 */
-        dparent = filter_parent_lock(obd, group, oa->o_id);
+        dparent = filter_parent_lock(obd, oa->o_gr, oa->o_id);
         if (IS_ERR(dparent))
                 GOTO(cleanup, rc = PTR_ERR(dparent));
         cleanup_phase = 3; /* filter_parent_unlock */
@@ -2795,8 +3046,10 @@ int filter_destroy(struct obd_export *exp, struct obdo *oa,
         /* Quota release need uid/gid of inode */
         obdo_from_inode(oa, dchild->d_inode, OBD_MD_FLUID|OBD_MD_FLGID);
 
+        filter_fmd_drop(exp, oa->o_id, oa->o_gr);
+
         /* this drops dchild->d_inode->i_mutex unconditionally */
-        rc = filter_destroy_internal(obd, oa->o_id, dparent, dchild);
+        rc = filter_destroy_internal(obd, oa->o_id, oa->o_gr, dparent, dchild);
 
         EXIT;
 cleanup:
@@ -2806,6 +3059,7 @@ cleanup:
                         fsfilt_add_journal_cb(obd, 0,
                                               oti ? oti->oti_handle : handle,
                                               filter_cancel_cookies_cb, fcc);
+                        fcc = NULL;
                 }
                 rc = filter_finish_transno(exp, oti, rc);
                 rc2 = fsfilt_commit(obd, dparent->d_inode, handle, 0);
@@ -2818,6 +3072,8 @@ cleanup:
                 filter_parent_unlock(dparent);
         case 2:
                 f_dput(dchild);
+                if (fcc != NULL)
+                        OBD_FREE(fcc, sizeof(*fcc));
         case 1:
                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
                 break;
@@ -2831,30 +3087,32 @@ cleanup:
         qcids[GRPQUOTA] = oa->o_gid;
         rc2 = lquota_adjust(quota_interface, obd, qcids, NULL, rc,
                             FSFILT_OP_UNLINK);
-        CDEBUG_EX(rc2 ? D_ERROR : D_QUOTA,
+
+        CDEBUG(rc ? D_ERROR : D_QUOTA,
                "filter adjust qunit! (rc:%d)\n", rc2);
         return rc;
 }
 
 /* NB start and end are used for punch, but not truncate */
-static int filter_truncate(struct obd_export *exp, struct obdo *oa,
-                           struct lov_stripe_md *lsm, obd_off start,
-                           obd_off end, struct obd_trans_info *oti)
+static int filter_truncate(struct obd_export *exp, struct obd_info *oinfo,
+                           struct obd_trans_info *oti,
+                           struct ptlrpc_request_set *rqset)
 {
         int rc;
         ENTRY;
 
-        if (end != OBD_OBJECT_EOF) {
+        if (oinfo->oi_policy.l_extent.end != OBD_OBJECT_EOF) {
                 CERROR("PUNCH not supported, only truncate: end = "LPX64"\n",
-                       end);
+                       oinfo->oi_policy.l_extent.end);
                 RETURN(-EFAULT);
         }
 
         CDEBUG(D_INODE, "calling truncate for object "LPU64", valid = "LPX64
-               ", o_size = "LPD64"\n", oa->o_id, oa->o_valid, start);
+               ", o_size = "LPD64"\n", oinfo->oi_oa->o_id,
+               oinfo->oi_oa->o_valid, oinfo->oi_policy.l_extent.start);
 
-        oa->o_size = start;
-        rc = filter_setattr(exp, oa, NULL, oti);
+        oinfo->oi_oa->o_size = oinfo->oi_policy.l_extent.start;
+        rc = filter_setattr(exp, oinfo, oti);
         RETURN(rc);
 }
 
@@ -3072,6 +3330,18 @@ static struct dentry *filter_lvfs_fid2dentry(__u64 id, __u32 gen, __u64 gr,
         return filter_fid2dentry(data, NULL, gr, id);
 }
 
+static int filter_process_config(struct obd_device *obd, obd_count len, void *buf)
+{
+        struct lustre_cfg *lcfg = buf;
+        struct lprocfs_static_vars lvars;
+        int rc = 0;
+
+        lprocfs_init_vars(filter, &lvars);
+        
+        rc = class_process_proc_param(PARAM_OST, lvars.obd_vars, lcfg, obd);
+        return(rc);
+}
+
 static struct lvfs_callback_ops filter_lvfs_ops = {
         l_fid2dentry:     filter_lvfs_fid2dentry,
 };
@@ -3086,6 +3356,7 @@ static struct obd_ops filter_obd_ops = {
         .o_connect        = filter_connect,
         .o_reconnect      = filter_reconnect,
         .o_disconnect     = filter_disconnect,
+        .o_ping           = filter_ping,
         .o_init_export    = filter_init_export,
         .o_destroy_export = filter_destroy_export,
         .o_statfs         = filter_statfs,
@@ -3103,6 +3374,7 @@ static struct obd_ops filter_obd_ops = {
         .o_llog_finish    = filter_llog_finish,
         .o_iocontrol      = filter_iocontrol,
         .o_health_check   = filter_health_check,
+        .o_process_config = filter_process_config,
 };
 
 static struct obd_ops filter_sanobd_ops = {
@@ -3115,6 +3387,7 @@ static struct obd_ops filter_sanobd_ops = {
         .o_connect        = filter_connect,
         .o_reconnect      = filter_reconnect,
         .o_disconnect     = filter_disconnect,
+        .o_ping           = filter_ping,
         .o_init_export    = filter_init_export,
         .o_destroy_export = filter_destroy_export,
         .o_statfs         = filter_statfs,
@@ -3152,6 +3425,12 @@ static int __init obdfilter_init(void)
         if (obdfilter_created_scratchpad == NULL)
                 return -ENOMEM;
 
+        ll_fmd_cachep = kmem_cache_create("ll_fmd_cache",
+                                         sizeof(struct filter_mod_data),
+                                         0, 0, NULL, NULL);
+        if (!ll_fmd_cachep)
+                GOTO(out, rc = -ENOMEM);
+
         quota_interface = PORTAL_SYMBOL_GET(filter_quota_interface);
         init_obd_quota_ops(quota_interface, &filter_obd_ops);
         init_obd_quota_ops(quota_interface, &filter_sanobd_ops);
@@ -3159,12 +3438,18 @@ static int __init obdfilter_init(void)
         rc = class_register_type(&filter_obd_ops, NULL, lvars.module_vars,
                                  LUSTRE_OST_NAME, NULL);
         if (rc)
-                GOTO(out, rc);
+                GOTO(out_fmd, rc);
 
         rc = class_register_type(&filter_sanobd_ops, NULL, lvars.module_vars,
                                  LUSTRE_OSTSAN_NAME, NULL);
         if (rc) {
+                int err;
+
                 class_unregister_type(LUSTRE_OST_NAME);
+out_fmd:
+                err = kmem_cache_destroy(ll_fmd_cachep);
+                LASSERTF(err == 0, "Cannot destroy ll_fmd_cachep: rc %d\n",err);
+                ll_fmd_cachep = NULL;
 out:
                 if (quota_interface)
                         PORTAL_SYMBOL_PUT(filter_quota_interface);
@@ -3182,9 +3467,14 @@ static void __exit obdfilter_exit(void)
         if (quota_interface)
                 PORTAL_SYMBOL_PUT(filter_quota_interface);
 
+        if (ll_fmd_cachep) {
+                int rc = kmem_cache_destroy(ll_fmd_cachep);
+                LASSERTF(rc == 0, "Cannot destroy ll_fmd_cachep: rc %d\n", rc);
+                ll_fmd_cachep = NULL;
+        }
+
         class_unregister_type(LUSTRE_OSTSAN_NAME);
         class_unregister_type(LUSTRE_OST_NAME);
-
         OBD_FREE(obdfilter_created_scratchpad,
                  OBDFILTER_CREATED_SCRATCHPAD_ENTRIES *
                  sizeof(*obdfilter_created_scratchpad));
index 4c68b34..685fdf0 100644 (file)
 
 #define FILTER_ROCOMPAT_SUPP (0)
 
-#define FILTER_RECOVERY_TIMEOUT (obd_timeout * 5 * HZ / 2) /* *waves hands* */
-
 #define FILTER_INCOMPAT_SUPP (OBD_INCOMPAT_GROUPS | OBD_INCOMPAT_OST | \
                               OBD_INCOMPAT_COMMON_LR)
 
 #define FILTER_GRANT_CHUNK (2ULL * PTLRPC_MAX_BRW_SIZE)
 #define GRANT_FOR_LLOG(obd) 16
 
+#define FILTER_RECOVERY_TIMEOUT (obd_timeout * 5 * HZ / 2) /* *waves hands* */
+
 /* Data stored per client in the last_rcvd file.  In le32 order. */
 struct filter_client_data {
         __u8  fcd_uuid[40];        /* client UUID */
@@ -44,11 +44,35 @@ struct filter_client_data {
                             OBD_MD_FLATIME | OBD_MD_FLMTIME | OBD_MD_FLCTIME)
 
 struct filter_fid {
-        struct ll_fid   ff_fid;
+        struct ll_fid   ff_fid;         /* ff_fid.f_type == file stripe number */
         __u64           ff_objid;
         __u64           ff_group;
 };
 
+/* per-client-per-object persistent state (LRU) */
+struct filter_mod_data {
+        struct list_head fmd_list;      /* linked to fed_mod_list */
+        __u64            fmd_id;        /* object being written to */
+        __u64            fmd_gr;        /* group being written to */
+        __u64            fmd_mactime_xid;/* xid highest {m,a,c}time setattr */
+        unsigned long    fmd_expire;    /* jiffies when it should expire */
+        int              fmd_refcount;  /* reference counter - list holds 1 */
+};
+
+#ifdef BGL_SUPPORT
+#define FILTER_FMD_MAX_NUM_DEFAULT 128 /* many active files per client on BGL */
+#else
+#define FILTER_FMD_MAX_NUM_DEFAULT  32
+#endif
+#define FILTER_FMD_MAX_AGE_DEFAULT ((obd_timeout + 10) * HZ)
+
+struct filter_mod_data *filter_fmd_find(struct obd_export *exp,
+                                        obd_id objid, obd_gr group);
+struct filter_mod_data *filter_fmd_get(struct obd_export *exp,
+                                       obd_id objid, obd_gr group);
+void filter_fmd_put(struct obd_export *exp, struct filter_mod_data *fmd);
+void filter_fmd_expire(struct obd_export *exp);
+
 enum {
         LPROC_FILTER_READ_BYTES = 0,
         LPROC_FILTER_WRITE_BYTES = 1,
@@ -73,7 +97,7 @@ struct dentry *__filter_oa2dentry(struct obd_device *obd, struct obdo *oa,
 
 int filter_finish_transno(struct obd_export *, struct obd_trans_info *, int rc);
 __u64 filter_next_id(struct filter_obd *, struct obdo *);
-__u64 filter_last_id(struct filter_obd *, struct obdo *);
+__u64 filter_last_id(struct filter_obd *, obd_gr group);
 int filter_update_fidea(struct obd_export *exp, struct inode *inode,
                         void *handle, struct obdo *oa);
 int filter_update_server_data(struct obd_device *, struct file *,
@@ -86,8 +110,8 @@ int filter_destroy(struct obd_export *exp, struct obdo *oa,
                    struct obd_export *);
 int filter_setattr_internal(struct obd_export *exp, struct dentry *dentry,
                             struct obdo *oa, struct obd_trans_info *oti);
-int filter_setattr(struct obd_export *exp, struct obdo *oa,
-                   struct lov_stripe_md *md, struct obd_trans_info *oti);
+int filter_setattr(struct obd_export *exp, struct obd_info *oinfo,
+                   struct obd_trans_info *oti);
 
 struct dentry *filter_create_object(struct obd_device *obd, struct obdo *oa);
 
@@ -102,9 +126,8 @@ int filter_preprw(int cmd, struct obd_export *, struct obdo *, int objcount,
 int filter_commitrw(int cmd, struct obd_export *, struct obdo *, int objcount,
                     struct obd_ioobj *, int niocount, struct niobuf_local *,
                     struct obd_trans_info *, int rc);
-int filter_brw(int cmd, struct obd_export *, struct obdo *,
-               struct lov_stripe_md *, obd_count oa_bufs, struct brw_page *,
-               struct obd_trans_info *);
+int filter_brw(int cmd, struct obd_export *, struct obd_info *oinfo,
+               obd_count oa_bufs, struct brw_page *pga, struct obd_trans_info *);
 void flip_into_page_cache(struct inode *inode, struct page *new_page);
 
 /* filter_io_*.c */
@@ -129,6 +152,7 @@ void filter_iobuf_put(struct filter_obd *filter, struct filter_iobuf *iobuf,
 int filter_direct_io(int rw, struct dentry *dchild, struct filter_iobuf *iobuf,
                      struct obd_export *exp, struct iattr *attr,
                      struct obd_trans_info *oti, void **wait_handle);
+int filter_clear_truncated_page(struct inode *inode);
 
 /* filter_log.c */
 struct ost_filterdata {
index fdc0492..38efbc2 100644 (file)
@@ -107,7 +107,7 @@ static void filter_grant_incoming(struct obd_export *exp, struct obdo *oa)
         /* Add some margin, since there is a small race if other RPCs arrive
          * out-or-order and have already consumed some grant.  We want to
          * leave this here in case there is a large error in accounting. */
-        CDEBUG_EX(oa->o_grant > fed->fed_grant + FILTER_GRANT_CHUNK ? mask:D_CACHE,
+        CDEBUG(oa->o_grant > fed->fed_grant + FILTER_GRANT_CHUNK ? mask:D_CACHE,
                "%s: cli %s/%p reports grant: "LPU64" dropped: %u, local: %lu\n",
                obd->obd_name, exp->exp_client_uuid.uuid, exp, oa->o_grant,
                oa->o_dropped, fed->fed_grant);
@@ -160,9 +160,10 @@ obd_size filter_grant_space_left(struct obd_export *exp)
 
         LASSERT_SPIN_LOCKED(&obd->obd_osfs_lock);
 
-        if (time_before(obd->obd_osfs_age, jiffies - HZ)) {
+        if (cfs_time_before_64(obd->obd_osfs_age, cfs_time_current_64() - HZ)) {
 restat:
-                rc = fsfilt_statfs(obd, obd->u.obt.obt_sb, jiffies + 1);
+                rc = fsfilt_statfs(obd, obd->u.obt.obt_sb,
+                                   cfs_time_current_64() + HZ);
                 if (rc) /* N.B. statfs can't really fail */
                         RETURN(0);
                 statfs_done = 1;
@@ -284,7 +285,8 @@ static int filter_preprw_read(int cmd, struct obd_export *exp, struct obdo *oa,
         ENTRY;
 
         /* We are currently not supporting multi-obj BRW_READ RPCS at all.
-         * When we do this function's dentry cleanup will need to be fixed */
+         * When we do this function's dentry cleanup will need to be fixed.
+         * These values are verified in ost_brw_write() from the wire. */
         LASSERTF(objcount == 1, "%d\n", objcount);
         LASSERTF(obj->ioo_bufcnt > 0, "%d\n", obj->ioo_bufcnt);
 
@@ -310,10 +312,8 @@ static int filter_preprw_read(int cmd, struct obd_export *exp, struct obdo *oa,
 
         inode = dentry->d_inode;
 
-        if (oa)
-                obdo_to_inode(inode, oa, OBD_MD_FLATIME);
-
-        fsfilt_check_slow(now, obd_timeout, "preprw_read setup");
+        obdo_to_inode(inode, oa, OBD_MD_FLATIME);
+        fsfilt_check_slow(obd, now, obd_timeout, "preprw_read setup");
 
         for (i = 0, lnb = res, rnb = nb; i < obj->ioo_bufcnt;
              i++, rnb++, lnb++) {
@@ -346,7 +346,7 @@ static int filter_preprw_read(int cmd, struct obd_export *exp, struct obdo *oa,
                 filter_iobuf_add_page(obd, iobuf, inode, lnb->page);
         }
 
-        fsfilt_check_slow(now, obd_timeout, "start_page_read");
+        fsfilt_check_slow(obd, now, obd_timeout, "start_page_read");
 
         rc = filter_direct_io(OBD_BRW_READ, dentry, iobuf,
                               exp, NULL, NULL, NULL);
@@ -458,7 +458,7 @@ static int filter_grant_check(struct obd_export *exp, int objcount,
         fed->fed_pending += used;
         exp->exp_obd->u.filter.fo_tot_pending += used;
 
-        CDEBUG_EX(mask,
+        CDEBUG(mask,
                "%s: cli %s/%p used: %lu ungranted: %lu grant: %lu dirty: %lu\n",
                exp->exp_obd->obd_name, exp->exp_client_uuid.uuid, exp, used,
                ungranted, fed->fed_grant, fed->fed_dirty);
@@ -510,6 +510,7 @@ static int filter_preprw_write(int cmd, struct obd_export *exp, struct obdo *oa,
         struct niobuf_remote *rnb;
         struct niobuf_local *lnb = res;
         struct fsfilt_objinfo fso;
+        struct filter_mod_data *fmd;
         struct dentry *dentry = NULL;
         void *iobuf;
         obd_size left;
@@ -540,13 +541,24 @@ static int filter_preprw_write(int cmd, struct obd_export *exp, struct obdo *oa,
         fso.fso_dentry = dentry;
         fso.fso_bufcnt = obj->ioo_bufcnt;
 
-        fsfilt_check_slow(now, obd_timeout, "preprw_write setup");
+        fsfilt_check_slow(exp->exp_obd, now, obd_timeout, "preprw_write setup");
+
+        /* Don't update inode timestamps if this write is older than a
+         * setattr which modifies the timestamps. b=10150 */
+        /* XXX when we start having persistent reservations this needs to
+         * be changed to filter_fmd_get() to create the fmd if it doesn't
+         * already exist so we can store the reservation handle there. */
+        fmd = filter_fmd_find(exp, obj->ioo_id, obj->ioo_gr);
 
         spin_lock(&exp->exp_obd->obd_osfs_lock);
         if (oa) {
                 filter_grant_incoming(exp, oa);
-                obdo_to_inode(dentry->d_inode, oa,
-                              OBD_MD_FLATIME | OBD_MD_FLMTIME | OBD_MD_FLCTIME);
+                if (fmd && fmd->fmd_mactime_xid > oti->oti_xid)
+                        oa->o_valid &= ~(OBD_MD_FLMTIME | OBD_MD_FLCTIME |
+                                         OBD_MD_FLATIME);
+                else
+                        obdo_to_inode(dentry->d_inode, oa, OBD_MD_FLATIME |
+                                      OBD_MD_FLMTIME | OBD_MD_FLCTIME);
         }
         cleanup_phase = 3;
 
@@ -563,6 +575,7 @@ static int filter_preprw_write(int cmd, struct obd_export *exp, struct obdo *oa,
         }
 
         spin_unlock(&exp->exp_obd->obd_osfs_lock);
+        filter_fmd_put(exp, fmd);
 
         if (rc)
                 GOTO(cleanup, rc);
@@ -631,7 +644,7 @@ static int filter_preprw_write(int cmd, struct obd_export *exp, struct obdo *oa,
         rc = filter_direct_io(OBD_BRW_READ, dentry, iobuf, exp,
                               NULL, NULL, NULL);
 
-        fsfilt_check_slow(now, obd_timeout, "start_page_write");
+        fsfilt_check_slow(exp->exp_obd, now, obd_timeout, "start_page_write");
 
         lprocfs_counter_add(exp->exp_obd->obd_stats, LPROC_FILTER_WRITE_BYTES,
                             tot_bytes);
@@ -811,9 +824,9 @@ int filter_commitrw(int cmd, struct obd_export *exp, struct obdo *oa,
         return -EPROTO;
 }
 
-int filter_brw(int cmd, struct obd_export *exp, struct obdo *oa,
-               struct lov_stripe_md *lsm, obd_count oa_bufs,
-               struct brw_page *pga, struct obd_trans_info *oti)
+int filter_brw(int cmd, struct obd_export *exp, struct obd_info *oinfo,
+               obd_count oa_bufs, struct brw_page *pga,
+               struct obd_trans_info *oti)
 {
         struct obd_ioobj ioo;
         struct niobuf_local *lnb;
@@ -834,14 +847,16 @@ int filter_brw(int cmd, struct obd_export *exp, struct obdo *oa,
                 rnb[i].len = pga[i].count;
         }
 
-        obdo_to_ioobj(oa, &ioo);
+        obdo_to_ioobj(oinfo->oi_oa, &ioo);
         ioo.ioo_bufcnt = oa_bufs;
 
-        ret = filter_preprw(cmd, exp, oa, 1, &ioo, oa_bufs, rnb, lnb, oti);
+        ret = filter_preprw(cmd, exp, oinfo->oi_oa, 1, &ioo,
+                            oa_bufs, rnb, lnb, oti);
         if (ret != 0)
                 GOTO(out, ret);
 
-        ret = filter_commitrw(cmd, exp, oa, 1, &ioo, oa_bufs, lnb, oti, ret);
+        ret = filter_commitrw(cmd, exp, oinfo->oi_oa, 1, &ioo,
+                              oa_bufs, lnb, oti, ret);
 
 out:
         if (lnb)
index b10a83a..314481b 100644 (file)
@@ -110,13 +110,9 @@ static void dump_page(int rw, unsigned long block, struct page *page)
  * free the buffers and drop the page from cache.  The buffers should not
  * be dirty, because we already called fdatasync/fdatawait on them.
  */
-static int filter_clear_page_cache(struct inode *inode, struct kiobuf *iobuf)
+static int filter_sync_inode_data(struct inode *inode)
 {
-        struct page *page;
-        int i, rc, rc2;
-
-        check_pending_bhs(KIOBUF_GET_BLOCKS(iobuf), iobuf->nr_pages,
-                          inode->i_dev, 1 << inode->i_blkbits);
+        int rc, rc2;
 
         /* This is nearly generic_osync_inode, without the waiting on the inode
         rc = generic_osync_inode(inode, inode->i_mapping,
@@ -129,6 +125,19 @@ static int filter_clear_page_cache(struct inode *inode, struct kiobuf *iobuf)
         rc2 = filemap_fdatawait(inode->i_mapping);
         if (rc == 0)
                 rc = rc2;
+
+        return rc;
+}
+
+static int filter_clear_page_cache(struct inode *inode, struct kiobuf *iobuf)
+{
+        struct page *page;
+        int i, rc;
+
+        check_pending_bhs(KIOBUF_GET_BLOCKS(iobuf), iobuf->nr_pages,
+                          inode->i_dev, 1 << inode->i_blkbits);
+
+        rc = filter_sync_inode_data(inode);
         if (rc != 0)
                 RETURN(rc);
 
@@ -139,6 +148,39 @@ static int filter_clear_page_cache(struct inode *inode, struct kiobuf *iobuf)
                                       iobuf->maplist[i]->index);
                 if (page == NULL)
                         continue;
+                if (page->mapping != NULL) {
+                        /* Now that the only source of such pages in truncate
+                         * path flushes these pages to disk and and then
+                         * discards, this is error condition */
+                        CERROR("Data page in page cache during write!\n");
+                        ll_truncate_complete_page(page);
+                }
+
+                unlock_page(page);
+                page_cache_release(page);
+        }
+
+        return 0;
+}
+
+int filter_clear_truncated_page(struct inode *inode)
+{
+        struct page *page;
+        int rc;
+
+        /* Truncate on page boundary, so nothing to flush? */
+        if (!(inode->i_size & (PAGE_CACHE_SIZE-1)))
+                return 0;
+
+        rc = filter_sync_inode_data(inode);
+        if (rc != 0)
+                RETURN(rc);
+
+        /* be careful to call this after fsync_inode_data_buffers has waited
+         * for IO to complete before we evict it from the cache */
+        page = find_lock_page(inode->i_mapping,
+                              inode->i_size >> PAGE_CACHE_SHIFT);
+        if (page) {
                 if (page->mapping != NULL)
                         ll_truncate_complete_page(page);
 
@@ -425,7 +467,7 @@ int filter_commitrw_write(struct obd_export *exp, struct obdo *oa, int objcount,
                 GOTO(cleanup, rc);
         }
 
-        fsfilt_check_slow(now, obd_timeout, "brw_start");
+        fsfilt_check_slow(obd, now, obd_timeout, "brw_start");
 
         i = OBD_MD_FLATIME | OBD_MD_FLMTIME | OBD_MD_FLCTIME;
 
@@ -461,18 +503,18 @@ int filter_commitrw_write(struct obd_export *exp, struct obdo *oa, int objcount,
         if (rc == 0)
                 obdo_from_inode(oa, inode, FILTER_VALID_FLAGS);
 
-        fsfilt_check_slow(now, obd_timeout, "direct_io");
+        fsfilt_check_slow(obd, now, obd_timeout, "direct_io");
 
         err = fsfilt_commit_wait(obd, inode, wait_handle);
         if (err) {
                 CERROR("Failure to commit OST transaction (%d)?\n", err);
                 rc = err;
         }
-        if (obd->obd_replayable && !err)
+        if (obd->obd_replayable && !rc)
                 LASSERTF(oti->oti_transno <= obd->obd_last_committed,
                          "oti_transno "LPU64" last_committed "LPU64"\n",
                          oti->oti_transno, obd->obd_last_committed);
-        fsfilt_check_slow(now, obd_timeout, "commitrw commit");
+        fsfilt_check_slow(obd, now, obd_timeout, "commitrw commit");
 
 cleanup:
         filter_grant_commit(exp, niocount, res);
index 1a07a95..6b4811a 100644 (file)
@@ -50,8 +50,7 @@ struct filter_iobuf {
         int               dr_error;
         struct page     **dr_pages;
         unsigned long    *dr_blocks;
-        spinlock_t        dr_lock;
-        unsigned long     dr_start_time; /* jiffies */
+        spinlock_t        dr_lock;              /* IRQ lock */
         unsigned int      dr_ignore_quota:1;
         struct filter_obd *dr_filter;
 };
@@ -59,65 +58,48 @@ struct filter_iobuf {
 static void record_start_io(struct filter_iobuf *iobuf, int rw, int size)
 {
         struct filter_obd *filter = iobuf->dr_filter;
-        unsigned long flags;
 
         atomic_inc(&iobuf->dr_numreqs);
 
         if (rw == OBD_BRW_READ) {
+                atomic_inc(&filter->fo_r_in_flight);
                 lprocfs_oh_tally(&filter->fo_read_rpc_hist,
-                                 filter->fo_r_in_flight);
+                                 atomic_read(&filter->fo_r_in_flight));
                 lprocfs_oh_tally_log2(&filter->fo_r_disk_iosize, size);
         } else {
+                atomic_inc(&filter->fo_w_in_flight);
                 lprocfs_oh_tally(&filter->fo_write_rpc_hist,
-                                 filter->fo_w_in_flight);
+                                 atomic_read(&filter->fo_w_in_flight));
                 lprocfs_oh_tally_log2(&filter->fo_w_disk_iosize, size);
         }
-        spin_lock_irqsave(&filter->fo_stats_lock, flags);
-        if (rw == OBD_BRW_READ)
-                filter->fo_r_in_flight++;
-        else
-                filter->fo_w_in_flight++;
-        spin_unlock_irqrestore(&filter->fo_stats_lock, flags);
-        iobuf->dr_start_time = jiffies;
 }
 
 static void record_finish_io(struct filter_iobuf *iobuf, int rw, int rc)
 {
         struct filter_obd *filter = iobuf->dr_filter;
-        unsigned long flags, stop_time = jiffies;
 
-        spin_lock_irqsave(&filter->fo_stats_lock, flags);
+        /* CAVEAT EMPTOR: possibly in IRQ context 
+         * DO NOT record procfs stats here!!! */
+
         if (rw == OBD_BRW_READ)
-                filter->fo_r_in_flight--;
+                atomic_dec(&filter->fo_r_in_flight);
         else
-                filter->fo_w_in_flight--;
-        spin_unlock_irqrestore(&filter->fo_stats_lock, flags);
+                atomic_dec(&filter->fo_w_in_flight);
 
         if (atomic_dec_and_test(&iobuf->dr_numreqs))
                 wake_up(&iobuf->dr_wait);
-
-        if (rc != 0)
-                return;
-
-        if (rw == OBD_BRW_READ) {
-                lprocfs_oh_tally_log2(&filter->fo_r_io_time,
-                                      stop_time - iobuf->dr_start_time);
-        } else {
-                lprocfs_oh_tally_log2(&filter->fo_w_io_time,
-                                      stop_time - iobuf->dr_start_time);
-        }
 }
 
 static int dio_complete_routine(struct bio *bio, unsigned int done, int error)
 {
         struct filter_iobuf *iobuf = bio->bi_private;
-        unsigned long flags;
+        unsigned long        flags;
 
-        if (bio->bi_size) {
-                CWARN("gets called against non-complete bio 0x%p: %d/%d/%d\n",
-                      bio, bio->bi_size, done, error);
+        /* CAVEAT EMPTOR: possibly in IRQ context 
+         * DO NOT record procfs stats here!!! */
+
+        if (bio->bi_size)                       /* Not complete */
                 return 1;
-        }
 
         if (iobuf == NULL) {
                 CERROR("***** bio->bi_private is NULL!  This should never "
@@ -258,6 +240,8 @@ int filter_do_bio(struct obd_device *obd, struct inode *inode,
         int            sector_bits = inode->i_sb->s_blocksize_bits - 9;
         unsigned int   blocksize = inode->i_sb->s_blocksize;
         struct bio    *bio = NULL;
+        int            frags = 0;
+        unsigned long  start_time = jiffies;
         struct page   *page;
         unsigned int   page_offset;
         sector_t       sector;
@@ -327,6 +311,7 @@ int filter_do_bio(struct obd_device *obd, struct inode *inode,
                                         record_finish_io(iobuf, rw, rc);
                                         goto out;
                                 }
+                                frags++;
                         }
 
                         /* allocate new bio */
@@ -353,6 +338,7 @@ int filter_do_bio(struct obd_device *obd, struct inode *inode,
                 record_start_io(iobuf, rw, bio->bi_size);
                 rc = fsfilt_send_bio(rw, obd, inode, bio);
                 if (rc >= 0) {
+                        frags++;
                         rc = 0;
                 } else {
                         CERROR("Can't send bio: %d\n", rc);
@@ -363,6 +349,16 @@ int filter_do_bio(struct obd_device *obd, struct inode *inode,
  out:
         wait_event(iobuf->dr_wait, atomic_read(&iobuf->dr_numreqs) == 0);
 
+        if (rw == OBD_BRW_READ) {
+                lprocfs_oh_tally(&obd->u.filter.fo_r_dio_frags, frags);
+                lprocfs_oh_tally_log2(&obd->u.filter.fo_r_io_time, 
+                                      jiffies - start_time);
+        } else {
+                lprocfs_oh_tally(&obd->u.filter.fo_w_dio_frags, frags);
+                lprocfs_oh_tally_log2(&obd->u.filter.fo_w_io_time,
+                                      jiffies - start_time);
+        }
+
         if (rc == 0)
                 rc = iobuf->dr_error;
         RETURN(rc);
@@ -380,27 +376,36 @@ int filter_do_bio(struct obd_device *obd, struct inode *inode,
  * to free the buffers and drop the page from cache.  The buffers should
  * not be dirty, because we already called fdatasync/fdatawait on them.
  */
+static int filter_sync_inode_data(struct inode *inode, int locked)
+{
+        int rc = 0;
+
+        /* This is nearly do_fsync(), without the waiting on the inode */
+        /* XXX: in 2.6.16 (at least) we don't need to hold i_mutex over
+         * filemap_fdatawrite() and filemap_fdatawait(), so we may no longer
+         * need this lock here at all. */
+        if (!locked)
+                LOCK_INODE_MUTEX(inode);
+        if (inode->i_mapping->nrpages) {
+                current->flags |= PF_SYNCWRITE;
+                rc = filemap_fdatawrite(inode->i_mapping);
+                if (rc == 0)
+                        rc = filemap_fdatawait(inode->i_mapping);
+                current->flags &= ~PF_SYNCWRITE;
+        }
+        if (!locked)
+                UNLOCK_INODE_MUTEX(inode);
+
+        return rc;
+}
+
 static int filter_clear_page_cache(struct inode *inode,
-                                    struct filter_iobuf *iobuf)
+                                   struct filter_iobuf *iobuf)
 {
         struct page *page;
-        int i, rc, rc2;
-
-        /* This is nearly generic_osync_inode, without the waiting on the inode
-        rc = generic_osync_inode(inode, inode->i_mapping,
-                                 OSYNC_DATA|OSYNC_METADATA);
-         */
-        down(&inode->i_sem);
-        current->flags |= PF_SYNCWRITE;
-        rc = filemap_fdatawrite(inode->i_mapping);
-        rc2 = sync_mapping_buffers(inode->i_mapping);
-        if (rc == 0)
-                rc = rc2;
-        rc2 = filemap_fdatawait(inode->i_mapping);
-        current->flags &= ~PF_SYNCWRITE;
-        up(&inode->i_sem);
-        if (rc == 0)
-                rc = rc2;
+        int i, rc;
+
+        rc = filter_sync_inode_data(inode, 0);
         if (rc != 0)
                 RETURN(rc);
 
@@ -412,6 +417,10 @@ static int filter_clear_page_cache(struct inode *inode,
                 if (page == NULL)
                         continue;
                 if (page->mapping != NULL) {
+                        /* Now that the only source of such pages in truncate
+                         * path flushes these pages to disk and and then
+                         * discards, this is error condition */
+                        CERROR("Data page in page cache during write!\n");
                         wait_on_page_writeback(page);
                         ll_truncate_complete_page(page);
                 }
@@ -423,6 +432,35 @@ static int filter_clear_page_cache(struct inode *inode,
         return 0;
 }
 
+int filter_clear_truncated_page(struct inode *inode)
+{
+        struct page *page;
+        int rc;
+
+        /* Truncate on page boundary, so nothing to flush? */
+        if (!(inode->i_size & (PAGE_CACHE_SIZE-1)))
+                return 0;
+
+        rc = filter_sync_inode_data(inode, 1);
+        if (rc != 0)
+                RETURN(rc);
+
+        /* be careful to call this after fsync_inode_data_buffers has waited
+         * for IO to complete before we evict it from the cache */
+        page = find_lock_page(inode->i_mapping,
+                              inode->i_size >> PAGE_CACHE_SHIFT);
+        if (page) {
+                if (page->mapping != NULL) {
+                        wait_on_page_writeback(page);
+                        ll_truncate_complete_page(page);
+                }
+                unlock_page(page);
+                page_cache_release(page);
+        }
+
+        return 0;
+}
+
 /* Must be called with i_mutex taken for writes; this will drop it */
 int filter_direct_io(int rw, struct dentry *dchild, struct filter_iobuf *iobuf,
                      struct obd_export *exp, struct iattr *attr,
@@ -598,20 +636,20 @@ int filter_commitrw_write(struct obd_export *exp, struct obdo *oa,
         cleanup_phase = 2;
 
         LOCK_INODE_MUTEX(inode);
-        fsfilt_check_slow(now, obd_timeout, "i_mutex");
+        fsfilt_check_slow(obd, now, obd_timeout, "i_mutex");
         oti->oti_handle = fsfilt_brw_start(obd, objcount, &fso, niocount, res,
                                            oti);
         if (IS_ERR(oti->oti_handle)) {
                 UNLOCK_INODE_MUTEX(inode);
                 rc = PTR_ERR(oti->oti_handle);
-                CDEBUG_EX(rc == -ENOSPC ? D_INODE : D_ERROR,
+                CDEBUG(rc == -ENOSPC ? D_INODE : D_ERROR,
                        "error starting transaction: rc = %d\n", rc);
                 oti->oti_handle = NULL;
                 GOTO(cleanup, rc);
         }
         /* have to call fsfilt_commit() from this point on */
 
-        fsfilt_check_slow(now, obd_timeout, "brw_start");
+        fsfilt_check_slow(obd, now, obd_timeout, "brw_start");
 
         i = OBD_MD_FLATIME | OBD_MD_FLMTIME | OBD_MD_FLCTIME;
 
@@ -639,6 +677,13 @@ int filter_commitrw_write(struct obd_export *exp, struct obdo *oa,
                         iattr.ia_mode &= ~S_ISGID;
 
                 rc = filter_update_fidea(exp, inode, oti->oti_handle, oa);
+
+                /* To avoid problems with quotas, UID and GID must be set
+                 * in the inode before filter_direct_io() - see bug 10357. */
+                if (iattr.ia_valid & ATTR_UID)
+                        inode->i_uid = iattr.ia_uid;
+                if (iattr.ia_valid & ATTR_GID)
+                        inode->i_gid = iattr.ia_gid;
         }
 
         /* filter_direct_io drops i_mutex */
@@ -652,18 +697,20 @@ int filter_commitrw_write(struct obd_export *exp, struct obdo *oa,
 
         lquota_getflag(quota_interface, obd, oa);
 
-        fsfilt_check_slow(now, obd_timeout, "direct_io");
+        fsfilt_check_slow(obd, now, obd_timeout, "direct_io");
 
         err = fsfilt_commit_wait(obd, inode, wait_handle);
-        if (err)
+        if (err) {
+                CERROR("Failure to commit OST transaction (%d)?\n", err);
                 rc = err;
+        }
 
-        if (obd->obd_replayable && !err)
+        if (obd->obd_replayable && !rc)
                 LASSERTF(oti->oti_transno <= obd->obd_last_committed,
                          "oti_transno "LPU64" last_committed "LPU64"\n",
                          oti->oti_transno, obd->obd_last_committed);
 
-        fsfilt_check_slow(now, obd_timeout, "commitrw commit");
+        fsfilt_check_slow(obd, now, obd_timeout, "commitrw commit");
 
 cleanup:
         filter_grant_commit(exp, niocount, res);
@@ -687,7 +734,7 @@ cleanup:
         qcids[GRPQUOTA] = oa->o_gid;
         err = lquota_adjust(quota_interface, obd, qcids, NULL, rc,
                             FSFILT_OP_CREATE);
-        CDEBUG_EX(err ? D_ERROR : D_QUOTA,
+        CDEBUG(err ? D_ERROR : D_QUOTA,
                "error filter adjust qunit! (rc:%d)\n", err);
 
         RETURN(rc);
index c61be24..001a0ad 100644 (file)
@@ -162,25 +162,25 @@ static int filter_recov_log_setattr_cb(struct llog_ctxt *ctxt,
         struct obd_device *obd = ctxt->loc_obd;
         struct obd_export *exp = obd->obd_self_export;
         struct llog_setattr_rec *lsr;
-        struct obdo *oa;
+        struct obd_info oinfo = { { { 0 } } };
         obd_id oid;
         int rc = 0;
         ENTRY;
 
         lsr = (struct llog_setattr_rec *)rec;
-        oa = obdo_alloc();
-
-        oa->o_valid |= (OBD_MD_FLID | OBD_MD_FLUID | OBD_MD_FLGID |
-                        OBD_MD_FLCOOKIE);
-        oa->o_id = lsr->lsr_oid;
-        oa->o_gr = lsr->lsr_ogen;
-        oa->o_uid = lsr->lsr_uid;
-        oa->o_gid = lsr->lsr_gid;
-        memcpy(obdo_logcookie(oa), cookie, sizeof(*cookie));
-        oid = oa->o_id;
-
-        rc = filter_setattr(exp, oa, NULL, NULL);
-        obdo_free(oa);
+        oinfo.oi_oa = obdo_alloc();
+
+        oinfo.oi_oa->o_valid |= (OBD_MD_FLID | OBD_MD_FLUID | OBD_MD_FLGID |
+                                 OBD_MD_FLCOOKIE);
+        oinfo.oi_oa->o_id = lsr->lsr_oid;
+        oinfo.oi_oa->o_gr = lsr->lsr_ogen;
+        oinfo.oi_oa->o_uid = lsr->lsr_uid;
+        oinfo.oi_oa->o_gid = lsr->lsr_gid;
+        memcpy(obdo_logcookie(oinfo.oi_oa), cookie, sizeof(*cookie));
+        oid = oinfo.oi_oa->o_id;
+
+        rc = filter_setattr(exp, &oinfo, NULL);
+        obdo_free(oinfo.oi_oa);
 
         if (rc == -ENOENT) {
                 CDEBUG(D_HA, "object already removed, send cookie\n");
index 935ae6f..4f165a8 100644 (file)
@@ -237,6 +237,62 @@ static int lprocfs_filter_wr_itune(struct file *file, const char *buffer,
 }
 #endif
 
+int lprocfs_filter_rd_fmd_max_num(char *page, char **start, off_t off,
+                                  int count, int *eof, void *data)
+{
+        struct obd_device *obd = data;
+        int rc;
+
+        rc = snprintf(page, count, "%u\n", obd->u.filter.fo_fmd_max_num);
+        return rc;
+}
+
+int lprocfs_filter_wr_fmd_max_num(struct file *file, const char *buffer,
+                                  unsigned long count, void *data)
+{
+        struct obd_device *obd = data;
+        int val;
+        int rc;
+
+        rc = lprocfs_write_helper(buffer, count, &val);
+        if (rc)
+                return rc;
+
+        if (val > 65536 || val < 1)
+                return -EINVAL;
+
+        obd->u.filter.fo_fmd_max_num = val;
+        return count;
+}
+
+int lprocfs_filter_rd_fmd_max_age(char *page, char **start, off_t off,
+                                  int count, int *eof, void *data)
+{
+        struct obd_device *obd = data;
+        int rc;
+
+        rc = snprintf(page, count, "%u\n", obd->u.filter.fo_fmd_max_age / HZ);
+        return rc;
+}
+
+int lprocfs_filter_wr_fmd_max_age(struct file *file, const char *buffer,
+                                  unsigned long count, void *data)
+{
+        struct obd_device *obd = data;
+        int val;
+        int rc;
+
+        rc = lprocfs_write_helper(buffer, count, &val);
+        if (rc)
+                return rc;
+
+        if (val > 65536 || val < 1)
+                return -EINVAL;
+
+        obd->u.filter.fo_fmd_max_age = val * HZ;
+        return count;
+}
+
 static struct lprocfs_vars lprocfs_obd_vars[] = {
         { "uuid",         lprocfs_rd_uuid,          0, 0 },
         { "blocksize",    lprocfs_rd_blksize,       0, 0 },
@@ -268,6 +324,10 @@ static struct lprocfs_vars lprocfs_obd_vars[] = {
         { "quota_itune_sz", lprocfs_filter_rd_itune,
                             lprocfs_filter_wr_itune, 0},
 #endif
+        { "client_cache_count", lprocfs_filter_rd_fmd_max_num,
+                          lprocfs_filter_wr_fmd_max_num, 0 },
+        { "client_cache_seconds", lprocfs_filter_rd_fmd_max_age,
+                          lprocfs_filter_wr_fmd_max_age, 0 },
         { 0 }
 };
 
@@ -427,6 +487,29 @@ static int filter_brw_stats_seq_show(struct seq_file *seq, void *v)
                         break;
         }
 
+        seq_printf(seq, "\n\t\t\tread\t\t\twrite\n");
+        seq_printf(seq, "dio frags             rpcs   %% cum %% |");
+        seq_printf(seq, "       rpcs   %% cum %%\n");
+
+        read_tot = lprocfs_oh_sum(&filter->fo_r_dio_frags);
+        write_tot = lprocfs_oh_sum(&filter->fo_w_dio_frags);
+
+        read_cum = 0;
+        write_cum = 0;
+        for (i = 0; i < OBD_HIST_MAX; i++) {
+                unsigned long r = filter->fo_r_dio_frags.oh_buckets[i];
+                unsigned long w = filter->fo_w_dio_frags.oh_buckets[i];
+                read_cum += r;
+                write_cum += w;
+                seq_printf(seq, "%u:\t\t%10lu %3lu %3lu   | %10lu %3lu %3lu\n",
+                                 i, r, pct(r, read_tot),
+                                 pct(read_cum, read_tot), w,
+                                 pct(w, write_tot),
+                                 pct(write_cum, write_tot));
+                if (read_cum == read_tot && write_cum == write_tot)
+                        break;
+        }
+
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
         seq_printf(seq, "\n\t\t\tread\t\t\twrite\n");
         seq_printf(seq, "disk ios in flight     ios   %% cum %% |");
@@ -565,6 +648,8 @@ static ssize_t filter_brw_stats_seq_write(struct file *file, const char *buf,
         lprocfs_oh_clear(&filter->fo_w_discont_blocks);
         lprocfs_oh_clear(&filter->fo_r_disk_iosize);
         lprocfs_oh_clear(&filter->fo_w_disk_iosize);
+        lprocfs_oh_clear(&filter->fo_r_dio_frags);
+        lprocfs_oh_clear(&filter->fo_w_dio_frags);
 
         return len;
 }
index 764c55c..7079547 100644 (file)
@@ -52,13 +52,14 @@ static int osc_wr_max_pages_per_rpc(struct file *file, const char *buffer,
 {
         struct obd_device *dev = data;
         struct client_obd *cli = &dev->u.cli;
+        struct obd_connect_data *ocd = &cli->cl_import->imp_connect_data;
         int val, rc;
 
         rc = lprocfs_write_helper(buffer, count, &val);
         if (rc)
                 return rc;
 
-        if (val < 1 || val > PTLRPC_MAX_BRW_PAGES)
+        if (val < 1 || val > ocd->ocd_brw_size >> PAGE_SHIFT)
                 return -ERANGE;
 
         client_obd_list_lock(&cli->cl_loi_list_lock);
@@ -111,13 +112,15 @@ static int osc_rd_max_dirty_mb(char *page, char **start, off_t off, int count,
 {
         struct obd_device *dev = data;
         struct client_obd *cli = &dev->u.cli;
-        unsigned val;
+        long val;
+        int mult;
 
         client_obd_list_lock(&cli->cl_loi_list_lock);
-        val = cli->cl_dirty_max >> 20;
+        val = cli->cl_dirty_max;
         client_obd_list_unlock(&cli->cl_loi_list_lock);
 
-        return snprintf(page, count, "%u\n", val);
+        mult = 1 << 20;
+        return lprocfs_read_frac_helper(page, count, val, mult);
 }
 
 static int osc_wr_max_dirty_mb(struct file *file, const char *buffer,
@@ -125,18 +128,19 @@ static int osc_wr_max_dirty_mb(struct file *file, const char *buffer,
 {
         struct obd_device *dev = data;
         struct client_obd *cli = &dev->u.cli;
-        int val, rc;
+        int pages_number, mult, rc;
 
-        rc = lprocfs_write_helper(buffer, count, &val);
+        mult = 1 << (20 - PAGE_SHIFT);
+        rc = lprocfs_write_frac_helper(buffer, count, &pages_number, mult);
         if (rc)
                 return rc;
 
-        if (val < 0 || val > OSC_MAX_DIRTY_MB_MAX ||
-            val > num_physpages >> (20 - PAGE_SHIFT - 2)) /* 1/4 of RAM */
+        if (pages_number < 0 || pages_number > OSC_MAX_DIRTY_MB_MAX << (20 - PAGE_SHIFT) ||
+            pages_number > num_physpages / 4) /* 1/4 of RAM */
                 return -ERANGE;
 
         client_obd_list_lock(&cli->cl_loi_list_lock);
-        cli->cl_dirty_max = (obd_count)val * 1024 * 1024;
+        cli->cl_dirty_max = (obd_count)(pages_number << PAGE_SHIFT);
         osc_wake_cache_waiters(cli);
         client_obd_list_unlock(&cli->cl_loi_list_lock);
 
index d21c3e8..5665c88 100644 (file)
@@ -55,7 +55,7 @@ static int osc_interpret_create(struct ptlrpc_request *req, void *data, int rc)
         ENTRY;
 
         if (req->rq_repmsg) {
-                body = lustre_swab_repbuf(req, 0, sizeof(*body),
+                body = lustre_swab_repbuf(req, REPLY_REC_OFF, sizeof(*body),
                                           lustre_swab_ost_body);
                 if (body == NULL && rc == 0)
                         rc = -EPROTO;
@@ -80,7 +80,8 @@ static int osc_interpret_create(struct ptlrpc_request *req, void *data, int rc)
                 spin_unlock(&oscc->oscc_lock);
                 DEBUG_REQ(D_ERROR, req,
                           "unknown rc %d from async create: failing oscc", rc);
-                ptlrpc_fail_import(req->rq_import, req->rq_reqmsg->conn_cnt);
+                ptlrpc_fail_import(req->rq_import,
+                                   lustre_msg_get_conn_cnt(req->rq_reqmsg));
         } else {
                 if (rc == 0) {
                         oscc->oscc_flags &= ~OSCC_FLAG_LOW;
@@ -91,8 +92,14 @@ static int osc_interpret_create(struct ptlrpc_request *req, void *data, int rc)
                                                 max(diff/3, OST_MIN_PRECREATE);
                                 oscc->oscc_last_id = body->oa.o_id;
                         }
+                } else {
+                        /* filter always set body->oa.o_id as the last_id 
+                         * of filter (see filter_handle_precreate for detail)*/
+                        if (body && body->oa.o_id > oscc->oscc_last_id)
+                                oscc->oscc_last_id = body->oa.o_id;
                 }
                 spin_unlock(&oscc->oscc_lock);
+
         }
 
         CDEBUG(D_HA, "preallocated through id "LPU64" (last used "LPU64")\n",
@@ -106,7 +113,7 @@ static int oscc_internal_create(struct osc_creator *oscc)
 {
         struct ptlrpc_request *request;
         struct ost_body *body;
-        int size = sizeof(*body);
+        int size[] = { sizeof(struct ptlrpc_body), sizeof(*body) };
         ENTRY;
 
         spin_lock(&oscc->oscc_lock);
@@ -130,8 +137,8 @@ static int oscc_internal_create(struct osc_creator *oscc)
         spin_unlock(&oscc->oscc_lock);
 
         request = ptlrpc_prep_req(oscc->oscc_obd->u.cli.cl_import,
-                                  LUSTRE_OST_VERSION, OST_CREATE, 1,
-                                  &size, NULL);
+                                  LUSTRE_OST_VERSION, OST_CREATE, 2,
+                                  size, NULL);
         if (request == NULL) {
                 spin_lock(&oscc->oscc_lock);
                 oscc->oscc_flags &= ~OSCC_FLAG_CREATING;
@@ -140,7 +147,7 @@ static int oscc_internal_create(struct osc_creator *oscc)
         }
 
         request->rq_request_portal = OST_CREATE_PORTAL; //XXX FIXME bug 249
-        body = lustre_msg_buf(request->rq_reqmsg, 0, sizeof(*body));
+        body = lustre_msg_buf(request->rq_reqmsg, REQ_REC_OFF, sizeof(*body));
 
         spin_lock(&oscc->oscc_lock);
         body->oa.o_id = oscc->oscc_last_id + oscc->oscc_grow_count;
@@ -149,7 +156,7 @@ static int oscc_internal_create(struct osc_creator *oscc)
         CDEBUG(D_HA, "preallocating through id "LPU64" (last used "LPU64")\n",
                body->oa.o_id, oscc->oscc_next_id);
 
-        request->rq_replen = lustre_msg_size(1, &size);
+        ptlrpc_req_set_repsize(request, 2, size);
 
         request->rq_async_args.pointer_arg[0] = oscc;
         request->rq_interpret_reply = osc_interpret_create;
index 667da17..18148c8 100644 (file)
@@ -9,20 +9,20 @@
 
 struct osc_async_page {
         int                     oap_magic;
-        int                     oap_cmd;
+        unsigned short          oap_cmd;
+        unsigned short          oap_interrupted:1;
+
         struct list_head        oap_pending_item;
         struct list_head        oap_urgent_item;
         struct list_head        oap_rpc_item;
 
         obd_off                 oap_obj_off;
-        obd_off                 oap_page_off;
-        int                     oap_count;
-        obd_flag                oap_brw_flags;
+        unsigned                oap_page_off;
         enum async_flags        oap_async_flags;
 
-        unsigned long           oap_interrupted:1;
+        struct brw_page         oap_brw_page;
+
         struct oig_callback_context oap_occ;
-        cfs_page_t              *oap_page;
         struct obd_io_group     *oap_oig;
         struct ptlrpc_request   *oap_request;
         struct client_obd       *oap_cli;
@@ -32,6 +32,10 @@ struct osc_async_page {
         void                    *oap_caller_data;
 };
 
+#define oap_page        oap_brw_page.pg
+#define oap_count       oap_brw_page.count
+#define oap_brw_flags   oap_brw_page.flag
+
 #define OAP_FROM_COOKIE(c)                                                    \
         (LASSERT(((struct osc_async_page *)(c))->oap_magic == OAP_MAGIC),     \
          (struct osc_async_page *)(c))
@@ -63,4 +67,9 @@ int lproc_osc_attach_seqstat(struct obd_device *dev);
 static inline int lproc_osc_attach_seqstat(struct obd_device *dev) {return 0;}
 #endif
 
+#ifndef min_t
+#define min_t(type,x,y) \
+        ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
+#endif
+
 #endif /* OSC_INTERNAL_H */
index fa9e292..c53dff4 100644 (file)
 #include <lprocfs_status.h>
 #include <lustre_log.h>
 #include <lustre_debug.h>
+#include <lustre_param.h>
 #include "osc_internal.h"
 
 static quota_interface_t *quota_interface = NULL;
 extern quota_interface_t osc_quota_interface;
 
+static void osc_release_ppga(struct brw_page **ppga, obd_count count);
+
 /* Pack OSC object metadata for disk storage (LE byte order). */
 static int osc_packmd(struct obd_export *exp, struct lov_mds_md **lmmp,
                       struct lov_stripe_md *lsm)
@@ -141,85 +144,85 @@ static int osc_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp,
 }
 
 static int osc_getattr_interpret(struct ptlrpc_request *req,
-                                 struct osc_getattr_async_args *aa, int rc)
+                                 struct osc_async_args *aa, int rc)
 {
         struct ost_body *body;
         ENTRY;
 
         if (rc != 0)
-                RETURN(rc);
+                GOTO(out, rc);
 
-        body = lustre_swab_repbuf(req, 0, sizeof(*body), lustre_swab_ost_body);
+        body = lustre_swab_repbuf(req, REPLY_REC_OFF, sizeof(*body),
+                                  lustre_swab_ost_body);
         if (body) {
                 CDEBUG(D_INODE, "mode: %o\n", body->oa.o_mode);
-                memcpy(aa->aa_oa, &body->oa, sizeof(*aa->aa_oa));
+                memcpy(aa->aa_oi->oi_oa, &body->oa, sizeof(*aa->aa_oi->oi_oa));
 
                 /* This should really be sent by the OST */
-                aa->aa_oa->o_blksize = PTLRPC_MAX_BRW_SIZE;
-                aa->aa_oa->o_valid |= OBD_MD_FLBLKSZ;
+                aa->aa_oi->oi_oa->o_blksize = PTLRPC_MAX_BRW_SIZE;
+                aa->aa_oi->oi_oa->o_valid |= OBD_MD_FLBLKSZ;
         } else {
                 CERROR("can't unpack ost_body\n");
                 rc = -EPROTO;
-                aa->aa_oa->o_valid = 0;
+                aa->aa_oi->oi_oa->o_valid = 0;
         }
-
+out:
+        rc = aa->aa_oi->oi_cb_up(aa->aa_oi, rc);
         RETURN(rc);
 }
 
-static int osc_getattr_async(struct obd_export *exp, struct obdo *oa,
-                             struct lov_stripe_md *md,
+static int osc_getattr_async(struct obd_export *exp, struct obd_info *oinfo,
                              struct ptlrpc_request_set *set)
 {
-        struct ptlrpc_request *request;
+        struct ptlrpc_request *req;
         struct ost_body *body;
-        int size = sizeof(*body);
-        struct osc_getattr_async_args *aa;
+        int size[2] = { sizeof(struct ptlrpc_body), sizeof(*body) };
+        struct osc_async_args *aa;
         ENTRY;
 
-        request = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_OST_VERSION,
-                                  OST_GETATTR, 1, &size, NULL);
-        if (!request)
+        req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_OST_VERSION,
+                              OST_GETATTR, 2, size,NULL);
+        if (!req)
                 RETURN(-ENOMEM);
 
-        body = lustre_msg_buf(request->rq_reqmsg, 0, sizeof (*body));
-        memcpy(&body->oa, oa, sizeof(*oa));
+        body = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, sizeof(*body));
+        memcpy(&body->oa, oinfo->oi_oa, sizeof(*oinfo->oi_oa));
 
-        request->rq_replen = lustre_msg_size(1, &size);
-        request->rq_interpret_reply = osc_getattr_interpret;
+        ptlrpc_req_set_repsize(req, 2, size);
+        req->rq_interpret_reply = osc_getattr_interpret;
 
-        LASSERT (sizeof (*aa) <= sizeof (request->rq_async_args));
-        aa = (struct osc_getattr_async_args *)&request->rq_async_args;
-        aa->aa_oa = oa;
+        LASSERT (sizeof (*aa) <= sizeof (req->rq_async_args));
+        aa = (struct osc_async_args *)&req->rq_async_args;
+        aa->aa_oi = oinfo;
 
-        ptlrpc_set_add_req (set, request);
+        ptlrpc_set_add_req(set, req);
         RETURN (0);
 }
 
-static int osc_getattr(struct obd_export *exp, struct obdo *oa,
-                       struct lov_stripe_md *md)
+static int osc_getattr(struct obd_export *exp, struct obd_info *oinfo)
 {
-        struct ptlrpc_request *request;
+        struct ptlrpc_request *req;
         struct ost_body *body;
-        int rc, size = sizeof(*body);
+        int rc, size[2] = { sizeof(struct ptlrpc_body), sizeof(*body) };
         ENTRY;
 
-        request = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_OST_VERSION,
-                                  OST_GETATTR, 1, &size, NULL);
-        if (!request)
+        req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_OST_VERSION,
+                              OST_GETATTR, 2, size, NULL);
+        if (!req)
                 RETURN(-ENOMEM);
 
-        body = lustre_msg_buf(request->rq_reqmsg, 0, sizeof (*body));
-        memcpy(&body->oa, oa, sizeof(*oa));
+        body = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, sizeof(*body));
+        memcpy(&body->oa, oinfo->oi_oa, sizeof(*oinfo->oi_oa));
 
-        request->rq_replen = lustre_msg_size(1, &size);
+        ptlrpc_req_set_repsize(req, 2, size);
 
-        rc = ptlrpc_queue_wait(request);
+        rc = ptlrpc_queue_wait(req);
         if (rc) {
                 CERROR("%s failed: rc = %d\n", __FUNCTION__, rc);
                 GOTO(out, rc);
         }
 
-        body = lustre_swab_repbuf(request, 0, sizeof (*body),
+        body = lustre_swab_repbuf(req, REPLY_REC_OFF, sizeof(*body),
                                   lustre_swab_ost_body);
         if (body == NULL) {
                 CERROR ("can't unpack ost_body\n");
@@ -227,90 +230,124 @@ static int osc_getattr(struct obd_export *exp, struct obdo *oa,
         }
 
         CDEBUG(D_INODE, "mode: %o\n", body->oa.o_mode);
-        memcpy(oa, &body->oa, sizeof(*oa));
+        memcpy(oinfo->oi_oa, &body->oa, sizeof(*oinfo->oi_oa));
 
         /* This should really be sent by the OST */
-        oa->o_blksize = PTLRPC_MAX_BRW_SIZE;
-        oa->o_valid |= OBD_MD_FLBLKSZ;
+        oinfo->oi_oa->o_blksize = PTLRPC_MAX_BRW_SIZE;
+        oinfo->oi_oa->o_valid |= OBD_MD_FLBLKSZ;
 
         EXIT;
  out:
-        ptlrpc_req_finished(request);
+        ptlrpc_req_finished(req);
         return rc;
 }
 
-static int osc_setattr(struct obd_export *exp, struct obdo *oa,
-                       struct lov_stripe_md *md, struct obd_trans_info *oti)
+static int osc_setattr(struct obd_export *exp, struct obd_info *oinfo,
+                       struct obd_trans_info *oti)
 {
-        struct ptlrpc_request *request;
+        struct ptlrpc_request *req;
         struct ost_body *body;
-        int rc, size = sizeof(*body);
+        int rc, size[2] = { sizeof(struct ptlrpc_body), sizeof(*body) };
         ENTRY;
 
-        request = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_OST_VERSION,
-                                  OST_SETATTR, 1, &size, NULL);
-        if (!request)
+        req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_OST_VERSION,
+                              OST_SETATTR, 2, size, NULL);
+        if (!req)
                 RETURN(-ENOMEM);
 
-        body = lustre_msg_buf(request->rq_reqmsg, 0, sizeof(*body));
-        memcpy(&body->oa, oa, sizeof(*oa));
+        body = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, sizeof(*body));
+        memcpy(&body->oa, oinfo->oi_oa, sizeof(*oinfo->oi_oa));
 
-        request->rq_replen = lustre_msg_size(1, &size);
+        ptlrpc_req_set_repsize(req, 2, size);
 
-        rc = ptlrpc_queue_wait(request);
+        rc = ptlrpc_queue_wait(req);
         if (rc)
                 GOTO(out, rc);
 
-        body = lustre_swab_repbuf(request, 0, sizeof(*body),
+        body = lustre_swab_repbuf(req, REPLY_REC_OFF, sizeof(*body),
                                   lustre_swab_ost_body);
         if (body == NULL)
                 GOTO(out, rc = -EPROTO);
 
-        memcpy(oa, &body->oa, sizeof(*oa));
+        memcpy(oinfo->oi_oa, &body->oa, sizeof(*oinfo->oi_oa));
 
         EXIT;
 out:
-        ptlrpc_req_finished(request);
-        RETURN(0);
+        ptlrpc_req_finished(req);
+        RETURN(rc);
 }
 
-static int osc_setattr_async(struct obd_export *exp, struct obdo *oa,
-                             struct lov_stripe_md *md,
-                             struct obd_trans_info *oti)
+static int osc_setattr_interpret(struct ptlrpc_request *req,
+                                 struct osc_async_args *aa, int rc)
 {
-        struct ptlrpc_request *request;
         struct ost_body *body;
-        int rc = 0, size = sizeof(*body);
         ENTRY;
 
-        LASSERT(oti);
+        if (rc != 0)
+                GOTO(out, rc);
+
+        body = lustre_swab_repbuf(req, REPLY_REC_OFF, sizeof(*body),
+                                  lustre_swab_ost_body);
+        if (body == NULL) {
+                CERROR("can't unpack ost_body\n");
+                GOTO(out, rc = -EPROTO);
+        }
+
+        memcpy(aa->aa_oi->oi_oa, &body->oa, sizeof(*aa->aa_oi->oi_oa));
+out:
+        rc = aa->aa_oi->oi_cb_up(aa->aa_oi, rc);
+        RETURN(rc);
+}
+
+static int osc_setattr_async(struct obd_export *exp, struct obd_info *oinfo,
+                             struct obd_trans_info *oti,
+                             struct ptlrpc_request_set *rqset)
+{
+        struct ptlrpc_request *req;
+        struct ost_body *body;
+        int size[2] = { sizeof(struct ptlrpc_body), sizeof(*body) };
+        struct osc_async_args *aa;
+        ENTRY;
 
-        request = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_OST_VERSION,
-                                  OST_SETATTR, 1, &size, NULL);
-        if (!request)
+        req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_OST_VERSION,
+                              OST_SETATTR, 2, size, NULL);
+        if (!req)
                 RETURN(-ENOMEM);
 
-        body = lustre_msg_buf(request->rq_reqmsg, 0, sizeof(*body));
+        body = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, sizeof(*body));
 
-        if (oa->o_valid & OBD_MD_FLCOOKIE)
-                memcpy(obdo_logcookie(oa), oti->oti_logcookies,
+        if (oinfo->oi_oa->o_valid & OBD_MD_FLCOOKIE) {
+                LASSERT(oti);
+                memcpy(obdo_logcookie(oinfo->oi_oa), oti->oti_logcookies,
                        sizeof(*oti->oti_logcookies));
+        }
 
-        memcpy(&body->oa, oa, sizeof(*oa));
-        request->rq_replen = lustre_msg_size(1, &size);
+        memcpy(&body->oa, oinfo->oi_oa, sizeof(*oinfo->oi_oa));
+        ptlrpc_req_set_repsize(req, 2, size);
         /* do mds to ost setattr asynchronouly */
-        ptlrpcd_add_req(request);
+        if (!rqset) {
+                /* Do not wait for response. */
+                ptlrpcd_add_req(req);
+        } else {
+                req->rq_interpret_reply = osc_setattr_interpret;
 
-        RETURN(rc);
+                LASSERT (sizeof (*aa) <= sizeof (req->rq_async_args));
+                aa = (struct osc_async_args *)&req->rq_async_args;
+                aa->aa_oi = oinfo;
+
+                ptlrpc_set_add_req(rqset, req);
+        }
+
+        RETURN(0);
 }
 
 int osc_real_create(struct obd_export *exp, struct obdo *oa,
                     struct lov_stripe_md **ea, struct obd_trans_info *oti)
 {
-        struct ptlrpc_request *request;
+        struct ptlrpc_request *req;
         struct ost_body *body;
         struct lov_stripe_md *lsm;
-        int rc, size = sizeof(*body);
+        int rc, size[2] = { sizeof(struct ptlrpc_body), sizeof(*body) };
         ENTRY;
 
         LASSERT(oa);
@@ -323,29 +360,29 @@ int osc_real_create(struct obd_export *exp, struct obdo *oa,
                         RETURN(rc);
         }
 
-        request = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_OST_VERSION,
-                                  OST_CREATE, 1, &size, NULL);
-        if (!request)
+        req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_OST_VERSION,
+                              OST_CREATE, 2, size, NULL);
+        if (!req)
                 GOTO(out, rc = -ENOMEM);
 
-        body = lustre_msg_buf(request->rq_reqmsg, 0, sizeof (*body));
+        body = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, sizeof(*body));
         memcpy(&body->oa, oa, sizeof(body->oa));
 
-        request->rq_replen = lustre_msg_size(1, &size);
+        ptlrpc_req_set_repsize(req, 2, size);
         if (oa->o_valid & OBD_MD_FLINLINE) {
                 LASSERT((oa->o_valid & OBD_MD_FLFLAGS) &&
                         oa->o_flags == OBD_FL_DELORPHAN);
-                DEBUG_REQ(D_HA, request,
+                DEBUG_REQ(D_HA, req,
                           "delorphan from OST integration");
-                /* Don't resend the delorphan request */
-                request->rq_no_resend = request->rq_no_delay = 1;
+                /* Don't resend the delorphan req */
+                req->rq_no_resend = req->rq_no_delay = 1;
         }
 
-        rc = ptlrpc_queue_wait(request);
+        rc = ptlrpc_queue_wait(req);
         if (rc)
                 GOTO(out_req, rc);
 
-        body = lustre_swab_repbuf(request, 0, sizeof(*body),
+        body = lustre_swab_repbuf(req, REPLY_REC_OFF, sizeof(*body),
                                   lustre_swab_ost_body);
         if (body == NULL) {
                 CERROR ("can't unpack ost_body\n");
@@ -366,7 +403,7 @@ int osc_real_create(struct obd_export *exp, struct obdo *oa,
         *ea = lsm;
 
         if (oti != NULL) {
-                oti->oti_transno = request->rq_repmsg->transno;
+                oti->oti_transno = lustre_msg_get_transno(req->rq_repmsg);
 
                 if (oa->o_valid & OBD_MD_FLCOOKIE) {
                         if (!oti->oti_logcookies)
@@ -376,70 +413,89 @@ int osc_real_create(struct obd_export *exp, struct obdo *oa,
                 }
         }
 
-        CDEBUG(D_HA, "transno: "LPD64"\n", request->rq_repmsg->transno);
+        CDEBUG(D_HA, "transno: "LPD64"\n",
+               lustre_msg_get_transno(req->rq_repmsg));
         EXIT;
 out_req:
-        ptlrpc_req_finished(request);
+        ptlrpc_req_finished(req);
 out:
         if (rc && !*ea)
                 obd_free_memmd(exp, &lsm);
         return rc;
 }
 
-static int osc_punch(struct obd_export *exp, struct obdo *oa,
-                     struct lov_stripe_md *md, obd_size start,
-                     obd_size end, struct obd_trans_info *oti)
+static int osc_punch_interpret(struct ptlrpc_request *req,
+                               struct osc_async_args *aa, int rc)
 {
-        struct ptlrpc_request *request;
         struct ost_body *body;
-        int rc, size = sizeof(*body);
         ENTRY;
 
-        if (!oa) {
+        if (rc != 0)
+                GOTO(out, rc);
+
+        body = lustre_swab_repbuf(req, REPLY_REC_OFF, sizeof (*body),
+                                  lustre_swab_ost_body);
+        if (body == NULL) {
+                CERROR ("can't unpack ost_body\n");
+                GOTO(out, rc = -EPROTO);
+        }
+
+        memcpy(aa->aa_oi->oi_oa, &body->oa, sizeof(*aa->aa_oi->oi_oa));
+out:
+        rc = aa->aa_oi->oi_cb_up(aa->aa_oi, rc);
+        RETURN(rc);
+}
+
+static int osc_punch(struct obd_export *exp, struct obd_info *oinfo,
+                     struct obd_trans_info *oti,
+                     struct ptlrpc_request_set *rqset)
+{
+        struct ptlrpc_request *req;
+        struct osc_async_args *aa;
+        struct ost_body *body;
+        int size[2] = { sizeof(struct ptlrpc_body), sizeof(*body) };
+        ENTRY;
+
+        if (!oinfo->oi_oa) {
                 CERROR("oa NULL\n");
                 RETURN(-EINVAL);
         }
 
-        request = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_OST_VERSION,
-                                  OST_PUNCH, 1, &size, NULL);
-        if (!request)
+        req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_OST_VERSION,
+                              OST_PUNCH, 2, size, NULL);
+        if (!req)
                 RETURN(-ENOMEM);
 
-        body = lustre_msg_buf(request->rq_reqmsg, 0, sizeof (*body));
-        memcpy(&body->oa, oa, sizeof(*oa));
+        /* FIXME bug 249. Also see bug 7198 */
+        if (class_exp2cliimp(exp)->imp_connect_data.ocd_connect_flags &
+            OBD_CONNECT_REQPORTAL)
+                req->rq_request_portal = OST_IO_PORTAL;
+
+        body = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, sizeof(*body));
+        memcpy(&body->oa, oinfo->oi_oa, sizeof(*oinfo->oi_oa));
 
         /* overload the size and blocks fields in the oa with start/end */
-        body->oa.o_size = start;
-        body->oa.o_blocks = end;
+        body->oa.o_size = oinfo->oi_policy.l_extent.start;
+        body->oa.o_blocks = oinfo->oi_policy.l_extent.end;
         body->oa.o_valid |= (OBD_MD_FLSIZE | OBD_MD_FLBLOCKS);
 
-        request->rq_replen = lustre_msg_size(1, &size);
-
-        rc = ptlrpc_queue_wait(request);
-        if (rc)
-                GOTO(out, rc);
-
-        body = lustre_swab_repbuf (request, 0, sizeof (*body),
-                                   lustre_swab_ost_body);
-        if (body == NULL) {
-                CERROR ("can't unpack ost_body\n");
-                GOTO (out, rc = -EPROTO);
-        }
+        ptlrpc_req_set_repsize(req, 2, size);
 
-        memcpy(oa, &body->oa, sizeof(*oa));
+        req->rq_interpret_reply = osc_punch_interpret;
+        LASSERT (sizeof (*aa) <= sizeof (req->rq_async_args));
+        aa = (struct osc_async_args *)&req->rq_async_args;
+        aa->aa_oi = oinfo;
+        ptlrpc_set_add_req(rqset, req);
 
-        EXIT;
- out:
-        ptlrpc_req_finished(request);
-        return rc;
+        RETURN(0);
 }
 
 static int osc_sync(struct obd_export *exp, struct obdo *oa,
                     struct lov_stripe_md *md, obd_size start, obd_size end)
 {
-        struct ptlrpc_request *request;
+        struct ptlrpc_request *req;
         struct ost_body *body;
-        int rc, size = sizeof(*body);
+        int rc, size[2] = { sizeof(struct ptlrpc_body), sizeof(*body) };
         ENTRY;
 
         if (!oa) {
@@ -447,12 +503,12 @@ static int osc_sync(struct obd_export *exp, struct obdo *oa,
                 RETURN(-EINVAL);
         }
 
-        request = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_OST_VERSION,
-                                  OST_SYNC, 1, &size, NULL);
-        if (!request)
+        req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_OST_VERSION,
+                              OST_SYNC, 2, size, NULL);
+        if (!req)
                 RETURN(-ENOMEM);
 
-        body = lustre_msg_buf(request->rq_reqmsg, 0, sizeof (*body));
+        body = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, sizeof(*body));
         memcpy(&body->oa, oa, sizeof(*oa));
 
         /* overload the size and blocks fields in the oa with start/end */
@@ -460,13 +516,13 @@ static int osc_sync(struct obd_export *exp, struct obdo *oa,
         body->oa.o_blocks = end;
         body->oa.o_valid |= (OBD_MD_FLSIZE | OBD_MD_FLBLOCKS);
 
-        request->rq_replen = lustre_msg_size(1, &size);
+        ptlrpc_req_set_repsize(req, 2, size);
 
-        rc = ptlrpc_queue_wait(request);
+        rc = ptlrpc_queue_wait(req);
         if (rc)
                 GOTO(out, rc);
 
-        body = lustre_swab_repbuf(request, 0, sizeof(*body),
+        body = lustre_swab_repbuf(req, REPLY_REC_OFF, sizeof(*body),
                                   lustre_swab_ost_body);
         if (body == NULL) {
                 CERROR ("can't unpack ost_body\n");
@@ -477,17 +533,27 @@ static int osc_sync(struct obd_export *exp, struct obdo *oa,
 
         EXIT;
  out:
-        ptlrpc_req_finished(request);
+        ptlrpc_req_finished(req);
         return rc;
 }
 
+/* Destroy requests can be async always on the client, and we don't even really
+ * care about the return code since the client cannot do anything at all about
+ * a destroy failure.
+ * When the MDS is unlinking a filename, it saves the file objects into a
+ * recovery llog, and these object records are cancelled when the OST reports
+ * they were destroyed and sync'd to disk (i.e. transaction committed).
+ * If the client dies, or the OST is down when the object should be destroyed,
+ * the records are not cancelled, and when the OST reconnects to the MDS next,
+ * it will retrieve the llog unlink logs and then sends the log cancellation
+ * cookies to the MDS after committing destroy transactions. */
 static int osc_destroy(struct obd_export *exp, struct obdo *oa,
                        struct lov_stripe_md *ea, struct obd_trans_info *oti,
                        struct obd_export *md_export)
 {
-        struct ptlrpc_request *request;
+        struct ptlrpc_request *req;
         struct ost_body *body;
-        int rc, size = sizeof(*body);
+        int size[2] = { sizeof(struct ptlrpc_body), sizeof(*body) };
         ENTRY;
 
         if (!oa) {
@@ -495,41 +561,28 @@ static int osc_destroy(struct obd_export *exp, struct obdo *oa,
                 RETURN(-EINVAL);
         }
 
-        request = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_OST_VERSION,
-                                  OST_DESTROY, 1, &size, NULL);
-        if (!request)
+        req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_OST_VERSION,
+                              OST_DESTROY, 2, size, NULL);
+        if (!req)
                 RETURN(-ENOMEM);
 
-        body = lustre_msg_buf(request->rq_reqmsg, 0, sizeof (*body));
+        /* FIXME bug 249. Also see bug 7198 */
+        if (class_exp2cliimp(exp)->imp_connect_data.ocd_connect_flags &
+            OBD_CONNECT_REQPORTAL)
+                req->rq_request_portal = OST_IO_PORTAL;
+
+        body = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, sizeof(*body));
 
         if (oti != NULL && oa->o_valid & OBD_MD_FLCOOKIE) {
                 memcpy(obdo_logcookie(oa), oti->oti_logcookies,
                        sizeof(*oti->oti_logcookies));
-                oti->oti_logcookies++;
         }
 
         memcpy(&body->oa, oa, sizeof(*oa));
-        request->rq_replen = lustre_msg_size(1, &size);
-
-        rc = ptlrpc_queue_wait(request);
-        if (rc == -ENOENT)
-                rc = 0;
-        if (rc)
-                GOTO(out, rc);
+        ptlrpc_req_set_repsize(req, 2, size);
 
-        body = lustre_swab_repbuf(request, 0, sizeof(*body),
-                                  lustre_swab_ost_body);
-        if (body == NULL) {
-                CERROR ("Can't unpack body\n");
-                GOTO (out, rc = -EPROTO);
-        }
-
-        memcpy(oa, &body->oa, sizeof(*oa));
-
-        EXIT;
- out:
-        ptlrpc_req_finished(request);
-        return rc;
+        ptlrpcd_add_req(req);
+        RETURN(0);
 }
 
 static void osc_announce_cached(struct client_obd *cli, struct obdo *oa,
@@ -643,52 +696,54 @@ static void osc_update_grant(struct client_obd *cli, struct ost_body *body)
  * via the LOV, and it _knows_ it's reading inside the file, it's just that
  * this stripe never got written at or beyond this stripe offset yet. */
 static void handle_short_read(int nob_read, obd_count page_count,
-                              struct brw_page *pga)
+                              struct brw_page **pga)
 {
         char *ptr;
+        int i = 0;
 
         /* skip bytes read OK */
         while (nob_read > 0) {
                 LASSERT (page_count > 0);
 
-                if (pga->count > nob_read) {
+                if (pga[i]->count > nob_read) {
                         /* EOF inside this page */
-                        ptr = cfs_kmap(pga->pg) + (pga->off & ~CFS_PAGE_MASK);
-                        memset(ptr + nob_read, 0, pga->count - nob_read);
-                        cfs_kunmap(pga->pg);
+                        ptr = cfs_kmap(pga[i]->pg) + 
+                                (pga[i]->off & ~CFS_PAGE_MASK);
+                        memset(ptr + nob_read, 0, pga[i]->count - nob_read);
+                        cfs_kunmap(pga[i]->pg);
                         page_count--;
-                        pga++;
+                        i++;
                         break;
                 }
 
-                nob_read -= pga->count;
+                nob_read -= pga[i]->count;
                 page_count--;
-                pga++;
+                i++;
         }
 
         /* zero remaining pages */
         while (page_count-- > 0) {
-                ptr = cfs_kmap(pga->pg) + (pga->off & ~CFS_PAGE_MASK);
-                memset(ptr, 0, pga->count);
-                cfs_kunmap(pga->pg);
-                pga++;
+                ptr = cfs_kmap(pga[i]->pg) + (pga[i]->off & ~CFS_PAGE_MASK);
+                memset(ptr, 0, pga[i]->count);
+                cfs_kunmap(pga[i]->pg);
+                i++;
         }
 }
 
-static int check_write_rcs(struct ptlrpc_request *request,
+static int check_write_rcs(struct ptlrpc_request *req,
                            int requested_nob, int niocount,
-                           obd_count page_count, struct brw_page *pga)
+                           obd_count page_count, struct brw_page **pga)
 {
         int    *remote_rcs, i;
 
         /* return error if any niobuf was in error */
-        remote_rcs = lustre_swab_repbuf(request, 1,
+        remote_rcs = lustre_swab_repbuf(req, REQ_REC_OFF + 1,
                                         sizeof(*remote_rcs) * niocount, NULL);
         if (remote_rcs == NULL) {
                 CERROR("Missing/short RC vector on BRW_WRITE reply\n");
                 return(-EPROTO);
         }
-        if (lustre_msg_swabbed(request->rq_repmsg))
+        if (lustre_msg_swabbed(req->rq_repmsg))
                 for (i = 0; i < niocount; i++)
                         __swab32s(&remote_rcs[i]);
 
@@ -698,14 +753,14 @@ static int check_write_rcs(struct ptlrpc_request *request,
 
                 if (remote_rcs[i] != 0) {
                         CERROR("rc[%d] invalid (%d) req %p\n",
-                                i, remote_rcs[i], request);
+                                i, remote_rcs[i], req);
                         return(-EPROTO);
                 }
         }
 
-        if (request->rq_bulk->bd_nob_transferred != requested_nob) {
+        if (req->rq_bulk->bd_nob_transferred != requested_nob) {
                 CERROR("Unexpected # bytes transferred: %d (requested %d)\n",
-                       requested_nob, request->rq_bulk->bd_nob_transferred);
+                       requested_nob, req->rq_bulk->bd_nob_transferred);
                 return(-EPROTO);
         }
 
@@ -729,24 +784,25 @@ static inline int can_merge_pages(struct brw_page *p1, struct brw_page *p2)
 }
 
 static obd_count osc_checksum_bulk(int nob, obd_count pg_count,
-                                   struct brw_page *pga)
+                                   struct brw_page **pga)
 {
         __u32 cksum = ~0;
+        int i = 0;
 
         LASSERT (pg_count > 0);
         while (nob > 0 && pg_count > 0) {
-                char *ptr = cfs_kmap(pga->pg);
-                int off = pga->off & ~CFS_PAGE_MASK;
-                int count = pga->count > nob ? nob : pga->count;
+                char *ptr = cfs_kmap(pga[i]->pg);
+                int off = pga[i]->off & ~CFS_PAGE_MASK;
+                int count = pga[i]->count > nob ? nob : pga[i]->count;
 
                 cksum = crc32_le(cksum, ptr + off, count);
-                cfs_kunmap(pga->pg);
-                LL_CDEBUG_PAGE(D_PAGE, pga->pg, "off %d checksum %x\n",
+                cfs_kunmap(pga[i]->pg);
+                LL_CDEBUG_PAGE(D_PAGE, pga[i]->pg, "off %d checksum %x\n",
                                off, cksum);
 
-                nob -= pga->count;
+                nob -= pga[i]->count;
                 pg_count--;
-                pga++;
+                i++;
         }
 
         return cksum;
@@ -754,7 +810,7 @@ static obd_count osc_checksum_bulk(int nob, obd_count pg_count,
 
 static int osc_brw_prep_request(int cmd, struct obd_import *imp,struct obdo *oa,
                                 struct lov_stripe_md *lsm, obd_count page_count,
-                                struct brw_page *pga, int *requested_nobp,
+                                struct brw_page **pga, int *requested_nobp,
                                 int *niocountp, struct ptlrpc_request **reqp)
 {
         struct ptlrpc_request   *req;
@@ -763,29 +819,25 @@ static int osc_brw_prep_request(int cmd, struct obd_import *imp,struct obdo *oa,
         struct ost_body         *body;
         struct obd_ioobj        *ioobj;
         struct niobuf_remote    *niobuf;
-        int                      niocount;
-        int                      size[3];
-        int                      i;
-        int                      requested_nob;
-        int                      opc;
-        int                      rc;
+        int size[4] = { sizeof(struct ptlrpc_body), sizeof(*body) };
+        int niocount, i, requested_nob, opc, rc;
         struct ptlrpc_request_pool *pool;
 
         ENTRY;
         opc = ((cmd & OBD_BRW_WRITE) != 0) ? OST_WRITE : OST_READ;
         pool = ((cmd & OBD_BRW_WRITE) != 0) ? imp->imp_rq_pool : NULL;
 
-        for (niocount = i = 1; i < page_count; i++)
-                if (!can_merge_pages(&pga[i - 1], &pga[i]))
+        for (niocount = i = 1; i < page_count; i++) {
+                if (!can_merge_pages(pga[i - 1], pga[i]))
                         niocount++;
+        }
 
-        size[0] = sizeof(*body);
-        size[1] = sizeof(*ioobj);
-        size[2] = niocount * sizeof(*niobuf);
+        size[REQ_REC_OFF + 1] = sizeof(*ioobj);
+        size[REQ_REC_OFF + 2] = niocount * sizeof(*niobuf);
 
         OBD_FAIL_RETURN(OBD_FAIL_OSC_BRW_PREP_REQ, -ENOMEM);
-        req = ptlrpc_prep_req_pool(imp, LUSTRE_OST_VERSION, opc, 3,
-                                   size, NULL, pool);
+        req = ptlrpc_prep_req_pool(imp, LUSTRE_OST_VERSION, opc, 4, size, NULL,
+                                   pool);
         if (req == NULL)
                 RETURN (-ENOMEM);
 
@@ -803,9 +855,10 @@ static int osc_brw_prep_request(int cmd, struct obd_import *imp,struct obdo *oa,
                 GOTO(out, rc = -ENOMEM);
         /* NB request now owns desc and will free it when it gets freed */
 
-        body = lustre_msg_buf(req->rq_reqmsg, 0, sizeof(*body));
-        ioobj = lustre_msg_buf(req->rq_reqmsg, 1, sizeof(*ioobj));
-        niobuf = lustre_msg_buf(req->rq_reqmsg, 2, niocount * sizeof(*niobuf));
+        body = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, sizeof(*body));
+        ioobj = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF + 1, sizeof(*ioobj));
+        niobuf = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF + 2,
+                                niocount * sizeof(*niobuf));
 
         memcpy(&body->oa, oa, sizeof(*oa));
 
@@ -814,8 +867,8 @@ static int osc_brw_prep_request(int cmd, struct obd_import *imp,struct obdo *oa,
 
         LASSERT (page_count > 0);
         for (requested_nob = i = 0; i < page_count; i++, niobuf++) {
-                struct brw_page *pg = &pga[i];
-                struct brw_page *pg_prev = pg - 1;
+                struct brw_page *pg = pga[i];
+                struct brw_page *pg_prev = pga[i - 1];
 
                 LASSERT(pg->count > 0);
                 LASSERTF((pg->off & ~CFS_PAGE_MASK) + pg->count <= CFS_PAGE_SIZE,
@@ -833,7 +886,7 @@ static int osc_brw_prep_request(int cmd, struct obd_import *imp,struct obdo *oa,
                 LASSERTF(i == 0 || pg->off > pg_prev->off,
                          "i %d p_c %u\n", i, page_count);
 #endif
-                LASSERT((pga[0].flag & OBD_BRW_SRVLOCK) ==
+                LASSERT((pga[0]->flag & OBD_BRW_SRVLOCK) ==
                         (pg->flag & OBD_BRW_SRVLOCK));
 
                 ptlrpc_prep_bulk_page(desc, pg->pg, pg->off & ~CFS_PAGE_MASK,
@@ -851,10 +904,11 @@ static int osc_brw_prep_request(int cmd, struct obd_import *imp,struct obdo *oa,
         }
 
         LASSERT((void *)(niobuf - niocount) ==
-                lustre_msg_buf(req->rq_reqmsg, 2, niocount * sizeof(*niobuf)));
+                lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF + 2,
+                               niocount * sizeof(*niobuf)));
         osc_announce_cached(cli, &body->oa, opc == OST_WRITE ? requested_nob:0);
 
-        /* size[0] still sizeof (*body) */
+        /* size[REQ_REC_OFF] still sizeof (*body) */
         if (opc == OST_WRITE) {
                 if (unlikely(cli->cl_checksum)) {
                         body->oa.o_valid |= OBD_MD_FLCKSUM;
@@ -867,13 +921,13 @@ static int osc_brw_prep_request(int cmd, struct obd_import *imp,struct obdo *oa,
                         oa->o_cksum = body->oa.o_cksum;
                 }
                 /* 1 RC per niobuf */
-                size[1] = sizeof(__u32) * niocount;
-                req->rq_replen = lustre_msg_size(2, size);
+                size[REPLY_REC_OFF + 1] = sizeof(__u32) * niocount;
+                ptlrpc_req_set_repsize(req, 3, size);
         } else {
                 if (unlikely(cli->cl_checksum))
                         body->oa.o_valid |= OBD_MD_FLCKSUM;
                 /* 1 RC for the whole I/O */
-                req->rq_replen = lustre_msg_size(1, size);
+                ptlrpc_req_set_repsize(req, 2, size);
         }
 
         *niocountp = niocount;
@@ -887,7 +941,7 @@ static int osc_brw_prep_request(int cmd, struct obd_import *imp,struct obdo *oa,
 }
 
 static void check_write_csum(__u32 cli, __u32 srv, int requested_nob,
-                             obd_count page_count, struct brw_page *pga)
+                             obd_count page_count, struct brw_page **pga)
 {
         __u32 new_csum;
 
@@ -921,7 +975,7 @@ static void check_write_csum(__u32 cli, __u32 srv, int requested_nob,
 
 static int osc_brw_fini_request(struct ptlrpc_request *req, struct obdo *oa,
                                 int requested_nob, int niocount,
-                                obd_count page_count, struct brw_page *pga,
+                                obd_count page_count, struct brw_page **pga,
                                 int rc)
 {
         const lnet_process_id_t *peer =
@@ -935,14 +989,15 @@ static int osc_brw_fini_request(struct ptlrpc_request *req, struct obdo *oa,
                 RETURN(rc);
 
         LASSERTF(req->rq_repmsg != NULL, "rc = %d\n", rc);
-        body = lustre_swab_repbuf(req, 0, sizeof(*body), lustre_swab_ost_body);
+        body = lustre_swab_repbuf(req, REPLY_REC_OFF, sizeof(*body),
+                                  lustre_swab_ost_body);
         if (body == NULL) {
                 CERROR ("Can't unpack body\n");
                 RETURN(-EPROTO);
         }
 
         /* set/clear over quota flag for a uid/gid */
-        if (req->rq_reqmsg->opc == OST_WRITE &&
+        if (lustre_msg_get_opc(req->rq_reqmsg) == OST_WRITE &&
             body->oa.o_valid & (OBD_MD_FLUSRQUOTA | OBD_MD_FLGRPQUOTA))
                 lquota_setdq(quota_interface, cli, body->oa.o_uid,
                              body->oa.o_gid, body->oa.o_valid,
@@ -957,7 +1012,7 @@ static int osc_brw_fini_request(struct ptlrpc_request *req, struct obdo *oa,
         osc_update_grant(cli, body);
         memcpy(oa, &body->oa, sizeof(*oa));
 
-        if (req->rq_reqmsg->opc == OST_WRITE) {
+        if (lustre_msg_get_opc(req->rq_reqmsg) == OST_WRITE) {
                 if (rc > 0) {
                         CERROR ("Unexpected +ve rc %d\n", rc);
                         RETURN(-EPROTO);
@@ -1028,86 +1083,93 @@ static int osc_brw_fini_request(struct ptlrpc_request *req, struct obdo *oa,
 
 static int osc_brw_internal(int cmd, struct obd_export *exp,struct obdo *oa,
                             struct lov_stripe_md *lsm,
-                            obd_count page_count, struct brw_page *pga)
+                            obd_count page_count, struct brw_page **pga)
 {
         int                    requested_nob;
         int                    niocount;
-        struct ptlrpc_request *request;
+        struct ptlrpc_request *req;
         int                    rc;
         ENTRY;
 
 restart_bulk:
         rc = osc_brw_prep_request(cmd, class_exp2cliimp(exp), oa, lsm,
                                   page_count, pga, &requested_nob, &niocount,
-                                  &request);
+                                  &req);
         if (rc != 0)
                 return (rc);
 
-        rc = ptlrpc_queue_wait(request);
+        rc = ptlrpc_queue_wait(req);
 
-        if (rc == -ETIMEDOUT && request->rq_resend) {
-                DEBUG_REQ(D_HA, request,  "BULK TIMEOUT");
-                ptlrpc_req_finished(request);
+        if (rc == -ETIMEDOUT && req->rq_resend) {
+                DEBUG_REQ(D_HA, req,  "BULK TIMEOUT");
+                ptlrpc_req_finished(req);
                 goto restart_bulk;
         }
 
-        rc = osc_brw_fini_request(request, oa, requested_nob, niocount,
+        rc = osc_brw_fini_request(req, oa, requested_nob, niocount,
                                   page_count, pga, rc);
 
-        ptlrpc_req_finished(request);
+        ptlrpc_req_finished(req);
         RETURN (rc);
 }
 
-static int brw_interpret(struct ptlrpc_request *request,
+static int brw_interpret(struct ptlrpc_request *req,
                          struct osc_brw_async_args *aa, int rc)
 {
         struct obdo *oa      = aa->aa_oa;
         int requested_nob    = aa->aa_requested_nob;
         int niocount         = aa->aa_nio_count;
         obd_count page_count = aa->aa_page_count;
-        struct brw_page *pga = aa->aa_pga;
+        struct brw_page **pga = aa->aa_ppga;
         ENTRY;
 
-        rc = osc_brw_fini_request(request, oa, requested_nob, niocount,
+        rc = osc_brw_fini_request(req, oa, requested_nob, niocount,
                                   page_count, pga, rc);
+        osc_release_ppga(pga, page_count);
         RETURN (rc);
 }
 
 static int async_internal(int cmd, struct obd_export *exp, struct obdo *oa,
                           struct lov_stripe_md *lsm, obd_count page_count,
-                          struct brw_page *pga, struct ptlrpc_request_set *set)
+                          struct brw_page **pga, struct ptlrpc_request_set *set)
 {
-        struct ptlrpc_request     *request;
+        struct ptlrpc_request     *req;
         int                        requested_nob;
         int                        nio_count;
         struct osc_brw_async_args *aa;
         int                        rc;
         ENTRY;
 
+        /* Consume write credits even if doing a sync write -
+         * otherwise we may run out of space on OST due to grant. */
+        spin_lock(&exp->exp_obd->u.cli.cl_loi_list_lock);
+        for (nio_count = 0; nio_count < page_count; nio_count++) {
+                if (exp->exp_obd->u.cli.cl_avail_grant >= PAGE_SIZE) {
+                        exp->exp_obd->u.cli.cl_avail_grant -= PAGE_SIZE;
+                        pga[nio_count]->flag |= OBD_BRW_FROM_GRANT;
+                }
+        }
+        spin_unlock(&exp->exp_obd->u.cli.cl_loi_list_lock);
+
         rc = osc_brw_prep_request(cmd, class_exp2cliimp(exp), oa, lsm,
                                   page_count, pga, &requested_nob, &nio_count,
-                                  &request);
+                                  &req);
 
         if (rc == 0) {
-                LASSERT(sizeof(*aa) <= sizeof(request->rq_async_args));
-                aa = (struct osc_brw_async_args *)&request->rq_async_args;
+                LASSERT(sizeof(*aa) <= sizeof(req->rq_async_args));
+                aa = (struct osc_brw_async_args *)&req->rq_async_args;
                 aa->aa_oa = oa;
                 aa->aa_requested_nob = requested_nob;
                 aa->aa_nio_count = nio_count;
                 aa->aa_page_count = page_count;
-                aa->aa_pga = pga;
+                aa->aa_ppga = pga;
 
-                request->rq_interpret_reply = brw_interpret;
-                ptlrpc_set_add_req(set, request);
+                req->rq_interpret_reply = brw_interpret;
+                ptlrpc_set_add_req(set, req);
         }
         RETURN (rc);
 }
 
-#ifndef min_t
-#define min_t(type,x,y) \
-        ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
-#endif
-
 /*
  * ugh, we want disk allocation on the target to happen in offset order.  we'll
  * follow sedgewicks advice and stick to the dead simple shellsort -- it'll do
@@ -1115,10 +1177,10 @@ static int async_internal(int cmd, struct obd_export *exp, struct obdo *oa,
  * insertion sort that swaps elements that are strides apart, shrinking the
  * stride down until its '1' and the array is sorted.
  */
-static void sort_brw_pages(struct brw_page *array, int num)
+static void sort_brw_pages(struct brw_page **array, int num)
 {
         int stride, i, j;
-        struct brw_page tmp;
+        struct brw_page *tmp;
 
         if (num == 1)
                 return;
@@ -1130,7 +1192,7 @@ static void sort_brw_pages(struct brw_page *array, int num)
                 for (i = stride ; i < num ; i++) {
                         tmp = array[i];
                         j = i;
-                        while (j >= stride && array[j - stride].off > tmp.off) {
+                        while (j >= stride && array[j - stride]->off > tmp->off) {
                                 array[j] = array[j - stride];
                                 j -= stride;
                         }
@@ -1139,43 +1201,66 @@ static void sort_brw_pages(struct brw_page *array, int num)
         } while (stride > 1);
 }
 
-static obd_count max_unfragmented_pages(struct brw_page *pg, obd_count pages)
+static obd_count max_unfragmented_pages(struct brw_page **pg, obd_count pages)
 {
         int count = 1;
         int offset;
+        int i = 0;
 
-       LASSERT (pages > 0);
-        offset = pg->off & (CFS_PAGE_SIZE - 1);
+        LASSERT (pages > 0);
+        offset = pg[i]->off & (CFS_PAGE_SIZE - 1);
 
         for (;;) {
                 pages--;
                 if (pages == 0)         /* that's all */
                         return count;
 
-                if (offset + pg->count < CFS_PAGE_SIZE)
-                       return count;   /* doesn't end on page boundary */
+                if (offset + pg[i]->count < CFS_PAGE_SIZE)
+                        return count;   /* doesn't end on page boundary */
 
-               pg++;
-                offset = pg->off & (CFS_PAGE_SIZE - 1);
-               if (offset != 0)        /* doesn't start on page boundary */
-                       return count;
+                i++;
+                offset = pg[i]->off & (CFS_PAGE_SIZE - 1);
+                if (offset != 0)        /* doesn't start on page boundary */
+                        return count;
 
                 count++;
         }
 }
 
-static int osc_brw(int cmd, struct obd_export *exp, struct obdo *oa,
-                   struct lov_stripe_md *md, obd_count page_count,
-                   struct brw_page *pga, struct obd_trans_info *oti)
+static struct brw_page **osc_build_ppga(struct brw_page *pga, obd_count count)
+{
+        struct brw_page **ppga;
+        int i;
+
+        OBD_ALLOC(ppga, sizeof(*ppga) * count);
+        if (ppga == NULL)
+                return NULL;
+
+        for (i = 0; i < count; i++)
+                ppga[i] = pga + i;
+        return ppga;
+}
+
+static void osc_release_ppga(struct brw_page **ppga, obd_count count)
+{
+        LASSERT(ppga != NULL);
+        OBD_FREE(ppga, sizeof(*ppga) * count);
+}
+
+static int osc_brw(int cmd, struct obd_export *exp, struct obd_info *oinfo,
+                   obd_count page_count, struct brw_page *pga,
+                   struct obd_trans_info *oti)
 {
         struct obdo *saved_oa = NULL;
-        int          rc;
+        struct brw_page **ppga, **orig;
+        struct obd_import *imp = class_exp2cliimp(exp);
+        struct client_obd *cli = &imp->imp_obd->u.cli;
+        int rc, page_count_orig;
         ENTRY;
 
         if (cmd & OBD_BRW_CHECK) {
                 /* The caller just wants to know if there's a chance that this
                  * I/O can succeed */
-                struct obd_import *imp = class_exp2cliimp(exp);
 
                 if (imp == NULL || imp->imp_invalid)
                         RETURN(-EIO);
@@ -1184,81 +1269,118 @@ static int osc_brw(int cmd, struct obd_export *exp, struct obdo *oa,
 
         rc = 0;
 
+        orig = ppga = osc_build_ppga(pga, page_count);
+        if (ppga == NULL)
+                RETURN(-ENOMEM);
+        page_count_orig = page_count;
+
+        sort_brw_pages(ppga, page_count);
         while (page_count) {
                 obd_count pages_per_brw;
 
-                if (page_count > PTLRPC_MAX_BRW_PAGES)
-                        pages_per_brw = PTLRPC_MAX_BRW_PAGES;
+                if (page_count > cli->cl_max_pages_per_rpc)
+                        pages_per_brw = cli->cl_max_pages_per_rpc;
                 else
                         pages_per_brw = page_count;
 
-                sort_brw_pages(pga, pages_per_brw);
-                pages_per_brw = max_unfragmented_pages(pga, pages_per_brw);
+                pages_per_brw = max_unfragmented_pages(ppga, pages_per_brw);
 
                 if (saved_oa != NULL) {
                         /* restore previously saved oa */
-                        *oa = *saved_oa;
+                        *oinfo->oi_oa = *saved_oa;
                 } else if (page_count > pages_per_brw) {
                         /* save a copy of oa (brw will clobber it) */
                         saved_oa = obdo_alloc();
                         if (saved_oa == NULL)
-                                RETURN(-ENOMEM);
-                        *saved_oa = *oa;
+                                GOTO(out, rc = -ENOMEM);
+                        *saved_oa = *oinfo->oi_oa;
                 }
 
-                rc = osc_brw_internal(cmd, exp, oa, md, pages_per_brw, pga);
+                rc = osc_brw_internal(cmd, exp, oinfo->oi_oa, oinfo->oi_md,
+                                      pages_per_brw, ppga);
 
                 if (rc != 0)
                         break;
 
                 page_count -= pages_per_brw;
-                pga += pages_per_brw;
+                ppga += pages_per_brw;
         }
 
+out:
+        osc_release_ppga(orig, page_count_orig);
+
         if (saved_oa != NULL)
                 obdo_free(saved_oa);
 
         RETURN(rc);
 }
 
-static int osc_brw_async(int cmd, struct obd_export *exp, struct obdo *oa,
-                         struct lov_stripe_md *md, obd_count page_count,
-                         struct brw_page *pga, struct ptlrpc_request_set *set,
-                         struct obd_trans_info *oti)
+static int osc_brw_async(int cmd, struct obd_export *exp,
+                         struct obd_info *oinfo, obd_count page_count,
+                         struct brw_page *pga, struct obd_trans_info *oti,
+                         struct ptlrpc_request_set *set)
 {
+        struct brw_page **ppga, **orig, **copy;
+        struct obd_import *imp = class_exp2cliimp(exp);
+        struct client_obd *cli = &imp->imp_obd->u.cli;
+        int page_count_orig;
+        int rc = 0;
         ENTRY;
 
         if (cmd & OBD_BRW_CHECK) {
                 /* The caller just wants to know if there's a chance that this
                  * I/O can succeed */
-                struct obd_import *imp = class_exp2cliimp(exp);
 
                 if (imp == NULL || imp->imp_invalid)
                         RETURN(-EIO);
                 RETURN(0);
         }
 
+        orig = ppga = osc_build_ppga(pga, page_count);
+        if (ppga == NULL)
+                RETURN(-ENOMEM);
+        page_count_orig = page_count;
+
+        sort_brw_pages(ppga, page_count);
         while (page_count) {
                 obd_count pages_per_brw;
-                int rc;
 
-                if (page_count > PTLRPC_MAX_BRW_PAGES)
-                        pages_per_brw = PTLRPC_MAX_BRW_PAGES;
+                if (page_count > cli->cl_max_pages_per_rpc)
+                        pages_per_brw = cli->cl_max_pages_per_rpc;
                 else
                         pages_per_brw = page_count;
 
-                sort_brw_pages(pga, pages_per_brw);
-                pages_per_brw = max_unfragmented_pages(pga, pages_per_brw);
+                pages_per_brw = max_unfragmented_pages(ppga, pages_per_brw);
+
+                /* use ppga only if single RPC is going to fly */
+                if (pages_per_brw != page_count_orig || ppga != orig) {
+                        int size = sizeof(struct brw_page *) * pages_per_brw;
+                        OBD_ALLOC(copy, size);
+                        if (copy == NULL)
+                                GOTO(out, rc = -ENOMEM);
+                        memcpy(copy, ppga, size);
+                } else
+                        copy = ppga;
 
-                rc = async_internal(cmd, exp, oa, md, pages_per_brw, pga, set);
+                rc = async_internal(cmd, exp, oinfo->oi_oa, oinfo->oi_md,
+                                    pages_per_brw, copy, set);
 
                 if (rc != 0)
-                        RETURN(rc);
+                        break;
+
+                if (copy == orig) {
+                        /* we passed it to async_internal() which is
+                         * now responsible for releasing memory */
+                        orig = NULL;
+                }
 
                 page_count -= pages_per_brw;
-                pga += pages_per_brw;
+                ppga += pages_per_brw;
         }
-        RETURN(0);
+out:
+        if (orig)
+                osc_release_ppga(orig, page_count_orig);
+        RETURN(rc);
 }
 
 static void osc_check_rpcs(struct client_obd *cli);
@@ -1384,7 +1506,7 @@ static void osc_occ_interrupted(struct oig_callback_context *occ)
                 lop_update_pending(oap->oap_cli, lop, oap->oap_cmd, -1);
                 loi_list_maint(oap->oap_cli, oap->oap_loi);
 
-                oig_complete_one(oap->oap_oig, &oap->oap_occ, 0);
+                oig_complete_one(oap->oap_oig, &oap->oap_occ, -EINTR);
                 oap->oap_oig = NULL;
         }
 
@@ -1414,13 +1536,27 @@ static void osc_process_ar(struct osc_async_rc *ar, struct ptlrpc_request *req,
                 ar->ar_force_sync = 0;
 }
 
+static void osc_oap_to_pending(struct osc_async_page *oap)
+{
+        struct loi_oap_pages *lop;
+
+        if (oap->oap_cmd & OBD_BRW_WRITE)
+                lop = &oap->oap_loi->loi_write_lop;
+        else
+                lop = &oap->oap_loi->loi_read_lop;
+
+        if (oap->oap_async_flags & ASYNC_URGENT)
+                list_add(&oap->oap_urgent_item, &lop->lop_urgent);
+        list_add_tail(&oap->oap_pending_item, &lop->lop_pending);
+        lop_update_pending(oap->oap_cli, lop, oap->oap_cmd, 1);
+}
+
 /* this must be called holding the loi list lock to give coverage to exit_cache,
  * async_flag maintenance, and oap_request */
 static void osc_ap_completion(struct client_obd *cli, struct obdo *oa,
                               struct osc_async_page *oap, int sent, int rc)
 {
         ENTRY;
-        osc_exit_cache(cli, oap, sent);
         oap->oap_async_flags = 0;
         oap->oap_interrupted = 0;
 
@@ -1446,18 +1582,28 @@ static void osc_ap_completion(struct client_obd *cli, struct obdo *oa,
         }
 
         if (oap->oap_oig) {
+                osc_exit_cache(cli, oap, sent);
                 oig_complete_one(oap->oap_oig, &oap->oap_occ, rc);
                 oap->oap_oig = NULL;
                 EXIT;
                 return;
         }
 
-        oap->oap_caller_ops->ap_completion(oap->oap_caller_data, oap->oap_cmd,
-                                           oa, rc);
+        rc = oap->oap_caller_ops->ap_completion(oap->oap_caller_data,
+                                                oap->oap_cmd, oa, rc);
+
+        /* ll_ap_completion (from llite) drops PG_locked. so, a new
+         * I/O on the page could start, but OSC calls it under lock
+         * and thus we can add oap back to pending safely */
+        if (rc)
+                /* upper layer wants to leave the page on pending queue */
+                osc_oap_to_pending(oap);
+        else
+                osc_exit_cache(cli, oap, sent);
         EXIT;
 }
 
-static int brw_interpret_oap(struct ptlrpc_request *request,
+static int brw_interpret_oap(struct ptlrpc_request *req,
                              struct osc_brw_async_args *aa, int rc)
 {
         struct osc_async_page *oap;
@@ -1465,11 +1611,11 @@ static int brw_interpret_oap(struct ptlrpc_request *request,
         struct list_head *pos, *n;
         ENTRY;
 
-        rc = osc_brw_fini_request(request, aa->aa_oa, aa->aa_requested_nob,
+        rc = osc_brw_fini_request(req, aa->aa_oa, aa->aa_requested_nob,
                                   aa->aa_nio_count, aa->aa_page_count,
-                                  aa->aa_pga, rc);
+                                  aa->aa_ppga, rc);
 
-        CDEBUG(D_INODE, "request %p aa %p rc %d\n", request, aa, rc);
+        CDEBUG(D_INODE, "request %p aa %p rc %d\n", req, aa, rc);
 
         cli = aa->aa_cli;
 
@@ -1478,7 +1624,7 @@ static int brw_interpret_oap(struct ptlrpc_request *request,
         /* We need to decrement before osc_ap_completion->osc_wake_cache_waiters
          * is called so we know whether to go to sync BRWs or wait for more
          * RPCs to complete */
-        if (request->rq_reqmsg->opc == OST_WRITE)
+        if (lustre_msg_get_opc(req->rq_reqmsg) == OST_WRITE)
                 cli->cl_w_in_flight--;
         else
                 cli->cl_r_in_flight--;
@@ -1501,7 +1647,7 @@ static int brw_interpret_oap(struct ptlrpc_request *request,
         client_obd_list_unlock(&cli->cl_loi_list_lock);
 
         obdo_free(aa->aa_oa);
-        OBD_FREE(aa->aa_pga, aa->aa_page_count * sizeof(struct brw_page));
+        OBD_FREE(aa->aa_ppga, aa->aa_page_count * sizeof(struct brw_page *));
 
         RETURN(0);
 }
@@ -1511,7 +1657,7 @@ static struct ptlrpc_request *osc_build_req(struct client_obd *cli,
                                             int page_count, int cmd)
 {
         struct ptlrpc_request *req;
-        struct brw_page *pga = NULL;
+        struct brw_page **pga = NULL;
         int requested_nob, nio_count;
         struct osc_brw_async_args *aa;
         struct obdo *oa = NULL;
@@ -1540,12 +1686,13 @@ static struct ptlrpc_request *osc_build_req(struct client_obd *cli,
                         ops = oap->oap_caller_ops;
                         caller_data = oap->oap_caller_data;
                 }
-                pga[i].off = oap->oap_obj_off + oap->oap_page_off;
-                pga[i].pg = oap->oap_page;
-                pga[i].count = oap->oap_count;
-                pga[i].flag = oap->oap_brw_flags;
+                pga[i] = &oap->oap_brw_page;
+                pga[i]->off = oap->oap_obj_off + oap->oap_page_off;
+                /*pga[i]->pg = oap->oap_page;
+                pga[i]->count = oap->oap_count;
+                pga[i]->flag = oap->oap_brw_flags;*/
                 CDEBUG(0, "put page %p index %lu oap %p flg %x to pga\n",
-                       pga[i].pg, cfs_page_index(oap->oap_page), oap, pga[i].flag);
+                       pga[i]->pg, cfs_page_index(oap->oap_page), oap, pga[i]->flag);
                 i++;
         }
 
@@ -1561,13 +1708,21 @@ static struct ptlrpc_request *osc_build_req(struct client_obd *cli,
                 GOTO(out, req = ERR_PTR(rc));
         }
 
+        /* Need to update the timestamps after the request is built in case
+         * we race with setattr (locally or in queue at OST).  If OST gets
+         * later setattr before earlier BRW (as determined by the request xid),
+         * the OST will not use BRW timestamps.  Sadly, there is no obvious
+         * way to do this in a single call.  bug 10150 */
+        ops->ap_update_obdo(caller_data, cmd, oa,
+                            OBD_MD_FLMTIME | OBD_MD_FLCTIME | OBD_MD_FLATIME);
+
         LASSERT(sizeof(*aa) <= sizeof(req->rq_async_args));
         aa = (struct osc_brw_async_args *)&req->rq_async_args;
         aa->aa_oa = oa;
         aa->aa_requested_nob = requested_nob;
         aa->aa_nio_count = nio_count;
         aa->aa_page_count = page_count;
-        aa->aa_pga = pga;
+        aa->aa_ppga = pga;
         aa->aa_cli = cli;
 
 out:
@@ -1585,7 +1740,7 @@ out:
 static int osc_send_oap_rpc(struct client_obd *cli, struct lov_oinfo *loi,
                             int cmd, struct loi_oap_pages *lop)
 {
-        struct ptlrpc_request *request;
+        struct ptlrpc_request *req;
         obd_count page_count = 0;
         struct list_head *tmp, *pos;
         struct osc_async_page *oap = NULL;
@@ -1712,8 +1867,8 @@ static int osc_send_oap_rpc(struct client_obd *cli, struct lov_oinfo *loi,
 
         client_obd_list_unlock(&cli->cl_loi_list_lock);
 
-        request = osc_build_req(cli, &rpc_list, page_count, cmd);
-        if (IS_ERR(request)) {
+        req = osc_build_req(cli, &rpc_list, page_count, cmd);
+        if (IS_ERR(req)) {
                 /* this should happen rarely and is pretty bad, it makes the
                  * pending list not follow the dirty order */
                 client_obd_list_lock(&cli->cl_loi_list_lock);
@@ -1730,22 +1885,14 @@ static int osc_send_oap_rpc(struct client_obd *cli, struct lov_oinfo *loi,
                                                   oap->oap_count);
                                 continue;
                         }
-                        osc_ap_completion(cli, NULL, oap, 0, PTR_ERR(request));
-
-                        /* put the page back in the loi/lop lists */
-                        list_add_tail(&oap->oap_pending_item,
-                                      &lop->lop_pending);
-                        lop_update_pending(cli, lop, cmd, 1);
-                        if (oap->oap_async_flags & ASYNC_URGENT)
-                                list_add(&oap->oap_urgent_item,
-                                         &lop->lop_urgent);
+                        osc_ap_completion(cli, NULL, oap, 0, PTR_ERR(req));
                 }
                 loi_list_maint(cli, loi);
-                RETURN(PTR_ERR(request));
+                RETURN(PTR_ERR(req));
         }
 
-        LASSERT(sizeof(*aa) <= sizeof(request->rq_async_args));
-        aa = (struct osc_brw_async_args *)&request->rq_async_args;
+        LASSERT(sizeof(*aa) <= sizeof(req->rq_async_args));
+        aa = (struct osc_brw_async_args *)&req->rq_async_args;
         CFS_INIT_LIST_HEAD(&aa->aa_oaps);
         list_splice(&rpc_list, &aa->aa_oaps);
         CFS_INIT_LIST_HEAD(&rpc_list);
@@ -1776,19 +1923,19 @@ static int osc_send_oap_rpc(struct client_obd *cli, struct lov_oinfo *loi,
                 oap = list_entry(pos, struct osc_async_page, oap_rpc_item);
                 if (oap->oap_interrupted) {
                         CDEBUG(D_INODE, "oap %p in req %p interrupted\n",
-                               oap, request);
-                        ptlrpc_mark_interrupted(request);
+                               oap, req);
+                        ptlrpc_mark_interrupted(req);
                         break;
                 }
         }
 
         CDEBUG(D_INODE, "req %p: %d pages, aa %p.  now %dr/%dw in flight\n",
-                        request, page_count, aa, cli->cl_r_in_flight,
+                        req, page_count, aa, cli->cl_r_in_flight,
                         cli->cl_w_in_flight);
 
-        oap->oap_request = ptlrpc_request_addref(request);
-        request->rq_interpret_reply = brw_interpret_oap;
-        ptlrpcd_add_req(request);
+        oap->oap_request = ptlrpc_request_addref(req);
+        req->rq_interpret_reply = brw_interpret_oap;
+        ptlrpcd_add_req(req);
         RETURN(1);
 }
 
@@ -2054,7 +2201,6 @@ static int osc_queue_async_io(struct obd_export *exp, struct lov_stripe_md *lsm,
 {
         struct client_obd *cli = &exp->exp_obd->u.cli;
         struct osc_async_page *oap;
-        struct loi_oap_pages *lop;
         int rc = 0;
         ENTRY;
 
@@ -2109,16 +2255,9 @@ static int osc_queue_async_io(struct obd_export *exp, struct lov_stripe_md *lsm,
                         client_obd_list_unlock(&cli->cl_loi_list_lock);
                         RETURN(rc);
                 }
-                lop = &loi->loi_write_lop;
-        } else {
-                lop = &loi->loi_read_lop;
         }
 
-        if (oap->oap_async_flags & ASYNC_URGENT)
-                list_add(&oap->oap_urgent_item, &lop->lop_urgent);
-        list_add_tail(&oap->oap_pending_item, &lop->lop_pending);
-        lop_update_pending(cli, lop, cmd, 1);
-
+        osc_oap_to_pending(oap);
         loi_list_maint(cli, loi);
 
         LOI_DEBUG(loi, "oap %p page %p added for cmd %d\n", oap, oap->oap_page,
@@ -2206,6 +2345,7 @@ static int osc_queue_group_io(struct obd_export *exp, struct lov_stripe_md *lsm,
         struct client_obd *cli = &exp->exp_obd->u.cli;
         struct osc_async_page *oap;
         struct loi_oap_pages *lop;
+        int rc = 0;
         ENTRY;
 
         oap = oap_from_cookie(cookie);
@@ -2239,14 +2379,15 @@ static int osc_queue_group_io(struct obd_export *exp, struct lov_stripe_md *lsm,
         list_add_tail(&oap->oap_pending_item, &lop->lop_pending_group);
         if (oap->oap_async_flags & ASYNC_GROUP_SYNC) {
                 oap->oap_oig = oig;
-                oig_add_one(oig, &oap->oap_occ);
+                rc = oig_add_one(oig, &oap->oap_occ);
         }
 
-        LOI_DEBUG(loi, "oap %p page %p on group pending\n", oap, oap->oap_page);
+        LOI_DEBUG(loi, "oap %p page %p on group pending: rc %d\n",
+                  oap, oap->oap_page, rc);
 
         client_obd_list_unlock(&cli->cl_loi_list_lock);
 
-        RETURN(0);
+        RETURN(rc);
 }
 
 static void osc_group_to_pending(struct client_obd *cli, struct lov_oinfo *loi,
@@ -2258,10 +2399,7 @@ static void osc_group_to_pending(struct client_obd *cli, struct lov_oinfo *loi,
         list_for_each_safe(pos, tmp, &lop->lop_pending_group) {
                 oap = list_entry(pos, struct osc_async_page, oap_pending_item);
                 list_del(&oap->oap_pending_item);
-                list_add_tail(&oap->oap_pending_item, &lop->lop_pending);
-                if (oap->oap_async_flags & ASYNC_URGENT)
-                        list_add(&oap->oap_urgent_item, &lop->lop_urgent);
-                lop_update_pending(cli, lop, cmd, 1);
+                osc_oap_to_pending(oap);
         }
         loi_list_maint(cli, loi);
 }
@@ -2337,42 +2475,42 @@ out:
 
 /* Note: caller will lock/unlock, and set uptodate on the pages */
 #if defined(__KERNEL__) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-static int sanosc_brw_read(struct obd_export *exp, struct obdo *oa,
-                           struct lov_stripe_md *lsm, obd_count page_count,
-                           struct brw_page *pga)
+static int sanosc_brw_read(struct obd_export *exp, struct obd_info *oinfo,
+                           obd_count page_count, struct brw_page *pga)
 {
-        struct ptlrpc_request *request = NULL;
+        struct ptlrpc_request *req = NULL;
         struct ost_body *body;
         struct niobuf_remote *nioptr;
         struct obd_ioobj *iooptr;
-        int rc, size[3] = {sizeof(*body)}, mapped = 0;
         struct obd_import *imp = class_exp2cliimp(exp);
-        int swab;
+        int size[4] = { sizeof(struct ptlrpc_body), sizeof(*body)};
+        int swab, mapped = 0, rc;
         ENTRY;
 
         /* XXX does not handle 'new' brw protocol */
 
-        size[1] = sizeof(struct obd_ioobj);
-        size[2] = page_count * sizeof(*nioptr);
+        size[REQ_REC_OFF + 1] = sizeof(struct obd_ioobj);
+        size[REQ_REC_OFF + 2] = page_count * sizeof(*nioptr);
 
-        request = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_OST_VERSION,
-                                  OST_SAN_READ, 3, size, NULL);
-        if (!request)
+        req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_OST_VERSION,
+                              OST_SAN_READ, 4, size, NULL);
+        if (!req)
                 RETURN(-ENOMEM);
 
         /* FIXME bug 249 */
         /* See bug 7198 */
         if (imp->imp_connect_data.ocd_connect_flags & OBD_CONNECT_REQPORTAL)
-                request->rq_request_portal = OST_IO_PORTAL;
+                req->rq_request_portal = OST_IO_PORTAL;
 
-        body = lustre_msg_buf(request->rq_reqmsg, 0, sizeof(*body));
-        iooptr = lustre_msg_buf(request->rq_reqmsg, 1, sizeof(*iooptr));
-        nioptr = lustre_msg_buf(request->rq_reqmsg, 2,
+        body = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, sizeof(*body));
+        iooptr = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF + 1,
+                                sizeof(*iooptr));
+        nioptr = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF + 2,
                                 sizeof(*nioptr) * page_count);
 
-        memcpy(&body->oa, oa, sizeof(body->oa));
+        memcpy(&body->oa, oinfo->oi_oa, sizeof(body->oa));
 
-        obdo_to_ioobj(oa, iooptr);
+        obdo_to_ioobj(oinfo->oi_oa, iooptr);
         iooptr->ioo_bufcnt = page_count;
 
         for (mapped = 0; mapped < page_count; mapped++, nioptr++) {
@@ -2384,25 +2522,26 @@ static int sanosc_brw_read(struct obd_export *exp, struct obdo *oa,
                 nioptr->flags  = pga[mapped].flag;
         }
 
-        size[1] = page_count * sizeof(*nioptr);
-        request->rq_replen = lustre_msg_size(2, size);
+        size[REPLY_REC_OFF + 1] = page_count * sizeof(*nioptr);
+        ptlrpc_req_set_repsize(req, 3, size);
 
-        rc = ptlrpc_queue_wait(request);
+        rc = ptlrpc_queue_wait(req);
         if (rc)
                 GOTO(out_req, rc);
 
-        body = lustre_swab_repbuf(request, 0, sizeof(*body),
+        body = lustre_swab_repbuf(req, REPLY_REC_OFF, sizeof(*body),
                                   lustre_swab_ost_body);
         if (body == NULL) {
                 CERROR("Can't unpack body\n");
                 GOTO(out_req, rc = -EPROTO);
         }
 
-        memcpy(oa, &body->oa, sizeof(*oa));
+        memcpy(oinfo->oi_oa, &body->oa, sizeof(*oinfo->oi_oa));
 
-        swab = lustre_msg_swabbed(request->rq_repmsg);
-        LASSERT_REPSWAB(request, 1);
-        nioptr = lustre_msg_buf(request->rq_repmsg, 1, size[1]);
+        swab = lustre_msg_swabbed(req->rq_repmsg);
+        LASSERT_REPSWAB(req, REPLY_REC_OFF + 1);
+        nioptr = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF + 1,
+                                size[REPLY_REC_OFF + 1]);
         if (!nioptr) {
                 /* nioptr missing or short */
                 GOTO(out_req, rc = -EPROTO);
@@ -2469,45 +2608,44 @@ static int sanosc_brw_read(struct obd_export *exp, struct obdo *oa,
         }
 
 out_req:
-        ptlrpc_req_finished(request);
+        ptlrpc_req_finished(req);
         RETURN(rc);
 }
 
-static int sanosc_brw_write(struct obd_export *exp, struct obdo *oa,
-                            struct lov_stripe_md *lsm, obd_count page_count,
-                            struct brw_page *pga)
+static int sanosc_brw_write(struct obd_export *exp, struct obd_info *oinfo,
+                            obd_count page_count, struct brw_page *pga)
 {
-        struct ptlrpc_request *request = NULL;
+        struct ptlrpc_request *req = NULL;
         struct ost_body *body;
         struct niobuf_remote *nioptr;
         struct obd_ioobj *iooptr;
         struct obd_import *imp = class_exp2cliimp(exp);
-        int rc, size[3] = {sizeof(*body)}, mapped = 0;
-        int swab;
+        int size[4] = { sizeof(struct ptlrpc_body), sizeof(*body) };
+        int swab, mapped = 0, rc;
         ENTRY;
 
-        size[1] = sizeof(struct obd_ioobj);
-        size[2] = page_count * sizeof(*nioptr);
+        size[REQ_REC_OFF + 1] = sizeof(struct obd_ioobj);
+        size[REQ_REC_OFF + 2] = page_count * sizeof(*nioptr);
 
-        request = ptlrpc_prep_req_pool(class_exp2cliimp(exp),
-                                       LUSTRE_OST_VERSION, OST_SAN_WRITE,
-                                       3, size, NULL, imp->imp_rq_pool);
-        if (!request)
+        req = ptlrpc_prep_req_pool(class_exp2cliimp(exp), LUSTRE_OST_VERSION,
+                                OST_SAN_WRITE, 4, size, NULL, imp->imp_rq_pool);
+        if (!req)
                 RETURN(-ENOMEM);
 
         /* FIXME bug 249 */
         /* See bug 7198 */
         if (imp->imp_connect_data.ocd_connect_flags & OBD_CONNECT_REQPORTAL)
-                request->rq_request_portal = OST_IO_PORTAL;
+                req->rq_request_portal = OST_IO_PORTAL;
 
-        body = lustre_msg_buf(request->rq_reqmsg, 0, sizeof (*body));
-        iooptr = lustre_msg_buf(request->rq_reqmsg, 1, sizeof (*iooptr));
-        nioptr = lustre_msg_buf(request->rq_reqmsg, 2,
-                                sizeof (*nioptr) * page_count);
+        body = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, sizeof(*body));
+        iooptr = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF + 1,
+                                sizeof(*iooptr));
+        nioptr = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF + 2,
+                                sizeof(*nioptr) * page_count);
 
-        memcpy(&body->oa, oa, sizeof(body->oa));
+        memcpy(&body->oa, oinfo->oi_oa, sizeof(body->oa));
 
-        obdo_to_ioobj(oa, iooptr);
+        obdo_to_ioobj(oinfo->oi_oa, iooptr);
         iooptr->ioo_bufcnt = page_count;
 
         /* pack request */
@@ -2520,16 +2658,17 @@ static int sanosc_brw_write(struct obd_export *exp, struct obdo *oa,
                 nioptr->flags  = pga[mapped].flag;
         }
 
-        size[1] = page_count * sizeof(*nioptr);
-        request->rq_replen = lustre_msg_size(2, size);
+        size[REPLY_REC_OFF + 1] = page_count * sizeof(*nioptr);
+        ptlrpc_req_set_repsize(req, 3, size);
 
-        rc = ptlrpc_queue_wait(request);
+        rc = ptlrpc_queue_wait(req);
         if (rc)
                 GOTO(out_req, rc);
 
-        swab = lustre_msg_swabbed (request->rq_repmsg);
-        LASSERT_REPSWAB (request, 1);
-        nioptr = lustre_msg_buf(request->rq_repmsg, 1, size[1]);
+        swab = lustre_msg_swabbed (req->rq_repmsg);
+        LASSERT_REPSWAB(req, REPLY_REC_OFF + 1);
+        nioptr = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF + 1,
+                                size[REPLY_REC_OFF + 1]);
         if (!nioptr) {
                 CERROR("absent/short niobuf array\n");
                 GOTO(out_req, rc = -EPROTO);
@@ -2589,29 +2728,31 @@ static int sanosc_brw_write(struct obd_export *exp, struct obdo *oa,
         }
 
 out_req:
-        ptlrpc_req_finished(request);
+        ptlrpc_req_finished(req);
         RETURN(rc);
 }
 
-static int sanosc_brw(int cmd, struct obd_export *exp, struct obdo *oa,
-                      struct lov_stripe_md *lsm, obd_count page_count,
-                      struct brw_page *pga, struct obd_trans_info *oti)
+static int sanosc_brw(int cmd, struct obd_export *exp, struct obd_info *oinfo,
+                      obd_count page_count, struct brw_page *pga,
+                      struct obd_trans_info *oti)
 {
+        struct obd_import *imp = class_exp2cliimp(exp);
+        struct client_obd *cli = &imp->imp_obd->u.cli;
         ENTRY;
 
         while (page_count) {
                 obd_count pages_per_brw;
                 int rc;
 
-                if (page_count > PTLRPC_MAX_BRW_PAGES)
-                        pages_per_brw = PTLRPC_MAX_BRW_PAGES;
+                if (page_count > cli->cl_max_pages_per_rpc)
+                        pages_per_brw = cli->cl_max_pages_per_rpc;
                 else
                         pages_per_brw = page_count;
 
                 if (cmd & OBD_BRW_WRITE)
-                        rc = sanosc_brw_write(exp, oa, lsm, pages_per_brw,pga);
+                        rc = sanosc_brw_write(exp, oinfo, pages_per_brw, pga);
                 else
-                        rc = sanosc_brw_read(exp, oa, lsm, pages_per_brw, pga);
+                        rc = sanosc_brw_read(exp, oinfo, pages_per_brw, pga);
 
                 if (rc != 0)
                         RETURN(rc);
@@ -2632,7 +2773,7 @@ static void osc_set_data_with_check(struct lustre_handle *lockh, void *data,
                 CERROR("lockh %p, data %p - client evicted?\n", lockh, data);
                 return;
         }
-        l_lock(&lock->l_resource->lr_namespace->ns_lock);
+        lock_res_and_lock(lock);
 #ifdef __KERNEL__
 #ifdef __LINUX__
         /* Liang XXX: Darwin and Winnt checking should be added */
@@ -2652,7 +2793,7 @@ static void osc_set_data_with_check(struct lustre_handle *lockh, void *data,
 #endif
         lock->l_ast_data = data;
         lock->l_flags |= (flags & LDLM_FL_NO_LRU);
-        l_unlock(&lock->l_resource->lr_namespace->ns_lock);
+        unlock_res_and_lock(lock);
         LDLM_LOCK_PUT(lock);
 }
 
@@ -2662,43 +2803,121 @@ static int osc_change_cbdata(struct obd_export *exp, struct lov_stripe_md *lsm,
         struct ldlm_res_id res_id = { .name = {lsm->lsm_object_id} };
         struct obd_device *obd = class_exp2obd(exp);
 
-        ldlm_change_cbdata(obd->obd_namespace, &res_id, replace, data);
+        ldlm_resource_iterate(obd->obd_namespace, &res_id, replace, data);
         return 0;
 }
 
-static int osc_enqueue(struct obd_export *exp, struct lov_stripe_md *lsm,
-                       __u32 type, ldlm_policy_data_t *policy, __u32 mode,
-                       int *flags, void *bl_cb, void *cp_cb, void *gl_cb,
-                       void *data, __u32 lvb_len, void *lvb_swabber,
-                       struct lustre_handle *lockh)
+static int osc_enqueue_fini(struct ptlrpc_request *req, struct obd_info *oinfo,
+                            int intent, int rc)
 {
-        struct ldlm_res_id res_id = { .name = {lsm->lsm_object_id} };
+        ENTRY;
+
+        if (intent) {
+                /* The request was created before ldlm_cli_enqueue call. */
+                if (rc == ELDLM_LOCK_ABORTED) {
+                        struct ldlm_reply *rep;
+
+                        /* swabbed by ldlm_cli_enqueue() */
+                        LASSERT_REPSWABBED(req, DLM_LOCKREPLY_OFF);
+                        rep = lustre_msg_buf(req->rq_repmsg, DLM_LOCKREPLY_OFF,
+                                             sizeof(*rep));
+                        LASSERT(rep != NULL);
+                        if (rep->lock_policy_res1)
+                                rc = rep->lock_policy_res1;
+                }
+        }
+
+        if ((intent && rc == ELDLM_LOCK_ABORTED) || !rc) {
+                CDEBUG(D_INODE,"got kms "LPU64" blocks "LPU64" mtime "LPU64"\n",
+                       oinfo->oi_md->lsm_oinfo->loi_lvb.lvb_size,
+                       oinfo->oi_md->lsm_oinfo->loi_lvb.lvb_blocks,
+                       oinfo->oi_md->lsm_oinfo->loi_lvb.lvb_mtime);
+        }
+
+        /* Call the update callback. */
+        rc = oinfo->oi_cb_up(oinfo, rc);
+        RETURN(rc);
+}
+
+static int osc_enqueue_interpret(struct ptlrpc_request *req,
+                                 struct osc_enqueue_args *aa, int rc)
+{
+        int intent = aa->oa_ei->ei_flags & LDLM_FL_HAS_INTENT;
+        struct lov_stripe_md *lsm = aa->oa_oi->oi_md;
+        struct ldlm_lock *lock;
+
+        /* ldlm_cli_enqueue is holding a reference on the lock, so it must
+         * be valid. */
+        lock = ldlm_handle2lock(aa->oa_oi->oi_lockh);
+
+        /* Complete obtaining the lock procedure. */
+        rc = ldlm_cli_enqueue_fini(aa->oa_exp, req, aa->oa_ei->ei_type, 1,
+                                   aa->oa_ei->ei_mode,
+                                   &aa->oa_ei->ei_flags,
+                                   &lsm->lsm_oinfo->loi_lvb,
+                                   sizeof(lsm->lsm_oinfo->loi_lvb),
+                                   lustre_swab_ost_lvb,
+                                   aa->oa_oi->oi_lockh, rc);
+
+        /* Complete osc stuff. */
+        rc = osc_enqueue_fini(req, aa->oa_oi, intent, rc);
+
+        /* Release the lock for async request. */
+        if (lustre_handle_is_used(aa->oa_oi->oi_lockh) && rc == ELDLM_OK)
+                ldlm_lock_decref(aa->oa_oi->oi_lockh, aa->oa_ei->ei_mode);
+
+        LASSERTF(lock != NULL, "lockh %p, req %p, aa %p - client evicted?\n",
+                 aa->oa_oi->oi_lockh, req, aa);
+        LDLM_LOCK_PUT(lock);
+        return rc;
+}
+
+/* When enqueuing asynchronously, locks are not ordered, we can obtain a lock
+ * from the 2nd OSC before a lock from the 1st one. This does not deadlock with
+ * other synchronous requests, however keeping some locks and trying to obtain
+ * others may take a considerable amount of time in a case of ost failure; and
+ * when other sync requests do not get released lock from a client, the client
+ * is excluded from the cluster -- such scenarious make the life difficult, so
+ * release locks just after they are obtained. */
+static int osc_enqueue(struct obd_export *exp, struct obd_info *oinfo,
+                       struct obd_enqueue_info *einfo)
+{
+        struct ldlm_res_id res_id = { .name = {oinfo->oi_md->lsm_object_id} };
         struct obd_device *obd = exp->exp_obd;
-        struct ost_lvb lvb;
         struct ldlm_reply *rep;
         struct ptlrpc_request *req = NULL;
+        int intent = einfo->ei_flags & LDLM_FL_HAS_INTENT;
         int rc;
         ENTRY;
 
         /* Filesystem lock extents are extended to page boundaries so that
          * dealing with the page cache is a little smoother.  */
-        policy->l_extent.start -= policy->l_extent.start & ~CFS_PAGE_MASK;
-        policy->l_extent.end |= ~CFS_PAGE_MASK;
+        oinfo->oi_policy.l_extent.start -=
+                oinfo->oi_policy.l_extent.start & ~CFS_PAGE_MASK;
+        oinfo->oi_policy.l_extent.end |= ~CFS_PAGE_MASK;
 
-        if (lsm->lsm_oinfo->loi_kms_valid == 0)
+        if (oinfo->oi_md->lsm_oinfo->loi_kms_valid == 0)
                 goto no_match;
 
         /* Next, search for already existing extent locks that will cover us */
-        rc = ldlm_lock_match(obd->obd_namespace, *flags, &res_id, type, policy,
-                             mode, lockh);
+        rc = ldlm_lock_match(obd->obd_namespace, einfo->ei_flags, &res_id,
+                             einfo->ei_type, &oinfo->oi_policy, einfo->ei_mode,
+                             oinfo->oi_lockh);
         if (rc == 1) {
-                osc_set_data_with_check(lockh, data, *flags);
-                if (*flags & LDLM_FL_HAS_INTENT) {
+                osc_set_data_with_check(oinfo->oi_lockh, einfo->ei_cbdata,
+                                        einfo->ei_flags);
+                if (intent) {
                         /* I would like to be able to ASSERT here that rss <=
                          * kms, but I can't, for reasons which are explained in
                          * lov_enqueue() */
                 }
+
+                /* For async requests, decref the lock. */
+                if (einfo->ei_rqset)
+                        ldlm_lock_decref(oinfo->oi_lockh, einfo->ei_mode);
+
                 /* We already have a lock, and it's referenced */
+                oinfo->oi_cb_up(oinfo, ELDLM_OK);
                 RETURN(ELDLM_OK);
         }
 
@@ -2714,58 +2933,75 @@ static int osc_enqueue(struct obd_export *exp, struct lov_stripe_md *lsm,
          * send us a blocking callback, but there are problems with canceling
          * locks out from other users right now, too. */
 
-        if (mode == LCK_PR) {
-                rc = ldlm_lock_match(obd->obd_namespace, *flags, &res_id, type,
-                                     policy, LCK_PW, lockh);
+        if (einfo->ei_mode == LCK_PR) {
+                rc = ldlm_lock_match(obd->obd_namespace, einfo->ei_flags,
+                                     &res_id, einfo->ei_type, &oinfo->oi_policy,
+                                     LCK_PW, oinfo->oi_lockh);
                 if (rc == 1) {
                         /* FIXME: This is not incredibly elegant, but it might
                          * be more elegant than adding another parameter to
                          * lock_match.  I want a second opinion. */
-                        ldlm_lock_addref(lockh, LCK_PR);
-                        ldlm_lock_decref(lockh, LCK_PW);
-                        osc_set_data_with_check(lockh, data, *flags);
+                        /* addref the lock only if not async requests. */
+                        if (!einfo->ei_rqset)
+                                ldlm_lock_addref(oinfo->oi_lockh, LCK_PR);
+                        osc_set_data_with_check(oinfo->oi_lockh,
+                                                einfo->ei_cbdata,
+                                                einfo->ei_flags);
+                        ldlm_lock_decref(oinfo->oi_lockh, LCK_PW);
+                        oinfo->oi_cb_up(oinfo, ELDLM_OK);
                         RETURN(ELDLM_OK);
                 }
         }
 
  no_match:
-        if (*flags & LDLM_FL_HAS_INTENT) {
-                int size[2] = {sizeof(struct ldlm_request), sizeof(lvb)};
+        if (intent) {
+                int size[3] = {
+                        [MSG_PTLRPC_BODY_OFF] = sizeof(struct ptlrpc_body),
+                        [DLM_LOCKREQ_OFF]     = sizeof(struct ldlm_request) };
 
-                req = ptlrpc_prep_req(class_exp2cliimp(exp),
-                                      LUSTRE_DLM_VERSION, LDLM_ENQUEUE, 1,
-                                      size, NULL);
+                req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_DLM_VERSION,
+                                      LDLM_ENQUEUE, 2, size, NULL);
                 if (req == NULL)
                         RETURN(-ENOMEM);
 
-                size[0] = sizeof(*rep);
-                req->rq_replen = lustre_msg_size(2, size);
+                size[DLM_LOCKREPLY_OFF] = sizeof(*rep);
+                size[DLM_REPLY_REC_OFF] = 
+                        sizeof(oinfo->oi_md->lsm_oinfo->loi_lvb);
+                ptlrpc_req_set_repsize(req, 3, size);
         }
 
         /* users of osc_enqueue() can pass this flag for ldlm_lock_match() */
-        *flags &= ~LDLM_FL_BLOCK_GRANTED;
-
-        rc = ldlm_cli_enqueue(exp, req, obd->obd_namespace, res_id, type,
-                              policy, mode, flags, bl_cb, cp_cb, gl_cb, data,
-                              &lvb, sizeof(lvb), lustre_swab_ost_lvb, lockh);
-
-        if (req != NULL) {
-                if (rc == ELDLM_LOCK_ABORTED) {
-                        /* swabbed by ldlm_cli_enqueue() */
-                        LASSERT_REPSWABBED(req, 0);
-                        rep = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*rep));
-                        LASSERT(rep != NULL);
-                        if (rep->lock_policy_res1)
-                                rc = rep->lock_policy_res1;
+        einfo->ei_flags &= ~LDLM_FL_BLOCK_GRANTED;
+
+        rc = ldlm_cli_enqueue(exp, &req, res_id, einfo->ei_type,
+                              &oinfo->oi_policy, einfo->ei_mode,
+                              &einfo->ei_flags, einfo->ei_cb_bl,
+                              einfo->ei_cb_cp, einfo->ei_cb_gl,
+                              einfo->ei_cbdata,
+                              &oinfo->oi_md->lsm_oinfo->loi_lvb,
+                              sizeof(oinfo->oi_md->lsm_oinfo->loi_lvb),
+                              lustre_swab_ost_lvb, oinfo->oi_lockh,
+                              einfo->ei_rqset ? 1 : 0);
+        if (einfo->ei_rqset) {
+                if (!rc) {
+                        struct osc_enqueue_args *aa;
+                        LASSERT (sizeof(*aa) <= sizeof(req->rq_async_args));
+                        aa = (struct osc_enqueue_args *)&req->rq_async_args;
+                        aa->oa_oi = oinfo;
+                        aa->oa_ei = einfo;
+                        aa->oa_exp = exp;
+
+                        req->rq_interpret_reply = osc_enqueue_interpret;
+                        ptlrpc_set_add_req(einfo->ei_rqset, req);
+                } else if (intent) {
+                        ptlrpc_req_finished(req);
                 }
-                ptlrpc_req_finished(req);
+                RETURN(rc);
         }
 
-        if ((*flags & LDLM_FL_HAS_INTENT && rc == ELDLM_LOCK_ABORTED) || !rc) {
-                CDEBUG(D_INODE,"got kms "LPU64" blocks "LPU64" mtime "LPU64"\n",
-                       lvb.lvb_size, lvb.lvb_blocks, lvb.lvb_mtime);
-                lsm->lsm_oinfo->loi_lvb = lvb;
-        }
+        rc = osc_enqueue_fini(req, oinfo, intent, rc);
+        if (intent)
+                ptlrpc_req_finished(req);
 
         RETURN(rc);
 }
@@ -2845,12 +3081,65 @@ static int osc_join_lru(struct obd_export *exp,
         return ldlm_cli_join_lru(obd->obd_namespace, &res_id, join);
 }
 
+static int osc_statfs_interpret(struct ptlrpc_request *req,
+                                struct osc_async_args *aa, int rc)
+{
+        struct obd_statfs *msfs;
+        ENTRY;
+
+        if (rc != 0)
+                GOTO(out, rc);
+
+        msfs = lustre_swab_repbuf(req, REPLY_REC_OFF, sizeof(*msfs),
+                                  lustre_swab_obd_statfs);
+        if (msfs == NULL) {
+                CERROR("Can't unpack obd_statfs\n");
+                GOTO(out, rc = -EPROTO);
+        }
+
+        memcpy(aa->aa_oi->oi_osfs, msfs, sizeof(*msfs));
+out:
+        rc = aa->aa_oi->oi_cb_up(aa->aa_oi, rc);
+        RETURN(rc);
+}
+
+static int osc_statfs_async(struct obd_device *obd, struct obd_info *oinfo,
+                            __u64 max_age, struct ptlrpc_request_set *rqset)
+{
+        struct ptlrpc_request *req;
+        struct osc_async_args *aa;
+        int size[2] = { sizeof(struct ptlrpc_body), sizeof(*oinfo->oi_osfs) };
+        ENTRY;
+
+        /* We could possibly pass max_age in the request (as an absolute
+         * timestamp or a "seconds.usec ago") so the target can avoid doing
+         * extra calls into the filesystem if that isn't necessary (e.g.
+         * during mount that would help a bit).  Having relative timestamps
+         * is not so great if request processing is slow, while absolute
+         * timestamps are not ideal because they need time synchronization. */
+        req = ptlrpc_prep_req(obd->u.cli.cl_import, LUSTRE_OST_VERSION,
+                              OST_STATFS, 1, NULL, NULL);
+        if (!req)
+                RETURN(-ENOMEM);
+
+        ptlrpc_req_set_repsize(req, 2, size);
+        req->rq_request_portal = OST_CREATE_PORTAL; //XXX FIXME bug 249
+
+        req->rq_interpret_reply = osc_statfs_interpret;
+        LASSERT (sizeof (*aa) <= sizeof (req->rq_async_args));
+        aa = (struct osc_async_args *)&req->rq_async_args;
+        aa->aa_oi = oinfo;
+
+        ptlrpc_set_add_req(rqset, req);
+        RETURN(0);
+}
+
 static int osc_statfs(struct obd_device *obd, struct obd_statfs *osfs,
-                      cfs_time_t max_age)
+                      __u64 max_age)
 {
         struct obd_statfs *msfs;
-        struct ptlrpc_request *request;
-        int rc, size = sizeof(*osfs);
+        struct ptlrpc_request *req;
+        int rc, size[2] = { sizeof(struct ptlrpc_body), sizeof(*osfs) };
         ENTRY;
 
         /* We could possibly pass max_age in the request (as an absolute
@@ -2859,19 +3148,19 @@ static int osc_statfs(struct obd_device *obd, struct obd_statfs *osfs,
          * during mount that would help a bit).  Having relative timestamps
          * is not so great if request processing is slow, while absolute
          * timestamps are not ideal because they need time synchronization. */
-        request = ptlrpc_prep_req(obd->u.cli.cl_import, LUSTRE_OST_VERSION,
-                                  OST_STATFS,0,NULL,NULL);
-        if (!request)
+        req = ptlrpc_prep_req(obd->u.cli.cl_import, LUSTRE_OST_VERSION,
+                              OST_STATFS, 1, NULL, NULL);
+        if (!req)
                 RETURN(-ENOMEM);
 
-        request->rq_replen = lustre_msg_size(1, &size);
-        request->rq_request_portal = OST_CREATE_PORTAL; //XXX FIXME bug 249
+        ptlrpc_req_set_repsize(req, 2, size);
+        req->rq_request_portal = OST_CREATE_PORTAL; //XXX FIXME bug 249
 
-        rc = ptlrpc_queue_wait(request);
+        rc = ptlrpc_queue_wait(req);
         if (rc)
                 GOTO(out, rc);
 
-        msfs = lustre_swab_repbuf(request, 0, sizeof(*msfs),
+        msfs = lustre_swab_repbuf(req, REPLY_REC_OFF, sizeof(*msfs),
                                   lustre_swab_obd_statfs);
         if (msfs == NULL) {
                 CERROR("Can't unpack obd_statfs\n");
@@ -2882,7 +3171,7 @@ static int osc_statfs(struct obd_device *obd, struct obd_statfs *osfs,
 
         EXIT;
  out:
-        ptlrpc_req_finished(request);
+        ptlrpc_req_finished(req);
         return rc;
 }
 
@@ -3040,19 +3329,21 @@ static int osc_get_info(struct obd_export *exp, obd_count keylen,
         } else if (keylen >= strlen("last_id") && strcmp(key, "last_id") == 0) {
                 struct ptlrpc_request *req;
                 obd_id *reply;
-                char *bufs[1] = {key};
-                int rc;
+                char *bufs[2] = { NULL, key };
+                int rc, size[2] = { sizeof(struct ptlrpc_body), keylen };
+
                 req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_OST_VERSION,
-                                      OST_GET_INFO, 1, &keylen, bufs);
+                                      OST_GET_INFO, 2, size, bufs);
                 if (req == NULL)
                         RETURN(-ENOMEM);
 
-                req->rq_replen = lustre_msg_size(1, vallen);
+                size[REPLY_REC_OFF] = *vallen;
+                ptlrpc_req_set_repsize(req, 2, size);
                 rc = ptlrpc_queue_wait(req);
                 if (rc)
                         GOTO(out, rc);
 
-                reply = lustre_swab_repbuf(req, 0, sizeof(*reply),
+                reply = lustre_swab_repbuf(req, REPLY_REC_OFF, sizeof(*reply),
                                            lustre_swab_ost_last_id);
                 if (reply == NULL) {
                         CERROR("Can't unpack OST last ID\n");
@@ -3099,8 +3390,8 @@ static int osc_set_info_async(struct obd_export *exp, obd_count keylen,
         struct ptlrpc_request *req;
         struct obd_device  *obd = exp->exp_obd;
         struct obd_import *imp = class_exp2cliimp(exp);
-        int size[2] = {keylen, vallen};
-        char *bufs[2] = {key, val};
+        int size[3] = { sizeof(struct ptlrpc_body), keylen, vallen };
+        char *bufs[3] = { NULL, key, val };
         ENTRY;
 
         OBD_FAIL_TIMEOUT(OBD_FAIL_OSC_SHUTDOWN, 10);
@@ -3151,15 +3442,15 @@ static int osc_set_info_async(struct obd_export *exp, obd_count keylen,
            Even if something bad goes through, we'd get a -EINVAL from OST
            anyway. */
 
-        req = ptlrpc_prep_req(imp, LUSTRE_OST_VERSION, OST_SET_INFO,
-                              2, size, bufs);
+        req = ptlrpc_prep_req(imp, LUSTRE_OST_VERSION, OST_SET_INFO, 3, size,
+                              bufs);
         if (req == NULL)
                 RETURN(-ENOMEM);
 
-        req->rq_replen = lustre_msg_size(0, NULL);
-
         if (KEY_IS("mds_conn"))
                 req->rq_interpret_reply = osc_setinfo_mds_conn_interpret;
+
+        ptlrpc_req_set_repsize(req, 1, NULL);
         ptlrpc_set_add_req(set, req);
         ptlrpc_check_set(set);
 
@@ -3186,11 +3477,22 @@ static int osc_llog_init(struct obd_device *obd, struct obd_device *tgt,
 
         rc = llog_setup(obd, LLOG_MDS_OST_ORIG_CTXT, tgt, count,
                         &catid->lci_logid, &osc_mds_ost_orig_logops);
-        if (rc)
-                RETURN(rc);
+        if (rc) {
+                CERROR("failed LLOG_MDS_OST_ORIG_CTXT\n");
+                GOTO (out, rc);
+        }
 
         rc = llog_setup(obd, LLOG_SIZE_REPL_CTXT, tgt, count, NULL,
                         &osc_size_repl_logops);
+        if (rc) 
+                CERROR("failed LLOG_SIZE_REPL_CTXT\n");
+out:
+        if (rc) {
+                CERROR("osc '%s' tgt '%s' cnt %d catid %p rc=%d\n", 
+                       obd->obd_name, tgt->obd_name, count, catid, rc);
+                CERROR("logid "LPX64":0x%x\n",
+                       catid->lci_logid.lgl_oid, catid->lci_logid.lgl_ogen);
+        }
         RETURN(rc);
 }
 
@@ -3417,6 +3719,17 @@ int osc_cleanup(struct obd_device *obd)
         RETURN(rc);
 }
 
+static int osc_process_config(struct obd_device *obd, obd_count len, void *buf)
+{
+        struct lustre_cfg *lcfg = buf;
+        struct lprocfs_static_vars lvars;
+        int rc = 0;
+
+        lprocfs_init_vars(osc, &lvars);
+
+        rc = class_process_proc_param(PARAM_OSC, lvars.obd_vars, lcfg, obd);
+        return(rc);
+}
 
 struct obd_ops osc_obd_ops = {
         .o_owner                = THIS_MODULE,
@@ -3429,6 +3742,7 @@ struct obd_ops osc_obd_ops = {
         .o_reconnect            = osc_reconnect,
         .o_disconnect           = osc_disconnect,
         .o_statfs               = osc_statfs,
+        .o_statfs_async         = osc_statfs_async,
         .o_packmd               = osc_packmd,
         .o_unpackmd             = osc_unpackmd,
         .o_create               = osc_create,
@@ -3459,6 +3773,7 @@ struct obd_ops osc_obd_ops = {
         .o_import_event         = osc_import_event,
         .o_llog_init            = osc_llog_init,
         .o_llog_finish          = osc_llog_finish,
+        .o_process_config       = osc_process_config,
 };
 
 #if defined(__KERNEL__) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
@@ -3473,6 +3788,7 @@ struct obd_ops sanosc_obd_ops = {
         .o_reconnect            = osc_reconnect,
         .o_disconnect           = client_disconnect_export,
         .o_statfs               = osc_statfs,
+        .o_statfs_async         = osc_statfs_async,
         .o_packmd               = osc_packmd,
         .o_unpackmd             = osc_unpackmd,
         .o_create               = osc_real_create,
@@ -3480,6 +3796,7 @@ struct obd_ops sanosc_obd_ops = {
         .o_getattr              = osc_getattr,
         .o_getattr_async        = osc_getattr_async,
         .o_setattr              = osc_setattr,
+        .o_setattr_async        = osc_setattr_async,
         .o_brw                  = sanosc_brw,
         .o_punch                = osc_punch,
         .o_sync                 = osc_sync,
@@ -3555,5 +3872,5 @@ MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
 MODULE_DESCRIPTION("Lustre Object Storage Client (OSC)");
 MODULE_LICENSE("GPL");
 
-cfs_module(osc, "1.0.0", osc_init, osc_exit);
+cfs_module(osc, LUSTRE_VERSION_STRING, osc_init, osc_exit);
 #endif
index 7b8e790..38f9518 100644 (file)
@@ -60,13 +60,13 @@ ost_print_req(void *seq_file, struct ptlrpc_request *req)
         case RQ_PHASE_INTERPRET:
                 /* being handled, so basic msg swabbed, and opc is valid
                  * but racing with ost_handle() */
-                seq_printf(sf, "opc %d\n", req->rq_reqmsg->opc);
+                seq_printf(sf, "opc %d\n", lustre_msg_get_opc(req->rq_reqmsg));
                 break;
                 
         case RQ_PHASE_COMPLETE:
                 /* been handled by ost_handle() reply state possibly still
                  * volatile */
-                seq_printf(sf, "opc %d\n", req->rq_reqmsg->opc);
+                seq_printf(sf, "opc %d\n", lustre_msg_get_opc(req->rq_reqmsg));
                 break;
 
         default:
index 9d6662c..3643451 100644 (file)
@@ -64,7 +64,7 @@ void oti_to_request(struct obd_trans_info *oti, struct ptlrpc_request *req)
                 return;
 
         if (req->rq_repmsg)
-                req->rq_repmsg->transno = oti->oti_transno;
+                lustre_msg_set_transno(req->rq_repmsg, oti->oti_transno);
         req->rq_transno = oti->oti_transno;
 
         /* XXX 4 == entries in oti_ack_locks??? */
@@ -80,20 +80,22 @@ static int ost_destroy(struct obd_export *exp, struct ptlrpc_request *req,
                        struct obd_trans_info *oti)
 {
         struct ost_body *body, *repbody;
-        int rc, size = sizeof(*body);
+        int rc, size[2] = { sizeof(struct ptlrpc_body), sizeof(*body) };
         ENTRY;
 
-        body = lustre_swab_reqbuf(req, 0, sizeof(*body), lustre_swab_ost_body);
+        body = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*body),
+                                  lustre_swab_ost_body);
         if (body == NULL)
                 RETURN(-EFAULT);
 
-        rc = lustre_pack_reply(req, 1, &size, NULL);
+        rc = lustre_pack_reply(req, 2, size, NULL);
         if (rc)
                 RETURN(rc);
 
         if (body->oa.o_valid & OBD_MD_FLCOOKIE)
                 oti->oti_logcookies = obdo_logcookie(&body->oa);
-        repbody = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*repbody));
+        repbody = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
+                                 sizeof(*repbody));
         memcpy(&repbody->oa, &body->oa, sizeof(body->oa));
         req->rq_status = obd_destroy(exp, &body->oa, NULL, oti, NULL);
         RETURN(0);
@@ -102,36 +104,42 @@ static int ost_destroy(struct obd_export *exp, struct ptlrpc_request *req,
 static int ost_getattr(struct obd_export *exp, struct ptlrpc_request *req)
 {
         struct ost_body *body, *repbody;
-        int rc, size = sizeof(*body);
+        struct obd_info oinfo = { { { 0 } } };
+        int rc, size[2] = { sizeof(struct ptlrpc_body), sizeof(*body) };
         ENTRY;
 
-        body = lustre_swab_reqbuf(req, 0, sizeof(*body), lustre_swab_ost_body);
+        body = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*body),
+                                  lustre_swab_ost_body);
         if (body == NULL)
                 RETURN(-EFAULT);
 
-        rc = lustre_pack_reply(req, 1, &size, NULL);
+        rc = lustre_pack_reply(req, 2, size, NULL);
         if (rc)
                 RETURN(rc);
 
-        repbody = lustre_msg_buf (req->rq_repmsg, 0, sizeof(*repbody));
+        repbody = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
+                                 sizeof(*repbody));
         memcpy(&repbody->oa, &body->oa, sizeof(body->oa));
-        req->rq_status = obd_getattr(exp, &repbody->oa, NULL);
+
+        oinfo.oi_oa = &repbody->oa;
+        req->rq_status = obd_getattr(exp, &oinfo);
         RETURN(0);
 }
 
 static int ost_statfs(struct ptlrpc_request *req)
 {
         struct obd_statfs *osfs;
-        int rc, size = sizeof(*osfs);
+        int rc, size[2] = { sizeof(struct ptlrpc_body), sizeof(*osfs) };
         ENTRY;
 
-        rc = lustre_pack_reply(req, 1, &size, NULL);
+        rc = lustre_pack_reply(req, 2, size, NULL);
         if (rc)
                 RETURN(rc);
 
-        osfs = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*osfs));
+        osfs = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF, sizeof(*osfs));
 
-        req->rq_status = obd_statfs(req->rq_export->exp_obd, osfs, jiffies-HZ);
+        req->rq_status = obd_statfs(req->rq_export->exp_obd, osfs, 
+                                    cfs_time_current_64() - HZ);
         if (OBD_FAIL_CHECK_ONCE(OBD_FAIL_OST_ENOSPC))
                 osfs->os_bfree = osfs->os_bavail = 64;
         if (req->rq_status != 0)
@@ -144,18 +152,20 @@ static int ost_create(struct obd_export *exp, struct ptlrpc_request *req,
                       struct obd_trans_info *oti)
 {
         struct ost_body *body, *repbody;
-        int rc, size = sizeof(*repbody);
+        int rc, size[2] = { sizeof(struct ptlrpc_body), sizeof(*repbody) };
         ENTRY;
 
-        body = lustre_swab_reqbuf(req, 0, sizeof(*body), lustre_swab_ost_body);
+        body = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*body),
+                                  lustre_swab_ost_body);
         if (body == NULL)
                 RETURN(-EFAULT);
 
-        rc = lustre_pack_reply(req, 1, &size, NULL);
+        rc = lustre_pack_reply(req, 2, size, NULL);
         if (rc)
                 RETURN(rc);
 
-        repbody = lustre_msg_buf (req->rq_repmsg, 0, sizeof(*repbody));
+        repbody = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
+                                 sizeof(*repbody));
         memcpy(&repbody->oa, &body->oa, sizeof(body->oa));
         oti->oti_logcookies = obdo_logcookie(&repbody->oa);
         req->rq_status = obd_create(exp, &repbody->oa, NULL, oti);
@@ -206,11 +216,10 @@ static int ost_punch_lock_get(struct obd_export *exp, struct obdo *oa,
         else
                 policy.l_extent.end = finis | ~CFS_PAGE_MASK;
 
-        RETURN(ldlm_cli_enqueue(NULL, NULL, exp->exp_obd->obd_namespace,
-                                res_id, LDLM_EXTENT, &policy, LCK_PW, &flags,
-                                ldlm_blocking_ast, ldlm_completion_ast,
-                                ldlm_glimpse_ast,
-                                NULL, NULL, 0, NULL, lh));
+        RETURN(ldlm_cli_enqueue_local(exp->exp_obd->obd_namespace, res_id, 
+                                      LDLM_EXTENT, &policy, LCK_PW, &flags,
+                                      ldlm_blocking_ast, ldlm_completion_ast,
+                                      ldlm_glimpse_ast, NULL, 0, NULL, lh));
 }
 
 /*
@@ -229,48 +238,48 @@ static void ost_punch_lock_put(struct obd_export *exp, struct obdo *oa,
 static int ost_punch(struct obd_export *exp, struct ptlrpc_request *req,
                      struct obd_trans_info *oti)
 {
-        struct obdo     *oa;
+        struct obd_info oinfo = { { { 0 } } };
         struct ost_body *body, *repbody;
+        int rc, size[2] = { sizeof(struct ptlrpc_body), sizeof(*repbody) };
         struct lustre_handle lh = {0,};
-
-        int rc, size = sizeof(*repbody);
-
         ENTRY;
 
-        /*
-         * check that we do support OBD_CONNECT_TRUNCLOCK.
-         */
+        /* check that we do support OBD_CONNECT_TRUNCLOCK. */
         CLASSERT(OST_CONNECT_SUPPORTED & OBD_CONNECT_TRUNCLOCK);
 
-        body = lustre_swab_reqbuf(req, 0, sizeof *body, lustre_swab_ost_body);
+        body = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*body),
+                                  lustre_swab_ost_body);
         if (body == NULL)
                 RETURN(-EFAULT);
 
-        oa = &body->oa;
-        if ((oa->o_valid & (OBD_MD_FLSIZE | OBD_MD_FLBLOCKS)) !=
+        oinfo.oi_oa = &body->oa;
+        oinfo.oi_policy.l_extent.start = oinfo.oi_oa->o_size;
+        oinfo.oi_policy.l_extent.end = oinfo.oi_oa->o_blocks;
+
+        if ((oinfo.oi_oa->o_valid & (OBD_MD_FLSIZE | OBD_MD_FLBLOCKS)) !=
             (OBD_MD_FLSIZE | OBD_MD_FLBLOCKS))
                 RETURN(-EINVAL);
 
-        rc = lustre_pack_reply(req, 1, &size, NULL);
+        rc = lustre_pack_reply(req, 2, size, NULL);
         if (rc)
                 RETURN(rc);
 
-        repbody = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*repbody));
-        repbody->oa = *oa;
-        rc = ost_punch_lock_get(exp, oa, &lh);
+        repbody = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
+                                 sizeof(*repbody));
+        repbody->oa = *oinfo.oi_oa;
+        rc = ost_punch_lock_get(exp, oinfo.oi_oa, &lh);
         if (rc == 0) {
-                if (oa->o_valid & OBD_MD_FLFLAGS &&
-                    oa->o_flags == OBD_FL_TRUNCLOCK)
+                if (oinfo.oi_oa->o_valid & OBD_MD_FLFLAGS &&
+                    oinfo.oi_oa->o_flags == OBD_FL_TRUNCLOCK)
                         /*
                          * If OBD_FL_TRUNCLOCK is the only bit set in
                          * ->o_flags, clear OBD_MD_FLFLAGS to avoid falling
                          * through filter_setattr() to filter_iocontrol().
                          */
-                        oa->o_valid &= ~OBD_MD_FLFLAGS;
+                        oinfo.oi_oa->o_valid &= ~OBD_MD_FLFLAGS;
 
-                req->rq_status = obd_punch(exp, oa, NULL,
-                                           oa->o_size, oa->o_blocks, oti);
-                ost_punch_lock_put(exp, oa, &lh);
+                req->rq_status = obd_punch(exp, &oinfo, oti, NULL);
+                ost_punch_lock_put(exp, oinfo.oi_oa, &lh);
         }
         RETURN(rc);
 }
@@ -278,18 +287,20 @@ static int ost_punch(struct obd_export *exp, struct ptlrpc_request *req,
 static int ost_sync(struct obd_export *exp, struct ptlrpc_request *req)
 {
         struct ost_body *body, *repbody;
-        int rc, size = sizeof(*repbody);
+        int rc, size[2] = { sizeof(struct ptlrpc_body), sizeof(*repbody) };
         ENTRY;
 
-        body = lustre_swab_reqbuf(req, 0, sizeof(*body), lustre_swab_ost_body);
+        body = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*body),
+                                  lustre_swab_ost_body);
         if (body == NULL)
                 RETURN(-EFAULT);
 
-        rc = lustre_pack_reply(req, 1, &size, NULL);
+        rc = lustre_pack_reply(req, 2, size, NULL);
         if (rc)
                 RETURN(rc);
 
-        repbody = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*repbody));
+        repbody = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
+                                 sizeof(*repbody));
         memcpy(&repbody->oa, &body->oa, sizeof(body->oa));
         req->rq_status = obd_sync(exp, &repbody->oa, NULL, repbody->oa.o_size,
                                   repbody->oa.o_blocks);
@@ -300,21 +311,25 @@ static int ost_setattr(struct obd_export *exp, struct ptlrpc_request *req,
                        struct obd_trans_info *oti)
 {
         struct ost_body *body, *repbody;
-        int rc, size = sizeof(*repbody);
+        int rc, size[2] = { sizeof(struct ptlrpc_body), sizeof(*repbody) };
+        struct obd_info oinfo = { { { 0 } } };
         ENTRY;
 
-        body = lustre_swab_reqbuf(req, 0, sizeof(*body), lustre_swab_ost_body);
+        body = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*body),
+                                  lustre_swab_ost_body);
         if (body == NULL)
                 RETURN(-EFAULT);
 
-        rc = lustre_pack_reply(req, 1, &size, NULL);
+        rc = lustre_pack_reply(req, 2, size, NULL);
         if (rc)
                 RETURN(rc);
 
-        repbody = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*repbody));
+        repbody = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
+                                 sizeof(*repbody));
         memcpy(&repbody->oa, &body->oa, sizeof(body->oa));
 
-        req->rq_status = obd_setattr(exp, &repbody->oa, NULL, oti);
+        oinfo.oi_oa = &repbody->oa;
+        req->rq_status = obd_setattr(exp, &oinfo, oti);
         RETURN(0);
 }
 
@@ -486,53 +501,6 @@ static void ost_nio_pages_put(struct ptlrpc_request *req,
         EXIT;
 }
 
-#if 0
-/* see ldlm_blocking_ast */
-/* cut-n-paste of mds_blocking_ast() */
-static int ost_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
-                            void *data, int flag)
-{
-        int do_ast;
-        ENTRY;
-
-        if (flag == LDLM_CB_CANCELING) {
-                /* Don't need to do anything here. */
-                RETURN(0);
-        }
-
-        /* XXX layering violation!  -phil */
-        l_lock(&lock->l_resource->lr_namespace->ns_lock);
-        /* Get this: if mds_blocking_ast is racing with mds_intent_policy,
-         * such that mds_blocking_ast is called just before l_i_p takes the
-         * ns_lock, then by the time we get the lock, we might not be the
-         * correct blocking function anymore.  So check, and return early, if
-         * so. */
-        if (lock->l_blocking_ast != ost_blocking_ast) {
-                l_unlock(&lock->l_resource->lr_namespace->ns_lock);
-                RETURN(0);
-        }
-
-        lock->l_flags |= LDLM_FL_CBPENDING;
-        do_ast = (!lock->l_readers && !lock->l_writers);
-        l_unlock(&lock->l_resource->lr_namespace->ns_lock);
-
-        if (do_ast) {
-                struct lustre_handle lockh;
-                int rc;
-
-                LDLM_DEBUG(lock, "already unused, calling ldlm_cli_cancel");
-                ldlm_lock2handle(lock, &lockh);
-                rc = ldlm_cli_cancel(&lockh);
-                if (rc < 0)
-                        CERROR("ldlm_cli_cancel: %d\n", rc);
-        } else {
-                LDLM_DEBUG(lock, "Lock still has references, will be "
-                           "cancelled later");
-        }
-        RETURN(0);
-}
-#endif
-
 static int ost_brw_lock_get(int mode, struct obd_export *exp,
                             struct obd_ioobj *obj, struct niobuf_remote *nb,
                             struct lustre_handle *lh)
@@ -560,11 +528,10 @@ static int ost_brw_lock_get(int mode, struct obd_export *exp,
         policy.l_extent.end   = (nb[nrbufs - 1].offset +
                                  nb[nrbufs - 1].len - 1) | ~CFS_PAGE_MASK;
 
-        RETURN(ldlm_cli_enqueue(NULL, NULL, exp->exp_obd->obd_namespace,
-                                res_id, LDLM_EXTENT, &policy, mode, &flags,
-                                ldlm_blocking_ast, ldlm_completion_ast,
-                                ldlm_glimpse_ast,
-                                NULL, NULL, 0, NULL, lh));
+        RETURN(ldlm_cli_enqueue_local(exp->exp_obd->obd_namespace, res_id, 
+                                      LDLM_EXTENT, &policy, mode, &flags,
+                                      ldlm_blocking_ast, ldlm_completion_ast,
+                                      ldlm_glimpse_ast, NULL, 0, NULL, lh));
 }
 
 static void ost_brw_lock_put(int mode,
@@ -580,23 +547,85 @@ static void ost_brw_lock_put(int mode,
         EXIT;
 }
 
+struct ost_prolong_data {
+        struct obd_export *opd_exp;
+        ldlm_policy_data_t opd_policy;
+        ldlm_mode_t opd_mode;
+};
+
+static int ost_prolong_locks_iter(struct ldlm_lock *lock, void *data)
+{
+        struct ost_prolong_data *opd = data;
+
+        LASSERT(lock->l_resource->lr_type == LDLM_EXTENT);
+
+        if (lock->l_req_mode != lock->l_granted_mode) {
+                /* scan granted locks only */
+                return LDLM_ITER_STOP;
+        }
+
+        if (lock->l_export != opd->opd_exp) {
+                /* prolong locks only for given client */
+                return LDLM_ITER_CONTINUE;
+        }
+
+        if (!(lock->l_granted_mode & opd->opd_mode)) {
+                /* we aren't interesting in all type of locks */
+                return LDLM_ITER_CONTINUE;
+        }
+
+        if (lock->l_policy_data.l_extent.end < opd->opd_policy.l_extent.start ||
+            lock->l_policy_data.l_extent.start > opd->opd_policy.l_extent.end) {
+                /* the request doesn't cross the lock, skip it */
+                return LDLM_ITER_CONTINUE;
+        }
+
+        if (!(lock->l_flags & LDLM_FL_AST_SENT)) {
+                /* ignore locks not being cancelled */
+                return LDLM_ITER_CONTINUE;
+        }
+
+        /* OK. this is a possible lock the user holds doing I/O
+         * let's refresh eviction timer for it */
+        ldlm_refresh_waiting_lock(lock);
+
+        return LDLM_ITER_CONTINUE;
+}
+
+static void ost_prolong_locks(struct obd_export *exp, struct obd_ioobj *obj,
+                              struct niobuf_remote *nb, ldlm_mode_t mode)
+{
+        struct ldlm_res_id res_id = { .name = { obj->ioo_id } };
+        int nrbufs = obj->ioo_bufcnt;
+        struct ost_prolong_data opd;
+
+        ENTRY;
+
+        opd.opd_mode = mode;
+        opd.opd_exp = exp;
+        opd.opd_policy.l_extent.start = nb[0].offset & CFS_PAGE_MASK;
+        opd.opd_policy.l_extent.end = (nb[nrbufs - 1].offset +
+                                       nb[nrbufs - 1].len - 1) | ~CFS_PAGE_MASK;
+
+        CDEBUG(D_DLMTRACE,"refresh locks: "LPU64"/"LPU64" ("LPU64"->"LPU64")\n",
+               res_id.name[0], res_id.name[1], opd.opd_policy.l_extent.start,
+               opd.opd_policy.l_extent.end);
+        ldlm_resource_iterate(exp->exp_obd->obd_namespace, &res_id,
+                              ost_prolong_locks_iter, &opd);
+}
+
 static int ost_brw_read(struct ptlrpc_request *req, struct obd_trans_info *oti)
 {
         struct ptlrpc_bulk_desc *desc;
-        struct niobuf_remote    *remote_nb;
-        struct niobuf_remote    *pp_rnb = NULL;
-        struct niobuf_local     *local_nb;
-        struct obd_ioobj        *ioo;
-        struct ost_body         *body, *repbody;
-        struct l_wait_info       lwi;
-        struct lustre_handle     lockh = {0};
-        int                      size[1] = { sizeof(*body) };
-        int                      comms_error = 0;
-        int                      niocount;
-        int                      npages;
-        int                      nob = 0;
-        int                      rc;
-        int                      i, do_checksum;
+        struct niobuf_remote *remote_nb;
+        struct niobuf_remote *pp_rnb = NULL;
+        struct niobuf_local *local_nb;
+        struct obd_ioobj *ioo;
+        struct ost_body *body, *repbody;
+        struct l_wait_info lwi;
+        struct lustre_handle lockh = { 0 };
+        int size[2] = { sizeof(struct ptlrpc_body), sizeof(*body) };
+        int comms_error = 0, niocount, npages, nob = 0, rc, i, do_checksum;
         ENTRY;
 
         if (OBD_FAIL_CHECK(OBD_FAIL_OST_BRW_READ_BULK))
@@ -605,13 +634,15 @@ static int ost_brw_read(struct ptlrpc_request *req, struct obd_trans_info *oti)
         OBD_FAIL_TIMEOUT(OBD_FAIL_OST_BRW_PAUSE_BULK | OBD_FAIL_ONCE,
                          (obd_timeout + 1) / 4);
 
-        body = lustre_swab_reqbuf(req, 0, sizeof(*body), lustre_swab_ost_body);
+        body = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*body),
+                                  lustre_swab_ost_body);
         if (body == NULL) {
                 CERROR("Missing/short ost_body\n");
                 GOTO(out, rc = -EFAULT);
         }
 
-        ioo = lustre_swab_reqbuf(req, 1, sizeof(*ioo), lustre_swab_obd_ioobj);
+        ioo = lustre_swab_reqbuf(req, REQ_REC_OFF + 1, sizeof(*ioo),
+                                 lustre_swab_obd_ioobj);
         if (ioo == NULL) {
                 CERROR("Missing/short ioobj\n");
                 GOTO(out, rc = -EFAULT);
@@ -624,7 +655,8 @@ static int ost_brw_read(struct ptlrpc_request *req, struct obd_trans_info *oti)
                 GOTO(out, rc = -EFAULT);
         }
 
-        remote_nb = lustre_swab_reqbuf(req, 2, niocount * sizeof(*remote_nb),
+        remote_nb = lustre_swab_reqbuf(req, REQ_REC_OFF + 2,
+                                       niocount * sizeof(*remote_nb),
                                        lustre_swab_niobuf_remote);
         if (remote_nb == NULL) {
                 CERROR("Missing/short niobuf\n");
@@ -635,7 +667,7 @@ static int ost_brw_read(struct ptlrpc_request *req, struct obd_trans_info *oti)
                         lustre_swab_niobuf_remote (&remote_nb[i]);
         }
 
-        rc = lustre_pack_reply(req, 1, size, NULL);
+        rc = lustre_pack_reply(req, 2, size, NULL);
         if (rc)
                 GOTO(out, rc);
 
@@ -670,6 +702,8 @@ static int ost_brw_read(struct ptlrpc_request *req, struct obd_trans_info *oti)
         if (rc != 0)
                 GOTO(out_lock, rc);
 
+        ost_prolong_locks(req->rq_export, ioo, pp_rnb, LCK_PW | LCK_PR);
+
         /* We're finishing using body->oa as an input variable */
         do_checksum = (body->oa.o_valid & OBD_MD_FLCKSUM);
         body->oa.o_valid = 0;
@@ -745,7 +779,8 @@ static int ost_brw_read(struct ptlrpc_request *req, struct obd_trans_info *oti)
         ost_nio_pages_put(req, local_nb, npages);
 
         if (rc == 0) {
-                repbody = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*repbody));
+                repbody = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
+                                         sizeof(*repbody));
                 memcpy(&repbody->oa, &body->oa, sizeof(repbody->oa));
 
                 if (unlikely(do_checksum)) {
@@ -777,20 +812,12 @@ static int ost_brw_read(struct ptlrpc_request *req, struct obd_trans_info *oti)
                         ptlrpc_rs_decref(req->rq_reply_state);
                         req->rq_reply_state = NULL;
                 }
-                if (req->rq_reqmsg->conn_cnt == req->rq_export->exp_conn_cnt) {
-                        CERROR("%s: bulk IO comm error evicting %s@%s id %s\n",
-                               req->rq_export->exp_obd->obd_name,
-                               req->rq_export->exp_client_uuid.uuid,
-                               req->rq_export->exp_connection->c_remote_uuid.uuid,
-                               libcfs_id2str(req->rq_peer));
-                        class_fail_export(req->rq_export);
-                } else {
-                        CERROR("ignoring bulk IO comms error: "
-                               "client reconnected %s@%s id %s\n",
-                               req->rq_export->exp_client_uuid.uuid,
-                               req->rq_export->exp_connection->c_remote_uuid.uuid,
-                               libcfs_id2str(req->rq_peer));
-                }
+                CWARN("%s: ignoring bulk IO comm error with %s@%s id %s - "
+                      "client will retry\n",
+                      req->rq_export->exp_obd->obd_name,
+                      req->rq_export->exp_client_uuid.uuid,
+                      req->rq_export->exp_connection->c_remote_uuid.uuid,
+                      libcfs_id2str(req->rq_peer));
         }
 
         RETURN(rc);
@@ -807,10 +834,9 @@ static int ost_brw_write(struct ptlrpc_request *req, struct obd_trans_info *oti)
         struct l_wait_info       lwi;
         struct lustre_handle     lockh = {0};
         __u32                   *rcs;
-        int                      size[2] = { sizeof(*body) };
-        int                      objcount, niocount, npages;
-        int                      comms_error = 0;
-        int                      rc, swab, i, j, do_checksum;
+        int size[3] = { sizeof(struct ptlrpc_body), sizeof(*body) };
+        int objcount, niocount, npages, comms_error = 0;
+        int rc, swab, i, j, do_checksum;
         ENTRY;
 
         if (OBD_FAIL_CHECK(OBD_FAIL_OST_BRW_WRITE_BULK))
@@ -821,14 +847,16 @@ static int ost_brw_write(struct ptlrpc_request *req, struct obd_trans_info *oti)
                          (obd_timeout + 1) / 4);
 
         swab = lustre_msg_swabbed(req->rq_reqmsg);
-        body = lustre_swab_reqbuf(req, 0, sizeof(*body), lustre_swab_ost_body);
+        body = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*body),
+                                  lustre_swab_ost_body);
         if (body == NULL) {
                 CERROR("Missing/short ost_body\n");
                 GOTO(out, rc = -EFAULT);
         }
 
-        LASSERT_REQSWAB(req, 1);
-        objcount = req->rq_reqmsg->buflens[1] / sizeof(*ioo);
+        LASSERT_REQSWAB(req, REQ_REC_OFF + 1);
+        objcount = lustre_msg_buflen(req->rq_reqmsg, REQ_REC_OFF + 1) /
+                   sizeof(*ioo);
         if (objcount == 0) {
                 CERROR("Missing/short ioobj\n");
                 GOTO(out, rc = -EFAULT);
@@ -838,11 +866,12 @@ static int ost_brw_write(struct ptlrpc_request *req, struct obd_trans_info *oti)
                 GOTO(out, rc = -EFAULT);
         }
 
-        ioo = lustre_msg_buf (req->rq_reqmsg, 1, objcount * sizeof(*ioo));
+        ioo = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF + 1,
+                             objcount * sizeof(*ioo));
         LASSERT (ioo != NULL);
         for (niocount = i = 0; i < objcount; i++) {
                 if (swab)
-                        lustre_swab_obd_ioobj (&ioo[i]);
+                        lustre_swab_obd_ioobj(&ioo[i]);
                 if (ioo[i].ioo_bufcnt == 0) {
                         CERROR("ioo[%d] has zero bufcnt\n", i);
                         GOTO(out, rc = -EFAULT);
@@ -856,7 +885,8 @@ static int ost_brw_write(struct ptlrpc_request *req, struct obd_trans_info *oti)
                 GOTO(out, rc = -EFAULT);
         }
 
-        remote_nb = lustre_swab_reqbuf(req, 2, niocount * sizeof(*remote_nb),
+        remote_nb = lustre_swab_reqbuf(req, REQ_REC_OFF + 2,
+                                       niocount * sizeof(*remote_nb),
                                        lustre_swab_niobuf_remote);
         if (remote_nb == NULL) {
                 CERROR("Missing/short niobuf\n");
@@ -867,11 +897,12 @@ static int ost_brw_write(struct ptlrpc_request *req, struct obd_trans_info *oti)
                         lustre_swab_niobuf_remote (&remote_nb[i]);
         }
 
-        size[1] = niocount * sizeof(*rcs);
-        rc = lustre_pack_reply(req, 2, size, NULL);
+        size[REPLY_REC_OFF + 1] = niocount * sizeof(*rcs);
+        rc = lustre_pack_reply(req, 3, size, NULL);
         if (rc != 0)
                 GOTO(out, rc);
-        rcs = lustre_msg_buf(req->rq_repmsg, 1, niocount * sizeof(*rcs));
+        rcs = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF + 1,
+                             niocount * sizeof(*rcs));
 
         /*
          * Per-thread array of struct niobuf_{local,remote}'s was allocated by
@@ -899,6 +930,8 @@ static int ost_brw_write(struct ptlrpc_request *req, struct obd_trans_info *oti)
         if (rc != 0)
                 GOTO(out_bulk, rc);
 
+        ost_prolong_locks(req->rq_export, ioo, pp_rnb, LCK_PW);
+
         /* obd_preprw clobbers oa->valid, so save what we need */
         do_checksum = (body->oa.o_valid & OBD_MD_FLCKSUM);
 
@@ -947,7 +980,8 @@ static int ost_brw_write(struct ptlrpc_request *req, struct obd_trans_info *oti)
         }
         comms_error = rc != 0;
 
-        repbody = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*repbody));
+        repbody = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
+                                 sizeof(*repbody));
         memcpy(&repbody->oa, &body->oa, sizeof(repbody->oa));
 
         if (unlikely(do_checksum && rc == 0)) {
@@ -1020,20 +1054,12 @@ static int ost_brw_write(struct ptlrpc_request *req, struct obd_trans_info *oti)
                         ptlrpc_rs_decref(req->rq_reply_state);
                         req->rq_reply_state = NULL;
                 }
-                if (req->rq_reqmsg->conn_cnt == req->rq_export->exp_conn_cnt) {
-                        CERROR("%s: bulk IO comm error evicting %s@%s id %s\n",
-                               req->rq_export->exp_obd->obd_name,
-                               req->rq_export->exp_client_uuid.uuid,
-                               req->rq_export->exp_connection->c_remote_uuid.uuid,
-                               libcfs_id2str(req->rq_peer));
-                        class_fail_export(req->rq_export);
-                } else {
-                        CERROR("ignoring bulk IO comms error: "
-                               "client reconnected %s@%s id %s\n",
-                               req->rq_export->exp_client_uuid.uuid,
-                               req->rq_export->exp_connection->c_remote_uuid.uuid,
-                               libcfs_id2str(req->rq_peer));
-                }
+                CWARN("%s: ignoring bulk IO comm error with %s@%s id %s - "
+                      "client will retry\n",
+                      req->rq_export->exp_obd->obd_name,
+                      req->rq_export->exp_client_uuid.uuid,
+                      req->rq_export->exp_connection->c_remote_uuid.uuid,
+                      libcfs_id2str(req->rq_peer));
         }
         RETURN(rc);
 }
@@ -1043,25 +1069,28 @@ static int ost_san_brw(struct ptlrpc_request *req, int cmd)
         struct niobuf_remote *remote_nb, *res_nb, *pp_rnb = NULL;
         struct obd_ioobj *ioo;
         struct ost_body *body, *repbody;
-        int rc, i, objcount, niocount, size[2] = {sizeof(*body)}, npages;
-        int swab;
+        int rc, i, objcount, niocount, npages, swab;
+        int size[3] = { sizeof(struct ptlrpc_body), sizeof(*body) };
         ENTRY;
 
         /* XXX not set to use latest protocol */
 
         swab = lustre_msg_swabbed(req->rq_reqmsg);
-        body = lustre_swab_reqbuf(req, 0, sizeof(*body), lustre_swab_ost_body);
+        body = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*body),
+                                  lustre_swab_ost_body);
         if (body == NULL) {
                 CERROR("Missing/short ost_body\n");
                 GOTO(out, rc = -EFAULT);
         }
 
-        ioo = lustre_swab_reqbuf(req, 1, sizeof(*ioo), lustre_swab_obd_ioobj);
+        ioo = lustre_swab_reqbuf(req, REQ_REC_OFF + 1, sizeof(*ioo),
+                                 lustre_swab_obd_ioobj);
         if (ioo == NULL) {
                 CERROR("Missing/short ioobj\n");
                 GOTO(out, rc = -EFAULT);
         }
-        objcount = req->rq_reqmsg->buflens[1] / sizeof(*ioo);
+        objcount = lustre_msg_buflen(req->rq_reqmsg, REQ_REC_OFF + 1) /
+                   sizeof(*ioo);
         niocount = ioo[0].ioo_bufcnt;
         for (i = 1; i < objcount; i++) {
                 if (swab)
@@ -1069,7 +1098,8 @@ static int ost_san_brw(struct ptlrpc_request *req, int cmd)
                 niocount += ioo[i].ioo_bufcnt;
         }
 
-        remote_nb = lustre_swab_reqbuf(req, 2, niocount * sizeof(*remote_nb),
+        remote_nb = lustre_swab_reqbuf(req, REQ_REC_OFF + 2,
+                                       niocount * sizeof(*remote_nb),
                                        lustre_swab_niobuf_remote);
         if (remote_nb == NULL) {
                 CERROR("Missing/short niobuf\n");
@@ -1091,8 +1121,8 @@ static int ost_san_brw(struct ptlrpc_request *req, int cmd)
         if (npages < 0)
                 GOTO (out, rc = npages);
 
-        size[1] = npages * sizeof(*pp_rnb);
-        rc = lustre_pack_reply(req, 2, size, NULL);
+        size[REPLY_REC_OFF + 1] = npages * sizeof(*pp_rnb);
+        rc = lustre_pack_reply(req, 3, size, NULL);
         if (rc)
                 GOTO(out, rc);
 
@@ -1102,11 +1132,13 @@ static int ost_san_brw(struct ptlrpc_request *req, int cmd)
         if (req->rq_status)
                 GOTO(out, rc = 0);
 
-        repbody = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*repbody));
+        repbody = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
+                                 sizeof(*repbody));
         memcpy(&repbody->oa, &body->oa, sizeof(body->oa));
 
-        res_nb = lustre_msg_buf(req->rq_repmsg, 1, size[1]);
-        memcpy(res_nb, remote_nb, size[1]);
+        res_nb = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF + 1,
+                                size[REPLY_REC_OFF + 1]);
+        memcpy(res_nb, remote_nb, size[REPLY_REC_OFF + 1]);
         rc = 0;
 out:
         target_committed_to_req(req);
@@ -1127,20 +1159,20 @@ static int ost_set_info(struct obd_export *exp, struct ptlrpc_request *req)
         int keylen, vallen, rc = 0;
         ENTRY;
 
-        key = lustre_msg_buf(req->rq_reqmsg, 0, 1);
+        key = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, 1);
         if (key == NULL) {
                 DEBUG_REQ(D_HA, req, "no set_info key");
                 RETURN(-EFAULT);
         }
-        keylen = lustre_msg_buflen(req->rq_reqmsg,0);
+        keylen = lustre_msg_buflen(req->rq_reqmsg, REQ_REC_OFF);
 
-        rc = lustre_pack_reply(req, 0, NULL, NULL);
+        rc = lustre_pack_reply(req, 1, NULL, NULL);
         if (rc)
                 RETURN(rc);
 
-        vallen = lustre_msg_buflen(req->rq_reqmsg, 1);
+        vallen = lustre_msg_buflen(req->rq_reqmsg, REQ_REC_OFF + 1);
         if (vallen)
-                val = lustre_msg_buf(req->rq_reqmsg, 1, 0);
+                val = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF + 1, 0);
 
         if (KEY_IS("evict_by_nid")) {
                 if (val && vallen)
@@ -1151,53 +1183,54 @@ static int ost_set_info(struct obd_export *exp, struct ptlrpc_request *req)
 
         rc = obd_set_info_async(exp, keylen, key, vallen, val, NULL);
 out:
-        req->rq_repmsg->status = 0;
+        lustre_msg_set_status(req->rq_repmsg, 0);
         RETURN(rc);
 }
 
 static int ost_get_info(struct obd_export *exp, struct ptlrpc_request *req)
 {
         char *key;
-        int keylen, rc = 0, size = sizeof(obd_id);
+        int keylen, rc = 0;
+        int size[2] = { sizeof(struct ptlrpc_body), sizeof(obd_id) };
         obd_id *reply;
         ENTRY;
 
-        key = lustre_msg_buf(req->rq_reqmsg, 0, 1);
+        key = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, 1);
         if (key == NULL) {
                 DEBUG_REQ(D_HA, req, "no get_info key");
                 RETURN(-EFAULT);
         }
-        keylen = req->rq_reqmsg->buflens[0];
+        keylen = lustre_msg_buflen(req->rq_reqmsg, REQ_REC_OFF);
 
         if (keylen < strlen("last_id") || memcmp(key, "last_id", 7) != 0)
                 RETURN(-EPROTO);
 
-        rc = lustre_pack_reply(req, 1, &size, NULL);
+        rc = lustre_pack_reply(req, 2, size, NULL);
         if (rc)
                 RETURN(rc);
 
-        reply = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*reply));
-        rc = obd_get_info(exp, keylen, key, &size, reply);
-        req->rq_repmsg->status = 0;
+        reply = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF, sizeof(*reply));
+        rc = obd_get_info(exp, keylen, key, size, reply);
+        lustre_msg_set_status(req->rq_repmsg, 0);
         RETURN(rc);
 }
 
 static int ost_handle_quotactl(struct ptlrpc_request *req)
 {
         struct obd_quotactl *oqctl, *repoqc;
-        int rc, size = sizeof(*repoqc);
+        int rc, size[2] = { sizeof(struct ptlrpc_body), sizeof(*repoqc) };
         ENTRY;
 
-        oqctl = lustre_swab_reqbuf(req, 0, sizeof(*oqctl),
+        oqctl = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*oqctl),
                                    lustre_swab_obd_quotactl);
         if (oqctl == NULL)
                 GOTO(out, rc = -EPROTO);
 
-        rc = lustre_pack_reply(req, 1, &size, NULL);
+        rc = lustre_pack_reply(req, 2, size, NULL);
         if (rc)
                 GOTO(out, rc);
 
-        repoqc = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*repoqc));
+        repoqc = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF, sizeof(*repoqc));
 
         req->rq_status = obd_quotactl(req->rq_export, oqctl);
         *repoqc = *oqctl;
@@ -1211,12 +1244,12 @@ static int ost_handle_quotacheck(struct ptlrpc_request *req)
         int rc;
         ENTRY;
 
-        oqctl = lustre_swab_reqbuf(req, 0, sizeof(*oqctl),
+        oqctl = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*oqctl),
                                    lustre_swab_obd_quotactl);
         if (oqctl == NULL)
                 RETURN(-EPROTO);
 
-        rc = lustre_pack_reply(req, 0, NULL, NULL);
+        rc = lustre_pack_reply(req, 1, NULL, NULL);
         if (rc) {
                 CERROR("ost: out of memory while packing quotacheck reply\n");
                 RETURN(-ENOMEM);
@@ -1229,7 +1262,7 @@ static int ost_handle_quotacheck(struct ptlrpc_request *req)
 static int ost_filter_recovery_request(struct ptlrpc_request *req,
                                        struct obd_device *obd, int *process)
 {
-        switch (req->rq_reqmsg->opc) {
+        switch (lustre_msg_get_opc(req->rq_reqmsg)) {
         case OST_CONNECT: /* This will never get here, but for completeness. */
         case OST_DISCONNECT:
                *process = 1;
@@ -1260,18 +1293,16 @@ int ost_msg_check_version(struct lustre_msg *msg)
 {
         int rc;
 
-        /* TODO: enable the below check while really introducing msg version.
-         * it's disabled because it will break compatibility with b1_4.
-         */
-        return (0);
-        switch(msg->opc) {
+        switch(lustre_msg_get_opc(msg)) {
         case OST_CONNECT:
         case OST_DISCONNECT:
         case OBD_PING:
                 rc = lustre_msg_check_version(msg, LUSTRE_OBD_VERSION);
                 if (rc)
                         CERROR("bad opc %u version %08x, expecting %08x\n",
-                               msg->opc, msg->version, LUSTRE_OBD_VERSION);
+                               lustre_msg_get_opc(msg),
+                               lustre_msg_get_version(msg),
+                               LUSTRE_OBD_VERSION);
                 break;
         case OST_CREATE:
         case OST_DESTROY:
@@ -1291,7 +1322,9 @@ int ost_msg_check_version(struct lustre_msg *msg)
                 rc = lustre_msg_check_version(msg, LUSTRE_OST_VERSION);
                 if (rc)
                         CERROR("bad opc %u version %08x, expecting %08x\n",
-                               msg->opc, msg->version, LUSTRE_OST_VERSION);
+                               lustre_msg_get_opc(msg),
+                               lustre_msg_get_version(msg),
+                               LUSTRE_OST_VERSION);
                 break;
         case LDLM_ENQUEUE:
         case LDLM_CONVERT:
@@ -1301,16 +1334,21 @@ int ost_msg_check_version(struct lustre_msg *msg)
                 rc = lustre_msg_check_version(msg, LUSTRE_DLM_VERSION);
                 if (rc)
                         CERROR("bad opc %u version %08x, expecting %08x\n",
-                               msg->opc, msg->version, LUSTRE_DLM_VERSION);
+                               lustre_msg_get_opc(msg),
+                               lustre_msg_get_version(msg),
+                               LUSTRE_DLM_VERSION);
                 break;
         case LLOG_ORIGIN_CONNECT:
         case OBD_LOG_CANCEL:
                 rc = lustre_msg_check_version(msg, LUSTRE_LOG_VERSION);
                 if (rc)
                         CERROR("bad opc %u version %08x, expecting %08x\n",
-                               msg->opc, msg->version, LUSTRE_LOG_VERSION);
+                               lustre_msg_get_opc(msg),
+                               lustre_msg_get_version(msg),
+                               LUSTRE_LOG_VERSION);
+                break;
         default:
-                CERROR("Unexpected opcode %d\n", msg->opc);
+                CERROR("Unexpected opcode %d\n", lustre_msg_get_opc(msg));
                 rc = -ENOTSUPP;
         }
         return rc;
@@ -1326,12 +1364,13 @@ static int ost_handle(struct ptlrpc_request *req)
 
         LASSERT(current->journal_info == NULL);
         /* XXX identical to MDS */
-        if (req->rq_reqmsg->opc != OST_CONNECT) {
+        if (lustre_msg_get_opc(req->rq_reqmsg) != OST_CONNECT) {
                 int abort_recovery, recovering;
 
                 if (req->rq_export == NULL) {
                         CDEBUG(D_HA,"operation %d on unconnected OST from %s\n",
-                               req->rq_reqmsg->opc, libcfs_id2str(req->rq_peer));
+                               lustre_msg_get_opc(req->rq_reqmsg),
+                               libcfs_id2str(req->rq_peer));
                         req->rq_status = -ENOTCONN;
                         GOTO(out, rc = -ENOTCONN);
                 }
@@ -1358,7 +1397,11 @@ static int ost_handle(struct ptlrpc_request *req)
         if (rc)
                 RETURN(rc);
 
-        switch (req->rq_reqmsg->opc) {
+        rc = ost_msg_check_version(req->rq_reqmsg);
+        if (rc)
+                RETURN(rc);
+
+        switch (lustre_msg_get_opc(req->rq_reqmsg)) {
         case OST_CONNECT: {
                 CDEBUG(D_INODE, "connect\n");
                 OBD_FAIL_RETURN(OBD_FAIL_OST_CONNECT_NET, 0);
@@ -1472,7 +1515,7 @@ static int ost_handle(struct ptlrpc_request *req)
                 DEBUG_REQ(D_INODE, req, "log connect\n");
                 rc = llog_handle_connect(req);
                 req->rq_status = rc;
-                rc = lustre_pack_reply(req, 0, NULL, NULL);
+                rc = lustre_pack_reply(req, 1, NULL, NULL);
                 if (rc)
                         RETURN(rc);
                 RETURN(ptlrpc_reply(req));
@@ -1481,7 +1524,7 @@ static int ost_handle(struct ptlrpc_request *req)
                 OBD_FAIL_RETURN(OBD_FAIL_OBD_LOG_CANCEL_NET, 0);
                 rc = llog_origin_handle_cancel(req);
                 req->rq_status = rc;
-                rc = lustre_pack_reply(req, 0, NULL, NULL);
+                rc = lustre_pack_reply(req, 1, NULL, NULL);
                 if (rc)
                         RETURN(rc);
                 RETURN(ptlrpc_reply(req));
@@ -1509,7 +1552,8 @@ static int ost_handle(struct ptlrpc_request *req)
                 CERROR("callbacks should not happen on OST\n");
                 /* fall through */
         default:
-                CERROR("Unexpected opcode %d\n", req->rq_reqmsg->opc);
+                CERROR("Unexpected opcode %d\n",
+                       lustre_msg_get_opc(req->rq_reqmsg));
                 req->rq_status = -ENOTSUPP;
                 rc = ptlrpc_error(req);
                 RETURN(rc);
@@ -1519,7 +1563,7 @@ static int ost_handle(struct ptlrpc_request *req)
 
         EXIT;
         /* If we're DISCONNECTing, the export_data is already freed */
-        if (!rc && req->rq_reqmsg->opc != OST_DISCONNECT)
+        if (!rc && lustre_msg_get_opc(req->rq_reqmsg) != OST_DISCONNECT)
                 target_committed_to_req(req);
 
 out:
index 2003051..38a9b33 100644 (file)
@@ -12,7 +12,7 @@ ldlm_objs += $(LDLM)ldlm_flock.o $(LDLM)ldlm_inodebits.o
 ptlrpc_objs := client.o recover.o connection.o niobuf.o pack_generic.o
 ptlrpc_objs += events.o ptlrpc_module.o service.o pinger.o recov_thread.o
 ptlrpc_objs += llog_net.o llog_client.o llog_server.o import.o ptlrpcd.o
-ptlrpc_objs += pers.o lproc_ptlrpc.o layout.o
+ptlrpc_objs += pers.o lproc_ptlrpc.o wiretest.o layout.o
 
 ptlrpc-objs := $(ldlm_objs) $(ptlrpc_objs)
 
index 9a2c3db..c80a8ca 100644 (file)
@@ -17,7 +17,7 @@ LDLM_COMM_SOURCES= $(top_srcdir)/lustre/ldlm/l_lock.c \
 
 COMMON_SOURCES =  client.c recover.c connection.c niobuf.c pack_generic.c   \
     events.c ptlrpc_module.c service.c pinger.c recov_thread.c llog_net.c   \
-    llog_client.c llog_server.c import.c ptlrpcd.c pers.c                  \
+    llog_client.c llog_server.c import.c ptlrpcd.c pers.c wiretest.c               \
     ptlrpc_internal.h layout.c $(LDLM_COMM_SOURCES)
 
 if LIBLUSTRE
@@ -56,6 +56,7 @@ ptlrpc_SOURCES := \
         recover.c \
         recov_thread.c \
         service.c \
+       wiretest.c \
         $(LDLM_COMM_SOURCES)
 
 ptlrpc_CFLAGS := $(EXTRA_KCFLAGS)
index fd74614..d636621 100644 (file)
@@ -330,18 +330,16 @@ ptlrpc_prep_req_pool(struct obd_import *imp, __u32 version, int opcode,
                 RETURN(NULL);
         }
 
-        rc = lustre_pack_request(request, count, lengths, bufs);
+        rc = lustre_pack_request(request, imp->imp_msg_magic, count, lengths,
+                                 bufs);
         if (rc) {
                 LASSERT(!request->rq_pool);
                 OBD_FREE(request, sizeof(*request));
                 RETURN(NULL);
         }
 
-#if 0   /* TODO: enable this while really introducing msg version.
-         * it's disabled because it will break compatibility with b1_4.
-         */        
-        request->rq_reqmsg->version |= version;
-#endif
+        lustre_msg_add_version(request->rq_reqmsg, version);
+
         if (imp->imp_server_timeout)
                 request->rq_timeout = obd_timeout / 2;
         else
@@ -371,18 +369,18 @@ ptlrpc_prep_req_pool(struct obd_import *imp, __u32 version, int opcode,
         request->rq_xid = ptlrpc_next_xid();
         atomic_set(&request->rq_refcount, 1);
 
-        request->rq_reqmsg->opc = opcode;
-        request->rq_reqmsg->flags = 0;
+        lustre_msg_set_opc(request->rq_reqmsg, opcode);
+        lustre_msg_set_flags(request->rq_reqmsg, 0);
 
         RETURN(request);
 }
 
 struct ptlrpc_request *
-ptlrpc_prep_req(struct obd_import *imp, __u32 version, int opcode,
-                int count, int *lengths, char **bufs)
+ptlrpc_prep_req(struct obd_import *imp, __u32 version, int opcode, int count,
+                int *lengths, char **bufs)
 {
-        return ptlrpc_prep_req_pool(imp, version, opcode, count, lengths,
-                                    bufs, NULL);
+        return ptlrpc_prep_req_pool(imp, version, opcode, count, lengths, bufs,
+                                    NULL);
 }
 
 struct ptlrpc_request_set *ptlrpc_prep_set(void)
@@ -473,12 +471,11 @@ void ptlrpc_set_add_req(struct ptlrpc_request_set *set,
 void ptlrpc_set_add_new_req(struct ptlrpc_request_set *set,
                             struct ptlrpc_request *req)
 {
-        unsigned long flags;
-        spin_lock_irqsave(&set->set_new_req_lock, flags);
+        spin_lock(&set->set_new_req_lock);
         /* The set takes over the caller's request reference */
         list_add_tail(&req->rq_set_chain, &set->set_new_requests);
         req->rq_set = set;
-        spin_unlock_irqrestore(&set->set_new_req_lock, flags);
+        spin_unlock(&set->set_new_req_lock);
 }
 
 /*
@@ -532,12 +529,11 @@ static int ptlrpc_import_delay_req(struct obd_import *imp,
 
 static int ptlrpc_check_reply(struct ptlrpc_request *req)
 {
-        unsigned long flags;
         int rc = 0;
         ENTRY;
 
         /* serialise with network callback */
-        spin_lock_irqsave (&req->rq_lock, flags);
+        spin_lock(&req->rq_lock);
 
         if (req->rq_replied) {
                 DEBUG_REQ(D_NET, req, "REPLIED:");
@@ -545,9 +541,9 @@ static int ptlrpc_check_reply(struct ptlrpc_request *req)
         }
 
         if (req->rq_net_err && !req->rq_timedout) {
-                spin_unlock_irqrestore (&req->rq_lock, flags);
+                spin_unlock(&req->rq_lock);
                 rc = ptlrpc_expire_one_request(req);
-                spin_lock_irqsave (&req->rq_lock, flags);
+                spin_lock(&req->rq_lock);
                 GOTO(out, rc);
         }
 
@@ -567,7 +563,7 @@ static int ptlrpc_check_reply(struct ptlrpc_request *req)
         }
         EXIT;
  out:
-        spin_unlock_irqrestore (&req->rq_lock, flags);
+        spin_unlock(&req->rq_lock);
         DEBUG_REQ(D_NET, req, "rc = %d for", rc);
         return rc;
 }
@@ -577,8 +573,8 @@ static int ptlrpc_check_status(struct ptlrpc_request *req)
         int err;
         ENTRY;
 
-        err = req->rq_repmsg->status;
-        if (req->rq_repmsg->type == PTL_RPC_MSG_ERR) {
+        err = lustre_msg_get_status(req->rq_repmsg);
+        if (lustre_msg_get_type(req->rq_repmsg) == PTL_RPC_MSG_ERR) {
                 DEBUG_REQ(D_ERROR, req, "type == PTL_RPC_MSG_ERR, err == %d",
                           err);
                 RETURN(err < 0 ? err : -EINVAL);
@@ -596,7 +592,6 @@ static int ptlrpc_check_status(struct ptlrpc_request *req)
 
 static int after_reply(struct ptlrpc_request *req)
 {
-        unsigned long flags;
         struct obd_import *imp = req->rq_import;
         int rc;
         ENTRY;
@@ -617,10 +612,16 @@ static int after_reply(struct ptlrpc_request *req)
                 RETURN(-EPROTO);
         }
 
-        if (req->rq_repmsg->type != PTL_RPC_MSG_REPLY &&
-            req->rq_repmsg->type != PTL_RPC_MSG_ERR) {
+        rc = lustre_unpack_ptlrpc_body(req->rq_repmsg);
+        if (rc) {
+                DEBUG_REQ(D_ERROR, req, "unpack ptlrpc body failed: %d\n", rc);
+                RETURN(-EPROTO);
+        }
+
+        if (lustre_msg_get_type(req->rq_repmsg) != PTL_RPC_MSG_REPLY &&
+            lustre_msg_get_type(req->rq_repmsg) != PTL_RPC_MSG_ERR) {
                 DEBUG_REQ(D_ERROR, req, "invalid packet received (type=%u)\n",
-                          req->rq_repmsg->type);
+                          lustre_msg_get_type(req->rq_repmsg));
                 RETURN(-EPROTO);
         }
 
@@ -641,30 +642,25 @@ static int after_reply(struct ptlrpc_request *req)
         }
 
         /* Store transno in reqmsg for replay. */
-        CDEBUG(D_INFO, "req@%p: replayable = %d, transno = "LPU64
-                       " committed = "LPU64"\n",
-                       req,
-                       req->rq_import->imp_replayable,
-                       req->rq_repmsg->transno,
-                       req->rq_repmsg->last_committed);
-        req->rq_reqmsg->transno = req->rq_transno = req->rq_repmsg->transno;
+        req->rq_transno = lustre_msg_get_transno(req->rq_repmsg);
+        lustre_msg_set_transno(req->rq_reqmsg, req->rq_transno);
 
         if (req->rq_import->imp_replayable) {
-                spin_lock_irqsave(&imp->imp_lock, flags);
+                spin_lock(&imp->imp_lock);
                 if (req->rq_transno != 0)
                         ptlrpc_retain_replayable_request(req, imp);
                 else if (req->rq_commit_cb != NULL) {
-                        spin_unlock_irqrestore(&imp->imp_lock, flags);
+                        spin_unlock(&imp->imp_lock);
                         req->rq_commit_cb(req);
-                        spin_lock_irqsave(&imp->imp_lock, flags);
+                        spin_lock(&imp->imp_lock);
                 }
 
                 /* Replay-enabled imports return commit-status information. */
-                if (req->rq_repmsg->last_committed)
+                if (lustre_msg_get_last_committed(req->rq_repmsg))
                         imp->imp_peer_committed_transno =
-                                req->rq_repmsg->last_committed;
+                                lustre_msg_get_last_committed(req->rq_repmsg);
                 ptlrpc_free_committed(imp);
-                spin_unlock_irqrestore(&imp->imp_lock, flags);
+                spin_unlock(&imp->imp_lock);
         }
 
         RETURN(rc);
@@ -673,7 +669,6 @@ static int after_reply(struct ptlrpc_request *req)
 static int ptlrpc_send_new_req(struct ptlrpc_request *req)
 {
         struct obd_import     *imp;
-        unsigned long          flags;
         int rc;
         ENTRY;
 
@@ -681,7 +676,7 @@ static int ptlrpc_send_new_req(struct ptlrpc_request *req)
         req->rq_phase = RQ_PHASE_RPC;
 
         imp = req->rq_import;
-        spin_lock_irqsave(&imp->imp_lock, flags);
+        spin_lock(&imp->imp_lock);
 
         req->rq_import_generation = imp->imp_generation;
 
@@ -692,18 +687,18 @@ static int ptlrpc_send_new_req(struct ptlrpc_request *req)
 
                 DEBUG_REQ(D_HA, req, "req from PID %d waiting for recovery: "
                           "(%s != %s)",
-                          req->rq_reqmsg->status,
+                          lustre_msg_get_status(req->rq_reqmsg) ,
                           ptlrpc_import_state_name(req->rq_send_state),
                           ptlrpc_import_state_name(imp->imp_state));
                 LASSERT(list_empty (&req->rq_list));
 
                 list_add_tail(&req->rq_list, &imp->imp_delayed_list);
-                spin_unlock_irqrestore(&imp->imp_lock, flags);
+                spin_unlock(&imp->imp_lock);
                 RETURN(0);
         }
 
         if (rc != 0) {
-                spin_unlock_irqrestore(&imp->imp_lock, flags);
+                spin_unlock(&imp->imp_lock);
                 req->rq_status = rc;
                 req->rq_phase = RQ_PHASE_INTERPRET;
                 RETURN(rc);
@@ -712,15 +707,15 @@ static int ptlrpc_send_new_req(struct ptlrpc_request *req)
         /* XXX this is the same as ptlrpc_queue_wait */
         LASSERT(list_empty(&req->rq_list));
         list_add_tail(&req->rq_list, &imp->imp_sending_list);
-        spin_unlock_irqrestore(&imp->imp_lock, flags);
+        spin_unlock(&imp->imp_lock);
 
-        req->rq_reqmsg->status = cfs_curproc_pid();
+        lustre_msg_set_status(req->rq_reqmsg, cfs_curproc_pid());
         CDEBUG(D_RPCTRACE, "Sending RPC pname:cluuid:pid:xid:nid:opc"
                " %s:%s:%d:"LPU64":%s:%d\n", cfs_curproc_comm(),
-               imp->imp_obd->obd_uuid.uuid, req->rq_reqmsg->status,
-               req->rq_xid,
+               imp->imp_obd->obd_uuid.uuid,
+               lustre_msg_get_status(req->rq_reqmsg), req->rq_xid,
                libcfs_nid2str(imp->imp_connection->c_peer.nid),
-               req->rq_reqmsg->opc);
+               lustre_msg_get_opc(req->rq_reqmsg));
 
         rc = ptl_send_rpc(req, 0);
         if (rc) {
@@ -734,7 +729,6 @@ static int ptlrpc_send_new_req(struct ptlrpc_request *req)
 /* this sends any unsent RPCs in @set and returns TRUE if all are sent */
 int ptlrpc_check_set(struct ptlrpc_request_set *set)
 {
-        unsigned long flags;
         struct list_head *tmp;
         int force_timer_recalc = 0;
         ENTRY;
@@ -776,9 +770,9 @@ int ptlrpc_check_set(struct ptlrpc_request_set *set)
                                 req->rq_status = -EIO;
                         req->rq_phase = RQ_PHASE_INTERPRET;
 
-                        spin_lock_irqsave(&imp->imp_lock, flags);
+                        spin_lock(&imp->imp_lock);
                         list_del_init(&req->rq_list);
-                        spin_unlock_irqrestore(&imp->imp_lock, flags);
+                        spin_unlock(&imp->imp_lock);
 
                         GOTO(interpret, req->rq_status);
                 }
@@ -794,9 +788,9 @@ int ptlrpc_check_set(struct ptlrpc_request_set *set)
                         req->rq_status = -EINTR;
                         req->rq_phase = RQ_PHASE_INTERPRET;
 
-                        spin_lock_irqsave(&imp->imp_lock, flags);
+                        spin_lock(&imp->imp_lock);
                         list_del_init(&req->rq_list);
-                        spin_unlock_irqrestore(&imp->imp_lock, flags);
+                        spin_unlock(&imp->imp_lock);
 
                         GOTO(interpret, req->rq_status);
                 }
@@ -807,11 +801,10 @@ int ptlrpc_check_set(struct ptlrpc_request_set *set)
 
                                 ptlrpc_unregister_reply(req);
 
-                                spin_lock_irqsave(&imp->imp_lock, flags);
+                                spin_lock(&imp->imp_lock);
 
                                 if (ptlrpc_import_delay_req(imp, req, &status)){
-                                        spin_unlock_irqrestore(&imp->imp_lock,
-                                                               flags);
+                                        spin_unlock(&imp->imp_lock);
                                         continue;
                                 }
 
@@ -819,21 +812,19 @@ int ptlrpc_check_set(struct ptlrpc_request_set *set)
                                 if (status != 0)  {
                                         req->rq_status = status;
                                         req->rq_phase = RQ_PHASE_INTERPRET;
-                                        spin_unlock_irqrestore(&imp->imp_lock,
-                                                               flags);
+                                        spin_unlock(&imp->imp_lock);
                                         GOTO(interpret, req->rq_status);
                                 }
                                 if (req->rq_no_resend) {
                                         req->rq_status = -ENOTCONN;
                                         req->rq_phase = RQ_PHASE_INTERPRET;
-                                        spin_unlock_irqrestore(&imp->imp_lock,
-                                                               flags);
+                                        spin_unlock(&imp->imp_lock);
                                         GOTO(interpret, req->rq_status);
                                 }
                                 list_add_tail(&req->rq_list,
                                               &imp->imp_sending_list);
 
-                                spin_unlock_irqrestore(&imp->imp_lock, flags);
+                                spin_unlock(&imp->imp_lock);
 
                                 req->rq_waiting = 0;
                                 if (req->rq_resend) {
@@ -872,19 +863,19 @@ int ptlrpc_check_set(struct ptlrpc_request_set *set)
                         if (!ptlrpc_client_replied(req))
                                 continue;
 
-                        spin_lock_irqsave(&imp->imp_lock, flags);
+                        spin_lock(&imp->imp_lock);
                         list_del_init(&req->rq_list);
-                        spin_unlock_irqrestore(&imp->imp_lock, flags);
+                        spin_unlock(&imp->imp_lock);
 
                         req->rq_status = after_reply(req);
                         if (req->rq_resend) {
                                 /* Add this req to the delayed list so
                                    it can be errored if the import is
                                    evicted after recovery. */
-                                spin_lock_irqsave (&req->rq_lock, flags);
+                                spin_lock(&req->rq_lock);
                                 list_add_tail(&req->rq_list,
                                               &imp->imp_delayed_list);
-                                spin_unlock_irqrestore(&req->rq_lock, flags);
+                                spin_unlock(&req->rq_lock);
                                 continue;
                         }
 
@@ -935,10 +926,10 @@ int ptlrpc_check_set(struct ptlrpc_request_set *set)
 
                 CDEBUG(D_RPCTRACE, "Completed RPC pname:cluuid:pid:xid:nid:"
                        "opc %s:%s:%d:"LPU64":%s:%d\n", cfs_curproc_comm(),
-                       imp->imp_obd->obd_uuid.uuid, req->rq_reqmsg->status,
-                       req->rq_xid,
+                       imp->imp_obd->obd_uuid.uuid,
+                       lustre_msg_get_status(req->rq_reqmsg), req->rq_xid,
                        libcfs_nid2str(imp->imp_connection->c_peer.nid),
-                       req->rq_reqmsg->opc);
+                       lustre_msg_get_opc(req->rq_reqmsg));
 
                 set->set_remaining--;
 
@@ -952,16 +943,15 @@ int ptlrpc_check_set(struct ptlrpc_request_set *set)
 
 int ptlrpc_expire_one_request(struct ptlrpc_request *req)
 {
-        unsigned long      flags;
         struct obd_import *imp = req->rq_import;
         ENTRY;
 
         DEBUG_REQ(D_ERROR, req, "timeout (sent at %lu, %lus ago)",
                   (long)req->rq_sent, CURRENT_SECONDS - req->rq_sent);
 
-        spin_lock_irqsave (&req->rq_lock, flags);
+        spin_lock(&req->rq_lock);
         req->rq_timedout = 1;
-        spin_unlock_irqrestore (&req->rq_lock, flags);
+        spin_unlock(&req->rq_lock);
 
         ptlrpc_unregister_reply (req);
 
@@ -984,14 +974,14 @@ int ptlrpc_expire_one_request(struct ptlrpc_request *req)
          * then error it out here. */
         if (req->rq_send_state != LUSTRE_IMP_FULL ||
             imp->imp_obd->obd_no_recov) {
-                spin_lock_irqsave (&req->rq_lock, flags);
+                spin_lock(&req->rq_lock);
                 req->rq_status = -ETIMEDOUT;
                 req->rq_err = 1;
-                spin_unlock_irqrestore (&req->rq_lock, flags);
+                spin_unlock(&req->rq_lock);
                 RETURN(1);
         }
 
-        ptlrpc_fail_import(imp, req->rq_reqmsg->conn_cnt);
+        ptlrpc_fail_import(imp, lustre_msg_get_conn_cnt(req->rq_reqmsg));
 
         RETURN(0);
 }
@@ -1033,10 +1023,9 @@ int ptlrpc_expired_set(void *data)
 
 void ptlrpc_mark_interrupted(struct ptlrpc_request *req)
 {
-        unsigned long flags;
-        spin_lock_irqsave(&req->rq_lock, flags);
+        spin_lock(&req->rq_lock);
         req->rq_intr = 1;
-        spin_unlock_irqrestore(&req->rq_lock, flags);
+        spin_unlock(&req->rq_lock);
 }
 
 void ptlrpc_interrupted_set(void *data)
@@ -1174,13 +1163,11 @@ static void __ptlrpc_free_req(struct ptlrpc_request *request, int locked)
         /* We must take it off the imp_replay_list first.  Otherwise, we'll set
          * request->rq_reqmsg to NULL while osc_close is dereferencing it. */
         if (request->rq_import != NULL) {
-                unsigned long flags = 0;
                 if (!locked)
-                        spin_lock_irqsave(&request->rq_import->imp_lock, flags);
+                        spin_lock(&request->rq_import->imp_lock);
                 list_del_init(&request->rq_replay_list);
                 if (!locked)
-                        spin_unlock_irqrestore(&request->rq_import->imp_lock,
-                                               flags);
+                        spin_unlock(&request->rq_import->imp_lock);
         }
         LASSERTF(list_empty(&request->rq_replay_list), "req %p\n", request);
 
@@ -1374,13 +1361,11 @@ void ptlrpc_cleanup_client(struct obd_import *imp)
 
 void ptlrpc_resend_req(struct ptlrpc_request *req)
 {
-        unsigned long flags;
-
         DEBUG_REQ(D_HA, req, "going to resend");
-        req->rq_reqmsg->handle.cookie = 0;
+        lustre_msg_set_handle(req->rq_reqmsg, &(struct lustre_handle){ 0 });
         req->rq_status = -EAGAIN;
 
-        spin_lock_irqsave (&req->rq_lock, flags);
+        spin_lock(&req->rq_lock);
         req->rq_resend = 1;
         req->rq_net_err = 0;
         req->rq_timedout = 0;
@@ -1393,22 +1378,20 @@ void ptlrpc_resend_req(struct ptlrpc_request *req)
                        old_xid, req->rq_xid);
         }
         ptlrpc_wake_client_req(req);
-        spin_unlock_irqrestore (&req->rq_lock, flags);
+        spin_unlock(&req->rq_lock);
 }
 
 /* XXX: this function and rq_status are currently unused */
 void ptlrpc_restart_req(struct ptlrpc_request *req)
 {
-        unsigned long flags;
-
         DEBUG_REQ(D_HA, req, "restarting (possibly-)completed request");
         req->rq_status = -ERESTARTSYS;
 
-        spin_lock_irqsave (&req->rq_lock, flags);
+        spin_lock(&req->rq_lock);
         req->rq_restart = 1;
         req->rq_timedout = 0;
         ptlrpc_wake_client_req(req);
-        spin_unlock_irqrestore (&req->rq_lock, flags);
+        spin_unlock(&req->rq_lock);
 }
 
 static int expired_request(void *data)
@@ -1421,13 +1404,11 @@ static int expired_request(void *data)
 
 static void interrupted_request(void *data)
 {
-        unsigned long flags;
-
         struct ptlrpc_request *req = data;
         DEBUG_REQ(D_HA, req, "request interrupted");
-        spin_lock_irqsave (&req->rq_lock, flags);
+        spin_lock(&req->rq_lock);
         req->rq_intr = 1;
-        spin_unlock_irqrestore (&req->rq_lock, flags);
+        spin_unlock(&req->rq_lock);
 }
 
 struct ptlrpc_request *ptlrpc_request_addref(struct ptlrpc_request *req)
@@ -1489,7 +1470,6 @@ int ptlrpc_queue_wait(struct ptlrpc_request *req)
         int brc;
         struct l_wait_info lwi;
         struct obd_import *imp = req->rq_import;
-        unsigned long flags;
         cfs_duration_t timeout = 0;
         ENTRY;
 
@@ -1498,26 +1478,26 @@ int ptlrpc_queue_wait(struct ptlrpc_request *req)
         atomic_inc(&imp->imp_inflight);
 
         /* for distributed debugging */
-        req->rq_reqmsg->status = cfs_curproc_pid();
+        lustre_msg_set_status(req->rq_reqmsg, cfs_curproc_pid());
         LASSERT(imp->imp_obd != NULL);
         CDEBUG(D_RPCTRACE, "Sending RPC pname:cluuid:pid:xid:nid:opc "
                "%s:%s:%d:"LPU64":%s:%d\n", cfs_curproc_comm(),
                imp->imp_obd->obd_uuid.uuid,
-               req->rq_reqmsg->status, req->rq_xid,
+               lustre_msg_get_status(req->rq_reqmsg), req->rq_xid,
                libcfs_nid2str(imp->imp_connection->c_peer.nid),
-               req->rq_reqmsg->opc);
+               lustre_msg_get_opc(req->rq_reqmsg));
 
         /* Mark phase here for a little debug help */
         req->rq_phase = RQ_PHASE_RPC;
 
-        spin_lock_irqsave(&imp->imp_lock, flags);
+        spin_lock(&imp->imp_lock);
         req->rq_import_generation = imp->imp_generation;
 restart:
         if (ptlrpc_import_delay_req(imp, req, &rc)) {
                 list_del(&req->rq_list);
 
                 list_add_tail(&req->rq_list, &imp->imp_delayed_list);
-                spin_unlock_irqrestore(&imp->imp_lock, flags);
+                spin_unlock(&imp->imp_lock);
 
                 DEBUG_REQ(D_HA, req, "\"%s\" waiting for recovery: (%s != %s)",
                           cfs_curproc_comm(),
@@ -1534,7 +1514,7 @@ restart:
                           ptlrpc_import_state_name(req->rq_send_state),
                           req->rq_err, req->rq_intr);
 
-                spin_lock_irqsave(&imp->imp_lock, flags);
+                spin_lock(&imp->imp_lock);
                 list_del_init(&req->rq_list);
 
                 if (req->rq_err) {
@@ -1544,7 +1524,7 @@ restart:
                         rc = -EINTR;
                 }
                 else if (req->rq_no_resend) {
-                        spin_unlock_irqrestore(&imp->imp_lock, flags);
+                        spin_unlock(&imp->imp_lock);
                         GOTO(out, rc = -ETIMEDOUT);
                 }
                 else {
@@ -1554,7 +1534,7 @@ restart:
 
         if (rc != 0) {
                 list_del_init(&req->rq_list);
-                spin_unlock_irqrestore(&imp->imp_lock, flags);
+                spin_unlock(&imp->imp_lock);
                 req->rq_status = rc; // XXX this ok?
                 GOTO(out, rc);
         }
@@ -1581,7 +1561,7 @@ restart:
         /* XXX this is the same as ptlrpc_set_wait */
         LASSERT(list_empty(&req->rq_list));
         list_add_tail(&req->rq_list, &imp->imp_sending_list);
-        spin_unlock_irqrestore(&imp->imp_lock, flags);
+        spin_unlock(&imp->imp_lock);
 
         rc = ptl_send_rpc(req, 0);
         if (rc) {
@@ -1600,13 +1580,13 @@ restart:
         CDEBUG(D_RPCTRACE, "Completed RPC pname:cluuid:pid:xid:nid:opc "
                "%s:%s:%d:"LPU64":%s:%d\n", cfs_curproc_comm(),
                imp->imp_obd->obd_uuid.uuid,
-               req->rq_reqmsg->status, req->rq_xid,
+               lustre_msg_get_status(req->rq_reqmsg), req->rq_xid,
                libcfs_nid2str(imp->imp_connection->c_peer.nid),
-               req->rq_reqmsg->opc);
+               lustre_msg_get_opc(req->rq_reqmsg));
 
-        spin_lock_irqsave(&imp->imp_lock, flags);
+        spin_lock(&imp->imp_lock);
         list_del_init(&req->rq_list);
-        spin_unlock_irqrestore(&imp->imp_lock, flags);
+        spin_unlock(&imp->imp_lock);
 
         /* If the reply was received normally, this just grabs the spinlock
          * (ensuring the reply callback has returned), sees that
@@ -1621,7 +1601,7 @@ restart:
                 /* ...unless we were specifically told otherwise. */
                 if (req->rq_no_resend)
                         GOTO(out, rc = -ETIMEDOUT);
-                spin_lock_irqsave(&imp->imp_lock, flags);
+                spin_lock(&imp->imp_lock);
                 goto restart;
         }
 
@@ -1644,10 +1624,10 @@ restart:
                 GOTO(out, rc = req->rq_status);
         }
 
-        rc = after_reply (req);
+        rc = after_reply(req);
         /* NB may return +ve success rc */
         if (req->rq_resend) {
-                spin_lock_irqsave(&imp->imp_lock, flags);
+                spin_lock(&imp->imp_lock);
                 goto restart;
         }
 
@@ -1695,7 +1675,6 @@ static int ptlrpc_replay_interpret(struct ptlrpc_request *req,
 {
         struct ptlrpc_replay_async_args *aa = data;
         struct obd_import *imp = req->rq_import;
-        unsigned long flags;
 
         ENTRY;
         atomic_dec(&imp->imp_replay_inflight);
@@ -1705,23 +1684,13 @@ static int ptlrpc_replay_interpret(struct ptlrpc_request *req,
                 GOTO(out, rc = -ETIMEDOUT);
         }
 
-#if SWAB_PARANOIA
-        /* Clear reply swab mask; this is a new reply in sender's byte order */
-        req->rq_rep_swab_mask = 0;
-#endif
-        LASSERT (req->rq_nob_received <= req->rq_replen);
-        rc = lustre_unpack_msg(req->rq_repmsg, req->rq_nob_received);
-        if (rc) {
-                DEBUG_REQ(D_ERROR, req, "unpack_rep failed: %d\n", rc);
-                GOTO(out, rc = -EPROTO);
-        }
-
-        if (req->rq_repmsg->type == PTL_RPC_MSG_ERR &&
-            req->rq_repmsg->status == -ENOTCONN)
-                GOTO(out, rc = req->rq_repmsg->status);
+        if (lustre_msg_get_type(req->rq_repmsg) == PTL_RPC_MSG_ERR &&
+            lustre_msg_get_status(req->rq_repmsg) == -ENOTCONN)
+                GOTO(out, rc = lustre_msg_get_status(req->rq_repmsg));
 
         /* The transno had better not change over replay. */
-        LASSERT(req->rq_reqmsg->transno == req->rq_repmsg->transno);
+        LASSERT(lustre_msg_get_transno(req->rq_reqmsg) ==
+                lustre_msg_get_transno(req->rq_repmsg));
 
         DEBUG_REQ(D_HA, req, "got rep");
 
@@ -1729,17 +1698,19 @@ static int ptlrpc_replay_interpret(struct ptlrpc_request *req,
         if (req->rq_replay_cb)
                 req->rq_replay_cb(req);
 
-        if (req->rq_replied && req->rq_repmsg->status != aa->praa_old_status) {
+        if (req->rq_replied &&
+            lustre_msg_get_status(req->rq_repmsg) != aa->praa_old_status) {
                 DEBUG_REQ(D_ERROR, req, "status %d, old was %d",
-                          req->rq_repmsg->status, aa->praa_old_status);
+                          lustre_msg_get_status(req->rq_repmsg),
+                          aa->praa_old_status);
         } else {
                 /* Put it back for re-replay. */
-                req->rq_repmsg->status = aa->praa_old_status;
+                lustre_msg_set_status(req->rq_repmsg, aa->praa_old_status);
         }
 
-        spin_lock_irqsave(&imp->imp_lock, flags);
+        spin_lock(&imp->imp_lock);
         imp->imp_last_replay_transno = req->rq_transno;
-        spin_unlock_irqrestore(&imp->imp_lock, flags);
+        spin_unlock(&imp->imp_lock);
 
         /* continue with recovery */
         rc = ptlrpc_import_recovery_state_machine(imp);
@@ -1774,7 +1745,7 @@ int ptlrpc_replay_req(struct ptlrpc_request *req)
         aa->praa_old_state = req->rq_send_state;
         req->rq_send_state = LUSTRE_IMP_REPLAY;
         req->rq_phase = RQ_PHASE_NEW;
-        aa->praa_old_status = req->rq_repmsg->status;
+        aa->praa_old_status = lustre_msg_get_status(req->rq_repmsg);
         req->rq_status = 0;
 
         req->rq_interpret_reply = ptlrpc_replay_interpret;
@@ -1787,7 +1758,6 @@ int ptlrpc_replay_req(struct ptlrpc_request *req)
 
 void ptlrpc_abort_inflight(struct obd_import *imp)
 {
-        unsigned long flags;
         struct list_head *tmp, *n;
         ENTRY;
 
@@ -1795,7 +1765,7 @@ void ptlrpc_abort_inflight(struct obd_import *imp)
          * ptlrpc_{queue,set}_wait must (and does) hold imp_lock while testing
          * this flag and then putting requests on sending_list or delayed_list.
          */
-        spin_lock_irqsave(&imp->imp_lock, flags);
+        spin_lock(&imp->imp_lock);
 
         /* XXX locking?  Maybe we should remove each request with the list
          * locked?  Also, how do we know if the requests on the list are
@@ -1834,7 +1804,7 @@ void ptlrpc_abort_inflight(struct obd_import *imp)
         if (imp->imp_replayable)
                 ptlrpc_free_committed(imp);
 
-        spin_unlock_irqrestore(&imp->imp_lock, flags);
+        spin_unlock(&imp->imp_lock);
 
         EXIT;
 }
index 08b1af5..96aa14b 100644 (file)
@@ -41,24 +41,23 @@ void request_out_callback(lnet_event_t *ev)
 {
         struct ptlrpc_cb_id   *cbid = ev->md.user_ptr;
         struct ptlrpc_request *req = cbid->cbid_arg;
-        unsigned long          flags;
         ENTRY;
 
         LASSERT (ev->type == LNET_EVENT_SEND ||
                  ev->type == LNET_EVENT_UNLINK);
         LASSERT (ev->unlinked);
 
-        DEBUG_REQ_EX((ev->status == 0) ? D_NET : D_ERROR, req,
-                     "type %d, status %d", ev->type, ev->status);
+        DEBUG_REQ((ev->status == 0) ? D_NET : D_ERROR, req,
+                  "type %d, status %d", ev->type, ev->status);
 
         if (ev->type == LNET_EVENT_UNLINK || ev->status != 0) {
 
                 /* Failed send: make it seem like the reply timed out, just
                  * like failing sends in client.c does currently...  */
 
-                spin_lock_irqsave(&req->rq_lock, flags);
+                spin_lock(&req->rq_lock);
                 req->rq_net_err = 1;
-                spin_unlock_irqrestore(&req->rq_lock, flags);
+                spin_unlock(&req->rq_lock);
 
                 ptlrpc_wake_client_req(req);
         }
@@ -77,7 +76,6 @@ void reply_in_callback(lnet_event_t *ev)
 {
         struct ptlrpc_cb_id   *cbid = ev->md.user_ptr;
         struct ptlrpc_request *req = cbid->cbid_arg;
-        unsigned long flags;
         ENTRY;
 
         LASSERT (ev->type == LNET_EVENT_PUT ||
@@ -87,10 +85,10 @@ void reply_in_callback(lnet_event_t *ev)
         LASSERT (ev->offset == 0);
         LASSERT (ev->mlength <= req->rq_replen);
 
-        DEBUG_REQ_EX((ev->status == 0) ? D_NET : D_ERROR, req,
-                     "type %d, status %d", ev->type, ev->status);
+        DEBUG_REQ((ev->status == 0) ? D_NET : D_ERROR, req,
+                  "type %d, status %d", ev->type, ev->status);
 
-        spin_lock_irqsave (&req->rq_lock, flags);
+        spin_lock(&req->rq_lock);
 
         LASSERT (req->rq_receiving_reply);
         req->rq_receiving_reply = 0;
@@ -104,7 +102,7 @@ void reply_in_callback(lnet_event_t *ev)
          * since we don't have our own ref */
         ptlrpc_wake_client_req(req);
 
-        spin_unlock_irqrestore (&req->rq_lock, flags);
+        spin_unlock(&req->rq_lock);
         EXIT;
 }
 
@@ -115,7 +113,6 @@ void client_bulk_callback (lnet_event_t *ev)
 {
         struct ptlrpc_cb_id     *cbid = ev->md.user_ptr;
         struct ptlrpc_bulk_desc *desc = cbid->cbid_arg;
-        unsigned long            flags;
         ENTRY;
 
         LASSERT ((desc->bd_type == BULK_PUT_SINK &&
@@ -125,11 +122,11 @@ void client_bulk_callback (lnet_event_t *ev)
                  ev->type == LNET_EVENT_UNLINK);
         LASSERT (ev->unlinked);
 
-        CDEBUG_EX((ev->status == 0) ? D_NET : D_ERROR,
+        CDEBUG((ev->status == 0) ? D_NET : D_ERROR,
                "event type %d, status %d, desc %p\n",
                ev->type, ev->status, desc);
 
-        spin_lock_irqsave (&desc->bd_lock, flags);
+        spin_lock(&desc->bd_lock);
 
         LASSERT(desc->bd_network_rw);
         desc->bd_network_rw = 0;
@@ -143,7 +140,7 @@ void client_bulk_callback (lnet_event_t *ev)
          * otherwise */
         ptlrpc_wake_client_req(desc->bd_req);
 
-        spin_unlock_irqrestore (&desc->bd_lock, flags);
+        spin_unlock(&desc->bd_lock);
         EXIT;
 }
 
@@ -156,7 +153,6 @@ void request_in_callback(lnet_event_t *ev)
         struct ptlrpc_request_buffer_desc *rqbd = cbid->cbid_arg;
         struct ptlrpc_service             *service = rqbd->rqbd_service;
         struct ptlrpc_request             *req;
-        unsigned long                     flags;
         ENTRY;
 
         LASSERT (ev->type == LNET_EVENT_PUT ||
@@ -165,7 +161,7 @@ void request_in_callback(lnet_event_t *ev)
         LASSERT ((char *)ev->md.start + ev->offset + ev->mlength <=
                  rqbd->rqbd_buffer + service->srv_buf_size);
 
-        CDEBUG_EX((ev->status == 0) ? D_NET : D_ERROR,
+        CDEBUG((ev->status == 0) ? D_NET : D_ERROR,
                "event type %d, status %d, service %s\n",
                ev->type, ev->status, service->srv_name);
 
@@ -209,23 +205,24 @@ void request_in_callback(lnet_event_t *ev)
         req->rq_uid = ev->uid;
 #endif
 
-        spin_lock_irqsave (&service->srv_lock, flags);
+        spin_lock(&service->srv_lock);
 
         req->rq_history_seq = service->srv_request_seq++;
         list_add_tail(&req->rq_history_list, &service->srv_request_history);
 
         if (ev->unlinked) {
                 service->srv_nrqbd_receiving--;
-                if (ev->type != LNET_EVENT_UNLINK &&
-                    service->srv_nrqbd_receiving == 0) {
-                        /* This service is off-air because all its request
-                         * buffers are busy.  Portals will start dropping
-                         * incoming requests until more buffers get posted.
-                         * NB don't moan if it's because we're tearing down the
-                         * service. */
-                        CERROR("All %s request buffers busy\n",
+                CDEBUG(D_RPCTRACE,"Buffer complete: %d buffers still posted\n",
+                       service->srv_nrqbd_receiving);
+
+                /* Normally, don't complain about 0 buffers posted; LNET won't
+                 * drop incoming reqs since we set the portal lazy */
+                if (test_req_buffer_pressure &&
+                    ev->type != LNET_EVENT_UNLINK &&
+                    service->srv_nrqbd_receiving == 0)
+                        CWARN("All %s request buffers busy\n",
                               service->srv_name);
-                }
+
                 /* req takes over the network's ref on rqbd */
         } else {
                 /* req takes a ref on rqbd */
@@ -239,7 +236,7 @@ void request_in_callback(lnet_event_t *ev)
          * has been queued and we unlock, so do the wake now... */
         cfs_waitq_signal(&service->srv_waitq);
 
-        spin_unlock_irqrestore(&service->srv_lock, flags);
+        spin_unlock(&service->srv_lock);
         EXIT;
 }
 
@@ -251,7 +248,6 @@ void reply_out_callback(lnet_event_t *ev)
         struct ptlrpc_cb_id       *cbid = ev->md.user_ptr;
         struct ptlrpc_reply_state *rs = cbid->cbid_arg;
         struct ptlrpc_service     *svc = rs->rs_service;
-        unsigned long              flags;
         ENTRY;
 
         LASSERT (ev->type == LNET_EVENT_SEND ||
@@ -273,10 +269,10 @@ void reply_out_callback(lnet_event_t *ev)
         if (ev->unlinked) {
                 /* Last network callback.  The net's ref on 'rs' stays put
                  * until ptlrpc_server_handle_reply() is done with it */
-                spin_lock_irqsave (&svc->srv_lock, flags);
+                spin_lock(&svc->srv_lock);
                 rs->rs_on_net = 0;
                 ptlrpc_schedule_difficult_reply (rs);
-                spin_unlock_irqrestore (&svc->srv_lock, flags);
+                spin_unlock(&svc->srv_lock);
         }
 
         EXIT;
@@ -289,7 +285,6 @@ void server_bulk_callback (lnet_event_t *ev)
 {
         struct ptlrpc_cb_id     *cbid = ev->md.user_ptr;
         struct ptlrpc_bulk_desc *desc = cbid->cbid_arg;
-        unsigned long            flags;
         ENTRY;
 
         LASSERT (ev->type == LNET_EVENT_SEND ||
@@ -299,12 +294,12 @@ void server_bulk_callback (lnet_event_t *ev)
                  (desc->bd_type == BULK_GET_SINK &&
                   ev->type == LNET_EVENT_REPLY));
 
-        CDEBUG_EX((ev->status == 0) ? D_NET : D_ERROR,
+        CDEBUG((ev->status == 0) ? D_NET : D_ERROR,
                "event type %d, status %d, desc %p\n",
                ev->type, ev->status, desc);
 
-        spin_lock_irqsave (&desc->bd_lock, flags);
-
+        spin_lock(&desc->bd_lock);
+        
         if ((ev->type == LNET_EVENT_ACK ||
              ev->type == LNET_EVENT_REPLY) &&
             ev->status == 0) {
@@ -321,7 +316,7 @@ void server_bulk_callback (lnet_event_t *ev)
                 cfs_waitq_signal(&desc->bd_waitq);
         }
 
-        spin_unlock_irqrestore (&desc->bd_lock, flags);
+        spin_unlock(&desc->bd_lock);
         EXIT;
 }
 
index 747c70f..b7a9e49 100644 (file)
@@ -56,13 +56,11 @@ do {                                                                           \
         }                                                                      \
 } while(0)
 
-#define IMPORT_SET_STATE(imp, state)                    \
-do {                                                    \
-        unsigned long flags;                            \
-                                                        \
-        spin_lock_irqsave(&imp->imp_lock, flags);       \
-        IMPORT_SET_STATE_NOLOCK(imp, state);            \
-        spin_unlock_irqrestore(&imp->imp_lock, flags);  \
+#define IMPORT_SET_STATE(imp, state)            \
+do {                                            \
+        spin_lock(&imp->imp_lock);              \
+        IMPORT_SET_STATE_NOLOCK(imp, state);    \
+        spin_unlock(&imp->imp_lock);            \
 } while(0)
 
 
@@ -77,21 +75,20 @@ int ptlrpc_import_recovery_state_machine(struct obd_import *imp);
  * though. */
 int ptlrpc_init_import(struct obd_import *imp)
 {
-        unsigned long flags;
-
-        spin_lock_irqsave(&imp->imp_lock, flags);
+        spin_lock(&imp->imp_lock);
 
         imp->imp_generation++;
         imp->imp_state =  LUSTRE_IMP_NEW;
 
-        spin_unlock_irqrestore(&imp->imp_lock, flags);
+        spin_unlock(&imp->imp_lock);
 
         return 0;
 }
 EXPORT_SYMBOL(ptlrpc_init_import);
 
 #define UUID_STR "_UUID"
-static void deuuidify(char *uuid, const char *prefix, char **uuid_start, int *uuid_len)
+static void deuuidify(char *uuid, const char *prefix, char **uuid_start,
+                      int *uuid_len)
 {
         *uuid_start = !prefix || strncmp(uuid, prefix, strlen(prefix))
                 ? uuid : uuid + strlen(prefix);
@@ -118,10 +115,9 @@ static void deuuidify(char *uuid, const char *prefix, char **uuid_start, int *uu
  */
 int ptlrpc_set_import_discon(struct obd_import *imp, __u32 conn_cnt)
 {
-        unsigned long flags;
         int rc = 0;
 
-        spin_lock_irqsave(&imp->imp_lock, flags);
+        spin_lock(&imp->imp_lock);
 
         if (imp->imp_state == LUSTRE_IMP_FULL &&
             (conn_cnt == 0 || conn_cnt == imp->imp_conn_cnt)) {
@@ -140,7 +136,7 @@ int ptlrpc_set_import_discon(struct obd_import *imp, __u32 conn_cnt)
                                       "wait for recovery to complete" : "fail");
 
                 IMPORT_SET_STATE_NOLOCK(imp, LUSTRE_IMP_DISCON);
-                spin_unlock_irqrestore(&imp->imp_lock, flags);
+                spin_unlock(&imp->imp_lock);
     
                 if (obd_dump_on_timeout)
                         libcfs_debug_dumplog();
@@ -148,7 +144,7 @@ int ptlrpc_set_import_discon(struct obd_import *imp, __u32 conn_cnt)
                 obd_import_event(imp->imp_obd, imp, IMP_EVENT_DISCON);
                 rc = 1;
         } else {
-                spin_unlock_irqrestore(&imp->imp_lock, flags);
+                spin_unlock(&imp->imp_lock);
                 CDEBUG(D_HA, "%s: import %p already %s (conn %u, was %u): %s\n",
                        imp->imp_client->cli_name, imp,
                        (imp->imp_state == LUSTRE_IMP_FULL &&
@@ -166,14 +162,13 @@ int ptlrpc_set_import_discon(struct obd_import *imp, __u32 conn_cnt)
  */
 void ptlrpc_deactivate_import(struct obd_import *imp)
 {
-        unsigned long flags;
         ENTRY;
 
-        spin_lock_irqsave(&imp->imp_lock, flags);
+        spin_lock(&imp->imp_lock);
         CDEBUG(D_HA, "setting import %s INVALID\n", obd2cli_tgt(imp->imp_obd));
         imp->imp_invalid = 1;
         imp->imp_generation++;
-        spin_unlock_irqrestore(&imp->imp_lock, flags);
+        spin_unlock(&imp->imp_lock);
 
         ptlrpc_abort_inflight(imp);
         obd_import_event(imp->imp_obd, imp, IMP_EVENT_INACTIVE);
@@ -196,8 +191,8 @@ void ptlrpc_invalidate_import(struct obd_import *imp)
         LASSERT(imp->imp_invalid);
 
         /* wait for all requests to error out and call completion callbacks */
-        lwi = LWI_TIMEOUT_INTR(cfs_timeout_cap(cfs_time_seconds(obd_timeout)), 
-                               NULL, NULL, NULL);
+        lwi = LWI_TIMEOUT_INTERVAL(cfs_timeout_cap(cfs_time_seconds(obd_timeout)), 
+                                   HZ, NULL, NULL);
         rc = l_wait_event(imp->imp_recovery_waitq,
                           (atomic_read(&imp->imp_inflight) == 0),
                           &lwi);
@@ -214,11 +209,10 @@ void ptlrpc_invalidate_import(struct obd_import *imp)
 void ptlrpc_activate_import(struct obd_import *imp)
 {
         struct obd_device *obd = imp->imp_obd;
-        unsigned long flags;
 
-        spin_lock_irqsave(&imp->imp_lock, flags);
+        spin_lock(&imp->imp_lock);
         imp->imp_invalid = 0;
-        spin_unlock_irqrestore(&imp->imp_lock, flags);
+        spin_unlock(&imp->imp_lock);
 
         obd_import_event(obd, imp, IMP_EVENT_ACTIVE);
 }
@@ -230,8 +224,6 @@ void ptlrpc_fail_import(struct obd_import *imp, __u32 conn_cnt)
         LASSERT(!imp->imp_dlm_fake);
 
         if (ptlrpc_set_import_discon(imp, conn_cnt)) {
-                unsigned long flags;
-
                 if (!imp->imp_replayable) {
                         CDEBUG(D_HA, "import %s@%s for %s not replayable, "
                                "auto-deactivating\n",
@@ -244,9 +236,9 @@ void ptlrpc_fail_import(struct obd_import *imp, __u32 conn_cnt)
                 CDEBUG(D_HA, "%s: waking up pinger\n",
                        obd2cli_tgt(imp->imp_obd));
 
-                spin_lock_irqsave(&imp->imp_lock, flags);
+                spin_lock(&imp->imp_lock);
                 imp->imp_force_verify = 1;
-                spin_unlock_irqrestore(&imp->imp_lock, flags);
+                spin_unlock(&imp->imp_lock);
 
                 ptlrpc_pinger_wake_up();
         }
@@ -255,7 +247,7 @@ void ptlrpc_fail_import(struct obd_import *imp, __u32 conn_cnt)
 
 static int import_select_connection(struct obd_import *imp)
 {
-        struct obd_import_conn *imp_conn;
+        struct obd_import_conn *imp_conn = NULL, *conn;
         struct obd_export *dlmexp;
         ENTRY;
 
@@ -268,14 +260,42 @@ static int import_select_connection(struct obd_import *imp)
                 RETURN(-EINVAL);
         }
 
-        if (imp->imp_conn_current &&
-            imp->imp_conn_current->oic_item.next != &imp->imp_conn_list) {
-                imp_conn = list_entry(imp->imp_conn_current->oic_item.next,
-                                      struct obd_import_conn, oic_item);
-        } else {
-                imp_conn = list_entry(imp->imp_conn_list.next,
-                                      struct obd_import_conn, oic_item);
+        list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
+                CDEBUG(D_HA, "%s: connect to NID %s last attempt "LPU64"\n",
+                       imp->imp_obd->obd_name,
+                       libcfs_nid2str(conn->oic_conn->c_peer.nid),
+                       conn->oic_last_attempt);
+                /* Throttle the reconnect rate to once per RECONNECT_INTERVAL */
+                if (cfs_time_before_64(conn->oic_last_attempt + 
+                                       RECONNECT_INTERVAL * HZ,
+                                       cfs_time_current_64())) {
+                        /* If we have never tried this connection since the
+                           the last successful attempt, go with this one */
+                        if (cfs_time_before_64(conn->oic_last_attempt,
+                                               imp->imp_last_success_conn)) {
+                                imp_conn = conn;
+                                break;
+                        }
+
+                        /* Both of these connections have already been tried
+                           since the last successful connection; just choose the
+                           least recently used */
+                        if (!imp_conn)
+                                imp_conn = conn;
+                        else if (cfs_time_before_64(conn->oic_last_attempt,
+                                                    imp_conn->oic_last_attempt))
+                                imp_conn = conn;
+                }
+        }
+
+        /* if not found, simply choose the current one */
+        if (!imp_conn) {
+                LASSERT(imp->imp_conn_current);
+                imp_conn = imp->imp_conn_current;
         }
+        LASSERT(imp_conn->oic_conn);
+
+        imp_conn->oic_last_attempt = cfs_time_current_64();
 
         /* switch connection, don't mind if it's same as the current one */
         if (imp->imp_connection)
@@ -289,48 +309,53 @@ static int import_select_connection(struct obd_import *imp)
         dlmexp->exp_connection = ptlrpc_connection_addref(imp_conn->oic_conn);
         class_export_put(dlmexp);
 
-        if (imp->imp_conn_current && (imp->imp_conn_current != imp_conn)) {
-                LCONSOLE_WARN("Changing connection for %s to %s\n",
-                              imp->imp_obd->obd_name, imp_conn->oic_uuid.uuid);
-        }
+        if (imp->imp_conn_current != imp_conn) {
+                LCONSOLE_INFO("Changing connection for %s to %s/%s\n",
+                              imp->imp_obd->obd_name, imp_conn->oic_uuid.uuid,
+                              libcfs_nid2str(imp_conn->oic_conn->c_peer.nid));
         imp->imp_conn_current = imp_conn;
-        CDEBUG(D_HA, "%s: import %p using connection %s\n",
-               imp->imp_obd->obd_name, imp, imp_conn->oic_uuid.uuid);
+        }
+
+        CDEBUG(D_HA, "%s: import %p using connection %s/%s\n",
+               imp->imp_obd->obd_name, imp, imp_conn->oic_uuid.uuid,
+               libcfs_nid2str(imp_conn->oic_conn->c_peer.nid));
+
         spin_unlock(&imp->imp_lock);
 
         RETURN(0);
 }
 
-int ptlrpc_connect_import(struct obd_import *imp, char * new_uuid)
+int ptlrpc_connect_import(struct obd_import *imp, char *new_uuid)
 {
         struct obd_device *obd = imp->imp_obd;
         int initial_connect = 0;
         int rc;
         __u64 committed_before_reconnect = 0;
         struct ptlrpc_request *request;
-        int size[] = {sizeof(imp->imp_obd->u.cli.cl_target_uuid),
-                      sizeof(obd->obd_uuid),
-                      sizeof(imp->imp_dlm_handle),
-                      sizeof(imp->imp_connect_data)};
-        char *tmp[] = {obd2cli_tgt(imp->imp_obd),
-                       obd->obd_uuid.uuid,
-                       (char *)&imp->imp_dlm_handle,
-                       (char *)&imp->imp_connect_data};
+        int size[] = { sizeof(struct ptlrpc_body),
+                       sizeof(imp->imp_obd->u.cli.cl_target_uuid),
+                       sizeof(obd->obd_uuid),
+                       sizeof(imp->imp_dlm_handle),
+                       sizeof(imp->imp_connect_data) };
+        char *tmp[] = { NULL,
+                        obd2cli_tgt(imp->imp_obd),
+                        obd->obd_uuid.uuid,
+                        (char *)&imp->imp_dlm_handle,
+                        (char *)&imp->imp_connect_data };
         struct ptlrpc_connect_async_args *aa;
-        unsigned long flags;
 
         ENTRY;
-        spin_lock_irqsave(&imp->imp_lock, flags);
+        spin_lock(&imp->imp_lock);
         if (imp->imp_state == LUSTRE_IMP_CLOSED) {
-                spin_unlock_irqrestore(&imp->imp_lock, flags);
+                spin_unlock(&imp->imp_lock);
                 CERROR("can't connect to a closed import\n");
                 RETURN(-EINVAL);
         } else if (imp->imp_state == LUSTRE_IMP_FULL) {
-                spin_unlock_irqrestore(&imp->imp_lock, flags);
+                spin_unlock(&imp->imp_lock);
                 CERROR("already connected\n");
                 RETURN(0);
         } else if (imp->imp_state == LUSTRE_IMP_CONNECTING) {
-                spin_unlock_irqrestore(&imp->imp_lock, flags);
+                spin_unlock(&imp->imp_lock);
                 CERROR("already connecting\n");
                 RETURN(-EALREADY);
         }
@@ -345,7 +370,7 @@ int ptlrpc_connect_import(struct obd_import *imp, char * new_uuid)
         else
                 committed_before_reconnect = imp->imp_peer_committed_transno;
 
-        spin_unlock_irqrestore(&imp->imp_lock, flags);
+        spin_unlock(&imp->imp_lock);
 
         if (new_uuid) {
                 struct obd_uuid uuid;
@@ -360,36 +385,48 @@ int ptlrpc_connect_import(struct obd_import *imp, char * new_uuid)
         if (rc)
                 GOTO(out, rc);
 
-        if (imp->imp_initial_recov_bk && initial_connect &&
-            /* last in list */
-            (imp->imp_conn_current->oic_item.next == &imp->imp_conn_list)) {
-                CDEBUG(D_HA, "Last connection attempt (%d) for %s\n",
-                       imp->imp_conn_cnt, obd2cli_tgt(imp->imp_obd));
-                /* Don't retry if connect fails */
-                rc = 0;
-                obd_set_info_async(obd->obd_self_export,
-                                   strlen(KEY_INIT_RECOV), KEY_INIT_RECOV,
-                                   sizeof(rc), &rc, NULL);
+        /* last in connection list */
+        if (imp->imp_conn_current->oic_item.next == &imp->imp_conn_list) {
+                if (imp->imp_initial_recov_bk && initial_connect) {
+                        CDEBUG(D_HA, "Last connection attempt (%d) for %s\n",
+                               imp->imp_conn_cnt, obd2cli_tgt(imp->imp_obd));
+                        /* Don't retry if connect fails */
+                        rc = 0;
+                        obd_set_info_async(obd->obd_self_export,
+                                           strlen(KEY_INIT_RECOV),
+                                           KEY_INIT_RECOV,
+                                           sizeof(rc), &rc, NULL);
+                }
+                if (imp->imp_recon_bk) {
+                        CDEBUG(D_HA, "Last reconnection attempt (%d) for %s\n",
+                               imp->imp_conn_cnt, obd2cli_tgt(imp->imp_obd));
+                        imp->imp_last_recon = 1;
+                }
         }
 
+        /* Reset connect flags to the originally requested flags, in case
+         * the server is updated on-the-fly we will get the new features. */
+        imp->imp_connect_data.ocd_connect_flags = imp->imp_connect_flags_orig;
         rc = obd_reconnect(imp->imp_obd->obd_self_export, obd,
                            &obd->obd_uuid, &imp->imp_connect_data);
         if (rc)
                 GOTO(out, rc);
 
         request = ptlrpc_prep_req(imp, LUSTRE_OBD_VERSION, imp->imp_connect_op,
-                                  4, size, tmp);
+                                  5, size, tmp);
         if (!request)
                 GOTO(out, rc = -ENOMEM);
 
 #ifndef __KERNEL__
         lustre_msg_add_op_flags(request->rq_reqmsg, MSG_CONNECT_LIBCLIENT);
 #endif
+        lustre_msg_add_op_flags(request->rq_reqmsg, MSG_CONNECT_NEXT_VER);
 
         request->rq_send_state = LUSTRE_IMP_CONNECTING;
         /* Allow a slightly larger reply for future growth compatibility */
-        size[0] = sizeof(struct obd_connect_data) + 16 * sizeof(__u64);
-        request->rq_replen = lustre_msg_size(1, size);
+        size[REPLY_REC_OFF] = sizeof(struct obd_connect_data) +
+                              16 * sizeof(__u64);
+        ptlrpc_req_set_repsize(request, 2, size);
         request->rq_interpret_reply = ptlrpc_connect_interpret;
 
         CLASSERT(sizeof (*aa) <= sizeof (request->rq_async_args));
@@ -421,12 +458,11 @@ EXPORT_SYMBOL(ptlrpc_connect_import);
 static void ptlrpc_maybe_ping_import_soon(struct obd_import *imp)
 {
         struct obd_import_conn *imp_conn;
-        unsigned long flags;
         int wake_pinger = 0;
 
         ENTRY;
 
-        spin_lock_irqsave(&imp->imp_lock, flags);
+        spin_lock(&imp->imp_lock);
         if (list_empty(&imp->imp_conn_list))
                 GOTO(unlock, 0);
 
@@ -440,7 +476,7 @@ static void ptlrpc_maybe_ping_import_soon(struct obd_import *imp)
         }
 
  unlock:
-        spin_unlock_irqrestore(&imp->imp_lock, flags);
+        spin_unlock(&imp->imp_lock);
 
         if (wake_pinger)
                 ptlrpc_pinger_wake_up();
@@ -453,17 +489,17 @@ static int ptlrpc_connect_interpret(struct ptlrpc_request *request,
 {
         struct ptlrpc_connect_async_args *aa = data;
         struct obd_import *imp = request->rq_import;
+        struct client_obd *cli = &imp->imp_obd->u.cli;
         struct lustre_handle old_hdl;
-        unsigned long flags;
         int msg_flags;
         ENTRY;
 
-        spin_lock_irqsave(&imp->imp_lock, flags);
+        spin_lock(&imp->imp_lock);
         if (imp->imp_state == LUSTRE_IMP_CLOSED) {
-                spin_unlock_irqrestore(&imp->imp_lock, flags);
+                spin_unlock(&imp->imp_lock);
                 RETURN(0);
         }
-        spin_unlock_irqrestore(&imp->imp_lock, flags);
+        spin_unlock(&imp->imp_lock);
 
         if (rc)
                 GOTO(out, rc);
@@ -483,7 +519,18 @@ static int ptlrpc_connect_interpret(struct ptlrpc_request *request,
                 } else {
                         imp->imp_replayable = 0;
                 }
-                imp->imp_remote_handle = request->rq_repmsg->handle;
+
+                if (msg_flags & MSG_CONNECT_NEXT_VER) {
+                        imp->imp_msg_magic = LUSTRE_MSG_MAGIC_V2;
+                        CDEBUG(D_RPCTRACE, "connect to %s with lustre_msg_v2\n",
+                               obd2cli_tgt(imp->imp_obd));
+                } else {
+                        CDEBUG(D_RPCTRACE, "connect to %s with lustre_msg_v1\n",
+                               obd2cli_tgt(imp->imp_obd));
+                }
+
+                imp->imp_remote_handle =
+                                *lustre_msg_get_handle(request->rq_repmsg);
 
                 IMPORT_SET_STATE(imp, LUSTRE_IMP_FULL);
                 GOTO(finish, rc = 0);
@@ -492,7 +539,7 @@ static int ptlrpc_connect_interpret(struct ptlrpc_request *request,
         /* Determine what recovery state to move the import to. */
         if (MSG_CONNECT_RECONNECT & msg_flags) {
                 memset(&old_hdl, 0, sizeof(old_hdl));
-                if (!memcmp(&old_hdl, &request->rq_repmsg->handle,
+                if (!memcmp(&old_hdl, lustre_msg_get_handle(request->rq_repmsg),
                             sizeof (old_hdl))) {
                         CERROR("%s@%s didn't like our handle "LPX64
                                ", failed\n", obd2cli_tgt(imp->imp_obd),
@@ -501,15 +548,25 @@ static int ptlrpc_connect_interpret(struct ptlrpc_request *request,
                         GOTO(out, rc = -ENOTCONN);
                 }
 
-                if (memcmp(&imp->imp_remote_handle, &request->rq_repmsg->handle,
+                if (memcmp(&imp->imp_remote_handle,
+                           lustre_msg_get_handle(request->rq_repmsg),
                            sizeof(imp->imp_remote_handle))) {
-                        CERROR("%s@%s changed handle from "LPX64" to "LPX64
+                        int level = D_ERROR;
+                        /* The MGC does this all the time */
+                        if (strcmp(imp->imp_obd->obd_type->typ_name,
+                                   LUSTRE_MGC_NAME) == 0) {
+                                level = D_CONFIG;
+                        }
+                        CDEBUG(level, 
+                               "%s@%s changed handle from "LPX64" to "LPX64
                                "; copying, but this may foreshadow disaster\n",
                                obd2cli_tgt(imp->imp_obd),
                                imp->imp_connection->c_remote_uuid.uuid,
                                imp->imp_remote_handle.cookie,
-                               request->rq_repmsg->handle.cookie);
-                        imp->imp_remote_handle = request->rq_repmsg->handle;
+                               lustre_msg_get_handle(request->rq_repmsg)->
+                                        cookie);
+                        imp->imp_remote_handle =
+                                     *lustre_msg_get_handle(request->rq_repmsg);
                 } else {
                         CDEBUG(D_HA, "reconnected to %s@%s after partition\n",
                                obd2cli_tgt(imp->imp_obd),
@@ -529,11 +586,13 @@ static int ptlrpc_connect_interpret(struct ptlrpc_request *request,
                 }
         } else if ((MSG_CONNECT_RECOVERING & msg_flags) && !imp->imp_invalid) {
                 LASSERT(imp->imp_replayable);
-                imp->imp_remote_handle = request->rq_repmsg->handle;
+                imp->imp_remote_handle =
+                                *lustre_msg_get_handle(request->rq_repmsg);
                 imp->imp_last_replay_transno = 0;
                 IMPORT_SET_STATE(imp, LUSTRE_IMP_REPLAY);
         } else {
-                imp->imp_remote_handle = request->rq_repmsg->handle;
+                imp->imp_remote_handle =
+                                *lustre_msg_get_handle(request->rq_repmsg);
                 IMPORT_SET_STATE(imp, LUSTRE_IMP_EVICTED);
         }
 
@@ -543,13 +602,14 @@ static int ptlrpc_connect_interpret(struct ptlrpc_request *request,
                        "after reconnect. We should LBUG right here.\n");
         }
 
-        if (request->rq_repmsg->last_committed < aa->pcaa_peer_committed) {
+        if (lustre_msg_get_last_committed(request->rq_repmsg) <
+            aa->pcaa_peer_committed) {
                 CERROR("%s went back in time (transno "LPD64
                        " was previously committed, server now claims "LPD64
                        ")!  See https://bugzilla.clusterfs.com/"
                        "long_list.cgi?buglist=9646\n",
                        obd2cli_tgt(imp->imp_obd), aa->pcaa_peer_committed,
-                       request->rq_repmsg->last_committed);
+                       lustre_msg_get_last_committed(request->rq_repmsg));
         }
 
 finish:
@@ -567,36 +627,51 @@ finish:
                 struct obd_connect_data *ocd;
                 struct obd_export *exp;
 
-                ocd = lustre_swab_repbuf(request, 0,
-                                         sizeof *ocd, lustre_swab_connect);
+                ocd = lustre_swab_repbuf(request, REPLY_REC_OFF, sizeof(*ocd),
+                                         lustre_swab_connect);
+
+                spin_lock(&imp->imp_lock);
+                list_del(&imp->imp_conn_current->oic_item);
+                list_add(&imp->imp_conn_current->oic_item, &imp->imp_conn_list);
+                imp->imp_last_success_conn =
+                        imp->imp_conn_current->oic_last_attempt;
+
                 if (ocd == NULL) {
+                        spin_unlock(&imp->imp_lock);
                         CERROR("Wrong connect data from server\n");
                         rc = -EPROTO;
                         GOTO(out, rc);
                 }
 
-                spin_lock_irqsave(&imp->imp_lock, flags);
-                
-                /*
-                 * check that server granted subset of flags we asked for.
-                 */
-                LASSERT((ocd->ocd_connect_flags &
-                         imp->imp_connect_data.ocd_connect_flags) ==
-                        ocd->ocd_connect_flags);
-
                 imp->imp_connect_data = *ocd;
-                if (!ocd->ocd_ibits_known &&
-                    ocd->ocd_connect_flags & OBD_CONNECT_IBITS)
-                        CERROR("Inodebits aware server returned zero compatible"
-                               " bits?\n");
 
                 exp = class_conn2export(&imp->imp_dlm_handle);
-                LASSERT(exp);
+                spin_unlock(&imp->imp_lock);
+
+                /* check that server granted subset of flags we asked for. */
+                LASSERTF((ocd->ocd_connect_flags &
+                          imp->imp_connect_flags_orig) ==
+                         ocd->ocd_connect_flags, LPX64" != "LPX64,
+                         imp->imp_connect_flags_orig, ocd->ocd_connect_flags);
+
+                if (!exp) {
+                        /* This could happen if export is cleaned during the 
+                           connect attempt */
+                        spin_unlock(&imp->imp_lock);
+                        CERROR("Missing export for %s\n", 
+                               imp->imp_obd->obd_name);
+                        GOTO(out, rc = -ENODEV);
+                }
                 exp->exp_connect_flags = ocd->ocd_connect_flags;
                 class_export_put(exp);
 
                 obd_import_event(imp->imp_obd, imp, IMP_EVENT_OCD);
 
+                if (!ocd->ocd_ibits_known &&
+                    ocd->ocd_connect_flags & OBD_CONNECT_IBITS)
+                        CERROR("Inodebits aware server returned zero compatible"
+                               " bits?\n");
+
                 if ((ocd->ocd_connect_flags & OBD_CONNECT_VERSION) &&
                     (ocd->ocd_version > LUSTRE_VERSION_CODE +
                     LUSTRE_VERSION_OFFSET_WARN)) {
@@ -618,20 +693,16 @@ finish:
                               action, LUSTRE_VERSION_STRING);
                 }
 
-                if (imp->imp_conn_current != NULL) {
-                        list_del(&imp->imp_conn_current->oic_item);
-                        list_add(&imp->imp_conn_current->oic_item,
-                                 &imp->imp_conn_list);
-                        imp->imp_conn_current = NULL;
-                        spin_unlock_irqrestore(&imp->imp_lock, flags);
+                if (ocd->ocd_connect_flags & OBD_CONNECT_BRW_SIZE) {
+                        cli->cl_max_pages_per_rpc = ocd->ocd_brw_size >> PAGE_SHIFT;
                 } else {
-                        static int bug7269_dump = 0;
-                        spin_unlock_irqrestore(&imp->imp_lock, flags);
-                        CERROR("this is bug 7269 - please attach log there\n");
-                        if (bug7269_dump == 0)
-                                libcfs_debug_dumplog();
-                        bug7269_dump = 1;
+                        cli->cl_max_pages_per_rpc = min((int)PTLRPC_MAX_BRW_PAGES,
+                                                        (int)(1024 * 1024 >> PAGE_SHIFT));
                 }
+
+                LASSERT(cli->cl_max_pages_per_rpc <= PTLRPC_MAX_BRW_PAGES &&
+                        cli->cl_max_pages_per_rpc > 0);
+
         }
 
  out:
@@ -640,9 +711,15 @@ finish:
                 if (aa->pcaa_initial_connect && !imp->imp_initial_recov)
                         ptlrpc_deactivate_import(imp);
 
+                if (imp->imp_recon_bk && imp->imp_last_recon) {
+                        /* Give up trying to reconnect */
+                        imp->imp_obd->obd_no_recov = 1;
+                        ptlrpc_deactivate_import(imp);
+                }
+
                 if (rc == -EPROTO) {
                         struct obd_connect_data *ocd;
-                        ocd = lustre_swab_repbuf(request, 0,
+                        ocd = lustre_swab_repbuf(request, REPLY_REC_OFF,
                                                  sizeof *ocd,
                                                  lustre_swab_connect);
                         if (ocd &&
@@ -673,6 +750,8 @@ finish:
                        obd2cli_tgt(imp->imp_obd),
                        (char *)imp->imp_connection->c_remote_uuid.uuid, rc);
         }
+        
+        imp->imp_last_recon = 0;
 
         cfs_waitq_signal(&imp->imp_recovery_waitq);
         RETURN(rc);
@@ -703,16 +782,15 @@ static int signal_completed_replay(struct obd_import *imp)
         LASSERT(atomic_read(&imp->imp_replay_inflight) == 0);
         atomic_inc(&imp->imp_replay_inflight);
 
-        req = ptlrpc_prep_req(imp, LUSTRE_OBD_VERSION, OBD_PING,
-                              0, NULL, NULL);
+        req = ptlrpc_prep_req(imp, LUSTRE_OBD_VERSION, OBD_PING, 1, NULL, NULL);
         if (!req) {
                 atomic_dec(&imp->imp_replay_inflight);
                 RETURN(-ENOMEM);
         }
 
-        req->rq_replen = lustre_msg_size(0, NULL);
+        ptlrpc_req_set_repsize(req, 1, NULL);
         req->rq_send_state = LUSTRE_IMP_REPLAY_WAIT;
-        req->rq_reqmsg->flags |= MSG_LAST_REPLAY;
+        lustre_msg_add_flags(req->rq_reqmsg, MSG_LAST_REPLAY);
         req->rq_timeout *= 3;
         req->rq_interpret_reply = completed_replay_interpret;
 
@@ -840,10 +918,8 @@ static int back_to_sleep(void *unused)
 
 int ptlrpc_disconnect_import(struct obd_import *imp)
 {
-        struct ptlrpc_request *request;
-        int rq_opc;
-        int rc = 0;
-        unsigned long flags;
+        struct ptlrpc_request *req;
+        int rq_opc, rc = 0;
         ENTRY;
 
         switch (imp->imp_connect_op) {
@@ -858,39 +934,40 @@ int ptlrpc_disconnect_import(struct obd_import *imp)
 
         if (ptlrpc_import_in_recovery(imp)) {
                 struct l_wait_info lwi;
-                lwi = LWI_TIMEOUT_INTR(cfs_timeout_cap(cfs_time_seconds(obd_timeout)), 
-                                       back_to_sleep, NULL, NULL);
+                cfs_duration_t timeout = cfs_time_seconds(obd_timeout);
+
+                lwi = LWI_TIMEOUT_INTR(cfs_timeout_cap(timeout), 
+                                       back_to_sleep, LWI_ON_SIGNAL_NOOP, NULL);
                 rc = l_wait_event(imp->imp_recovery_waitq,
                                   !ptlrpc_import_in_recovery(imp), &lwi);
 
         }
 
-        spin_lock_irqsave(&imp->imp_lock, flags);
+        spin_lock(&imp->imp_lock);
         if (imp->imp_state != LUSTRE_IMP_FULL)
                 GOTO(out, 0);
 
-        spin_unlock_irqrestore(&imp->imp_lock, flags);
+        spin_unlock(&imp->imp_lock);
 
-        request = ptlrpc_prep_req(imp, LUSTRE_OBD_VERSION, rq_opc,
-                                  0, NULL, NULL);
-        if (request) {
+        req = ptlrpc_prep_req(imp, LUSTRE_OBD_VERSION, rq_opc, 1, NULL, NULL);
+        if (req) {
                 /* We are disconnecting, do not retry a failed DISCONNECT rpc if
                  * it fails.  We can get through the above with a down server
                  * if the client doesn't know the server is gone yet. */
-                request->rq_no_resend = 1;
-                request->rq_timeout = 5;
+                req->rq_no_resend = 1;
+                req->rq_timeout = 5;
                 IMPORT_SET_STATE(imp, LUSTRE_IMP_CONNECTING);
-                request->rq_send_state =  LUSTRE_IMP_CONNECTING;
-                request->rq_replen = lustre_msg_size(0, NULL);
-                rc = ptlrpc_queue_wait(request);
-                ptlrpc_req_finished(request);
+                req->rq_send_state =  LUSTRE_IMP_CONNECTING;
+                ptlrpc_req_set_repsize(req, 1, NULL);
+                rc = ptlrpc_queue_wait(req);
+                ptlrpc_req_finished(req);
         }
 
-        spin_lock_irqsave(&imp->imp_lock, flags);
+        spin_lock(&imp->imp_lock);
 out:
         IMPORT_SET_STATE_NOLOCK(imp, LUSTRE_IMP_CLOSED);
         memset(&imp->imp_remote_handle, 0, sizeof(imp->imp_remote_handle));
-        spin_unlock_irqrestore(&imp->imp_lock, flags);
+        spin_unlock(&imp->imp_lock);
 
         RETURN(rc);
 }
index 6a124b0..2ef99ab 100644 (file)
 #include <lustre_req_layout.h>
 #include <linux/lustre_acl.h>
 
+#if __KERNEL__
+#define __POSIX_ACL_MAX_SIZE \
+        (sizeof(xattr_acl_header) + 32 * sizeof(xattr_acl_entry))
+#else
+#define __POSIX_ACL_MAX_SIZE 0
+#endif
+
 static const struct req_msg_field *empty[] = {}; /* none */
 
 static const struct req_msg_field *mdt_body_only[] = {
+        &RMF_PTLRPC_BODY,
         &RMF_MDT_BODY
 };
 
 static const struct req_msg_field *mds_statfs_server[] = {
+        &RMF_PTLRPC_BODY,
         &RMF_OBD_STATFS
 };
 
 static const struct req_msg_field *seq_query_client[] = {
+        &RMF_PTLRPC_BODY,
         &RMF_SEQ_OPC
 };
 
 static const struct req_msg_field *seq_query_server[] = {
+        &RMF_PTLRPC_BODY,
         &RMF_SEQ_RANGE
 };
 
 static const struct req_msg_field *fld_query_client[] = {
+        &RMF_PTLRPC_BODY,
         &RMF_FLD_OPC,
         &RMF_FLD_MDFLD
 };
 
 static const struct req_msg_field *fld_query_server[] = {
+        &RMF_PTLRPC_BODY,
         &RMF_FLD_MDFLD
 };
 
 static const struct req_msg_field *mds_getattr_name_client[] = {
+        &RMF_PTLRPC_BODY,
         &RMF_MDT_BODY,
         &RMF_NAME
 };
 
 static const struct req_msg_field *mds_reint_client[] = {
+        &RMF_PTLRPC_BODY,
         &RMF_REINT_OPC
 };
 
 static const struct req_msg_field *mds_reint_create_client[] = {
+        &RMF_PTLRPC_BODY,
         &RMF_REC_CREATE,
         &RMF_NAME,
         &RMF_SYMTGT
 };
 
 static const struct req_msg_field *mds_reint_open_client[] = {
+        &RMF_PTLRPC_BODY,
         &RMF_REC_CREATE,
         &RMF_NAME,
         &RMF_EADATA
 };
 
 static const struct req_msg_field *mds_reint_open_server[] = {
+        &RMF_PTLRPC_BODY,
         &RMF_MDT_BODY,
         &RMF_MDT_MD,
         &RMF_ACL
 };
 
 static const struct req_msg_field *mds_reint_unlink_client[] = {
+        &RMF_PTLRPC_BODY,
         &RMF_REC_UNLINK,
         &RMF_NAME
 };
 
 static const struct req_msg_field *mds_reint_link_client[] = {
+        &RMF_PTLRPC_BODY,
         &RMF_REC_LINK,
         &RMF_NAME
 };
 
 static const struct req_msg_field *mds_reint_rename_client[] = {
+        &RMF_PTLRPC_BODY,
         &RMF_REC_RENAME,
         &RMF_NAME,
         &RMF_SYMTGT
 };
 
 static const struct req_msg_field *mds_last_unlink_server[] = {
+        &RMF_PTLRPC_BODY,
         &RMF_MDT_BODY,
         &RMF_MDT_MD,
         &RMF_LOGCOOKIES
 };
 
 static const struct req_msg_field *mds_reint_setattr_client[] = {
+        &RMF_PTLRPC_BODY,
         &RMF_REC_SETATTR,
         &RMF_EADATA,
         &RMF_LOGCOOKIES
 };
 
 static const struct req_msg_field *mds_connect_client[] = {
+        &RMF_PTLRPC_BODY,
         &RMF_TGTUUID,
         &RMF_CLUUID,
         &RMF_CONN,
@@ -144,24 +168,29 @@ static const struct req_msg_field *mds_connect_client[] = {
 };
 
 static const struct req_msg_field *mds_connect_server[] = {
+        &RMF_PTLRPC_BODY,
         &RMF_CONNECT_DATA
 };
 
 static const struct req_msg_field *ldlm_enqueue_client[] = {
+        &RMF_PTLRPC_BODY,
         &RMF_DLM_REQ
 };
 
 static const struct req_msg_field *ldlm_enqueue_server[] = {
+        &RMF_PTLRPC_BODY,
         &RMF_DLM_REP
 };
 
 static const struct req_msg_field *ldlm_intent_client[] = {
+        &RMF_PTLRPC_BODY,
         &RMF_DLM_REQ,
         &RMF_LDLM_INTENT,
         &RMF_REINT_OPC
 };
 
 static const struct req_msg_field *ldlm_intent_server[] = {
+        &RMF_PTLRPC_BODY,
         &RMF_DLM_REP,
         &RMF_MDT_BODY,
         &RMF_MDT_MD,
@@ -169,6 +198,7 @@ static const struct req_msg_field *ldlm_intent_server[] = {
 };
 
 static const struct req_msg_field *ldlm_intent_getattr_client[] = {
+        &RMF_PTLRPC_BODY,
         &RMF_DLM_REQ,
         &RMF_LDLM_INTENT,
         &RMF_MDT_BODY,     /* coincides with mds_getattr_name_client[] */
@@ -176,6 +206,7 @@ static const struct req_msg_field *ldlm_intent_getattr_client[] = {
 };
 
 static const struct req_msg_field *ldlm_intent_create_client[] = {
+        &RMF_PTLRPC_BODY,
         &RMF_DLM_REQ,
         &RMF_LDLM_INTENT,
         &RMF_REC_CREATE,    /* coincides with mds_reint_create_client[] */
@@ -184,6 +215,7 @@ static const struct req_msg_field *ldlm_intent_create_client[] = {
 };
 
 static const struct req_msg_field *ldlm_intent_open_client[] = {
+        &RMF_PTLRPC_BODY,
         &RMF_DLM_REQ,
         &RMF_LDLM_INTENT,
         &RMF_REC_CREATE,    /* coincides with mds_reint_open_client[] */
@@ -192,6 +224,7 @@ static const struct req_msg_field *ldlm_intent_open_client[] = {
 };
 
 static const struct req_msg_field *ldlm_intent_unlink_client[] = {
+        &RMF_PTLRPC_BODY,
         &RMF_DLM_REQ,
         &RMF_LDLM_INTENT,
         &RMF_REC_UNLINK,    /* coincides with mds_reint_unlink_client[] */
@@ -199,22 +232,26 @@ static const struct req_msg_field *ldlm_intent_unlink_client[] = {
 };
 
 static const struct req_msg_field *mds_getxattr_client[] = {
+        &RMF_PTLRPC_BODY,
         &RMF_MDT_BODY,
         &RMF_NAME
 };
 
 static const struct req_msg_field *mds_getxattr_server[] = {
+        &RMF_PTLRPC_BODY,
         &RMF_MDT_BODY,
         &RMF_EADATA
 };
 
 static const struct req_msg_field *mds_setxattr_client[] = {
+        &RMF_PTLRPC_BODY,
         &RMF_MDT_BODY,
         &RMF_NAME,
         &RMF_EADATA
 };
 
 static const struct req_msg_field *mds_getattr_server[] = {
+        &RMF_PTLRPC_BODY,
         &RMF_MDT_BODY,
         &RMF_MDT_MD,
         &RMF_ACL
@@ -303,6 +340,11 @@ const struct req_msg_field RMF_MDT_BODY =
                     sizeof(struct mdt_body), lustre_swab_mdt_body);
 EXPORT_SYMBOL(RMF_MDT_BODY);
 
+const struct req_msg_field RMF_PTLRPC_BODY =
+        DEFINE_MSGF("ptlrpc_body", 0,
+                    sizeof(struct ptlrpc_body), lustre_swab_ptlrpc_body);
+EXPORT_SYMBOL(RMF_PTLRPC_BODY);
+
 const struct req_msg_field RMF_OBD_STATFS =
         DEFINE_MSGF("obd_statfs", 0,
                     sizeof(struct obd_statfs), lustre_swab_obd_statfs);
@@ -364,7 +406,7 @@ EXPORT_SYMBOL(RMF_MDT_MD);
 
 const struct req_msg_field RMF_REC_UNLINK =
         DEFINE_MSGF("rec_unlink", 0, sizeof(struct mdt_rec_unlink),
-                    lustre_swab_mds_rec_unlink);
+                    lustre_swab_mdt_rec_unlink);
 EXPORT_SYMBOL(RMF_REC_UNLINK);
 
 const struct req_msg_field RMF_REC_LINK =
@@ -387,12 +429,12 @@ const struct req_msg_field RMF_REC_SETATTR =
                     lustre_swab_mdt_rec_setattr);
 EXPORT_SYMBOL(RMF_REC_SETATTR);
 
-/* FIXME: this length should be defined as a macro*/
+/* FIXME: this length should be defined as a macro */
 const struct req_msg_field RMF_EADATA = DEFINE_MSGF("eadata", 0, -1, NULL);
 EXPORT_SYMBOL(RMF_EADATA);
 
 const struct req_msg_field RMF_ACL = DEFINE_MSGF("acl", 0, 
-                                     LUSTRE_POSIX_ACL_MAX_SIZE, NULL);
+                                     __POSIX_ACL_MAX_SIZE, NULL);
 EXPORT_SYMBOL(RMF_ACL);
 
 const struct req_msg_field RMF_LOGCOOKIES =
@@ -731,7 +773,7 @@ static void *__req_capsule_get(struct req_capsule *pill,
                 DEBUG_REQ(D_ERROR, pill->rc_req,
                           "Wrong buffer for field `%s' (%d of %d) "
                           "in format `%s': %d vs. %d (%s)\n",
-                          field->rmf_name, offset, msg->bufcount, fmt->rf_name,
+                          field->rmf_name, offset, lustre_msg_bufcount(msg), fmt->rf_name,
                           lustre_msg_buflen(msg, offset), field->rmf_size,
                           rcl_names[loc]);
         return value;
@@ -827,7 +869,7 @@ int req_capsule_field_present(const struct req_capsule *pill,
 
         loc = pill->rc_loc ^ 1;
         offset = __req_capsule_offset(pill, field, loc);
-        return __req_msg(pill, loc)->bufcount > offset;
+        return lustre_msg_bufcount(__req_msg(pill, loc)) > offset;
 }
 EXPORT_SYMBOL(req_capsule_field_present);
 
index bcab551..27578a4 100644 (file)
@@ -53,10 +53,9 @@ static int llog_client_create(struct llog_ctxt *ctxt, struct llog_handle **res,
         struct llogd_body *body;
         struct llog_handle *handle;
         struct ptlrpc_request *req = NULL;
-        int size[2] = {sizeof(req_body)};
-        char *tmp[2] = {(char*) &req_body};
-        int bufcount = 1;
-        int repsize[] = {sizeof (req_body)};
+        int size[3] = { sizeof(struct ptlrpc_body), sizeof(req_body) };
+        char *bufs[3] = { NULL, (char*)&req_body };
+        int bufcount = 2;
         int rc;
         ENTRY;
 
@@ -81,21 +80,21 @@ static int llog_client_create(struct llog_ctxt *ctxt, struct llog_handle **res,
 
         if (name) {
                 size[bufcount] = strlen(name) + 1;
-                tmp[bufcount] = name;
+                bufs[bufcount] = name;
                 bufcount++;
         }
 
         req = ptlrpc_prep_req(imp, LUSTRE_LOG_VERSION,
-                              LLOG_ORIGIN_HANDLE_CREATE, bufcount, size, tmp);
+                              LLOG_ORIGIN_HANDLE_CREATE, bufcount, size, bufs);
         if (!req)
                 GOTO(err_free, rc = -ENOMEM);
 
-        req->rq_replen = lustre_msg_size(1, repsize);
+        ptlrpc_req_set_repsize(req, 2, size);
         rc = ptlrpc_queue_wait(req);
         if (rc)
                 GOTO(err_free, rc);
 
-        body = lustre_swab_repbuf(req, 0, sizeof(*body),
+        body = lustre_swab_repbuf(req, REPLY_REC_OFF, sizeof(*body),
                                  lustre_swab_llogd_body);
         if (body == NULL) {
                 CERROR ("Can't unpack llogd_body\n");
@@ -120,21 +119,20 @@ static int llog_client_destroy(struct llog_handle *loghandle)
         struct obd_import *imp = loghandle->lgh_ctxt->loc_imp;
         struct ptlrpc_request *req = NULL;
         struct llogd_body *body;
-        int size = sizeof(*body);
-        int repsize[2] = {sizeof (*body)};
+        int size[] = { sizeof(struct ptlrpc_body), sizeof(*body) };
         int rc;
         ENTRY;
 
         req = ptlrpc_prep_req(imp, LUSTRE_LOG_VERSION, 
-                              LLOG_ORIGIN_HANDLE_DESTROY, 1, &size, NULL);
+                              LLOG_ORIGIN_HANDLE_DESTROY, 2, size, NULL);
         if (!req)
                 RETURN(-ENOMEM);
 
-        body = lustre_msg_buf(req->rq_reqmsg, 0, sizeof (*body));
+        body = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, sizeof(*body));
         body->lgd_logid = loghandle->lgh_id;
         body->lgd_llh_flags = loghandle->lgh_hdr->llh_flags;
 
-        req->rq_replen = lustre_msg_size(1, repsize);
+        ptlrpc_req_set_repsize(req, 2, size);
         rc = ptlrpc_queue_wait(req);
         
         ptlrpc_req_finished(req);
@@ -150,17 +148,16 @@ static int llog_client_next_block(struct llog_handle *loghandle,
         struct ptlrpc_request *req = NULL;
         struct llogd_body *body;
         void * ptr;
-        int size = sizeof(*body);
-        int repsize[2] = {sizeof (*body)};
+        int size[3] = { sizeof(struct ptlrpc_body), sizeof(*body) };
         int rc;
         ENTRY;
 
         req = ptlrpc_prep_req(imp, LUSTRE_LOG_VERSION,
-                              LLOG_ORIGIN_HANDLE_NEXT_BLOCK, 1,&size,NULL);
+                              LLOG_ORIGIN_HANDLE_NEXT_BLOCK, 2, size, NULL);
         if (!req)
                 GOTO(out, rc = -ENOMEM);
 
-        body = lustre_msg_buf(req->rq_reqmsg, 0, sizeof (*body));
+        body = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, sizeof(*body));
         body->lgd_logid = loghandle->lgh_id;
         body->lgd_ctxt_idx = loghandle->lgh_ctxt->loc_idx - 1;
         body->lgd_llh_flags = loghandle->lgh_hdr->llh_flags;
@@ -168,14 +165,14 @@ static int llog_client_next_block(struct llog_handle *loghandle,
         body->lgd_saved_index = *cur_idx;
         body->lgd_len = len;
         body->lgd_cur_offset = *cur_offset;
-        repsize[1] = len;
 
-        req->rq_replen = lustre_msg_size(2, repsize);
+        size[REPLY_REC_OFF + 1] = len;
+        ptlrpc_req_set_repsize(req, 3, size);
         rc = ptlrpc_queue_wait(req);
         if (rc)
                 GOTO(out, rc);
 
-        body = lustre_swab_repbuf(req, 0, sizeof(*body),
+        body = lustre_swab_repbuf(req, REPLY_REC_OFF, sizeof(*body),
                                  lustre_swab_llogd_body);
         if (body == NULL) {
                 CERROR ("Can't unpack llogd_body\n");
@@ -183,7 +180,7 @@ static int llog_client_next_block(struct llog_handle *loghandle,
         }
 
         /* The log records are swabbed as they are processed */
-        ptr = lustre_msg_buf(req->rq_repmsg, 1, len);
+        ptr = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF + 1, len);
         if (ptr == NULL) {
                 CERROR ("Can't unpack bitmap\n");
                 GOTO(out, rc =-EFAULT);
@@ -207,37 +204,36 @@ static int llog_client_prev_block(struct llog_handle *loghandle,
         struct ptlrpc_request *req = NULL;
         struct llogd_body *body;
         void * ptr;
-        int size = sizeof(*body);
-        int repsize[2] = {sizeof (*body)};
+        int size[3] = { sizeof(struct ptlrpc_body), sizeof(*body) };
         int rc;
         ENTRY;
 
         req = ptlrpc_prep_req(imp, LUSTRE_LOG_VERSION,
-                              LLOG_ORIGIN_HANDLE_PREV_BLOCK, 1,&size,NULL);
+                              LLOG_ORIGIN_HANDLE_PREV_BLOCK, 2, size, NULL);
         if (!req)
                 GOTO(out, rc = -ENOMEM);
 
-        body = lustre_msg_buf(req->rq_reqmsg, 0, sizeof (*body));
+        body = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, sizeof(*body));
         body->lgd_logid = loghandle->lgh_id;
         body->lgd_ctxt_idx = loghandle->lgh_ctxt->loc_idx - 1;
         body->lgd_llh_flags = loghandle->lgh_hdr->llh_flags;
         body->lgd_index = prev_idx;
         body->lgd_len = len;
-        repsize[1] = len;
 
-        req->rq_replen = lustre_msg_size(2, repsize);
+        size[REPLY_REC_OFF + 1] = len;
+        ptlrpc_req_set_repsize(req, 3, size);
         rc = ptlrpc_queue_wait(req);
         if (rc)
                 GOTO(out, rc);
 
-        body = lustre_swab_repbuf(req, 0, sizeof(*body),
+        body = lustre_swab_repbuf(req, REPLY_REC_OFF, sizeof(*body),
                                  lustre_swab_llogd_body);
         if (body == NULL) {
                 CERROR ("Can't unpack llogd_body\n");
                 GOTO(out, rc =-EFAULT);
         }
 
-        ptr = lustre_msg_buf(req->rq_repmsg, 1, len);
+        ptr = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF + 1, len);
         if (ptr == NULL) {
                 CERROR ("Can't unpack bitmap\n");
                 GOTO(out, rc =-EFAULT);
@@ -258,27 +254,28 @@ static int llog_client_read_header(struct llog_handle *handle)
         struct llogd_body *body;
         struct llog_log_hdr *hdr;
         struct llog_rec_hdr *llh_hdr;
-        int size = sizeof(*body);
-        int repsize = sizeof (*hdr);
+        int size[2] = { sizeof(struct ptlrpc_body), sizeof(*body) };
+        int repsize[2] = { sizeof(struct ptlrpc_body), sizeof(*hdr) };
         int rc;
         ENTRY;
 
         req = ptlrpc_prep_req(imp, LUSTRE_LOG_VERSION,
-                              LLOG_ORIGIN_HANDLE_READ_HEADER, 1, &size, NULL);
+                              LLOG_ORIGIN_HANDLE_READ_HEADER, 2, size, NULL);
         if (!req)
                 GOTO(out, rc = -ENOMEM);
 
-        body = lustre_msg_buf(req->rq_reqmsg, 0, sizeof (*body));
+        body = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, sizeof(*body));
         body->lgd_logid = handle->lgh_id;
         body->lgd_ctxt_idx = handle->lgh_ctxt->loc_idx - 1;
         body->lgd_llh_flags = handle->lgh_hdr->llh_flags;
 
-        req->rq_replen = lustre_msg_size(1, &repsize);
+        ptlrpc_req_set_repsize(req, 2, repsize);
         rc = ptlrpc_queue_wait(req);
         if (rc)
                 GOTO(out, rc);
 
-        hdr = lustre_swab_repbuf(req, 0, sizeof(*hdr), lustre_swab_llog_hdr);
+        hdr = lustre_swab_repbuf(req, REPLY_REC_OFF, sizeof(*hdr),
+                                 lustre_swab_llog_hdr);
         if (hdr == NULL) {
                 CERROR ("Can't unpack llog_hdr\n");
                 GOTO(out, rc =-EFAULT);
index 735ed31..8702071 100644 (file)
@@ -55,7 +55,8 @@ int llog_origin_connect(struct llog_ctxt *ctxt, int count,
         struct obd_import *imp;
         struct ptlrpc_request *request;
         struct llogd_conn_body *req_body;
-        int size = sizeof(struct llogd_conn_body);
+        int size[2] = { sizeof(struct ptlrpc_body),
+                        sizeof(struct llogd_conn_body) };
         int rc;
         ENTRY;
 
@@ -83,16 +84,17 @@ int llog_origin_connect(struct llog_ctxt *ctxt, int count,
         imp = ctxt->loc_imp;
 
         request = ptlrpc_prep_req(imp, LUSTRE_LOG_VERSION,
-                                  LLOG_ORIGIN_CONNECT, 1, &size, NULL);
+                                  LLOG_ORIGIN_CONNECT, 2, size, NULL);
         if (!request)
                 RETURN(-ENOMEM);
 
-        req_body = lustre_msg_buf(request->rq_reqmsg, 0, sizeof(*req_body));
+        req_body = lustre_msg_buf(request->rq_reqmsg, REQ_REC_OFF,
+                                  sizeof(*req_body));
 
         req_body->lgdc_gen = ctxt->loc_gen;
         req_body->lgdc_logid = ctxt->loc_handle->lgh_id;
         req_body->lgdc_ctxt_idx = ctxt->loc_idx + 1;
-        request->rq_replen = lustre_msg_size(0, NULL);
+        ptlrpc_req_set_repsize(request, 1, NULL);
 
         rc = ptlrpc_queue_wait(request);
         ptlrpc_req_finished(request);
@@ -109,7 +111,8 @@ int llog_handle_connect(struct ptlrpc_request *req)
         int rc;
         ENTRY;
 
-        req_body = lustre_msg_buf(req->rq_reqmsg, 0, sizeof(*req_body));
+        req_body = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF,
+                                  sizeof(*req_body));
 
         ctxt = llog_get_context(obd, req_body->lgdc_ctxt_idx);
         rc = llog_connect(ctxt, 1, &req_body->lgdc_logid,
index cf588d3..a45208b 100644 (file)
@@ -55,11 +55,11 @@ int llog_origin_handle_create(struct ptlrpc_request *req)
         struct llog_logid *logid = NULL;
         struct llog_ctxt *ctxt;
         char * name = NULL;
-        int size = sizeof (*body);
+        int size[2] = { sizeof(struct ptlrpc_body), sizeof(*body) };
         int rc, rc2;
         ENTRY;
 
-        body = lustre_swab_reqbuf(req, 0, sizeof(*body),
+        body = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*body),
                                  lustre_swab_llogd_body);
         if (body == NULL) {
                 CERROR ("Can't unpack llogd_body\n");
@@ -69,8 +69,8 @@ int llog_origin_handle_create(struct ptlrpc_request *req)
         if (body->lgd_logid.lgl_oid > 0)
                 logid = &body->lgd_logid;
 
-        if (req->rq_reqmsg->bufcount > 1) {
-                name = lustre_msg_string(req->rq_reqmsg, 1, 0);
+        if (lustre_msg_bufcount(req->rq_reqmsg) > 2) {
+                name = lustre_msg_string(req->rq_reqmsg, REQ_REC_OFF + 1, 0);
                 if (name == NULL) {
                         CERROR("Can't unpack name\n");
                         GOTO(out, rc = -EFAULT);
@@ -88,11 +88,11 @@ int llog_origin_handle_create(struct ptlrpc_request *req)
         if (rc)
                 GOTO(out_pop, rc);
 
-        rc = lustre_pack_reply(req, 1, &size, NULL);
+        rc = lustre_pack_reply(req, 2, size, NULL);
         if (rc)
                 GOTO(out_close, rc = -ENOMEM);
 
-        body = lustre_msg_buf(req->rq_repmsg, 0, sizeof (*body));
+        body = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF, sizeof(*body));
         body->lgd_logid = loghandle->lgh_id;
 
 out_close:
@@ -115,12 +115,12 @@ int llog_origin_handle_destroy(struct ptlrpc_request *req)
         struct lvfs_run_ctxt saved;
         struct llog_logid *logid = NULL;
         struct llog_ctxt *ctxt;
-        int size = sizeof (*body);
+        int size[] = { sizeof(struct ptlrpc_body), sizeof(*body) };
         int rc;
         __u32 flags;
         ENTRY;
 
-        body = lustre_swab_reqbuf(req, 0, sizeof(*body),
+        body = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*body),
                                  lustre_swab_llogd_body);
         if (body == NULL) {
                 CERROR ("Can't unpack llogd_body\n");
@@ -140,11 +140,11 @@ int llog_origin_handle_destroy(struct ptlrpc_request *req)
         if (rc)
                 GOTO(out_pop, rc);
 
-        rc = lustre_pack_reply(req, 1, &size, NULL);
+        rc = lustre_pack_reply(req, 2, size, NULL);
         if (rc)
                 GOTO(out_close, rc = -ENOMEM);
 
-        body = lustre_msg_buf(req->rq_repmsg, 0, sizeof (*body));
+        body = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF, sizeof (*body));
         body->lgd_logid = loghandle->lgh_id;
         flags = body->lgd_llh_flags;
         rc = llog_init_handle(loghandle, LLOG_F_IS_PLAIN, NULL);
@@ -176,12 +176,13 @@ int llog_origin_handle_next_block(struct ptlrpc_request *req)
         __u32 flags;
         __u8 *buf;
         void * ptr;
-        int size[] = {sizeof (*body),
-                      LLOG_CHUNK_SIZE};
+        int size[3] = { sizeof(struct ptlrpc_body),
+                        sizeof(*body),
+                        LLOG_CHUNK_SIZE };
         int rc, rc2;
         ENTRY;
 
-        body = lustre_swab_reqbuf(req, 0, sizeof(*body),
+        body = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*body),
                                   lustre_swab_llogd_body);
         if (body == NULL) {
                 CERROR ("Can't unpack llogd_body\n");
@@ -194,7 +195,7 @@ int llog_origin_handle_next_block(struct ptlrpc_request *req)
 
         ctxt = llog_get_context(obd, body->lgd_ctxt_idx);
         if (ctxt == NULL)
-                GOTO(out, rc = -EINVAL);
+                GOTO(out_free, rc = -EINVAL);
         disk_obd = ctxt->loc_exp->exp_obd;
         push_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);
 
@@ -215,14 +216,14 @@ int llog_origin_handle_next_block(struct ptlrpc_request *req)
                 GOTO(out_close, rc);
 
 
-        rc = lustre_pack_reply(req, 2, size, NULL);
+        rc = lustre_pack_reply(req, 3, size, NULL);
         if (rc)
                 GOTO(out_close, rc = -ENOMEM);
 
-        ptr = lustre_msg_buf(req->rq_repmsg, 0, sizeof (body));
+        ptr = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF, sizeof (body));
         memcpy(ptr, body, sizeof(*body));
 
-        ptr = lustre_msg_buf(req->rq_repmsg, 1, LLOG_CHUNK_SIZE);
+        ptr = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF + 1, LLOG_CHUNK_SIZE);
         memcpy(ptr, buf, LLOG_CHUNK_SIZE);
 
 out_close:
@@ -232,6 +233,7 @@ out_close:
 
 out_pop:
         pop_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);
+out_free:
         OBD_FREE(buf, LLOG_CHUNK_SIZE);
 out:
         RETURN(rc);
@@ -249,12 +251,13 @@ int llog_origin_handle_prev_block(struct ptlrpc_request *req)
         __u32 flags;
         __u8 *buf;
         void * ptr;
-        int size[] = {sizeof (*body),
-                      LLOG_CHUNK_SIZE};
+        int size[] = { sizeof(struct ptlrpc_body),
+                       sizeof(*body),
+                       LLOG_CHUNK_SIZE };
         int rc, rc2;
         ENTRY;
 
-        body = lustre_swab_reqbuf(req, 0, sizeof(*body),
+        body = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*body),
                                   lustre_swab_llogd_body);
         if (body == NULL) {
                 CERROR ("Can't unpack llogd_body\n");
@@ -286,14 +289,14 @@ int llog_origin_handle_prev_block(struct ptlrpc_request *req)
                 GOTO(out_close, rc);
 
 
-        rc = lustre_pack_reply(req, 2, size, NULL);
+        rc = lustre_pack_reply(req, 3, size, NULL);
         if (rc)
                 GOTO(out_close, rc = -ENOMEM);
 
-        ptr = lustre_msg_buf(req->rq_repmsg, 0, sizeof (body));
+        ptr = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF, sizeof(body));
         memcpy(ptr, body, sizeof(*body));
 
-        ptr = lustre_msg_buf(req->rq_repmsg, 1, LLOG_CHUNK_SIZE);
+        ptr = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF+1, LLOG_CHUNK_SIZE);
         memcpy(ptr, buf, LLOG_CHUNK_SIZE);
 
 out_close:
@@ -319,11 +322,11 @@ int llog_origin_handle_read_header(struct ptlrpc_request *req)
         struct lvfs_run_ctxt saved;
         struct llog_ctxt *ctxt;
         __u32 flags;
-        int size[] = {sizeof (*hdr)};
+        int size[2] = { sizeof(struct ptlrpc_body), sizeof(*hdr) };
         int rc, rc2;
         ENTRY;
 
-        body = lustre_swab_reqbuf(req, 0, sizeof(*body),
+        body = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*body),
                                   lustre_swab_llogd_body);
         if (body == NULL) {
                 CERROR ("Can't unpack llogd_body\n");
@@ -346,11 +349,11 @@ int llog_origin_handle_read_header(struct ptlrpc_request *req)
         if (rc)
                 GOTO(out_close, rc);
 
-        rc = lustre_pack_reply(req, 1, size, NULL);
+        rc = lustre_pack_reply(req, 2, size, NULL);
         if (rc)
                 GOTO(out_close, rc = -ENOMEM);
 
-        hdr = lustre_msg_buf(req->rq_repmsg, 0, sizeof (*hdr));
+        hdr = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF, sizeof(*hdr));
         memcpy(hdr, loghandle->lgh_hdr, sizeof(*hdr));
 
 out_close:
@@ -387,8 +390,10 @@ int llog_origin_handle_cancel(struct ptlrpc_request *req)
         void *handle;
         ENTRY;
 
-        logcookies = lustre_msg_buf(req->rq_reqmsg, 0, sizeof(*logcookies));
-        num_cookies = req->rq_reqmsg->buflens[0]/sizeof(*logcookies);
+        logcookies = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF,
+                                    sizeof(*logcookies));
+        num_cookies = lustre_msg_buflen(req->rq_reqmsg, REQ_REC_OFF) /
+                      sizeof(*logcookies);
         if (logcookies == NULL || num_cookies == 0) {
                 DEBUG_REQ(D_HA, req, "no cookies sent");
                 RETURN(-EFAULT);
@@ -631,16 +636,18 @@ int llog_catinfo(struct ptlrpc_request *req)
         char *keyword;
         char *buf, *reply;
         int rc, buf_len = LLOG_CHUNK_SIZE;
+        int size[2] = { sizeof(struct ptlrpc_body), buf_len };
 
         OBD_ALLOC(buf, buf_len);
         if (buf == NULL)
                 return -ENOMEM;
         memset(buf, 0, buf_len);
 
-        keyword = lustre_msg_string(req->rq_reqmsg, 0, 0);
+        keyword = lustre_msg_string(req->rq_reqmsg, REQ_REC_OFF, 0);
 
         if (strcmp(keyword, "config") == 0) {
-                char *client = lustre_msg_string(req->rq_reqmsg, 1, 0);
+                char *client = lustre_msg_string(req->rq_reqmsg,
+                                                 REQ_REC_OFF + 1, 0);
                 rc = llog_catinfo_config(obd, buf, buf_len, client);
         } else if (strcmp(keyword, "deletions") == 0) {
                 rc = llog_catinfo_deletions(obd, buf, buf_len);
@@ -648,11 +655,11 @@ int llog_catinfo(struct ptlrpc_request *req)
                 rc = -EOPNOTSUPP;
         }
 
-        rc = lustre_pack_reply(req, 1, &buf_len, NULL);
+        rc = lustre_pack_reply(req, 2, size, NULL);
         if (rc)
                 GOTO(out_free, rc = -ENOMEM);
 
-        reply = lustre_msg_buf(req->rq_repmsg, 0, buf_len);
+        reply = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF, buf_len);
         if (strlen(buf) == 0)
                 sprintf(buf, "%s", "No log informations\n");
         memcpy(reply, buf, buf_len);
index aa92378..88aad1a 100644 (file)
@@ -58,7 +58,7 @@ struct ll_rpc_opcode {
         { OST_QUOTACHECK,   "ost_quotacheck" },
         { OST_QUOTACTL,     "ost_quotactl" },
         { MDS_GETATTR,      "mds_getattr" },
-        { MDS_GETATTR_NAME, "mds_getattr_name" },
+        { MDS_GETATTR_NAME, "mds_getattr_lock" },
         { MDS_CLOSE,        "mds_close" },
         { MDS_REINT,        "mds_reint" },
         { MDS_READPAGE,     "mds_readpage" },
@@ -184,7 +184,6 @@ ptlrpc_lprocfs_write_req_history_max(struct file *file, const char *buffer,
 {
         struct ptlrpc_service *svc = data;
         int                    bufpages;
-        unsigned long          flags;
         int                    val;
         int                    rc = lprocfs_write_helper(buffer, count, &val);
 
@@ -201,9 +200,9 @@ ptlrpc_lprocfs_write_req_history_max(struct file *file, const char *buffer,
         if (val > num_physpages/(2*bufpages))
                 return -ERANGE;
 
-        spin_lock_irqsave(&svc->srv_lock, flags);
+        spin_lock(&svc->srv_lock);
         svc->srv_max_history_rqbds = val;
-        spin_unlock_irqrestore(&svc->srv_lock, flags);
+        spin_unlock(&svc->srv_lock);
 
         return count;
 }
@@ -257,7 +256,6 @@ ptlrpc_lprocfs_svc_req_history_start(struct seq_file *s, loff_t *pos)
 {
         struct ptlrpc_service       *svc = s->private;
         struct ptlrpc_srh_iterator  *srhi;
-        unsigned long                flags;
         int                          rc;
 
         OBD_ALLOC(srhi, sizeof(*srhi));
@@ -267,9 +265,9 @@ ptlrpc_lprocfs_svc_req_history_start(struct seq_file *s, loff_t *pos)
         srhi->srhi_seq = 0;
         srhi->srhi_req = NULL;
 
-        spin_lock_irqsave(&svc->srv_lock, flags);
+        spin_lock(&svc->srv_lock);
         rc = ptlrpc_lprocfs_svc_req_history_seek(svc, srhi, *pos);
-        spin_unlock_irqrestore(&svc->srv_lock, flags);
+        spin_unlock(&svc->srv_lock);
 
         if (rc == 0) {
                 *pos = srhi->srhi_seq;
@@ -295,12 +293,11 @@ ptlrpc_lprocfs_svc_req_history_next(struct seq_file *s,
 {
         struct ptlrpc_service       *svc = s->private;
         struct ptlrpc_srh_iterator  *srhi = iter;
-        unsigned long                flags;
         int                          rc;
 
-        spin_lock_irqsave(&svc->srv_lock, flags);
+        spin_lock(&svc->srv_lock);
         rc = ptlrpc_lprocfs_svc_req_history_seek(svc, srhi, *pos + 1);
-        spin_unlock_irqrestore(&svc->srv_lock, flags);
+        spin_unlock(&svc->srv_lock);
 
         if (rc != 0) {
                 OBD_FREE(srhi, sizeof(*srhi));
@@ -316,10 +313,9 @@ static int ptlrpc_lprocfs_svc_req_history_show(struct seq_file *s, void *iter)
         struct ptlrpc_service      *svc = s->private;
         struct ptlrpc_srh_iterator *srhi = iter;
         struct ptlrpc_request      *req;
-        unsigned long               flags;
         int                         rc;
 
-        spin_lock_irqsave(&svc->srv_lock, flags);
+        spin_lock(&svc->srv_lock);
 
         rc = ptlrpc_lprocfs_svc_req_history_seek(svc, srhi, srhi->srhi_seq);
 
@@ -343,7 +339,7 @@ static int ptlrpc_lprocfs_svc_req_history_show(struct seq_file *s, void *iter)
                         svc->srv_request_history_print_fn(s, srhi->srhi_req);
         }
 
-        spin_unlock_irqrestore(&svc->srv_lock, flags);
+        spin_unlock(&svc->srv_lock);
 
         return rc;
 }
@@ -422,7 +418,7 @@ EXPORT_SYMBOL(ptlrpc_lprocfs_register_obd);
 void ptlrpc_lprocfs_rpc_sent(struct ptlrpc_request *req)
 {
         struct lprocfs_stats *svc_stats;
-        int opc =  opcode_offset(req->rq_reqmsg->opc);
+        int opc = opcode_offset(lustre_msg_get_opc(req->rq_reqmsg));
 
         svc_stats = req->rq_import->imp_obd->obd_svc_stats;
         if (svc_stats == NULL || opc <= 0)
@@ -480,11 +476,11 @@ int lprocfs_wr_ping(struct file *file, const char *buffer,
         ENTRY;
 
         req = ptlrpc_prep_req(obd->u.cli.cl_import, LUSTRE_OBD_VERSION,
-                              OBD_PING, 0, NULL, NULL);
+                              OBD_PING, 1, NULL, NULL);
         if (req == NULL)
                 RETURN(-ENOMEM);
 
-        req->rq_replen = lustre_msg_size(0, NULL);
+        ptlrpc_req_set_repsize(req, 1, NULL);
         req->rq_send_state = LUSTRE_IMP_FULL;
         req->rq_no_resend = 1;
 
index b05c5a3..53fac91 100644 (file)
@@ -318,7 +318,7 @@ int ptlrpc_send_reply (struct ptlrpc_request *req, int may_be_difficult)
         LASSERT (rs != NULL);
         LASSERT (req->rq_repmsg != NULL);
         LASSERT (may_be_difficult || !rs->rs_difficult);
-        LASSERT (req->rq_repmsg == &rs->rs_msg);
+        LASSERT (req->rq_repmsg == rs->rs_msg);
         LASSERT (rs->rs_cb_id.cbid_fn == reply_out_callback);
         LASSERT (rs->rs_cb_id.cbid_arg == rs);
         LASSERT (req->rq_repmsg != NULL);
@@ -335,9 +335,9 @@ int ptlrpc_send_reply (struct ptlrpc_request *req, int may_be_difficult)
         if (req->rq_type != PTL_RPC_MSG_ERR)
                 req->rq_type = PTL_RPC_MSG_REPLY;
 
-        req->rq_repmsg->type   = req->rq_type;
-        req->rq_repmsg->status = req->rq_status;
-        req->rq_repmsg->opc    = req->rq_reqmsg->opc;
+        lustre_msg_set_type(req->rq_repmsg, req->rq_type);
+        lustre_msg_set_status(req->rq_repmsg, req->rq_status);
+        lustre_msg_set_opc(req->rq_repmsg, lustre_msg_get_opc(req->rq_reqmsg));
 
         if (req->rq_export == NULL || req->rq_export->exp_connection == NULL)
                 conn = ptlrpc_get_connection(req->rq_peer, req->rq_self, NULL);
@@ -374,14 +374,14 @@ int ptlrpc_error(struct ptlrpc_request *req)
         ENTRY;
 
         if (!req->rq_repmsg) {
-                rc = lustre_pack_reply(req, 0, NULL, NULL);
+                rc = lustre_pack_reply(req, 1, NULL, NULL);
                 if (rc)
                         RETURN(rc);
         }
 
         req->rq_type = PTL_RPC_MSG_ERR;
 
-        rc = ptlrpc_send_reply (req, 0);
+        rc = ptlrpc_send_reply(req, 0);
         RETURN(rc);
 }
 
@@ -390,7 +390,6 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply)
         int rc;
         int rc2;
         struct ptlrpc_connection *connection;
-        unsigned long flags;
         lnet_handle_me_t  reply_me_h;
         lnet_md_t         reply_md;
         ENTRY;
@@ -420,9 +419,11 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply)
                         RETURN(rc);
         }
 
-        request->rq_reqmsg->handle = request->rq_import->imp_remote_handle;
-        request->rq_reqmsg->type = PTL_RPC_MSG_REQUEST;
-        request->rq_reqmsg->conn_cnt = request->rq_import->imp_conn_cnt;
+        lustre_msg_set_handle(request->rq_reqmsg,
+                              &request->rq_import->imp_remote_handle);
+        lustre_msg_set_type(request->rq_reqmsg, PTL_RPC_MSG_REQUEST);
+        lustre_msg_set_conn_cnt(request->rq_reqmsg,
+                                request->rq_import->imp_conn_cnt);
 
         if (!noreply) {
                 LASSERT (request->rq_replen != 0);
@@ -441,7 +442,7 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply)
                 }
         }
 
-        spin_lock_irqsave (&request->rq_lock, flags);
+        spin_lock(&request->rq_lock);
         /* If the MD attach succeeds, there _will_ be a reply_in callback */
         request->rq_receiving_reply = !noreply;
         /* Clear any flags that may be present from previous sends. */
@@ -451,7 +452,7 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply)
         request->rq_net_err = 0;
         request->rq_resend = 0;
         request->rq_restart = 0;
-        spin_unlock_irqrestore (&request->rq_lock, flags);
+        spin_unlock(&request->rq_lock);
 
         if (!noreply) {
                 reply_md.start     = request->rq_repmsg;
@@ -466,10 +467,10 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply)
                 if (rc != 0) {
                         CERROR("LNetMDAttach failed: %d\n", rc);
                         LASSERT (rc == -ENOMEM);
-                        spin_lock_irqsave (&request->rq_lock, flags);
+                        spin_lock(&request->rq_lock);
                         /* ...but the MD attach didn't succeed... */
                         request->rq_receiving_reply = 0;
-                        spin_unlock_irqrestore (&request->rq_lock, flags);
+                        spin_unlock(&request->rq_lock);
                         GOTO(cleanup_me, rc -ENOMEM);
                 }
 
@@ -500,7 +501,7 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply)
 
          /* drop request_out_callback refs, we couldn't start the send */
         atomic_dec(&request->rq_import->imp_inflight);
-        ptlrpc_req_finished (request);
+        ptlrpc_req_finished(request);
 
         if (noreply)
                 RETURN(rc);
index b30e12f..49e571c 100644 (file)
 #include <obd_class.h>
 #include <lustre_net.h>
 
+#if LUSTRE_VERSION_CODE > OBD_OCD_VERSION(2,0,0,0)
+#error "lustre_msg_v1 has been deprecated since 1.6.0, please remove it"
+#elif LUSTRE_VERSION_CODE > OBD_OCD_VERSION(1,6,7,0)
+#warning "lustre_msg_v1 has been deprecated since 1.6.0, consider removing it"
+#endif
+
+static inline int lustre_msg_hdr_size_v1(int count)
+{
+        return size_round(offsetof(struct lustre_msg_v1, lm_buflens[count]));
+}
 
-#define HDR_SIZE(count) \
-    size_round(offsetof (struct lustre_msg, buflens[(count)]))
+static inline int lustre_msg_hdr_size_v2(int count)
+{
+        return size_round(offsetof(struct lustre_msg_v2, lm_buflens[count]));
+}
 
 int lustre_msg_swabbed(struct lustre_msg *msg)
 {
-        return (msg->magic == __swab32(PTLRPC_MSG_MAGIC));
+        return (msg->lm_magic == LUSTRE_MSG_MAGIC_V1_SWABBED) ||
+               (msg->lm_magic == LUSTRE_MSG_MAGIC_V2_SWABBED);
 }
 
-int lustre_msg_check_version(struct lustre_msg *msg, __u32 version)
+static inline int
+lustre_msg_check_version_v2(struct lustre_msg_v2 *msg, __u32 version)
 {
-        __u32 msgversion = msg->version;
+        __u32 ver = lustre_msg_get_version(msg);
+
         if (lustre_msg_swabbed(msg))
-                __swab32s(&msgversion);
+                 return (__swab32(ver) & LUSTRE_VERSION_MASK) != version;
 
-        return (msgversion & LUSTRE_VERSION_MASK) != version;
+        return (ver & LUSTRE_VERSION_MASK) != version;
+}
+
+int lustre_msg_check_version(struct lustre_msg *msg, __u32 version)
+{
+        switch (msg->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+        case LUSTRE_MSG_MAGIC_V1_SWABBED:
+                return 0;
+        case LUSTRE_MSG_MAGIC_V2:
+        case LUSTRE_MSG_MAGIC_V2_SWABBED:
+                return lustre_msg_check_version_v2(msg, version);
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic);
+                return -EINVAL;
+        }
+}
+
+static inline int lustre_msg_size_v1(int count, int *lengths)
+{
+        int size;
+        int i;
+
+        LASSERT(count >= 0);
+        size = lustre_msg_hdr_size_v1(count);
+        for (i = 0; i < count; i++)
+                size += size_round(lengths[i]);
+
+        return size;
+}
+
+static inline int lustre_msg_size_v2(int count, int *lengths)
+{
+        int size;
+        int i;
+
+        size = lustre_msg_hdr_size_v2(count);
+        for (i = 0; i < count; i++)
+                size += size_round(lengths[i]);
+
+        return size;
+}
+
+/* This returns the size of the buffer that is required to hold a lustre_msg
+ * with the given sub-buffer lengths. */
+int lustre_msg_size(__u32 magic, int count, int *lens)
+{
+        int size[] = { sizeof(struct ptlrpc_body) };
+
+        if (!lens) {
+                LASSERT(count == 1);
+                lens = size;
+        }
+
+        LASSERT(count > 0);
+        LASSERT(lens[MSG_PTLRPC_BODY_OFF] == sizeof(struct ptlrpc_body));
+
+        switch (magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+                return lustre_msg_size_v1(count - 1, lens + 1);
+        case LUSTRE_MSG_MAGIC_V2:
+                return lustre_msg_size_v2(count, lens);
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n", magic);
+                return -EINVAL;
+        }
 }
 
 static void
-lustre_init_msg (struct lustre_msg *msg,
-                 int count, const int *lens, char **bufs)
+lustre_init_msg_v1(void *m, int count, int *lens, char **bufs)
 {
+        struct lustre_msg_v1 *msg = (struct lustre_msg_v1 *)m;
         char *ptr;
-        int   i;
+        int i;
+
+        LASSERT(count >= 0);
+        msg->lm_magic = LUSTRE_MSG_MAGIC_V1;
+        msg->lm_version = PTLRPC_MSG_VERSION;
+        msg->lm_bufcount = count;
 
-        msg->magic = PTLRPC_MSG_MAGIC;
-        msg->version = PTLRPC_MSG_VERSION;
-        msg->bufcount = count;
         for (i = 0; i < count; i++)
-                msg->buflens[i] = lens[i];
+                msg->lm_buflens[i] = lens[i];
 
         if (bufs == NULL)
                 return;
 
-        ptr = (char *)msg + HDR_SIZE(count);
+        ptr = (char *)msg + lustre_msg_hdr_size_v1(count);
         for (i = 0; i < count; i++) {
                 char *tmp = bufs[i];
                 LOGL(tmp, lens[i], ptr);
         }
 }
 
-int lustre_pack_request (struct ptlrpc_request *req,
-                         int count, const int *lens, char **bufs)
+static void
+lustre_init_msg_v2(struct lustre_msg_v2 *msg, int count, int *lens, char **bufs)
+{
+        char *ptr;
+        int i;
+
+        msg->lm_bufcount = count;
+        /* XXX: lm_secflvr uninitialized here */
+        msg->lm_magic = LUSTRE_MSG_MAGIC_V2;
+
+        for (i = 0; i < count; i++)
+                msg->lm_buflens[i] = lens[i];
+
+        if (bufs == NULL)
+                return;
+
+        ptr = (char *)msg + lustre_msg_hdr_size_v2(count);
+        for (i = 0; i < count; i++) {
+                char *tmp = bufs[i];
+                LOGL(tmp, lens[i], ptr);
+        }
+}
+
+static int lustre_pack_request_v1(struct ptlrpc_request *req,
+                                  int count, int *lens, char **bufs)
 {
         int reqlen;
-        ENTRY;
 
-        reqlen = lustre_msg_size (count, lens);
+        reqlen = lustre_msg_size_v1(count, lens);
+
         /* See if we got it from prealloc pool */
         if (req->rq_reqmsg) {
                 /* Cannot return error here, that would create
@@ -98,13 +203,74 @@ int lustre_pack_request (struct ptlrpc_request *req,
                 memset(req->rq_reqmsg, 0, reqlen);
         } else {
                 OBD_ALLOC(req->rq_reqmsg, reqlen);
-                if (req->rq_reqmsg == NULL)
-                        RETURN(-ENOMEM);
+                if (req->rq_reqmsg == NULL) {
+                        CERROR("alloc reqmsg (len %d) failed\n", reqlen);
+                        return -ENOMEM;
+                }
         }
+
         req->rq_reqlen = reqlen;
 
-        lustre_init_msg (req->rq_reqmsg, count, lens, bufs);
-        RETURN (0);
+        lustre_init_msg_v1(req->rq_reqmsg, count, lens, bufs);
+        return 0;
+}
+
+static int lustre_pack_request_v2(struct ptlrpc_request *req,
+                                  int count, int *lens, char **bufs)
+{
+        int reqlen;
+
+        reqlen = lustre_msg_size_v2(count, lens);
+
+        /* See if we got it from prealloc pool */
+        if (req->rq_reqmsg) {
+                /* Cannot return error here, that would create
+                   infinite loop in ptlrpc_prep_req_pool */
+                /* In this case ptlrpc_prep_req_from_pool sets req->rq_reqlen
+                   to maximum size that would fit into this preallocated
+                   request */
+                LASSERTF(req->rq_reqlen >= reqlen, "req->rq_reqlen %d, "
+                                                   "reqlen %d\n",req->rq_reqlen,
+                                                    reqlen);
+                memset(req->rq_reqmsg, 0, reqlen);
+        } else {
+                OBD_ALLOC(req->rq_reqmsg, reqlen);
+                if (req->rq_reqmsg == NULL) {
+                        CERROR("alloc reqmsg (len %d) failed\n", reqlen);
+                        return -ENOMEM;
+                }
+        }
+
+        req->rq_reqlen = reqlen;
+
+        lustre_init_msg_v2(req->rq_reqmsg, count, lens, bufs);
+        lustre_msg_add_version(req->rq_reqmsg, PTLRPC_MSG_VERSION);
+        return 0;
+}
+
+int lustre_pack_request(struct ptlrpc_request *req, __u32 magic, int count,
+                        int *lens, char **bufs)
+{
+        int size[] = { sizeof(struct ptlrpc_body) };
+
+        if (!lens) {
+                LASSERT(count == 1);
+                lens = size;
+        }
+
+        LASSERT(count > 0);
+        LASSERT(lens[MSG_PTLRPC_BODY_OFF] == sizeof(struct ptlrpc_body));
+
+        switch (magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+                return lustre_pack_request_v1(req, count - 1, lens + 1,
+                                              bufs ? bufs + 1 : NULL);
+        case LUSTRE_MSG_MAGIC_V2:
+                return lustre_pack_request_v2(req, count, lens, bufs);
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n", magic);
+                return -EINVAL;
+        }
 }
 
 #if RS_DEBUG
@@ -113,20 +279,16 @@ spinlock_t ptlrpc_rs_debug_lock;
 
 #define PTLRPC_RS_DEBUG_LRU_ADD(rs)                                     \
 do {                                                                    \
-        unsigned long __flags;                                          \
-                                                                        \
-        spin_lock_irqsave(&ptlrpc_rs_debug_lock, __flags);              \
+        spin_lock(&ptlrpc_rs_debug_lock);                               \
         list_add_tail(&(rs)->rs_debug_list, &ptlrpc_rs_debug_lru);      \
-        spin_unlock_irqrestore(&ptlrpc_rs_debug_lock, __flags);         \
+        spin_unlock(&ptlrpc_rs_debug_lock);                             \
 } while (0)
 
-#define PTLRPC_RS_DEBUG_LRU_DEL(rs)                                     \
-do {                                                                    \
-        unsigned long __flags;                                          \
-                                                                        \
-        spin_lock_irqsave(&ptlrpc_rs_debug_lock, __flags);              \
-        list_del(&(rs)->rs_debug_list);                                 \
-        spin_unlock_irqrestore(&ptlrpc_rs_debug_lock, __flags);         \
+#define PTLRPC_RS_DEBUG_LRU_DEL(rs)             \
+do {                                            \
+        spin_lock(&ptlrpc_rs_debug_lock);       \
+        list_del(&(rs)->rs_debug_list);         \
+        spin_unlock(&ptlrpc_rs_debug_lock);     \
 } while (0)
 #else
 # define PTLRPC_RS_DEBUG_LRU_ADD(rs) do {} while(0)
@@ -136,15 +298,14 @@ do {                                                                    \
 static struct ptlrpc_reply_state *lustre_get_emerg_rs(struct ptlrpc_service *svc,
                                                       int size)
 {
-        unsigned long flags;
         struct ptlrpc_reply_state *rs = NULL;
 
-        spin_lock_irqsave(&svc->srv_lock, flags);
+        spin_lock(&svc->srv_lock);
         /* See if we have anything in a pool, and wait if nothing */
         while (list_empty(&svc->srv_free_rs_list)) {
                 struct l_wait_info lwi;
                 int rc;
-                spin_unlock_irqrestore(&svc->srv_lock, flags);
+                spin_unlock(&svc->srv_lock);
                 /* If we cannot get anything for some long time, we better
                    bail out instead of waiting infinitely */
                 lwi = LWI_TIMEOUT(cfs_time_seconds(10), NULL, NULL);
@@ -152,13 +313,13 @@ static struct ptlrpc_reply_state *lustre_get_emerg_rs(struct ptlrpc_service *svc
                                   !list_empty(&svc->srv_free_rs_list), &lwi);
                 if (rc)
                         goto out;
-                spin_lock_irqsave(&svc->srv_lock, flags);
+                spin_lock(&svc->srv_lock);
         }
 
         rs = list_entry(svc->srv_free_rs_list.next, struct ptlrpc_reply_state,
                         rs_list);
         list_del(&rs->rs_list);
-        spin_unlock_irqrestore(&svc->srv_lock, flags);
+        spin_unlock(&svc->srv_lock);
         LASSERT(rs);
         LASSERTF(svc->srv_max_reply_size > size, "Want %d, prealloc %d\n", size,
                  svc->srv_max_reply_size);
@@ -168,352 +329,1221 @@ out:
         return rs;
 }
 
+static int lustre_pack_reply_v1(struct ptlrpc_request *req, int count,
+                                int *lens, char **bufs)
+{
+        struct ptlrpc_reply_state *rs;
+        int                        msg_len;
+        int                        size;
+        ENTRY;
+
+        LASSERT (req->rq_reply_state == NULL);
+
+        msg_len = lustre_msg_size_v1(count, lens);
+        size = sizeof(struct ptlrpc_reply_state) + msg_len;
+        OBD_ALLOC(rs, size);
+        if (unlikely(rs == NULL)) {
+                rs = lustre_get_emerg_rs(req->rq_rqbd->rqbd_service, size);
+                if (!rs)
+                        RETURN (-ENOMEM);
+        }
+        atomic_set(&rs->rs_refcount, 1);        /* 1 ref for rq_reply_state */
+        rs->rs_cb_id.cbid_fn = reply_out_callback;
+        rs->rs_cb_id.cbid_arg = rs;
+        rs->rs_service = req->rq_rqbd->rqbd_service;
+        rs->rs_size = size;
+        CFS_INIT_LIST_HEAD(&rs->rs_exp_list);
+        CFS_INIT_LIST_HEAD(&rs->rs_obd_list);
+        rs->rs_msg = (struct lustre_msg *)(rs + 1);
+
+        req->rq_replen = msg_len;
+        req->rq_reply_state = rs;
+        req->rq_repmsg = rs->rs_msg;
+        lustre_init_msg_v1(rs->rs_msg, count, lens, bufs);
+
+        PTLRPC_RS_DEBUG_LRU_ADD(rs);
+
+        RETURN (0);
+}
+
+static int lustre_pack_reply_v2(struct ptlrpc_request *req, int count,
+                                int *lens, char **bufs)
+{
+        struct ptlrpc_reply_state *rs;
+        int                        msg_len;
+        int                        size;
+        ENTRY;
+
+        LASSERT(req->rq_reply_state == NULL);
+
+        msg_len = lustre_msg_size_v2(count, lens);
+        size = sizeof(struct ptlrpc_reply_state) + msg_len;
+        OBD_ALLOC(rs, size);
+        if (unlikely(rs == NULL)) {
+                rs = lustre_get_emerg_rs(req->rq_rqbd->rqbd_service, size);
+                if (!rs)
+                        RETURN (-ENOMEM);
+        }
+        atomic_set(&rs->rs_refcount, 1);        /* 1 ref for rq_reply_state */
+        rs->rs_cb_id.cbid_fn = reply_out_callback;
+        rs->rs_cb_id.cbid_arg = rs;
+        rs->rs_service = req->rq_rqbd->rqbd_service;
+        rs->rs_size = size;
+        CFS_INIT_LIST_HEAD(&rs->rs_exp_list);
+        CFS_INIT_LIST_HEAD(&rs->rs_obd_list);
+        rs->rs_msg = (struct lustre_msg *)(rs + 1);
+
+        req->rq_replen = msg_len;
+        req->rq_reply_state = rs;
+        req->rq_repmsg = rs->rs_msg;
+        lustre_init_msg_v2(rs->rs_msg, count, lens, bufs);
+        lustre_msg_add_version(rs->rs_msg, PTLRPC_MSG_VERSION);
+
+        PTLRPC_RS_DEBUG_LRU_ADD(rs);
+
+        RETURN(0);
+}
+
+int lustre_pack_reply(struct ptlrpc_request *req, int count, int *lens,
+                      char **bufs)
+{
+        int size[] = { sizeof(struct ptlrpc_body) };
+
+        if (!lens) {
+                LASSERT(count == 1);
+                lens = size;
+        }
+
+        LASSERT(count > 0);
+        LASSERT(lens[MSG_PTLRPC_BODY_OFF] == sizeof(struct ptlrpc_body));
+
+        switch (req->rq_reqmsg->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+        case LUSTRE_MSG_MAGIC_V1_SWABBED:
+                return lustre_pack_reply_v1(req, count - 1, lens + 1,
+                                            bufs ? bufs + 1 : NULL);
+        case LUSTRE_MSG_MAGIC_V2:
+        case LUSTRE_MSG_MAGIC_V2_SWABBED:
+                return lustre_pack_reply_v2(req, count, lens, bufs);
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n",
+                         req->rq_reqmsg->lm_magic);
+                return -EINVAL;
+        }
+}
+
+void *lustre_msg_buf_v1(void *msg, int n, int min_size)
+{
+        struct lustre_msg_v1 *m = (struct lustre_msg_v1 *)msg;
+        int i, offset, buflen, bufcount;
+
+        LASSERT(m != NULL);
+        LASSERT(n >= 0);
+
+        bufcount = m->lm_bufcount;
+        if (n >= bufcount) {
+                CDEBUG(D_INFO, "msg %p buffer[%d] not present (count %d)\n",
+                       m, n, bufcount);
+                return NULL;
+        }
+
+        buflen = m->lm_buflens[n];
+        if (buflen < min_size) {
+                CERROR("msg %p buffer[%d] size %d too small (required %d)\n",
+                       m, n, buflen, min_size);
+                LBUG();
+                return NULL;
+        }
+
+        offset = lustre_msg_hdr_size_v1(bufcount);
+        for (i = 0; i < n; i++)
+                offset += size_round(m->lm_buflens[i]);
+
+        return (char *)m + offset;
+}
+
+void *lustre_msg_buf_v2(struct lustre_msg_v2 *m, int n, int min_size)
+{
+        int i, offset, buflen, bufcount;
+
+        LASSERT(m != NULL);
+        LASSERT(n >= 0);
+
+        bufcount = m->lm_bufcount;
+        if (n >= bufcount) {
+                CDEBUG(D_INFO, "msg %p buffer[%d] not present (count %d)\n",
+                       m, n, bufcount);
+                return NULL;
+        }
+
+        buflen = m->lm_buflens[n];
+        if (buflen < min_size) {
+                CERROR("msg %p buffer[%d] size %d too small (required %d)\n",
+                       m, n, buflen, min_size);
+                return NULL;
+        }
+
+        offset = lustre_msg_hdr_size_v2(bufcount);
+        for (i = 0; i < n; i++)
+                offset += size_round(m->lm_buflens[i]);
+
+        return (char *)m + offset;
+}
+
+void *lustre_msg_buf(struct lustre_msg *m, int n, int min_size)
+{
+        switch (m->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+        case LUSTRE_MSG_MAGIC_V1_SWABBED:
+                return lustre_msg_buf_v1(m, n - 1, min_size);
+        case LUSTRE_MSG_MAGIC_V2:
+        case LUSTRE_MSG_MAGIC_V2_SWABBED:
+                return lustre_msg_buf_v2(m, n, min_size);
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n", m->lm_magic);
+                return NULL;
+        }
+}
+
+void lustre_shrink_reply_v1(struct ptlrpc_request *req, int segment,
+                            unsigned int newlen, int move_data)
+{
+        struct lustre_msg_v1 *msg = (struct lustre_msg_v1 *)req->rq_repmsg;
+        char *tail = NULL, *newpos;
+        int tail_len = 0, n;
+
+        LASSERT(req->rq_reply_state);
+        LASSERT(msg);
+        LASSERT(segment >= 0);
+        LASSERT(msg->lm_bufcount > segment);
+        LASSERT(msg->lm_buflens[segment] >= newlen);
+
+        if (msg->lm_buflens[segment] == newlen)
+                return;
+
+        if (move_data && msg->lm_bufcount > segment + 1) {
+                tail = lustre_msg_buf_v1(msg, segment + 1, 0);
+                for (n = segment + 1; n < msg->lm_bufcount; n++)
+                        tail_len += size_round(msg->lm_buflens[n]);
+        }
+
+        msg->lm_buflens[segment] = newlen;
+
+        if (tail && tail_len) {
+                newpos = lustre_msg_buf_v1(msg, segment + 1, 0);
+                LASSERT(newpos <= tail);
+                if (newpos != tail)
+                        memcpy(newpos, tail, tail_len);
+        }
+
+        if (newlen == 0 && msg->lm_bufcount > segment + 1) {
+                memmove(&msg->lm_buflens[segment], &msg->lm_buflens[segment + 1],
+                        (msg->lm_bufcount - segment - 1) * sizeof(__u32));
+                msg->lm_buflens[msg->lm_bufcount - 1] = 0;
+        }
+
+        req->rq_replen = lustre_msg_size_v1(msg->lm_bufcount, msg->lm_buflens);
+}
+
+void lustre_shrink_reply_v2(struct ptlrpc_request *req, int segment,
+                            unsigned int newlen, int move_data)
+{
+        struct lustre_msg_v2 *msg = req->rq_repmsg;
+        char *tail = NULL, *newpos;
+        int tail_len = 0, n;
+
+        LASSERT(req->rq_reply_state);
+        LASSERT(msg);
+        LASSERT(msg->lm_bufcount > segment);
+        LASSERT(msg->lm_buflens[segment] >= newlen);
+
+        if (msg->lm_buflens[segment] == newlen)
+                return;
+
+        if (move_data && msg->lm_bufcount > segment + 1) {
+                tail = lustre_msg_buf_v2(msg, segment + 1, 0);
+                for (n = segment + 1; n < msg->lm_bufcount; n++)
+                        tail_len += size_round(msg->lm_buflens[n]);
+        }
+
+        msg->lm_buflens[segment] = newlen;
+
+        if (tail && tail_len) {
+                newpos = lustre_msg_buf_v2(msg, segment + 1, 0);
+                LASSERT(newpos <= tail);
+                if (newpos != tail)
+                        memcpy(newpos, tail, tail_len);
+        }
+
+        if (newlen == 0 && msg->lm_bufcount > segment + 1) {
+                memmove(&msg->lm_buflens[segment], &msg->lm_buflens[segment + 1],
+                        (msg->lm_bufcount - segment - 1) * sizeof(__u32));
+                msg->lm_buflens[msg->lm_bufcount - 1] = 0;
+        }
+
+        req->rq_replen = lustre_msg_size_v2(msg->lm_bufcount, msg->lm_buflens);
+}
+
+/*
+ * shrink @segment to size @newlen. if @move_data is non-zero, we also move
+ * data forward from @segment + 1.
+ * 
+ * if @newlen == 0, we remove the segment completely, but we still keep the
+ * totally bufcount the same to save possible data moving. this will leave a
+ * unused segment with size 0 at the tail, but that's ok.
+ *
+ * CAUTION:
+ * + if any buffers higher than @segment has been filled in, must call shrink
+ *   with non-zero @move_data.
+ * + caller should NOT keep pointers to msg buffers which higher than @segment
+ *   after call shrink.
+ */
+void lustre_shrink_reply(struct ptlrpc_request *req, int segment,
+                        unsigned int newlen, int move_data)
+{
+        switch (req->rq_repmsg->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+                lustre_shrink_reply_v1(req, segment - 1, newlen, move_data);
+                return;
+        case LUSTRE_MSG_MAGIC_V2:
+                lustre_shrink_reply_v2(req, segment, newlen, move_data);
+                return;
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n",
+                         req->rq_repmsg->lm_magic);
+        }
+}
+
+void lustre_free_reply_state(struct ptlrpc_reply_state *rs)
+{
+        PTLRPC_RS_DEBUG_LRU_DEL(rs);
+
+        LASSERT (atomic_read(&rs->rs_refcount) == 0);
+        LASSERT (!rs->rs_difficult || rs->rs_handled);
+        LASSERT (!rs->rs_on_net);
+        LASSERT (!rs->rs_scheduled);
+        LASSERT (rs->rs_export == NULL);
+        LASSERT (rs->rs_nlocks == 0);
+        LASSERT (list_empty(&rs->rs_exp_list));
+        LASSERT (list_empty(&rs->rs_obd_list));
+
+        if (unlikely(rs->rs_prealloc)) {
+                struct ptlrpc_service *svc = rs->rs_service;
+
+                spin_lock(&svc->srv_lock);
+                list_add(&rs->rs_list,
+                         &svc->srv_free_rs_list);
+                spin_unlock(&svc->srv_lock);
+                cfs_waitq_signal(&svc->srv_free_rs_waitq);
+        } else {
+                OBD_FREE(rs, rs->rs_size);
+        }
+}
+
+int lustre_unpack_msg_v1(void *msg, int len)
+{
+        struct lustre_msg_v1 *m = (struct lustre_msg_v1 *)msg;
+        int flipped, required_len, i;
+        ENTRY;
+
+        /* Now we know the sender speaks my language. */
+        required_len = lustre_msg_hdr_size_v1(0);
+        if (len < required_len) {
+                /* can't even look inside the message */
+                CERROR("message length %d too small for lustre_msg\n", len);
+                RETURN(-EINVAL);
+        }
+
+        flipped = lustre_msg_swabbed((struct lustre_msg *)m);
+
+        if (flipped) {
+                __swab32s(&m->lm_type);
+                __swab32s(&m->lm_version);
+                __swab32s(&m->lm_opc);
+                __swab64s(&m->lm_last_xid);
+                __swab64s(&m->lm_last_committed);
+                __swab64s(&m->lm_transno);
+                __swab32s(&m->lm_status);
+                __swab32s(&m->lm_flags);
+                __swab32s(&m->lm_conn_cnt);
+                __swab32s(&m->lm_bufcount);
+        }
+
+        if (m->lm_version != PTLRPC_MSG_VERSION) {
+                CERROR("wrong lustre_msg version %08x\n", m->lm_version);
+                RETURN(-EINVAL);
+        }
+
+        required_len = lustre_msg_hdr_size_v1(m->lm_bufcount);
+        if (len < required_len) {
+                /* didn't receive all the buffer lengths */
+                CERROR("message length %d too small for %d buflens\n",
+                        len, m->lm_bufcount);
+                RETURN(-EINVAL);
+        }
+
+        for (i = 0; i < m->lm_bufcount; i++) {
+                if (flipped)
+                        __swab32s (&m->lm_buflens[i]);
+                required_len += size_round(m->lm_buflens[i]);
+        }
+
+        if (len < required_len) {
+                CERROR("len: %d, required_len %d\n", len, required_len);
+                CERROR("bufcount: %d\n", m->lm_bufcount);
+                for (i = 0; i < m->lm_bufcount; i++)
+                        CERROR("buffer %d length %d\n", i, m->lm_buflens[i]);
+                RETURN(-EINVAL);
+        }
+
+        RETURN(0);
+}
+
+static int lustre_unpack_msg_v2(struct lustre_msg_v2 *m, int len)
+{
+        int flipped, required_len, i;
+
+        required_len = lustre_msg_hdr_size_v2(m->lm_bufcount);
+        if (len < required_len) {
+                /* didn't receive all the buffer lengths */
+                CERROR ("message length %d too small for %d buflens\n",
+                        len, m->lm_bufcount);
+                return -EINVAL;
+        }
+
+        flipped = lustre_msg_swabbed(m);
+
+        if (flipped) {
+                __swab32s(&m->lm_bufcount);
+                __swab32s(&m->lm_secflvr);
+                __swab32s(&m->lm_repsize);
+        }
+
+        for (i = 0; i < m->lm_bufcount; i++) {
+                if (flipped)
+                        __swab32s(&m->lm_buflens[i]);
+                required_len += size_round(m->lm_buflens[i]);
+        }
+
+        if (len < required_len) {
+                CERROR("len: %d, required_len %d\n", len, required_len);
+                CERROR("bufcount: %d\n", m->lm_bufcount);
+                for (i = 0; i < m->lm_bufcount; i++)
+                        CERROR("buffer %d length %d\n", i, m->lm_buflens[i]);
+                return -EINVAL;
+        }
+
+        return 0;
+}
+
+int lustre_unpack_msg(struct lustre_msg *m, int len)
+{
+        int required_len, rc;
+        ENTRY;
+
+        /* We can provide a slightly better error log, if we check the
+         * message magic and version first.  In the future, struct
+         * lustre_msg may grow, and we'd like to log a version mismatch,
+         * rather than a short message.
+         *
+         */
+        required_len = offsetof(struct lustre_msg, lm_magic) +
+                       sizeof(m->lm_magic);
+        if (len < required_len) {
+                /* can't even look inside the message */
+                CERROR("message length %d too small for magic/version check\n",
+                       len);
+                RETURN(-EINVAL);
+        }
+
+        switch (m->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+        case LUSTRE_MSG_MAGIC_V1_SWABBED:
+                rc = lustre_unpack_msg_v1(m, len);
+                break;
+        case LUSTRE_MSG_MAGIC_V2:
+        case LUSTRE_MSG_MAGIC_V2_SWABBED:
+                rc = lustre_unpack_msg_v2(m, len);
+                break;
+        default:
+                CERROR("bad lustre msg magic: %#08X\n", m->lm_magic);
+                return -EINVAL;
+        }
+
+        RETURN(rc);
+}
+
+static inline int lustre_unpack_ptlrpc_body_v2(struct lustre_msg_v2 *m)
+{
+        struct ptlrpc_body *pb;
+
+        pb = lustre_swab_buf(m, MSG_PTLRPC_BODY_OFF, sizeof(*pb),
+                             lustre_swab_ptlrpc_body);
+        if (!pb) {
+                CERROR("error unpacking ptlrpc body");
+                return -EFAULT;
+        }
+
+        if ((pb->pb_version & ~LUSTRE_VERSION_MASK) != PTLRPC_MSG_VERSION) {
+                 CERROR("wrong lustre_msg version %08x\n", pb->pb_version);
+                 return -EINVAL;
+         }
+
+        return 0;
+}
+
+int lustre_unpack_ptlrpc_body(struct lustre_msg *m)
+{
+        switch (m->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+        case LUSTRE_MSG_MAGIC_V1_SWABBED:
+                return 0;
+        case LUSTRE_MSG_MAGIC_V2:
+        case LUSTRE_MSG_MAGIC_V2_SWABBED:
+                return lustre_unpack_ptlrpc_body_v2(m);
+        default:
+                CERROR("bad lustre msg magic: %#08X\n", m->lm_magic);
+                return -EINVAL;
+        }
+}
+
+static inline int lustre_msg_buflen_v1(void *msg, int n)
+{
+        struct lustre_msg_v1 *m = (struct lustre_msg_v1 *)msg;
+
+        LASSERT(n >= 0);
+        if (n >= m->lm_bufcount)
+                return 0;
+
+        return m->lm_buflens[n];
+}
+
+static inline int lustre_msg_buflen_v2(struct lustre_msg_v2 *m, int n)
+{
+        if (n >= m->lm_bufcount)
+                return 0;
+
+        return m->lm_buflens[n];
+}
+
+/**
+ * lustre_msg_buflen - return the length of buffer @n in message @m
+ * @m - lustre_msg (request or reply) to look at
+ * @n - message index (base 0)
+ *
+ * returns zero for non-existent message indices
+ */
+int lustre_msg_buflen(struct lustre_msg *m, int n)
+{
+        switch (m->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+        case LUSTRE_MSG_MAGIC_V1_SWABBED:
+                return lustre_msg_buflen_v1(m, n - 1);
+        case LUSTRE_MSG_MAGIC_V2:
+        case LUSTRE_MSG_MAGIC_V2_SWABBED:
+                return lustre_msg_buflen_v2(m, n);
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n", m->lm_magic);
+                return -EINVAL;
+        }
+}
+EXPORT_SYMBOL(lustre_msg_buflen);
+
+static inline void lustre_msg_set_buflen_v1(void *msg, int n, int len)
+{
+        struct lustre_msg_v1 *m = (struct lustre_msg_v1 *)msg;
+
+        LASSERT(n >= 0);
+        if (n >= m->lm_bufcount)
+                LBUG();
+
+        m->lm_buflens[n] = len;
+}
+
+static inline int
+lustre_msg_set_buflen_v2(struct lustre_msg_v2 *m, int n, int len)
+{
+        if (n >= m->lm_bufcount)
+                LBUG();
+
+        m->lm_buflens[n] = len;
+}
+
+void lustre_msg_set_buflen(struct lustre_msg *m, int n, int len)
+{
+        switch (m->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+        case LUSTRE_MSG_MAGIC_V1_SWABBED:
+                lustre_msg_set_buflen_v1(m, n - 1, len);
+                return;
+        case LUSTRE_MSG_MAGIC_V2:
+        case LUSTRE_MSG_MAGIC_V2_SWABBED:
+                lustre_msg_set_buflen_v2(m, n, len);
+                return;
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n", m->lm_magic);
+        }
+}
+
+EXPORT_SYMBOL(lustre_msg_set_buflen);
+
+/* NB return the bufcount for lustre_msg_v2 format, so if message is packed
+ * in V1 format, the result is one bigger. (add struct ptlrpc_body). */
+int lustre_msg_bufcount(struct lustre_msg *m)
+{
+        switch (m->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+        case LUSTRE_MSG_MAGIC_V1_SWABBED:
+                return ((struct lustre_msg_v1 *)m)->lm_bufcount + 1;
+        case LUSTRE_MSG_MAGIC_V2:
+        case LUSTRE_MSG_MAGIC_V2_SWABBED:
+                return m->lm_bufcount;
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n", m->lm_magic);
+                return -EINVAL;
+        }
+}
+EXPORT_SYMBOL(lustre_msg_bufcount);
+
+char *lustre_msg_string(struct lustre_msg *m, int index, int max_len)
+{
+        /* max_len == 0 means the string should fill the buffer */
+        char *str;
+        int slen, blen;
+
+        switch (m->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+        case LUSTRE_MSG_MAGIC_V1_SWABBED:
+                str = lustre_msg_buf_v1(m, index - 1, 0);
+                blen = lustre_msg_buflen_v1(m, index - 1);
+                break;
+        case LUSTRE_MSG_MAGIC_V2:
+        case LUSTRE_MSG_MAGIC_V2_SWABBED:
+                str = lustre_msg_buf_v2(m, index, 0);
+                blen = lustre_msg_buflen_v2(m, index);
+                break;
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n", m->lm_magic);
+        }
+
+        if (str == NULL) {
+                CERROR ("can't unpack string in msg %p buffer[%d]\n", m, index);
+                return NULL;
+        }
+
+        slen = strnlen(str, blen);
+
+        if (slen == blen) {                     /* not NULL terminated */
+                CERROR("can't unpack non-NULL terminated string in "
+                        "msg %p buffer[%d] len %d\n", m, index, blen);
+                return NULL;
+        }
+
+        if (max_len == 0) {
+                if (slen != blen - 1) {
+                        CERROR("can't unpack short string in msg %p "
+                               "buffer[%d] len %d: strlen %d\n",
+                               m, index, blen, slen);
+                        return NULL;
+                }
+        } else if (slen > max_len) {
+                CERROR("can't unpack oversized string in msg %p "
+                       "buffer[%d] len %d strlen %d: max %d expected\n",
+                       m, index, blen, slen, max_len);
+                return NULL;
+        }
+
+        return str;
+}
+
+/* Wrap up the normal fixed length cases */
+void *lustre_swab_buf(struct lustre_msg *msg, int index, int min_size,
+                      void *swabber)
+{
+        void *ptr;
+
+        switch (msg->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+        case LUSTRE_MSG_MAGIC_V1_SWABBED:
+                ptr = lustre_msg_buf_v1(msg, index - 1, min_size);
+                break;
+        case LUSTRE_MSG_MAGIC_V2:
+        case LUSTRE_MSG_MAGIC_V2_SWABBED:
+                ptr = lustre_msg_buf_v2(msg, index, min_size);
+                break;
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic);
+        }
+        if (ptr == NULL)
+                return NULL;
+
+        if (swabber != NULL && lustre_msg_swabbed(msg))
+                ((void (*)(void *))swabber)(ptr);
+
+        return ptr;
+}
+
+void *lustre_swab_reqbuf(struct ptlrpc_request *req, int index, int min_size,
+                         void *swabber)
+{
+        LASSERT_REQSWAB(req, index);
+        return lustre_swab_buf(req->rq_reqmsg, index, min_size, swabber);
+}
+
+void *lustre_swab_repbuf(struct ptlrpc_request *req, int index, int min_size,
+                         void *swabber)
+{
+        LASSERT_REPSWAB(req, index);
+        return lustre_swab_buf(req->rq_repmsg, index, min_size, swabber);
+}
+
+__u32 lustre_msg_get_flags(struct lustre_msg *msg)
+{
+        switch (msg->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+        case LUSTRE_MSG_MAGIC_V1_SWABBED:
+                return ((struct lustre_msg_v1 *)msg)->lm_flags &
+                       MSG_GEN_FLAG_MASK;
+        case LUSTRE_MSG_MAGIC_V2:
+        case LUSTRE_MSG_MAGIC_V2_SWABBED: {
+                struct ptlrpc_body *pb;
+
+                pb = lustre_msg_buf_v2(msg, MSG_PTLRPC_BODY_OFF, sizeof(*pb));
+                LASSERTF(pb, "invalid msg %p: no ptlrpc body!\n", msg);
+                return pb->pb_flags;
+        }
+        default:
+                /* flags might be printed in debug code while message
+                 * uninitialized */
+                return 0;
+        }
+}
+
+void lustre_msg_add_flags(struct lustre_msg *msg, int flags)
+{
+        switch (msg->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+                ((struct lustre_msg_v1 *)msg)->lm_flags |=
+                                        MSG_GEN_FLAG_MASK & flags;
+                return;
+        case LUSTRE_MSG_MAGIC_V2: {
+                struct ptlrpc_body *pb;
+
+                pb = lustre_msg_buf_v2(msg, MSG_PTLRPC_BODY_OFF, sizeof(*pb));
+                LASSERTF(pb, "invalid msg %p: no ptlrpc body!\n", msg);
+                pb->pb_flags |= flags;
+                return;
+        }
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic);
+        }
+}
 
-int lustre_pack_reply (struct ptlrpc_request *req,
-                       int count, const int *lens, char **bufs)
+void lustre_msg_set_flags(struct lustre_msg *msg, int flags)
 {
-        struct ptlrpc_reply_state *rs;
-        int                        msg_len;
-        int                        size;
-        ENTRY;
-
-        LASSERT (req->rq_reply_state == NULL);
+        switch (msg->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+                ((struct lustre_msg_v1 *)msg)->lm_flags &= ~MSG_GEN_FLAG_MASK;
+                ((struct lustre_msg_v1 *)msg)->lm_flags |=
+                                        MSG_GEN_FLAG_MASK & flags;
+                return;
+        case LUSTRE_MSG_MAGIC_V2: {
+                struct ptlrpc_body *pb;
 
-        msg_len = lustre_msg_size (count, lens);
-        size = offsetof (struct ptlrpc_reply_state, rs_msg) + msg_len;
-        OBD_ALLOC (rs, size);
-        if (unlikely(rs == NULL)) {
-                rs = lustre_get_emerg_rs(req->rq_rqbd->rqbd_service, size);
-                if (!rs)
-                        RETURN (-ENOMEM);
+                pb = lustre_msg_buf_v2(msg, MSG_PTLRPC_BODY_OFF, sizeof(*pb));
+                LASSERTF(pb, "invalid msg %p: no ptlrpc body!\n", msg);
+                pb->pb_flags = flags;
+                return;
         }
-        atomic_set(&rs->rs_refcount, 1);        /* 1 ref for rq_reply_state */
-        rs->rs_cb_id.cbid_fn = reply_out_callback;
-        rs->rs_cb_id.cbid_arg = rs;
-        rs->rs_service = req->rq_rqbd->rqbd_service;
-        rs->rs_size = size;
-        CFS_INIT_LIST_HEAD(&rs->rs_exp_list);
-        CFS_INIT_LIST_HEAD(&rs->rs_obd_list);
-
-        req->rq_replen = msg_len;
-        req->rq_reply_state = rs;
-        req->rq_repmsg = &rs->rs_msg;
-        lustre_init_msg (&rs->rs_msg, count, lens, bufs);
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic);
+        }
+}
 
-        PTLRPC_RS_DEBUG_LRU_ADD(rs);
+void lustre_msg_clear_flags(struct lustre_msg *msg, int flags)
+{
+        switch (msg->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+        case LUSTRE_MSG_MAGIC_V1_SWABBED:
+                ((struct lustre_msg_v1 *)msg)->lm_flags &=
+                                        ~(MSG_GEN_FLAG_MASK & flags);
+                return;
+        case LUSTRE_MSG_MAGIC_V2:
+        case LUSTRE_MSG_MAGIC_V2_SWABBED: {
+                struct ptlrpc_body *pb;
 
-        RETURN (0);
+                pb = lustre_msg_buf_v2(msg, MSG_PTLRPC_BODY_OFF, sizeof(*pb));
+                LASSERTF(pb, "invalid msg %p: no ptlrpc body!\n", msg);
+                pb->pb_flags = 0;
+                return;
+        }
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic);
+        }
 }
 
-/*
- * shrink @segment to size @newlen. if @move_data is non-zero, we also move
- * data forward from @segment + 1.
- *
- * if @newlen == 0, we remove the segment completely, but we still keep the
- * totally bufcount the same to save possible data moving. this will leave a
- * unused segment with size 0 at the tail, but that's ok.
- *
- * CAUTION:
- * + if any buffers higher than @segment has been filled in, must call shrink
- *   with non-zero @move_data.
- * + caller should NOT keep pointers to msg buffers which higher than @segment
- *   after call shrink.
- */
-void lustre_shrink_reply(struct ptlrpc_request *req,
-                         int segment, unsigned int newlen, int move_data)
+__u32 lustre_msg_get_op_flags(struct lustre_msg *msg)
 {
-        struct lustre_msg *msg = req->rq_repmsg;
-        char              *tail = NULL, *newpos;
-        int                tail_len = 0, n;
+        switch (msg->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+        case LUSTRE_MSG_MAGIC_V1_SWABBED:
+                return ((struct lustre_msg_v1 *)msg)->lm_flags >>
+                       MSG_OP_FLAG_SHIFT;
+        case LUSTRE_MSG_MAGIC_V2:
+        case LUSTRE_MSG_MAGIC_V2_SWABBED: {
+                struct ptlrpc_body *pb;
 
-        LASSERT(req->rq_reply_state);
-        LASSERT(msg);
-        LASSERT(msg->bufcount > segment);
-        LASSERT(msg->buflens[segment] >= newlen);
+                pb = lustre_msg_buf_v2(msg, MSG_PTLRPC_BODY_OFF, sizeof(*pb));
+                LASSERTF(pb, "invalid msg %p: no ptlrpc body!\n", msg);
+                return pb->pb_op_flags;
+        }
+        default:
+                return 0;
+        }
+}
 
-        if (msg->buflens[segment] == newlen)
+void lustre_msg_add_op_flags(struct lustre_msg *msg, int flags)
+{
+        switch (msg->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+                ((struct lustre_msg_v1 *)msg)->lm_flags |=
+                        (flags & MSG_GEN_FLAG_MASK) << MSG_OP_FLAG_SHIFT;
                 return;
+        case LUSTRE_MSG_MAGIC_V2: {
+                struct ptlrpc_body *pb;
 
-        if (move_data && msg->bufcount > segment + 1) {
-                tail = lustre_msg_buf(msg, segment + 1, 0);
-                for (n = segment + 1; n < msg->bufcount; n++)
-                        tail_len += size_round(msg->buflens[n]);
+                pb = lustre_msg_buf_v2(msg, MSG_PTLRPC_BODY_OFF, sizeof(*pb));
+                LASSERTF(pb, "invalid msg %p: no ptlrpc body!\n", msg);
+                pb->pb_op_flags |= flags;
+                return;
+        }
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic);
         }
+}
 
-        msg->buflens[segment] = newlen;
+void lustre_msg_set_op_flags(struct lustre_msg *msg, int flags)
+{
+        switch (msg->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+                ((struct lustre_msg_v1 *)msg)->lm_flags &= ~MSG_OP_FLAG_MASK;
+                ((struct lustre_msg_v1 *)msg)->lm_flags |=
+                        ((flags & MSG_GEN_FLAG_MASK) <<MSG_OP_FLAG_SHIFT);
+                return;
+        case LUSTRE_MSG_MAGIC_V2: {
+                struct ptlrpc_body *pb;
 
-        if (tail && tail_len) {
-                newpos = lustre_msg_buf(msg, segment + 1, 0);
-                LASSERT(newpos <= tail);
-                if (newpos != tail)
-                        memcpy(newpos, tail, tail_len);
+                pb = lustre_msg_buf_v2(msg, MSG_PTLRPC_BODY_OFF, sizeof(*pb));
+                LASSERTF(pb, "invalid msg %p: no ptlrpc body!\n", msg);
+                pb->pb_op_flags |= flags;
+                return;
         }
-
-        if (newlen == 0 && msg->bufcount > segment + 1) {
-                memmove(&msg->buflens[segment], &msg->buflens[segment + 1],
-                        (msg->bufcount - segment - 1) * sizeof(__u32));
-                msg->buflens[msg->bufcount - 1] = 0;
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic);
         }
-
-        req->rq_replen = lustre_msg_size(msg->bufcount, msg->buflens);
 }
 
-void lustre_free_reply_state (struct ptlrpc_reply_state *rs)
+struct lustre_handle *lustre_msg_get_handle(struct lustre_msg *msg)
 {
-        PTLRPC_RS_DEBUG_LRU_DEL(rs);
+        switch (msg->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+        case LUSTRE_MSG_MAGIC_V1_SWABBED:
+                return &((struct lustre_msg_v1 *)msg)->lm_handle;
+        case LUSTRE_MSG_MAGIC_V2:
+        case LUSTRE_MSG_MAGIC_V2_SWABBED: {
+                struct ptlrpc_body *pb;
 
-        LASSERT (atomic_read(&rs->rs_refcount) == 0);
-        LASSERT (!rs->rs_difficult || rs->rs_handled);
-        LASSERT (!rs->rs_on_net);
-        LASSERT (!rs->rs_scheduled);
-        LASSERT (rs->rs_export == NULL);
-        LASSERT (rs->rs_nlocks == 0);
-        LASSERT (list_empty(&rs->rs_exp_list));
-        LASSERT (list_empty(&rs->rs_obd_list));
+                pb = lustre_msg_buf_v2(msg, MSG_PTLRPC_BODY_OFF, sizeof(*pb));
+                LASSERTF(pb, "invalid msg %p: no ptlrpc body!\n", msg);
+                return &pb->pb_handle;
+        }
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic);
+                return NULL;
+        }
+}
 
-        if (unlikely(rs->rs_prealloc)) {
-                unsigned long flags;
-                struct ptlrpc_service *svc = rs->rs_service;
+__u32 lustre_msg_get_type(struct lustre_msg *msg)
+{
+        switch (msg->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+        case LUSTRE_MSG_MAGIC_V1_SWABBED:
+                return ((struct lustre_msg_v1 *)msg)->lm_type;
+        case LUSTRE_MSG_MAGIC_V2:
+        case LUSTRE_MSG_MAGIC_V2_SWABBED: {
+                struct ptlrpc_body *pb;
 
-                spin_lock_irqsave(&svc->srv_lock, flags);
-                list_add(&rs->rs_list,
-                         &svc->srv_free_rs_list);
-                spin_unlock_irqrestore(&svc->srv_lock, flags);
-                cfs_waitq_signal(&svc->srv_free_rs_waitq);
-        } else {
-                OBD_FREE(rs, rs->rs_size);
+                pb = lustre_msg_buf_v2(msg, MSG_PTLRPC_BODY_OFF, sizeof(*pb));
+                LASSERTF(pb, "invalid msg %p: no ptlrpc body!\n", msg);
+                return pb->pb_type;
+        }
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic);
+                return 0;
         }
 }
 
-/* This returns the size of the buffer that is required to hold a lustre_msg
- * with the given sub-buffer lengths. */
-int lustre_msg_size(int count, const int *lengths)
+__u32 lustre_msg_get_version(struct lustre_msg *msg)
 {
-        int size;
-        int i;
-
-        size = HDR_SIZE (count);
-        for (i = 0; i < count; i++)
-                size += size_round(lengths[i]);
+        switch (msg->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+        case LUSTRE_MSG_MAGIC_V1_SWABBED:
+                return ((struct lustre_msg_v1 *)msg)->lm_version;
+        case LUSTRE_MSG_MAGIC_V2:
+        case LUSTRE_MSG_MAGIC_V2_SWABBED: {
+                struct ptlrpc_body *pb;
 
-        return size;
+                pb = lustre_msg_buf_v2(msg, MSG_PTLRPC_BODY_OFF, sizeof(*pb));
+                LASSERTF(pb, "invalid msg %p: no ptlrpc body!\n", msg);
+                return pb->pb_version;
+        }
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic);
+                return 0;
+        }
 }
 
-int lustre_unpack_msg(struct lustre_msg *m, int len)
+void lustre_msg_add_version(struct lustre_msg *msg, int version)
 {
-        int   flipped;
-        int   required_len;
-        int   i;
-        ENTRY;
+        switch (msg->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+        case LUSTRE_MSG_MAGIC_V1_SWABBED:
+                return;
+        case LUSTRE_MSG_MAGIC_V2:
+        case LUSTRE_MSG_MAGIC_V2_SWABBED: {
+                struct ptlrpc_body *pb;
 
-        /* We can provide a slightly better error log, if we check the
-         * message magic and version first.  In the future, struct
-         * lustre_msg may grow, and we'd like to log a version mismatch,
-         * rather than a short message.
-         *
-         */
-        required_len = MAX (offsetof (struct lustre_msg, version) +
-                            sizeof (m->version),
-                            offsetof (struct lustre_msg, magic) +
-                            sizeof (m->magic));
-        if (len < required_len) {
-                /* can't even look inside the message */
-                CERROR ("message length %d too small for magic/version check\n",
-                        len);
-                RETURN (-EINVAL);
+                pb = lustre_msg_buf_v2(msg, MSG_PTLRPC_BODY_OFF, sizeof(*pb));
+                LASSERTF(pb, "invalid msg %p: no ptlrpc body!\n", msg);
+                pb->pb_version |= version;
+                return;
         }
-
-        flipped = lustre_msg_swabbed(m);
-        if (flipped)
-                __swab32s (&m->version);
-        else if (m->magic != PTLRPC_MSG_MAGIC) {
-                CERROR("wrong lustre_msg magic %#08x\n", m->magic);
-                RETURN (-EINVAL);
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic);
         }
+}
 
-        if ((m->version & ~LUSTRE_VERSION_MASK) != PTLRPC_MSG_VERSION) {
-                CERROR("wrong lustre_msg version %#08x\n", m->version);
-                RETURN (-EINVAL);
-        }
+__u32 lustre_msg_get_opc(struct lustre_msg *msg)
+{
+        switch (msg->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+        case LUSTRE_MSG_MAGIC_V1_SWABBED:
+                return ((struct lustre_msg_v1 *)msg)->lm_opc;
+        case LUSTRE_MSG_MAGIC_V2:
+        case LUSTRE_MSG_MAGIC_V2_SWABBED: {
+                struct ptlrpc_body *pb;
 
-        /* Now we know the sender speaks my language (but possibly flipped)...*/
-        required_len = HDR_SIZE(0);
-        if (len < required_len) {
-                /* can't even look inside the message */
-                CERROR ("message length %d too small for lustre_msg\n", len);
-                RETURN (-EINVAL);
+                pb = lustre_msg_buf_v2(msg, MSG_PTLRPC_BODY_OFF, sizeof(*pb));
+                LASSERTF(pb, "invalid msg %p: no ptlrpc body!\n", msg);
+                return pb->pb_opc;
         }
-
-        if (flipped) {
-                __swab32s (&m->type);
-                __swab32s (&m->opc);
-                __swab64s (&m->last_xid);
-                __swab64s (&m->last_committed);
-                __swab64s (&m->transno);
-                __swab32s (&m->status);
-                __swab32s (&m->flags);
-                __swab32s (&m->conn_cnt);
-                __swab32s (&m->bufcount);
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic);
+                return 0;
         }
+}
 
-        required_len = HDR_SIZE(m->bufcount);
+__u64 lustre_msg_get_last_xid(struct lustre_msg *msg)
+{
+        switch (msg->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+        case LUSTRE_MSG_MAGIC_V1_SWABBED:
+                return ((struct lustre_msg_v1 *)msg)->lm_last_xid;
+        case LUSTRE_MSG_MAGIC_V2:
+        case LUSTRE_MSG_MAGIC_V2_SWABBED: {
+                struct ptlrpc_body *pb;
 
-        if (len < required_len) {
-                /* didn't receive all the buffer lengths */
-                CERROR ("message length %d too small for %d buflens\n",
-                        len, m->bufcount);
-                RETURN(-EINVAL);
+                pb = lustre_msg_buf_v2(msg, MSG_PTLRPC_BODY_OFF, sizeof(*pb));
+                LASSERTF(pb, "invalid msg %p: no ptlrpc body!\n", msg);
+                return pb->pb_last_xid;
         }
-
-        for (i = 0; i < m->bufcount; i++) {
-                if (flipped)
-                        __swab32s (&m->buflens[i]);
-                required_len += size_round(m->buflens[i]);
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic);
+                return 0;
         }
+}
 
-        if (len < required_len) {
-                CERROR("len: %d, required_len %d\n", len, required_len);
-                CERROR("bufcount: %d\n", m->bufcount);
-                for (i = 0; i < m->bufcount; i++)
-                        CERROR("buffer %d length %d\n", i, m->buflens[i]);
-                RETURN(-EINVAL);
-        }
+__u64 lustre_msg_get_last_committed(struct lustre_msg *msg)
+{
+        switch (msg->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+        case LUSTRE_MSG_MAGIC_V1_SWABBED:
+                return ((struct lustre_msg_v1 *)msg)->lm_last_committed;
+        case LUSTRE_MSG_MAGIC_V2:
+        case LUSTRE_MSG_MAGIC_V2_SWABBED: {
+                struct ptlrpc_body *pb;
 
-        RETURN(0);
+                pb = lustre_msg_buf_v2(msg, MSG_PTLRPC_BODY_OFF, sizeof(*pb));
+                LASSERTF(pb, "invalid msg %p: no ptlrpc body!\n", msg);
+                return pb->pb_last_committed;
+        }
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic);
+                return 0;
+        }
 }
 
-/**
- * lustre_msg_buflen - return the length of buffer @n in message @m
- * @m - lustre_msg (request or reply) to look at
- * @n - message index (base 0)
- *
- * returns zero for non-existent message indices
- */
-int lustre_msg_buflen(struct lustre_msg *m, int n)
+__u64 lustre_msg_get_transno(struct lustre_msg *msg)
 {
-        if (n >= m->bufcount)
-                return 0;
+        switch (msg->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+        case LUSTRE_MSG_MAGIC_V1_SWABBED:
+                return ((struct lustre_msg_v1 *)msg)->lm_transno;
+        case LUSTRE_MSG_MAGIC_V2:
+        case LUSTRE_MSG_MAGIC_V2_SWABBED: {
+                struct ptlrpc_body *pb;
 
-        return m->buflens[n];
+                pb = lustre_msg_buf_v2(msg, MSG_PTLRPC_BODY_OFF, sizeof(*pb));
+                LASSERTF(pb, "invalid msg %p: no ptlrpc body!\n", msg);
+                return pb->pb_transno;
+        }
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic);
+                return 0;
+        }
 }
-EXPORT_SYMBOL(lustre_msg_buflen);
 
-void *lustre_msg_buf(struct lustre_msg *m, int n, int min_size)
+__u32 lustre_msg_get_status(struct lustre_msg *msg)
 {
-        int i;
-        int offset;
-        int buflen;
-        int bufcount;
+        switch (msg->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+        case LUSTRE_MSG_MAGIC_V1_SWABBED:
+                return ((struct lustre_msg_v1 *)msg)->lm_status;
+        case LUSTRE_MSG_MAGIC_V2:
+        case LUSTRE_MSG_MAGIC_V2_SWABBED: {
+                struct ptlrpc_body *pb;
 
-        LASSERT (m != NULL);
-        LASSERT (n >= 0);
+                pb = lustre_msg_buf_v2(msg, MSG_PTLRPC_BODY_OFF, sizeof(*pb));
+                LASSERTF(pb, "invalid msg %p: no ptlrpc body!\n", msg);
+                return pb->pb_status;
+        }
+        default:
+                /* status might be printed in debug code while message
+                 * uninitialized */
+                return 0;
+        }
+}
 
-        bufcount = m->bufcount;
-        if (n >= bufcount) {
-                CERROR("msg %p buffer[%d] not present (count %d)\n",
-                       m, n, bufcount);
-                return NULL;
+__u32 lustre_msg_get_conn_cnt(struct lustre_msg *msg)
+{
+        switch (msg->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+        case LUSTRE_MSG_MAGIC_V1_SWABBED:
+                return ((struct lustre_msg_v1 *)msg)->lm_conn_cnt;
+        case LUSTRE_MSG_MAGIC_V2:
+        case LUSTRE_MSG_MAGIC_V2_SWABBED: {
+                struct ptlrpc_body *pb;
+
+                pb = lustre_msg_buf_v2(msg, MSG_PTLRPC_BODY_OFF, sizeof(*pb));
+                LASSERTF(pb, "invalid msg %p: no ptlrpc body!\n", msg);
+                return pb->pb_conn_cnt;
+        }
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic);
+                return 0;
         }
+}
 
-        buflen = m->buflens[n];
-        if (buflen < min_size) {
-                CERROR("msg %p buffer[%d] size %d too small (required %d)\n",
-                       m, n, buflen, min_size);
-                return NULL;
+__u32 lustre_msg_get_magic(struct lustre_msg *msg)
+{
+        switch (msg->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+        case LUSTRE_MSG_MAGIC_V1_SWABBED:
+        case LUSTRE_MSG_MAGIC_V2:
+        case LUSTRE_MSG_MAGIC_V2_SWABBED:
+                return msg->lm_magic;
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic);
+                return 0;
         }
+}
 
-        offset = HDR_SIZE(bufcount);
-        for (i = 0; i < n; i++)
-                offset += size_round(m->buflens[i]);
+void lustre_msg_set_handle(struct lustre_msg *msg, struct lustre_handle *handle)
+{
+        switch (msg->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+                ((struct lustre_msg_v1 *)msg)->lm_handle = *handle;
+                return;
+        case LUSTRE_MSG_MAGIC_V2: {
+                struct ptlrpc_body *pb;
 
-        return (char *)m + offset;
+                pb = lustre_msg_buf_v2(msg, MSG_PTLRPC_BODY_OFF, sizeof(*pb));
+                LASSERTF(pb, "invalid msg %p: no ptlrpc body!\n", msg);
+                pb->pb_handle = *handle;
+                return;
+        }
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic);
+        }
 }
 
-char *lustre_msg_string (struct lustre_msg *m, int index, int max_len)
+void lustre_msg_set_type(struct lustre_msg *msg, __u32 type)
 {
-        /* max_len == 0 means the string should fill the buffer */
-        char *str = lustre_msg_buf (m, index, 0);
-        int   slen;
-        int   blen;
+        switch (msg->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+                ((struct lustre_msg_v1 *)msg)->lm_type = type;
+                return;
+        case LUSTRE_MSG_MAGIC_V2: {
+                struct ptlrpc_body *pb;
 
-        if (str == NULL) {
-                CERROR ("can't unpack string in msg %p buffer[%d]\n", m, index);
-                return (NULL);
+                pb = lustre_msg_buf_v2(msg, MSG_PTLRPC_BODY_OFF, sizeof(*pb));
+                LASSERTF(pb, "invalid msg %p: no ptlrpc body!\n", msg);
+                pb->pb_type = type;
+                return;
+        }
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic);
         }
+}
 
-        blen = m->buflens[index];
-        slen = strnlen (str, blen);
+void lustre_msg_set_opc(struct lustre_msg *msg, __u32 opc)
+{
+        switch (msg->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+                ((struct lustre_msg_v1 *)msg)->lm_opc = opc;
+                return;
+        case LUSTRE_MSG_MAGIC_V2: {
+                struct ptlrpc_body *pb;
 
-        if (slen == blen) {                     /* not NULL terminated */
-                CERROR ("can't unpack non-NULL terminated string in "
-                        "msg %p buffer[%d] len %d\n", m, index, blen);
-                return (NULL);
+                pb = lustre_msg_buf_v2(msg, MSG_PTLRPC_BODY_OFF, sizeof(*pb));
+                LASSERTF(pb, "invalid msg %p: no ptlrpc body!\n", msg);
+                pb->pb_opc = opc;
+                return;
         }
-
-        if (max_len == 0) {
-                if (slen != blen - 1) {
-                        CERROR ("can't unpack short string in msg %p "
-                                "buffer[%d] len %d: strlen %d\n",
-                                m, index, blen, slen);
-                        return (NULL);
-                }
-        } else if (slen > max_len) {
-                CERROR ("can't unpack oversized string in msg %p "
-                        "buffer[%d] len %d strlen %d: max %d expected\n",
-                        m, index, blen, slen, max_len);
-                return (NULL);
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic);
         }
+}
+
+void lustre_msg_set_last_xid(struct lustre_msg *msg, __u64 last_xid)
+{
+        switch (msg->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+                ((struct lustre_msg_v1 *)msg)->lm_last_xid = last_xid;
+                return;
+        case LUSTRE_MSG_MAGIC_V2: {
+                struct ptlrpc_body *pb;
 
-        return (str);
+                pb = lustre_msg_buf_v2(msg, MSG_PTLRPC_BODY_OFF, sizeof(*pb));
+                LASSERTF(pb, "invalid msg %p: no ptlrpc body!\n", msg);
+                pb->pb_last_xid = last_xid;
+                return;
+        }
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic);
+        }
 }
 
-/* Wrap up the normal fixed length cases */
-void *lustre_swab_buf(struct lustre_msg *msg, int index, int min_size,
-                      void *swabber)
+void lustre_msg_set_last_committed(struct lustre_msg *msg, __u64 last_committed)
 {
-        void *ptr;
+        switch (msg->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+                ((struct lustre_msg_v1 *)msg)->lm_last_committed=last_committed;
+                return;
+        case LUSTRE_MSG_MAGIC_V2: {
+                struct ptlrpc_body *pb;
 
-        ptr = lustre_msg_buf(msg, index, min_size);
-        if (ptr == NULL)
-                return NULL;
+                pb = lustre_msg_buf_v2(msg, MSG_PTLRPC_BODY_OFF, sizeof(*pb));
+                LASSERTF(pb, "invalid msg %p: no ptlrpc body!\n", msg);
+                pb->pb_last_committed = last_committed;
+                return;
+        }
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic);
+        }
+}
 
-        if (swabber != NULL && lustre_msg_swabbed(msg))
-                ((void (*)(void *))swabber)(ptr);
+void lustre_msg_set_transno(struct lustre_msg *msg, __u64 transno)
+{
+        switch (msg->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+                ((struct lustre_msg_v1 *)msg)->lm_transno = transno;
+                return;
+        case LUSTRE_MSG_MAGIC_V2: {
+                struct ptlrpc_body *pb;
 
-        return ptr;
+                pb = lustre_msg_buf_v2(msg, MSG_PTLRPC_BODY_OFF, sizeof(*pb));
+                LASSERTF(pb, "invalid msg %p: no ptlrpc body!\n", msg);
+                pb->pb_transno = transno;
+                return;
+        }
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic);
+        }
 }
 
-void *lustre_swab_reqbuf(struct ptlrpc_request *req, int index, int min_size,
-                         void *swabber)
+void lustre_msg_set_status(struct lustre_msg *msg, __u32 status)
 {
-        LASSERT_REQSWAB(req, index);
-        return lustre_swab_buf(req->rq_reqmsg, index, min_size, swabber);
+        switch (msg->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+                ((struct lustre_msg_v1 *)msg)->lm_status = status;
+                return;
+        case LUSTRE_MSG_MAGIC_V2: {
+                struct ptlrpc_body *pb;
+
+                pb = lustre_msg_buf_v2(msg, MSG_PTLRPC_BODY_OFF, sizeof(*pb));
+                LASSERTF(pb, "invalid msg %p: no ptlrpc body!\n", msg);
+                pb->pb_status = status;
+                return;
+        }
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic);
+        }
 }
 
-void *lustre_swab_repbuf(struct ptlrpc_request *req, int index, int min_size,
-                         void *swabber)
+void lustre_msg_set_conn_cnt(struct lustre_msg *msg, __u32 conn_cnt)
 {
-        LASSERT_REPSWAB(req, index);
-        return lustre_swab_buf(req->rq_repmsg, index, min_size, swabber);
+        switch (msg->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V1:
+                ((struct lustre_msg_v1 *)msg)->lm_conn_cnt = conn_cnt;
+                return;
+        case LUSTRE_MSG_MAGIC_V2: {
+                struct ptlrpc_body *pb;
+
+                pb = lustre_msg_buf_v2(msg, MSG_PTLRPC_BODY_OFF, sizeof(*pb));
+                LASSERTF(pb, "invalid msg %p: no ptlrpc body!\n", msg);
+                pb->pb_conn_cnt = conn_cnt;
+                return;
+        }
+        default:
+                LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic);
+        }
 }
 
 /* byte flipping routines for all wire types declared in
  * lustre_idl.h implemented here.
  */
+void lustre_swab_ptlrpc_body(struct ptlrpc_body *b)
+{
+        __swab32s (&b->pb_type);
+        __swab32s (&b->pb_version);
+        __swab32s (&b->pb_opc);
+        __swab32s (&b->pb_status);
+        __swab64s (&b->pb_last_xid);
+        __swab64s (&b->pb_last_committed);
+        __swab64s (&b->pb_transno);
+        __swab32s (&b->pb_flags);
+        __swab32s (&b->pb_op_flags);
+        __swab32s (&b->pb_conn_cnt);
+        __swab32s (&b->pb_paddings[0]);
+        __swab32s (&b->pb_paddings[1]);
+        __swab32s (&b->pb_paddings[2]);
+}
 
 void lustre_swab_connect(struct obd_connect_data *ocd)
 {
-        __swab64s (&ocd->ocd_connect_flags);
-        __swab32s (&ocd->ocd_version);
-        __swab32s (&ocd->ocd_grant);
-        __swab32s (&ocd->ocd_index);
-        __swab32s (&ocd->ocd_unused);
-        __swab64s (&ocd->ocd_ibits_known);
+        __swab64s(&ocd->ocd_connect_flags);
+        __swab32s(&ocd->ocd_version);
+        __swab32s(&ocd->ocd_grant);
+        __swab32s(&ocd->ocd_index);
+        __swab32s(&ocd->ocd_brw_size);
+        __swab64s(&ocd->ocd_ibits_known);
+        __swab32s(&ocd->ocd_nllu);
+        __swab32s(&ocd->ocd_nllg);
+        CLASSERT(offsetof(typeof(*ocd), padding1) != 0);
         CLASSERT(offsetof(typeof(*ocd), padding2) != 0);
         CLASSERT(offsetof(typeof(*ocd), padding3) != 0);
         CLASSERT(offsetof(typeof(*ocd), padding4) != 0);
-        CLASSERT(offsetof(typeof(*ocd), padding5) != 0);
-        CLASSERT(offsetof(typeof(*ocd), padding6) != 0);
 }
 
 void lustre_swab_obdo (struct obdo  *o)
@@ -666,19 +1696,14 @@ void lustre_swab_mdt_body (struct mdt_body *b)
 void lustre_swab_mgs_target_info(struct mgs_target_info *mti)
 {
         int i;
-        LASSERT(sizeof(lnet_nid_t) == sizeof(__u64));
-        for (i = 0; i < MTI_NIDS_MAX; i++) {
-                __swab64s(&mti->mti_nids[i]);
-                __swab64s(&mti->mti_failnids[i]);
-        }
-        for (i = 0; i < 8; i++) {
-                __swab16s(&mti->mti_failnodes[i]);
-        }
+        __swab32s(&mti->mti_lustre_ver);
         __swab32s(&mti->mti_stripe_index);
-        __swab32s(&mti->mti_nid_count);
-        __swab32s(&mti->mti_failnid_count);
         __swab32s(&mti->mti_config_ver);
         __swab32s(&mti->mti_flags);
+        __swab32s(&mti->mti_nid_count);
+        LASSERT(sizeof(lnet_nid_t) == sizeof(__u64));
+        for (i = 0; i < MTI_NIDS_MAX; i++) 
+                __swab64s(&mti->mti_nids[i]);
 }
 
 static void lustre_swab_obd_dqinfo (struct obd_dqinfo *i)
@@ -915,7 +1940,6 @@ void lustre_swab_lov_desc (struct lov_desc *ld)
         __swab64s (&ld->ld_default_stripe_size);
         __swab64s (&ld->ld_default_stripe_offset);
         __swab32s (&ld->ld_pattern);
-        __swab32s (&ld->ld_qos_threshold);
         __swab32s (&ld->ld_qos_maxage);
         /* uuid endian insensitive */
 }
@@ -1122,1794 +2146,3 @@ void lustre_swab_qdata(struct qunit_data *d)
         __swab32s (&d->qd_isblk);
 }
 
-void lustre_assert_wire_constants(void)
-{
-        /* Wire protocol assertions generated by 'wirecheck'
-         * running on Linux tau 2.6.15-dirty #13 SMP Sat Feb 11 18:30:54 MSK 2006 i686 i686 i386 GNU/
-         * with gcc version 3.3.3 (SuSE Linux) */
-
-        /* Constants... */
-        LASSERTF(PTLRPC_MSG_MAGIC == 0x0BD00BD0," found %lld\n",
-                 (long long)PTLRPC_MSG_MAGIC);
-        LASSERTF(PTLRPC_MSG_VERSION == 0x00000003," found %lld\n",
-                 (long long)PTLRPC_MSG_VERSION);
-        LASSERTF(PTL_RPC_MSG_REQUEST == 4711, " found %lld\n",
-                 (long long)PTL_RPC_MSG_REQUEST);
-        LASSERTF(PTL_RPC_MSG_ERR == 4712, " found %lld\n",
-                 (long long)PTL_RPC_MSG_ERR);
-        LASSERTF(PTL_RPC_MSG_REPLY == 4713, " found %lld\n",
-                 (long long)PTL_RPC_MSG_REPLY);
-        LASSERTF(MSG_LAST_REPLAY == 1, " found %lld\n",
-                 (long long)MSG_LAST_REPLAY);
-        LASSERTF(MSG_RESENT == 2, " found %lld\n",
-                 (long long)MSG_RESENT);
-        LASSERTF(MSG_REPLAY == 4, " found %lld\n",
-                 (long long)MSG_REPLAY);
-        LASSERTF(MSG_CONNECT_RECOVERING == 1, " found %lld\n",
-                 (long long)MSG_CONNECT_RECOVERING);
-        LASSERTF(MSG_CONNECT_RECONNECT == 2, " found %lld\n",
-                 (long long)MSG_CONNECT_RECONNECT);
-        LASSERTF(MSG_CONNECT_REPLAYABLE == 4, " found %lld\n",
-                 (long long)MSG_CONNECT_REPLAYABLE);
-        LASSERTF(OST_REPLY == 0, " found %lld\n",
-                 (long long)OST_REPLY);
-        LASSERTF(OST_GETATTR == 1, " found %lld\n",
-                 (long long)OST_GETATTR);
-        LASSERTF(OST_SETATTR == 2, " found %lld\n",
-                 (long long)OST_SETATTR);
-        LASSERTF(OST_READ == 3, " found %lld\n",
-                 (long long)OST_READ);
-        LASSERTF(OST_WRITE == 4, " found %lld\n",
-                 (long long)OST_WRITE);
-        LASSERTF(OST_CREATE == 5, " found %lld\n",
-                 (long long)OST_CREATE);
-        LASSERTF(OST_DESTROY == 6, " found %lld\n",
-                 (long long)OST_DESTROY);
-        LASSERTF(OST_GET_INFO == 7, " found %lld\n",
-                 (long long)OST_GET_INFO);
-        LASSERTF(OST_CONNECT == 8, " found %lld\n",
-                 (long long)OST_CONNECT);
-        LASSERTF(OST_DISCONNECT == 9, " found %lld\n",
-                 (long long)OST_DISCONNECT);
-        LASSERTF(OST_PUNCH == 10, " found %lld\n",
-                 (long long)OST_PUNCH);
-        LASSERTF(OST_OPEN == 11, " found %lld\n",
-                 (long long)OST_OPEN);
-        LASSERTF(OST_CLOSE == 12, " found %lld\n",
-                 (long long)OST_CLOSE);
-        LASSERTF(OST_STATFS == 13, " found %lld\n",
-                 (long long)OST_STATFS);
-        LASSERTF(OST_SAN_READ == 14, " found %lld\n",
-                 (long long)OST_SAN_READ);
-        LASSERTF(OST_SAN_WRITE == 15, " found %lld\n",
-                 (long long)OST_SAN_WRITE);
-        LASSERTF(OST_SYNC == 16, " found %lld\n",
-                 (long long)OST_SYNC);
-        LASSERTF(OST_QUOTACHECK == 18, " found %lld\n",
-                 (long long)OST_QUOTACHECK);
-        LASSERTF(OST_QUOTACTL == 19, " found %lld\n",
-                 (long long)OST_QUOTACTL);
-        LASSERTF(OST_LAST_OPC == 20, " found %lld\n",
-                 (long long)OST_LAST_OPC);
-        LASSERTF(OBD_OBJECT_EOF == 0xffffffffffffffffULL," found %lld\n",
-                 (long long)OBD_OBJECT_EOF);
-        LASSERTF(MDS_GETATTR == 33, " found %lld\n",
-                 (long long)MDS_GETATTR);
-        LASSERTF(MDS_GETATTR_NAME == 34, " found %lld\n",
-                 (long long)MDS_GETATTR_NAME);
-        LASSERTF(MDS_CLOSE == 35, " found %lld\n",
-                 (long long)MDS_CLOSE);
-        LASSERTF(MDS_REINT == 36, " found %lld\n",
-                 (long long)MDS_REINT);
-        LASSERTF(MDS_READPAGE == 37, " found %lld\n",
-                 (long long)MDS_READPAGE);
-        LASSERTF(MDS_CONNECT == 38, " found %lld\n",
-                 (long long)MDS_CONNECT);
-        LASSERTF(MDS_DISCONNECT == 39, " found %lld\n",
-                 (long long)MDS_DISCONNECT);
-        LASSERTF(MDS_GETSTATUS == 40, " found %lld\n",
-                 (long long)MDS_GETSTATUS);
-        LASSERTF(MDS_STATFS == 41, " found %lld\n",
-                 (long long)MDS_STATFS);
-        LASSERTF(MDS_PIN == 42, " found %lld\n",
-                 (long long)MDS_PIN);
-        LASSERTF(MDS_UNPIN == 43, " found %lld\n",
-                 (long long)MDS_UNPIN);
-        LASSERTF(MDS_SYNC == 44, " found %lld\n",
-                 (long long)MDS_SYNC);
-        LASSERTF(MDS_DONE_WRITING == 45, " found %lld\n",
-                 (long long)MDS_DONE_WRITING);
-        LASSERTF(MDS_SET_INFO == 46, " found %lld\n",
-                 (long long)MDS_SET_INFO);
-        LASSERTF(MDS_QUOTACHECK == 47, " found %lld\n",
-                 (long long)MDS_QUOTACHECK);
-        LASSERTF(MDS_QUOTACTL == 48, " found %lld\n",
-                 (long long)MDS_QUOTACTL);
-        LASSERTF(MDS_LAST_OPC == 51, " found %lld\n",
-                 (long long)MDS_LAST_OPC);
-        LASSERTF(REINT_SETATTR == 1, " found %lld\n",
-                 (long long)REINT_SETATTR);
-        LASSERTF(REINT_CREATE == 2, " found %lld\n",
-                 (long long)REINT_CREATE);
-        LASSERTF(REINT_LINK == 3, " found %lld\n",
-                 (long long)REINT_LINK);
-        LASSERTF(REINT_UNLINK == 4, " found %lld\n",
-                 (long long)REINT_UNLINK);
-        LASSERTF(REINT_RENAME == 5, " found %lld\n",
-                 (long long)REINT_RENAME);
-        LASSERTF(REINT_OPEN == 6, " found %lld\n",
-                 (long long)REINT_OPEN);
-        LASSERTF(REINT_MAX == 7, " found %lld\n",
-                 (long long)REINT_MAX);
-        LASSERTF(MGS_CONNECT == 250, " found %lld\n",
-                 (long long)MGS_CONNECT);
-        LASSERTF(MGS_DISCONNECT == 251, " found %lld\n",
-                 (long long)MGS_DISCONNECT);
-        LASSERTF(MGS_EXCEPTION == 252, " found %lld\n",
-                 (long long)MGS_EXCEPTION);
-        LASSERTF(MGS_TARGET_REG == 253, " found %lld\n",
-                 (long long)MGS_TARGET_REG);
-        LASSERTF(MGS_TARGET_DEL == 254, " found %lld\n",
-                 (long long)MGS_TARGET_DEL);
-        LASSERTF(DISP_IT_EXECD == 1, " found %lld\n",
-                 (long long)DISP_IT_EXECD);
-        LASSERTF(DISP_LOOKUP_EXECD == 2, " found %lld\n",
-                 (long long)DISP_LOOKUP_EXECD);
-        LASSERTF(DISP_LOOKUP_NEG == 4, " found %lld\n",
-                 (long long)DISP_LOOKUP_NEG);
-        LASSERTF(DISP_LOOKUP_POS == 8, " found %lld\n",
-                 (long long)DISP_LOOKUP_POS);
-        LASSERTF(DISP_OPEN_CREATE == 16, " found %lld\n",
-                 (long long)DISP_OPEN_CREATE);
-        LASSERTF(DISP_OPEN_OPEN == 32, " found %lld\n",
-                 (long long)DISP_OPEN_OPEN);
-        LASSERTF(MDS_STATUS_CONN == 1, " found %lld\n",
-                 (long long)MDS_STATUS_CONN);
-        LASSERTF(MDS_STATUS_LOV == 2, " found %lld\n",
-                 (long long)MDS_STATUS_LOV);
-        LASSERTF(LDLM_ENQUEUE == 101, " found %lld\n",
-                 (long long)LDLM_ENQUEUE);
-        LASSERTF(LDLM_CONVERT == 102, " found %lld\n",
-                 (long long)LDLM_CONVERT);
-        LASSERTF(LDLM_CANCEL == 103, " found %lld\n",
-                 (long long)LDLM_CANCEL);
-        LASSERTF(LDLM_BL_CALLBACK == 104, " found %lld\n",
-                 (long long)LDLM_BL_CALLBACK);
-        LASSERTF(LDLM_CP_CALLBACK == 105, " found %lld\n",
-                 (long long)LDLM_CP_CALLBACK);
-        LASSERTF(LDLM_GL_CALLBACK == 106, " found %lld\n",
-                 (long long)LDLM_GL_CALLBACK);
-        LASSERTF(LDLM_LAST_OPC == 107, " found %lld\n",
-                 (long long)LDLM_LAST_OPC);
-        LASSERTF(LCK_EX == 1, " found %lld\n",
-                 (long long)LCK_EX);
-        LASSERTF(LCK_PW == 2, " found %lld\n",
-                 (long long)LCK_PW);
-        LASSERTF(LCK_PR == 4, " found %lld\n",
-                 (long long)LCK_PR);
-        LASSERTF(LCK_CW == 8, " found %lld\n",
-                 (long long)LCK_CW);
-        LASSERTF(LCK_CR == 16, " found %lld\n",
-                 (long long)LCK_CR);
-        LASSERTF(LCK_NL == 32, " found %lld\n",
-                 (long long)LCK_NL);
-        LASSERTF(LCK_GROUP == 64, " found %lld\n",
-                 (long long)LCK_GROUP);
-        LASSERTF(LCK_MAXMODE == 65, " found %lld\n",
-                 (long long)LCK_MAXMODE);
-        CLASSERT(LDLM_PLAIN == 10);
-        CLASSERT(LDLM_EXTENT == 11);
-        CLASSERT(LDLM_FLOCK == 12);
-        CLASSERT(LDLM_IBITS == 13);
-        LASSERTF(OBD_PING == 400, " found %lld\n",
-                 (long long)OBD_PING);
-        LASSERTF(OBD_LOG_CANCEL == 401, " found %lld\n",
-                 (long long)OBD_LOG_CANCEL);
-        LASSERTF(OBD_QC_CALLBACK == 402, " found %lld\n",
-                 (long long)OBD_QC_CALLBACK);
-        LASSERTF(OBD_LAST_OPC == 403, " found %lld\n",
-                 (long long)OBD_LAST_OPC);
-        LASSERTF(QUOTA_DQACQ == 601, " found %lld\n",
-                 (long long)QUOTA_DQACQ);
-        LASSERTF(QUOTA_DQREL == 602, " found %lld\n",
-                 (long long)QUOTA_DQREL);
-        CLASSERT(OBD_CONNECT_RDONLY == 0x1ULL);
-        CLASSERT(OBD_CONNECT_INDEX == 0x2ULL);
-        CLASSERT(OBD_CONNECT_GRANT == 0x8ULL);
-        CLASSERT(OBD_CONNECT_SRVLOCK == 0x10ULL);
-        CLASSERT(OBD_CONNECT_VERSION == 0x20ULL);
-        CLASSERT(OBD_CONNECT_REQPORTAL == 0x40ULL);
-        CLASSERT(OBD_CONNECT_ACL == 0x80ULL);
-        CLASSERT(OBD_CONNECT_XATTR == 0x100ULL);
-        CLASSERT(OBD_CONNECT_CROW == 0x200ULL);
-        CLASSERT(OBD_CONNECT_TRUNCLOCK == 0x400ULL);
-        CLASSERT(OBD_CONNECT_TRANSNO == 0x800ULL);
-        CLASSERT(OBD_CONNECT_IBITS == 0x1000ULL);
-        CLASSERT(OBD_CONNECT_JOIN == 0x2000ULL);
-        /* Sizes and Offsets */
-
-
-        /* Checks for struct lustre_handle */
-        LASSERTF((int)sizeof(struct lustre_handle) == 8, " found %lld\n",
-                 (long long)(int)sizeof(struct lustre_handle));
-        LASSERTF((int)offsetof(struct lustre_handle, cookie) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct lustre_handle, cookie));
-        LASSERTF((int)sizeof(((struct lustre_handle *)0)->cookie) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct lustre_handle *)0)->cookie));
-
-        /* Checks for struct lustre_msg */
-        LASSERTF((int)sizeof(struct lustre_msg) == 64, " found %lld\n",
-                 (long long)(int)sizeof(struct lustre_msg));
-        LASSERTF((int)offsetof(struct lustre_msg, handle) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct lustre_msg, handle));
-        LASSERTF((int)sizeof(((struct lustre_msg *)0)->handle) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct lustre_msg *)0)->handle));
-        LASSERTF((int)offsetof(struct lustre_msg, magic) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct lustre_msg, magic));
-        LASSERTF((int)sizeof(((struct lustre_msg *)0)->magic) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lustre_msg *)0)->magic));
-        LASSERTF((int)offsetof(struct lustre_msg, type) == 12, " found %lld\n",
-                 (long long)(int)offsetof(struct lustre_msg, type));
-        LASSERTF((int)sizeof(((struct lustre_msg *)0)->type) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lustre_msg *)0)->type));
-        LASSERTF((int)offsetof(struct lustre_msg, version) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct lustre_msg, version));
-        LASSERTF((int)sizeof(((struct lustre_msg *)0)->version) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lustre_msg *)0)->version));
-        LASSERTF((int)offsetof(struct lustre_msg, opc) == 20, " found %lld\n",
-                 (long long)(int)offsetof(struct lustre_msg, opc));
-        LASSERTF((int)sizeof(((struct lustre_msg *)0)->opc) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lustre_msg *)0)->opc));
-        LASSERTF((int)offsetof(struct lustre_msg, last_xid) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct lustre_msg, last_xid));
-        LASSERTF((int)sizeof(((struct lustre_msg *)0)->last_xid) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct lustre_msg *)0)->last_xid));
-        LASSERTF((int)offsetof(struct lustre_msg, last_committed) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct lustre_msg, last_committed));
-        LASSERTF((int)sizeof(((struct lustre_msg *)0)->last_committed) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct lustre_msg *)0)->last_committed));
-        LASSERTF((int)offsetof(struct lustre_msg, transno) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct lustre_msg, transno));
-        LASSERTF((int)sizeof(((struct lustre_msg *)0)->transno) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct lustre_msg *)0)->transno));
-        LASSERTF((int)offsetof(struct lustre_msg, status) == 48, " found %lld\n",
-                 (long long)(int)offsetof(struct lustre_msg, status));
-        LASSERTF((int)sizeof(((struct lustre_msg *)0)->status) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lustre_msg *)0)->status));
-        LASSERTF((int)offsetof(struct lustre_msg, flags) == 52, " found %lld\n",
-                 (long long)(int)offsetof(struct lustre_msg, flags));
-        LASSERTF((int)sizeof(((struct lustre_msg *)0)->flags) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lustre_msg *)0)->flags));
-        LASSERTF((int)offsetof(struct lustre_msg, bufcount) == 60, " found %lld\n",
-                 (long long)(int)offsetof(struct lustre_msg, bufcount));
-        LASSERTF((int)sizeof(((struct lustre_msg *)0)->bufcount) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lustre_msg *)0)->bufcount));
-        LASSERTF((int)offsetof(struct lustre_msg, buflens[7]) == 92, " found %lld\n",
-                 (long long)(int)offsetof(struct lustre_msg, buflens[7]));
-        LASSERTF((int)sizeof(((struct lustre_msg *)0)->buflens[7]) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lustre_msg *)0)->buflens[7]));
-
-        /* Checks for struct obdo */
-        LASSERTF((int)sizeof(struct obdo) == 208, " found %lld\n",
-                 (long long)(int)sizeof(struct obdo));
-        LASSERTF((int)offsetof(struct obdo, o_valid) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_valid));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_valid) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_valid));
-        LASSERTF((int)offsetof(struct obdo, o_id) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_id));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_id) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_id));
-        LASSERTF((int)offsetof(struct obdo, o_gr) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_gr));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_gr) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_gr));
-        LASSERTF((int)offsetof(struct obdo, o_fid) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_fid));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_fid) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_fid));
-        LASSERTF((int)offsetof(struct obdo, o_size) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_size));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_size) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_size));
-        LASSERTF((int)offsetof(struct obdo, o_mtime) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_mtime));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_mtime) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_mtime));
-        LASSERTF((int)offsetof(struct obdo, o_atime) == 48, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_atime));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_atime) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_atime));
-        LASSERTF((int)offsetof(struct obdo, o_ctime) == 56, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_ctime));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_ctime) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_ctime));
-        LASSERTF((int)offsetof(struct obdo, o_blocks) == 64, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_blocks));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_blocks) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_blocks));
-        LASSERTF((int)offsetof(struct obdo, o_grant) == 72, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_grant));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_grant) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_grant));
-        LASSERTF((int)offsetof(struct obdo, o_blksize) == 80, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_blksize));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_blksize) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_blksize));
-        LASSERTF((int)offsetof(struct obdo, o_mode) == 84, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_mode));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_mode) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_mode));
-        LASSERTF((int)offsetof(struct obdo, o_uid) == 88, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_uid));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_uid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_uid));
-        LASSERTF((int)offsetof(struct obdo, o_gid) == 92, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_gid));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_gid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_gid));
-        LASSERTF((int)offsetof(struct obdo, o_flags) == 96, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_flags));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_flags) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_flags));
-        LASSERTF((int)offsetof(struct obdo, o_nlink) == 100, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_nlink));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_nlink) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_nlink));
-        LASSERTF((int)offsetof(struct obdo, o_generation) == 104, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_generation));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_generation) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_generation));
-        LASSERTF((int)offsetof(struct obdo, o_misc) == 108, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_misc));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_misc) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_misc));
-        LASSERTF((int)offsetof(struct obdo, o_easize) == 112, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_easize));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_easize) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_easize));
-        LASSERTF((int)offsetof(struct obdo, o_mds) == 116, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_mds));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_mds) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_mds));
-        LASSERTF((int)offsetof(struct obdo, o_stripe_idx) == 120, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_stripe_idx));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_stripe_idx) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_stripe_idx));
-        LASSERTF((int)offsetof(struct obdo, o_padding_1) == 124, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_padding_1));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_padding_1) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_padding_1));
-        LASSERTF((int)offsetof(struct obdo, o_inline) == 128, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_inline));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_inline) == 80, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_inline));
-        LASSERTF(OBD_INLINESZ == 80, " found %lld\n",
-                 (long long)OBD_INLINESZ);
-        CLASSERT(OBD_MD_FLID == (0x0000000000000001ULL));
-        CLASSERT(OBD_MD_FLATIME == (0x0000000000000002ULL));
-        CLASSERT(OBD_MD_FLMTIME == (0x0000000000000004ULL));
-        CLASSERT(OBD_MD_FLCTIME == (0x0000000000000008ULL));
-        CLASSERT(OBD_MD_FLSIZE == (0x0000000000000010ULL));
-        CLASSERT(OBD_MD_FLBLOCKS == (0x0000000000000020ULL));
-        CLASSERT(OBD_MD_FLBLKSZ == (0x0000000000000040ULL));
-        CLASSERT(OBD_MD_FLMODE == (0x0000000000000080ULL));
-        CLASSERT(OBD_MD_FLTYPE == (0x0000000000000100ULL));
-        CLASSERT(OBD_MD_FLUID == (0x0000000000000200ULL));
-        CLASSERT(OBD_MD_FLGID == (0x0000000000000400ULL));
-        CLASSERT(OBD_MD_FLFLAGS == (0x0000000000000800ULL));
-        CLASSERT(OBD_MD_FLNLINK == (0x0000000000002000ULL));
-        CLASSERT(OBD_MD_FLGENER == (0x0000000000004000ULL));
-        CLASSERT(OBD_MD_FLINLINE == (0x0000000000008000ULL));
-        CLASSERT(OBD_MD_FLRDEV == (0x0000000000010000ULL));
-        CLASSERT(OBD_MD_FLEASIZE == (0x0000000000020000ULL));
-        CLASSERT(OBD_MD_LINKNAME == (0x0000000000040000ULL));
-        CLASSERT(OBD_MD_FLHANDLE == (0x0000000000080000ULL));
-        CLASSERT(OBD_MD_FLCKSUM == (0x0000000000100000ULL));
-        CLASSERT(OBD_MD_FLQOS == (0x0000000000200000ULL));
-        CLASSERT(OBD_MD_FLCOOKIE == (0x0000000000800000ULL));
-        CLASSERT(OBD_MD_FLGROUP == (0x0000000001000000ULL));
-        CLASSERT(OBD_MD_FLFID == (0x0000000002000000ULL));
-        CLASSERT(OBD_MD_FLEPOCH == (0x0000000004000000ULL));
-        CLASSERT(OBD_MD_FLGRANT == (0x0000000008000000ULL));
-        CLASSERT(OBD_MD_FLDIREA == (0x0000000010000000ULL));
-        CLASSERT(OBD_MD_FLUSRQUOTA == (0x0000000020000000ULL));
-        CLASSERT(OBD_MD_FLGRPQUOTA == (0x0000000040000000ULL));
-        CLASSERT(OBD_MD_FLMODEASIZE == (0x0000000080000000ULL));
-        CLASSERT(OBD_MD_MDS == (0x0000000100000000ULL));
-        CLASSERT(OBD_MD_REINT == (0x0000000200000000ULL));
-        CLASSERT(OBD_MD_FLXATTR == (0x0000001000000000ULL));
-        CLASSERT(OBD_MD_FLXATTRLS == (0x0000002000000000ULL));
-        CLASSERT(OBD_MD_FLXATTRRM == (0x0000004000000000ULL));
-        CLASSERT(OBD_MD_FLACL == (0x0000008000000000ULL));
-        CLASSERT(OBD_FL_INLINEDATA == (0x00000001));
-        CLASSERT(OBD_FL_OBDMDEXISTS == (0x00000002));
-        CLASSERT(OBD_FL_DELORPHAN == (0x00000004));
-        CLASSERT(OBD_FL_NORPC == (0x00000008));
-        CLASSERT(OBD_FL_IDONLY == (0x00000010));
-        CLASSERT(OBD_FL_RECREATE_OBJS == (0x00000020));
-        CLASSERT(OBD_FL_DEBUG_CHECK == (0x00000040));
-        CLASSERT(OBD_FL_NO_USRQUOTA == (0x00000100));
-        CLASSERT(OBD_FL_NO_GRPQUOTA == (0x00000200));
-        CLASSERT(OBD_FL_CREATE_CROW == (0x00000400));
-
-        /* Checks for struct lov_mds_md_v1 */
-        LASSERTF((int)sizeof(struct lov_mds_md_v1) == 32, " found %lld\n",
-                 (long long)(int)sizeof(struct lov_mds_md_v1));
-        LASSERTF((int)offsetof(struct lov_mds_md_v1, lmm_magic) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_mds_md_v1, lmm_magic));
-        LASSERTF((int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_magic) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_magic));
-        LASSERTF((int)offsetof(struct lov_mds_md_v1, lmm_pattern) == 4, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_mds_md_v1, lmm_pattern));
-        LASSERTF((int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_pattern) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_pattern));
-        LASSERTF((int)offsetof(struct lov_mds_md_v1, lmm_object_id) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_mds_md_v1, lmm_object_id));
-        LASSERTF((int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_object_id) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_object_id));
-        LASSERTF((int)offsetof(struct lov_mds_md_v1, lmm_object_gr) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_mds_md_v1, lmm_object_gr));
-        LASSERTF((int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_object_gr) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_object_gr));
-        LASSERTF((int)offsetof(struct lov_mds_md_v1, lmm_stripe_size) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_mds_md_v1, lmm_stripe_size));
-        LASSERTF((int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_stripe_size) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_stripe_size));
-        LASSERTF((int)offsetof(struct lov_mds_md_v1, lmm_stripe_count) == 28, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_mds_md_v1, lmm_stripe_count));
-        LASSERTF((int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_stripe_count) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_stripe_count));
-        LASSERTF((int)offsetof(struct lov_mds_md_v1, lmm_objects) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_mds_md_v1, lmm_objects));
-        LASSERTF((int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_objects) == 0, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_objects));
-
-        /* Checks for struct lov_ost_data_v1 */
-        LASSERTF((int)sizeof(struct lov_ost_data_v1) == 24, " found %lld\n",
-                 (long long)(int)sizeof(struct lov_ost_data_v1));
-        LASSERTF((int)offsetof(struct lov_ost_data_v1, l_object_id) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_ost_data_v1, l_object_id));
-        LASSERTF((int)sizeof(((struct lov_ost_data_v1 *)0)->l_object_id) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_ost_data_v1 *)0)->l_object_id));
-        LASSERTF((int)offsetof(struct lov_ost_data_v1, l_object_gr) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_ost_data_v1, l_object_gr));
-        LASSERTF((int)sizeof(((struct lov_ost_data_v1 *)0)->l_object_gr) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_ost_data_v1 *)0)->l_object_gr));
-        LASSERTF((int)offsetof(struct lov_ost_data_v1, l_ost_gen) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_ost_data_v1, l_ost_gen));
-        LASSERTF((int)sizeof(((struct lov_ost_data_v1 *)0)->l_ost_gen) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_ost_data_v1 *)0)->l_ost_gen));
-        LASSERTF((int)offsetof(struct lov_ost_data_v1, l_ost_idx) == 20, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_ost_data_v1, l_ost_idx));
-        LASSERTF((int)sizeof(((struct lov_ost_data_v1 *)0)->l_ost_idx) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_ost_data_v1 *)0)->l_ost_idx));
-        CLASSERT(LOV_MAGIC_V1 == 0x0BD10BD0);
-        CLASSERT(LOV_MAGIC_JOIN == 0x0BD20BD0);
-        LASSERTF(LOV_PATTERN_RAID0 == 1, " found %lld\n",
-                 (long long)LOV_PATTERN_RAID0);
-        LASSERTF(LOV_PATTERN_RAID1 == 2, " found %lld\n",
-                 (long long)LOV_PATTERN_RAID1);
-
-        /* Checks for struct lov_mds_md_join */
-        LASSERTF((int)sizeof(struct lov_mds_md_join) == 56, " found %lld\n",
-                 (long long)(int)sizeof(struct lov_mds_md_join));
-        LASSERTF((int)offsetof(struct lov_mds_md_join, lmmj_md) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_mds_md_join, lmmj_md));
-        LASSERTF((int)sizeof(((struct lov_mds_md_join *)0)->lmmj_md) == 32, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_mds_md_join *)0)->lmmj_md));
-        LASSERTF((int)offsetof(struct lov_mds_md_join, lmmj_array_id) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_mds_md_join, lmmj_array_id));
-        LASSERTF((int)sizeof(((struct lov_mds_md_join *)0)->lmmj_array_id) == 20, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_mds_md_join *)0)->lmmj_array_id));
-        LASSERTF((int)offsetof(struct lov_mds_md_join, lmmj_extent_count) == 52, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_mds_md_join, lmmj_extent_count));
-        LASSERTF((int)sizeof(((struct lov_mds_md_join *)0)->lmmj_extent_count) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_mds_md_join *)0)->lmmj_extent_count));
-
-        /* Checks for struct obd_statfs */
-        LASSERTF((int)sizeof(struct obd_statfs) == 144, " found %lld\n",
-                 (long long)(int)sizeof(struct obd_statfs));
-        LASSERTF((int)offsetof(struct obd_statfs, os_type) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_type));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_type) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_type));
-        LASSERTF((int)offsetof(struct obd_statfs, os_blocks) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_blocks));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_blocks) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_blocks));
-        LASSERTF((int)offsetof(struct obd_statfs, os_bfree) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_bfree));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_bfree) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_bfree));
-        LASSERTF((int)offsetof(struct obd_statfs, os_bavail) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_bavail));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_bavail) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_bavail));
-        LASSERTF((int)offsetof(struct obd_statfs, os_ffree) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_ffree));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_ffree) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_ffree));
-        LASSERTF((int)offsetof(struct obd_statfs, os_fsid) == 48, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_fsid));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_fsid) == 40, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_fsid));
-        LASSERTF((int)offsetof(struct obd_statfs, os_bsize) == 88, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_bsize));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_bsize) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_bsize));
-        LASSERTF((int)offsetof(struct obd_statfs, os_namelen) == 92, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_namelen));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_namelen) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_namelen));
-        LASSERTF((int)offsetof(struct obd_statfs, os_state) == 104, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_state));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_state) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_state));
-        LASSERTF((int)offsetof(struct obd_statfs, os_spare1) == 108, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_spare1));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_spare1) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_spare1));
-        LASSERTF((int)offsetof(struct obd_statfs, os_spare2) == 112, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_spare2));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_spare2) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_spare2));
-        LASSERTF((int)offsetof(struct obd_statfs, os_spare3) == 116, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_spare3));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_spare3) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_spare3));
-        LASSERTF((int)offsetof(struct obd_statfs, os_spare4) == 120, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_spare4));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_spare4) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_spare4));
-        LASSERTF((int)offsetof(struct obd_statfs, os_spare5) == 124, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_spare5));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_spare5) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_spare5));
-        LASSERTF((int)offsetof(struct obd_statfs, os_spare6) == 128, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_spare6));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_spare6) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_spare6));
-        LASSERTF((int)offsetof(struct obd_statfs, os_spare7) == 132, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_spare7));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_spare7) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_spare7));
-        LASSERTF((int)offsetof(struct obd_statfs, os_spare8) == 136, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_spare8));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_spare8) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_spare8));
-        LASSERTF((int)offsetof(struct obd_statfs, os_spare9) == 140, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_spare9));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_spare9) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_spare9));
-
-        /* Checks for struct obd_ioobj */
-        LASSERTF((int)sizeof(struct obd_ioobj) == 24, " found %lld\n",
-                 (long long)(int)sizeof(struct obd_ioobj));
-        LASSERTF((int)offsetof(struct obd_ioobj, ioo_id) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_ioobj, ioo_id));
-        LASSERTF((int)sizeof(((struct obd_ioobj *)0)->ioo_id) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_ioobj *)0)->ioo_id));
-        LASSERTF((int)offsetof(struct obd_ioobj, ioo_gr) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_ioobj, ioo_gr));
-        LASSERTF((int)sizeof(((struct obd_ioobj *)0)->ioo_gr) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_ioobj *)0)->ioo_gr));
-        LASSERTF((int)offsetof(struct obd_ioobj, ioo_type) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_ioobj, ioo_type));
-        LASSERTF((int)sizeof(((struct obd_ioobj *)0)->ioo_type) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_ioobj *)0)->ioo_type));
-        LASSERTF((int)offsetof(struct obd_ioobj, ioo_bufcnt) == 20, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_ioobj, ioo_bufcnt));
-        LASSERTF((int)sizeof(((struct obd_ioobj *)0)->ioo_bufcnt) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_ioobj *)0)->ioo_bufcnt));
-
-        /* Checks for struct obd_quotactl */
-        LASSERTF((int)sizeof(struct obd_quotactl) == 112, " found %lld\n",
-                 (long long)(int)sizeof(struct obd_quotactl));
-        LASSERTF((int)offsetof(struct obd_quotactl, qc_cmd) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_quotactl, qc_cmd));
-        LASSERTF((int)sizeof(((struct obd_quotactl *)0)->qc_cmd) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_quotactl *)0)->qc_cmd));
-        LASSERTF((int)offsetof(struct obd_quotactl, qc_type) == 4, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_quotactl, qc_type));
-        LASSERTF((int)sizeof(((struct obd_quotactl *)0)->qc_type) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_quotactl *)0)->qc_type));
-        LASSERTF((int)offsetof(struct obd_quotactl, qc_id) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_quotactl, qc_id));
-        LASSERTF((int)sizeof(((struct obd_quotactl *)0)->qc_id) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_quotactl *)0)->qc_id));
-        LASSERTF((int)offsetof(struct obd_quotactl, qc_stat) == 12, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_quotactl, qc_stat));
-        LASSERTF((int)sizeof(((struct obd_quotactl *)0)->qc_stat) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_quotactl *)0)->qc_stat));
-        LASSERTF((int)offsetof(struct obd_quotactl, qc_dqinfo) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_quotactl, qc_dqinfo));
-        LASSERTF((int)sizeof(((struct obd_quotactl *)0)->qc_dqinfo) == 24, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_quotactl *)0)->qc_dqinfo));
-        LASSERTF((int)offsetof(struct obd_quotactl, qc_dqblk) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_quotactl, qc_dqblk));
-        LASSERTF((int)sizeof(((struct obd_quotactl *)0)->qc_dqblk) == 72, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_quotactl *)0)->qc_dqblk));
-
-        /* Checks for struct obd_dqinfo */
-        LASSERTF((int)sizeof(struct obd_dqinfo) == 24, " found %lld\n",
-                 (long long)(int)sizeof(struct obd_dqinfo));
-        LASSERTF((int)offsetof(struct obd_dqinfo, dqi_bgrace) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_dqinfo, dqi_bgrace));
-        LASSERTF((int)sizeof(((struct obd_dqinfo *)0)->dqi_bgrace) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_dqinfo *)0)->dqi_bgrace));
-        LASSERTF((int)offsetof(struct obd_dqinfo, dqi_igrace) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_dqinfo, dqi_igrace));
-        LASSERTF((int)sizeof(((struct obd_dqinfo *)0)->dqi_igrace) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_dqinfo *)0)->dqi_igrace));
-        LASSERTF((int)offsetof(struct obd_dqinfo, dqi_flags) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_dqinfo, dqi_flags));
-        LASSERTF((int)sizeof(((struct obd_dqinfo *)0)->dqi_flags) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_dqinfo *)0)->dqi_flags));
-        LASSERTF((int)offsetof(struct obd_dqinfo, dqi_valid) == 20, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_dqinfo, dqi_valid));
-        LASSERTF((int)sizeof(((struct obd_dqinfo *)0)->dqi_valid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_dqinfo *)0)->dqi_valid));
-
-        /* Checks for struct obd_dqblk */
-        LASSERTF((int)sizeof(struct obd_dqblk) == 72, " found %lld\n",
-                 (long long)(int)sizeof(struct obd_dqblk));
-        LASSERTF((int)offsetof(struct obd_dqblk, dqb_bhardlimit) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_dqblk, dqb_bhardlimit));
-        LASSERTF((int)sizeof(((struct obd_dqblk *)0)->dqb_bhardlimit) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_dqblk *)0)->dqb_bhardlimit));
-        LASSERTF((int)offsetof(struct obd_dqblk, dqb_bsoftlimit) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_dqblk, dqb_bsoftlimit));
-        LASSERTF((int)sizeof(((struct obd_dqblk *)0)->dqb_bsoftlimit) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_dqblk *)0)->dqb_bsoftlimit));
-        LASSERTF((int)offsetof(struct obd_dqblk, dqb_curspace) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_dqblk, dqb_curspace));
-        LASSERTF((int)sizeof(((struct obd_dqblk *)0)->dqb_curspace) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_dqblk *)0)->dqb_curspace));
-        LASSERTF((int)offsetof(struct obd_dqblk, dqb_ihardlimit) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_dqblk, dqb_ihardlimit));
-        LASSERTF((int)sizeof(((struct obd_dqblk *)0)->dqb_ihardlimit) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_dqblk *)0)->dqb_ihardlimit));
-        LASSERTF((int)offsetof(struct obd_dqblk, dqb_isoftlimit) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_dqblk, dqb_isoftlimit));
-        LASSERTF((int)sizeof(((struct obd_dqblk *)0)->dqb_isoftlimit) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_dqblk *)0)->dqb_isoftlimit));
-        LASSERTF((int)offsetof(struct obd_dqblk, dqb_curinodes) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_dqblk, dqb_curinodes));
-        LASSERTF((int)sizeof(((struct obd_dqblk *)0)->dqb_curinodes) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_dqblk *)0)->dqb_curinodes));
-        LASSERTF((int)offsetof(struct obd_dqblk, dqb_btime) == 48, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_dqblk, dqb_btime));
-        LASSERTF((int)sizeof(((struct obd_dqblk *)0)->dqb_btime) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_dqblk *)0)->dqb_btime));
-        LASSERTF((int)offsetof(struct obd_dqblk, dqb_itime) == 56, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_dqblk, dqb_itime));
-        LASSERTF((int)sizeof(((struct obd_dqblk *)0)->dqb_itime) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_dqblk *)0)->dqb_itime));
-        LASSERTF((int)offsetof(struct obd_dqblk, dqb_valid) == 64, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_dqblk, dqb_valid));
-        LASSERTF((int)sizeof(((struct obd_dqblk *)0)->dqb_valid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_dqblk *)0)->dqb_valid));
-        LASSERTF((int)offsetof(struct obd_dqblk, padding) == 68, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_dqblk, padding));
-        LASSERTF((int)sizeof(((struct obd_dqblk *)0)->padding) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_dqblk *)0)->padding));
-        LASSERTF(Q_QUOTACHECK == 0x800100," found %lld\n",
-                 (long long)Q_QUOTACHECK);
-        LASSERTF(Q_INITQUOTA == 0x800101," found %lld\n",
-                 (long long)Q_INITQUOTA);
-        LASSERTF(Q_GETOINFO == 0x800102," found %lld\n",
-                 (long long)Q_GETOINFO);
-        LASSERTF(Q_GETOQUOTA == 0x800103," found %lld\n",
-                 (long long)Q_GETOQUOTA);
-
-        /* Checks for struct niobuf_remote */
-        LASSERTF((int)sizeof(struct niobuf_remote) == 16, " found %lld\n",
-                 (long long)(int)sizeof(struct niobuf_remote));
-        LASSERTF((int)offsetof(struct niobuf_remote, offset) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct niobuf_remote, offset));
-        LASSERTF((int)sizeof(((struct niobuf_remote *)0)->offset) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct niobuf_remote *)0)->offset));
-        LASSERTF((int)offsetof(struct niobuf_remote, len) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct niobuf_remote, len));
-        LASSERTF((int)sizeof(((struct niobuf_remote *)0)->len) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct niobuf_remote *)0)->len));
-        LASSERTF((int)offsetof(struct niobuf_remote, flags) == 12, " found %lld\n",
-                 (long long)(int)offsetof(struct niobuf_remote, flags));
-        LASSERTF((int)sizeof(((struct niobuf_remote *)0)->flags) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct niobuf_remote *)0)->flags));
-        LASSERTF(OBD_BRW_READ == 1, " found %lld\n",
-                 (long long)OBD_BRW_READ);
-        LASSERTF(OBD_BRW_WRITE == 2, " found %lld\n",
-                 (long long)OBD_BRW_WRITE);
-        LASSERTF(OBD_BRW_SYNC == 8, " found %lld\n",
-                 (long long)OBD_BRW_SYNC);
-        LASSERTF(OBD_BRW_FROM_GRANT == 32, " found %lld\n",
-                 (long long)OBD_BRW_FROM_GRANT);
-        LASSERTF(OBD_BRW_NOQUOTA == 256, " found %lld\n",
-                 (long long)OBD_BRW_NOQUOTA);
-
-        /* Checks for struct ost_body */
-        LASSERTF((int)sizeof(struct ost_body) == 208, " found %lld\n",
-                 (long long)(int)sizeof(struct ost_body));
-        LASSERTF((int)offsetof(struct ost_body, oa) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct ost_body, oa));
-        LASSERTF((int)sizeof(((struct ost_body *)0)->oa) == 208, " found %lld\n",
-                 (long long)(int)sizeof(((struct ost_body *)0)->oa));
-
-        /* Checks for struct ll_fid */
-        LASSERTF((int)sizeof(struct ll_fid) == 16, " found %lld\n",
-                 (long long)(int)sizeof(struct ll_fid));
-        LASSERTF((int)offsetof(struct ll_fid, id) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct ll_fid, id));
-        LASSERTF((int)sizeof(((struct ll_fid *)0)->id) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ll_fid *)0)->id));
-        LASSERTF((int)offsetof(struct ll_fid, generation) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct ll_fid, generation));
-        LASSERTF((int)sizeof(((struct ll_fid *)0)->generation) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct ll_fid *)0)->generation));
-        LASSERTF((int)offsetof(struct ll_fid, f_type) == 12, " found %lld\n",
-                 (long long)(int)offsetof(struct ll_fid, f_type));
-        LASSERTF((int)sizeof(((struct ll_fid *)0)->f_type) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct ll_fid *)0)->f_type));
-
-        /* Checks for struct mds_status_req */
-        LASSERTF((int)sizeof(struct mds_status_req) == 8, " found %lld\n",
-                 (long long)(int)sizeof(struct mds_status_req));
-        LASSERTF((int)offsetof(struct mds_status_req, flags) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_status_req, flags));
-        LASSERTF((int)sizeof(((struct mds_status_req *)0)->flags) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_status_req *)0)->flags));
-        LASSERTF((int)offsetof(struct mds_status_req, repbuf) == 4, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_status_req, repbuf));
-        LASSERTF((int)sizeof(((struct mds_status_req *)0)->repbuf) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_status_req *)0)->repbuf));
-
-        /* Checks for struct mds_body */
-        LASSERTF((int)sizeof(struct mds_body) == 168, " found %lld\n",
-                 (long long)(int)sizeof(struct mds_body));
-        LASSERTF((int)offsetof(struct mds_body, fid1) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, fid1));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->fid1) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->fid1));
-        LASSERTF((int)offsetof(struct mds_body, fid2) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, fid2));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->fid2) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->fid2));
-        LASSERTF((int)offsetof(struct mds_body, handle) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, handle));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->handle) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->handle));
-        LASSERTF((int)offsetof(struct mds_body, size) == 48, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, size));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->size) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->size));
-        LASSERTF((int)offsetof(struct mds_body, blocks) == 80, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, blocks));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->blocks) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->blocks));
-        LASSERTF((int)offsetof(struct mds_body, io_epoch) == 88, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, io_epoch));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->io_epoch) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->io_epoch));
-        LASSERTF((int)offsetof(struct mds_body, ino) == 96, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, ino));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->ino) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->ino));
-        LASSERTF((int)offsetof(struct mds_body, valid) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, valid));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->valid) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->valid));
-        LASSERTF((int)offsetof(struct mds_body, fsuid) == 104, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, fsuid));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->fsuid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->fsuid));
-        LASSERTF((int)offsetof(struct mds_body, fsgid) == 108, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, fsgid));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->fsgid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->fsgid));
-        LASSERTF((int)offsetof(struct mds_body, capability) == 112, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, capability));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->capability) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->capability));
-        LASSERTF((int)offsetof(struct mds_body, mode) == 116, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, mode));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->mode) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->mode));
-        LASSERTF((int)offsetof(struct mds_body, uid) == 120, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, uid));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->uid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->uid));
-        LASSERTF((int)offsetof(struct mds_body, gid) == 124, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, gid));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->gid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->gid));
-        LASSERTF((int)offsetof(struct mds_body, mtime) == 56, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, mtime));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->mtime) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->mtime));
-        LASSERTF((int)offsetof(struct mds_body, ctime) == 72, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, ctime));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->ctime) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->ctime));
-        LASSERTF((int)offsetof(struct mds_body, atime) == 64, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, atime));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->atime) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->atime));
-        LASSERTF((int)offsetof(struct mds_body, flags) == 128, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, flags));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->flags) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->flags));
-        LASSERTF((int)offsetof(struct mds_body, rdev) == 132, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, rdev));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->rdev) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->rdev));
-        LASSERTF((int)offsetof(struct mds_body, nlink) == 136, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, nlink));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->nlink) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->nlink));
-        LASSERTF((int)offsetof(struct mds_body, generation) == 140, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, generation));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->generation) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->generation));
-        LASSERTF((int)offsetof(struct mds_body, suppgid) == 144, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, suppgid));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->suppgid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->suppgid));
-        LASSERTF((int)offsetof(struct mds_body, eadatasize) == 148, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, eadatasize));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->eadatasize) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->eadatasize));
-        LASSERTF((int)offsetof(struct mds_body, aclsize) == 152, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, aclsize));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->aclsize) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->aclsize));
-        LASSERTF((int)offsetof(struct mds_body, max_mdsize) == 156, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, max_mdsize));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->max_mdsize) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->max_mdsize));
-        LASSERTF((int)offsetof(struct mds_body, max_cookiesize) == 160, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, max_cookiesize));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->max_cookiesize) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->max_cookiesize));
-        LASSERTF((int)offsetof(struct mds_body, padding_4) == 164, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, padding_4));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->padding_4) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->padding_4));
-        LASSERTF(FMODE_READ == 1, " found %lld\n",
-                 (long long)FMODE_READ);
-        LASSERTF(FMODE_WRITE == 2, " found %lld\n",
-                 (long long)FMODE_WRITE);
-        LASSERTF(MDS_FMODE_EXEC == 4, " found %lld\n",
-                 (long long)MDS_FMODE_EXEC);
-        CLASSERT(MDS_OPEN_CREAT == 00000100);
-        CLASSERT(MDS_OPEN_EXCL == 00000200);
-        CLASSERT(MDS_OPEN_TRUNC == 00001000);
-        CLASSERT(MDS_OPEN_APPEND == 00002000);
-        CLASSERT(MDS_OPEN_SYNC == 00010000);
-        CLASSERT(MDS_OPEN_DIRECTORY == 00200000);
-        CLASSERT(MDS_OPEN_DELAY_CREATE == 0100000000);
-        CLASSERT(MDS_OPEN_OWNEROVERRIDE == 0200000000);
-        CLASSERT(MDS_OPEN_JOIN_FILE == 0400000000);
-        CLASSERT(MDS_OPEN_HAS_EA == 010000000000);
-        CLASSERT(MDS_OPEN_HAS_OBJS == 020000000000);
-        CLASSERT(MDS_INODELOCK_LOOKUP == 0x000001);
-        CLASSERT(MDS_INODELOCK_UPDATE == 0x000002);
-        CLASSERT(MDS_INODELOCK_OPEN == 0x000004);
-
-        /* Checks for struct mds_rec_setattr */
-        LASSERTF((int)sizeof(struct mds_rec_setattr) == 96, " found %lld\n",
-                 (long long)(int)sizeof(struct mds_rec_setattr));
-        LASSERTF((int)offsetof(struct mds_rec_setattr, sa_opcode) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_setattr, sa_opcode));
-        LASSERTF((int)sizeof(((struct mds_rec_setattr *)0)->sa_opcode) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_setattr *)0)->sa_opcode));
-        LASSERTF((int)offsetof(struct mds_rec_setattr, sa_fsuid) == 4, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_setattr, sa_fsuid));
-        LASSERTF((int)sizeof(((struct mds_rec_setattr *)0)->sa_fsuid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_setattr *)0)->sa_fsuid));
-        LASSERTF((int)offsetof(struct mds_rec_setattr, sa_fsgid) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_setattr, sa_fsgid));
-        LASSERTF((int)sizeof(((struct mds_rec_setattr *)0)->sa_fsgid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_setattr *)0)->sa_fsgid));
-        LASSERTF((int)offsetof(struct mds_rec_setattr, sa_cap) == 12, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_setattr, sa_cap));
-        LASSERTF((int)sizeof(((struct mds_rec_setattr *)0)->sa_cap) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_setattr *)0)->sa_cap));
-        LASSERTF((int)offsetof(struct mds_rec_setattr, sa_suppgid) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_setattr, sa_suppgid));
-        LASSERTF((int)sizeof(((struct mds_rec_setattr *)0)->sa_suppgid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_setattr *)0)->sa_suppgid));
-        LASSERTF((int)offsetof(struct mds_rec_setattr, sa_mode) == 20, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_setattr, sa_mode));
-        LASSERTF((int)sizeof(((struct mds_rec_setattr *)0)->sa_mode) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_setattr *)0)->sa_mode));
-        LASSERTF((int)offsetof(struct mds_rec_setattr, sa_fid) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_setattr, sa_fid));
-        LASSERTF((int)sizeof(((struct mds_rec_setattr *)0)->sa_fid) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_setattr *)0)->sa_fid));
-        LASSERTF((int)offsetof(struct mds_rec_setattr, sa_valid) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_setattr, sa_valid));
-        LASSERTF((int)sizeof(((struct mds_rec_setattr *)0)->sa_valid) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_setattr *)0)->sa_valid));
-        LASSERTF((int)offsetof(struct mds_rec_setattr, sa_size) == 48, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_setattr, sa_size));
-        LASSERTF((int)sizeof(((struct mds_rec_setattr *)0)->sa_size) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_setattr *)0)->sa_size));
-        LASSERTF((int)offsetof(struct mds_rec_setattr, sa_mtime) == 56, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_setattr, sa_mtime));
-        LASSERTF((int)sizeof(((struct mds_rec_setattr *)0)->sa_mtime) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_setattr *)0)->sa_mtime));
-        LASSERTF((int)offsetof(struct mds_rec_setattr, sa_atime) == 64, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_setattr, sa_atime));
-        LASSERTF((int)sizeof(((struct mds_rec_setattr *)0)->sa_atime) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_setattr *)0)->sa_atime));
-        LASSERTF((int)offsetof(struct mds_rec_setattr, sa_ctime) == 72, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_setattr, sa_ctime));
-        LASSERTF((int)sizeof(((struct mds_rec_setattr *)0)->sa_ctime) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_setattr *)0)->sa_ctime));
-        LASSERTF((int)offsetof(struct mds_rec_setattr, sa_uid) == 80, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_setattr, sa_uid));
-        LASSERTF((int)sizeof(((struct mds_rec_setattr *)0)->sa_uid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_setattr *)0)->sa_uid));
-        LASSERTF((int)offsetof(struct mds_rec_setattr, sa_gid) == 84, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_setattr, sa_gid));
-        LASSERTF((int)sizeof(((struct mds_rec_setattr *)0)->sa_gid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_setattr *)0)->sa_gid));
-        LASSERTF((int)offsetof(struct mds_rec_setattr, sa_attr_flags) == 88, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_setattr, sa_attr_flags));
-        LASSERTF((int)sizeof(((struct mds_rec_setattr *)0)->sa_attr_flags) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_setattr *)0)->sa_attr_flags));
-
-        /* Checks for struct mds_rec_create */
-        LASSERTF((int)sizeof(struct mds_rec_create) == 96, " found %lld\n",
-                 (long long)(int)sizeof(struct mds_rec_create));
-        LASSERTF((int)offsetof(struct mds_rec_create, cr_opcode) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_create, cr_opcode));
-        LASSERTF((int)sizeof(((struct mds_rec_create *)0)->cr_opcode) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_create *)0)->cr_opcode));
-        LASSERTF((int)offsetof(struct mds_rec_create, cr_fsuid) == 4, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_create, cr_fsuid));
-        LASSERTF((int)sizeof(((struct mds_rec_create *)0)->cr_fsuid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_create *)0)->cr_fsuid));
-        LASSERTF((int)offsetof(struct mds_rec_create, cr_fsgid) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_create, cr_fsgid));
-        LASSERTF((int)sizeof(((struct mds_rec_create *)0)->cr_fsgid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_create *)0)->cr_fsgid));
-        LASSERTF((int)offsetof(struct mds_rec_create, cr_cap) == 12, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_create, cr_cap));
-        LASSERTF((int)sizeof(((struct mds_rec_create *)0)->cr_cap) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_create *)0)->cr_cap));
-        LASSERTF((int)offsetof(struct mds_rec_create, cr_flags) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_create, cr_flags));
-        LASSERTF((int)sizeof(((struct mds_rec_create *)0)->cr_flags) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_create *)0)->cr_flags));
-        LASSERTF((int)offsetof(struct mds_rec_create, cr_mode) == 20, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_create, cr_mode));
-        LASSERTF((int)sizeof(((struct mds_rec_create *)0)->cr_mode) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_create *)0)->cr_mode));
-        LASSERTF((int)offsetof(struct mds_rec_create, cr_fid) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_create, cr_fid));
-        LASSERTF((int)sizeof(((struct mds_rec_create *)0)->cr_fid) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_create *)0)->cr_fid));
-        LASSERTF((int)offsetof(struct mds_rec_create, cr_replayfid) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_create, cr_replayfid));
-        LASSERTF((int)sizeof(((struct mds_rec_create *)0)->cr_replayfid) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_create *)0)->cr_replayfid));
-        LASSERTF((int)offsetof(struct mds_rec_create, cr_time) == 56, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_create, cr_time));
-        LASSERTF((int)sizeof(((struct mds_rec_create *)0)->cr_time) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_create *)0)->cr_time));
-        LASSERTF((int)offsetof(struct mds_rec_create, cr_rdev) == 64, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_create, cr_rdev));
-        LASSERTF((int)sizeof(((struct mds_rec_create *)0)->cr_rdev) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_create *)0)->cr_rdev));
-        LASSERTF((int)offsetof(struct mds_rec_create, cr_suppgid) == 72, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_create, cr_suppgid));
-        LASSERTF((int)sizeof(((struct mds_rec_create *)0)->cr_suppgid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_create *)0)->cr_suppgid));
-
-        /* Checks for struct mds_rec_link */
-        LASSERTF((int)sizeof(struct mds_rec_link) == 80, " found %lld\n",
-                 (long long)(int)sizeof(struct mds_rec_link));
-        LASSERTF((int)offsetof(struct mds_rec_link, lk_opcode) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_link, lk_opcode));
-        LASSERTF((int)sizeof(((struct mds_rec_link *)0)->lk_opcode) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_link *)0)->lk_opcode));
-        LASSERTF((int)offsetof(struct mds_rec_link, lk_fsuid) == 4, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_link, lk_fsuid));
-        LASSERTF((int)sizeof(((struct mds_rec_link *)0)->lk_fsuid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_link *)0)->lk_fsuid));
-        LASSERTF((int)offsetof(struct mds_rec_link, lk_fsgid) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_link, lk_fsgid));
-        LASSERTF((int)sizeof(((struct mds_rec_link *)0)->lk_fsgid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_link *)0)->lk_fsgid));
-        LASSERTF((int)offsetof(struct mds_rec_link, lk_cap) == 12, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_link, lk_cap));
-        LASSERTF((int)sizeof(((struct mds_rec_link *)0)->lk_cap) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_link *)0)->lk_cap));
-        LASSERTF((int)offsetof(struct mds_rec_link, lk_suppgid1) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_link, lk_suppgid1));
-        LASSERTF((int)sizeof(((struct mds_rec_link *)0)->lk_suppgid1) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_link *)0)->lk_suppgid1));
-        LASSERTF((int)offsetof(struct mds_rec_link, lk_suppgid2) == 20, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_link, lk_suppgid2));
-        LASSERTF((int)sizeof(((struct mds_rec_link *)0)->lk_suppgid2) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_link *)0)->lk_suppgid2));
-        LASSERTF((int)offsetof(struct mds_rec_link, lk_fid1) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_link, lk_fid1));
-        LASSERTF((int)sizeof(((struct mds_rec_link *)0)->lk_fid1) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_link *)0)->lk_fid1));
-        LASSERTF((int)offsetof(struct mds_rec_link, lk_fid2) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_link, lk_fid2));
-        LASSERTF((int)sizeof(((struct mds_rec_link *)0)->lk_fid2) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_link *)0)->lk_fid2));
-        LASSERTF((int)offsetof(struct mds_rec_link, lk_time) == 56, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_link, lk_time));
-        LASSERTF((int)sizeof(((struct mds_rec_link *)0)->lk_time) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_link *)0)->lk_time));
-
-        /* Checks for struct mds_rec_unlink */
-        LASSERTF((int)sizeof(struct mds_rec_unlink) == 80, " found %lld\n",
-                 (long long)(int)sizeof(struct mds_rec_unlink));
-        LASSERTF((int)offsetof(struct mds_rec_unlink, ul_opcode) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_unlink, ul_opcode));
-        LASSERTF((int)sizeof(((struct mds_rec_unlink *)0)->ul_opcode) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_unlink *)0)->ul_opcode));
-        LASSERTF((int)offsetof(struct mds_rec_unlink, ul_fsuid) == 4, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_unlink, ul_fsuid));
-        LASSERTF((int)sizeof(((struct mds_rec_unlink *)0)->ul_fsuid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_unlink *)0)->ul_fsuid));
-        LASSERTF((int)offsetof(struct mds_rec_unlink, ul_fsgid) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_unlink, ul_fsgid));
-        LASSERTF((int)sizeof(((struct mds_rec_unlink *)0)->ul_fsgid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_unlink *)0)->ul_fsgid));
-        LASSERTF((int)offsetof(struct mds_rec_unlink, ul_cap) == 12, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_unlink, ul_cap));
-        LASSERTF((int)sizeof(((struct mds_rec_unlink *)0)->ul_cap) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_unlink *)0)->ul_cap));
-        LASSERTF((int)offsetof(struct mds_rec_unlink, ul_suppgid) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_unlink, ul_suppgid));
-        LASSERTF((int)sizeof(((struct mds_rec_unlink *)0)->ul_suppgid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_unlink *)0)->ul_suppgid));
-        LASSERTF((int)offsetof(struct mds_rec_unlink, ul_mode) == 20, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_unlink, ul_mode));
-        LASSERTF((int)sizeof(((struct mds_rec_unlink *)0)->ul_mode) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_unlink *)0)->ul_mode));
-        LASSERTF((int)offsetof(struct mds_rec_unlink, ul_fid1) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_unlink, ul_fid1));
-        LASSERTF((int)sizeof(((struct mds_rec_unlink *)0)->ul_fid1) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_unlink *)0)->ul_fid1));
-        LASSERTF((int)offsetof(struct mds_rec_unlink, ul_fid2) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_unlink, ul_fid2));
-        LASSERTF((int)sizeof(((struct mds_rec_unlink *)0)->ul_fid2) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_unlink *)0)->ul_fid2));
-        LASSERTF((int)offsetof(struct mds_rec_unlink, ul_time) == 56, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_unlink, ul_time));
-        LASSERTF((int)sizeof(((struct mds_rec_unlink *)0)->ul_time) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_unlink *)0)->ul_time));
-
-        /* Checks for struct mds_rec_rename */
-        LASSERTF((int)sizeof(struct mds_rec_rename) == 80, " found %lld\n",
-                 (long long)(int)sizeof(struct mds_rec_rename));
-        LASSERTF((int)offsetof(struct mds_rec_rename, rn_opcode) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_rename, rn_opcode));
-        LASSERTF((int)sizeof(((struct mds_rec_rename *)0)->rn_opcode) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_rename *)0)->rn_opcode));
-        LASSERTF((int)offsetof(struct mds_rec_rename, rn_fsuid) == 4, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_rename, rn_fsuid));
-        LASSERTF((int)sizeof(((struct mds_rec_rename *)0)->rn_fsuid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_rename *)0)->rn_fsuid));
-        LASSERTF((int)offsetof(struct mds_rec_rename, rn_fsgid) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_rename, rn_fsgid));
-        LASSERTF((int)sizeof(((struct mds_rec_rename *)0)->rn_fsgid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_rename *)0)->rn_fsgid));
-        LASSERTF((int)offsetof(struct mds_rec_rename, rn_cap) == 12, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_rename, rn_cap));
-        LASSERTF((int)sizeof(((struct mds_rec_rename *)0)->rn_cap) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_rename *)0)->rn_cap));
-        LASSERTF((int)offsetof(struct mds_rec_rename, rn_suppgid1) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_rename, rn_suppgid1));
-        LASSERTF((int)sizeof(((struct mds_rec_rename *)0)->rn_suppgid1) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_rename *)0)->rn_suppgid1));
-        LASSERTF((int)offsetof(struct mds_rec_rename, rn_suppgid2) == 20, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_rename, rn_suppgid2));
-        LASSERTF((int)sizeof(((struct mds_rec_rename *)0)->rn_suppgid2) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_rename *)0)->rn_suppgid2));
-        LASSERTF((int)offsetof(struct mds_rec_rename, rn_fid1) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_rename, rn_fid1));
-        LASSERTF((int)sizeof(((struct mds_rec_rename *)0)->rn_fid1) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_rename *)0)->rn_fid1));
-        LASSERTF((int)offsetof(struct mds_rec_rename, rn_fid2) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_rename, rn_fid2));
-        LASSERTF((int)sizeof(((struct mds_rec_rename *)0)->rn_fid2) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_rename *)0)->rn_fid2));
-        LASSERTF((int)offsetof(struct mds_rec_rename, rn_time) == 56, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_rename, rn_time));
-        LASSERTF((int)sizeof(((struct mds_rec_rename *)0)->rn_time) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_rename *)0)->rn_time));
-
-        /* Checks for struct mds_rec_join */
-        LASSERTF((int)sizeof(struct mds_rec_join) == 24, " found %lld\n",
-                 (long long)(int)sizeof(struct mds_rec_join));
-        LASSERTF((int)offsetof(struct mds_rec_join, jr_fid) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_join, jr_fid));
-        LASSERTF((int)sizeof(((struct mds_rec_join *)0)->jr_fid) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_join *)0)->jr_fid));
-        LASSERTF((int)offsetof(struct mds_rec_join, jr_headsize) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_join, jr_headsize));
-        LASSERTF((int)sizeof(((struct mds_rec_join *)0)->jr_headsize) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_join *)0)->jr_headsize));
-
-        /* Checks for struct lov_desc */
-        LASSERTF((int)sizeof(struct lov_desc) == 88, " found %lld\n",
-                 (long long)(int)sizeof(struct lov_desc));
-        LASSERTF((int)offsetof(struct lov_desc, ld_tgt_count) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_desc, ld_tgt_count));
-        LASSERTF((int)sizeof(((struct lov_desc *)0)->ld_tgt_count) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_desc *)0)->ld_tgt_count));
-        LASSERTF((int)offsetof(struct lov_desc, ld_active_tgt_count) == 4, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_desc, ld_active_tgt_count));
-        LASSERTF((int)sizeof(((struct lov_desc *)0)->ld_active_tgt_count) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_desc *)0)->ld_active_tgt_count));
-        LASSERTF((int)offsetof(struct lov_desc, ld_default_stripe_count) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_desc, ld_default_stripe_count));
-        LASSERTF((int)sizeof(((struct lov_desc *)0)->ld_default_stripe_count) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_desc *)0)->ld_default_stripe_count));
-        LASSERTF((int)offsetof(struct lov_desc, ld_pattern) == 12, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_desc, ld_pattern));
-        LASSERTF((int)sizeof(((struct lov_desc *)0)->ld_pattern) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_desc *)0)->ld_pattern));
-        LASSERTF((int)offsetof(struct lov_desc, ld_default_stripe_size) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_desc, ld_default_stripe_size));
-        LASSERTF((int)sizeof(((struct lov_desc *)0)->ld_default_stripe_size) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_desc *)0)->ld_default_stripe_size));
-        LASSERTF((int)offsetof(struct lov_desc, ld_default_stripe_offset) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_desc, ld_default_stripe_offset));
-        LASSERTF((int)sizeof(((struct lov_desc *)0)->ld_default_stripe_offset) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_desc *)0)->ld_default_stripe_offset));
-        LASSERTF((int)offsetof(struct lov_desc, ld_qos_threshold) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_desc, ld_qos_threshold));
-        LASSERTF((int)sizeof(((struct lov_desc *)0)->ld_qos_threshold) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_desc *)0)->ld_qos_threshold));
-        LASSERTF((int)offsetof(struct lov_desc, ld_qos_maxage) == 36, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_desc, ld_qos_maxage));
-        LASSERTF((int)sizeof(((struct lov_desc *)0)->ld_qos_maxage) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_desc *)0)->ld_qos_maxage));
-        LASSERTF((int)offsetof(struct lov_desc, ld_padding_1) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_desc, ld_padding_1));
-        LASSERTF((int)sizeof(((struct lov_desc *)0)->ld_padding_1) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_desc *)0)->ld_padding_1));
-        LASSERTF((int)offsetof(struct lov_desc, ld_padding_2) == 44, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_desc, ld_padding_2));
-        LASSERTF((int)sizeof(((struct lov_desc *)0)->ld_padding_2) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_desc *)0)->ld_padding_2));
-        LASSERTF((int)offsetof(struct lov_desc, ld_uuid) == 48, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_desc, ld_uuid));
-        LASSERTF((int)sizeof(((struct lov_desc *)0)->ld_uuid) == 40, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_desc *)0)->ld_uuid));
-
-        /* Checks for struct ldlm_res_id */
-        LASSERTF((int)sizeof(struct ldlm_res_id) == 32, " found %lld\n",
-                 (long long)(int)sizeof(struct ldlm_res_id));
-        LASSERTF((int)offsetof(struct ldlm_res_id, name[4]) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_res_id, name[4]));
-        LASSERTF((int)sizeof(((struct ldlm_res_id *)0)->name[4]) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_res_id *)0)->name[4]));
-
-        /* Checks for struct ldlm_extent */
-        LASSERTF((int)sizeof(struct ldlm_extent) == 24, " found %lld\n",
-                 (long long)(int)sizeof(struct ldlm_extent));
-        LASSERTF((int)offsetof(struct ldlm_extent, start) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_extent, start));
-        LASSERTF((int)sizeof(((struct ldlm_extent *)0)->start) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_extent *)0)->start));
-        LASSERTF((int)offsetof(struct ldlm_extent, end) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_extent, end));
-        LASSERTF((int)sizeof(((struct ldlm_extent *)0)->end) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_extent *)0)->end));
-        LASSERTF((int)offsetof(struct ldlm_extent, gid) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_extent, gid));
-        LASSERTF((int)sizeof(((struct ldlm_extent *)0)->gid) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_extent *)0)->gid));
-
-        /* Checks for struct ldlm_flock */
-        LASSERTF((int)sizeof(struct ldlm_flock) == 32, " found %lld\n",
-                 (long long)(int)sizeof(struct ldlm_flock));
-        LASSERTF((int)offsetof(struct ldlm_flock, start) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_flock, start));
-        LASSERTF((int)sizeof(((struct ldlm_flock *)0)->start) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_flock *)0)->start));
-        LASSERTF((int)offsetof(struct ldlm_flock, end) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_flock, end));
-        LASSERTF((int)sizeof(((struct ldlm_flock *)0)->end) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_flock *)0)->end));
-        LASSERTF((int)offsetof(struct ldlm_flock, blocking_pid) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_flock, blocking_pid));
-        LASSERTF((int)sizeof(((struct ldlm_flock *)0)->blocking_pid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_flock *)0)->blocking_pid));
-        LASSERTF((int)offsetof(struct ldlm_flock, pid) == 28, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_flock, pid));
-        LASSERTF((int)sizeof(((struct ldlm_flock *)0)->pid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_flock *)0)->pid));
-
-        /* Checks for struct ldlm_inodebits */
-        LASSERTF((int)sizeof(struct ldlm_inodebits) == 8, " found %lld\n",
-                 (long long)(int)sizeof(struct ldlm_inodebits));
-        LASSERTF((int)offsetof(struct ldlm_inodebits, bits) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_inodebits, bits));
-        LASSERTF((int)sizeof(((struct ldlm_inodebits *)0)->bits) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_inodebits *)0)->bits));
-
-        /* Checks for struct ldlm_intent */
-        LASSERTF((int)sizeof(struct ldlm_intent) == 8, " found %lld\n",
-                 (long long)(int)sizeof(struct ldlm_intent));
-        LASSERTF((int)offsetof(struct ldlm_intent, opc) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_intent, opc));
-        LASSERTF((int)sizeof(((struct ldlm_intent *)0)->opc) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_intent *)0)->opc));
-
-        /* Checks for struct ldlm_resource_desc */
-        LASSERTF((int)sizeof(struct ldlm_resource_desc) == 40, " found %lld\n",
-                 (long long)(int)sizeof(struct ldlm_resource_desc));
-        LASSERTF((int)offsetof(struct ldlm_resource_desc, lr_type) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_resource_desc, lr_type));
-        LASSERTF((int)sizeof(((struct ldlm_resource_desc *)0)->lr_type) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_resource_desc *)0)->lr_type));
-        LASSERTF((int)offsetof(struct ldlm_resource_desc, lr_padding) == 4, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_resource_desc, lr_padding));
-        LASSERTF((int)sizeof(((struct ldlm_resource_desc *)0)->lr_padding) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_resource_desc *)0)->lr_padding));
-        LASSERTF((int)offsetof(struct ldlm_resource_desc, lr_name) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_resource_desc, lr_name));
-        LASSERTF((int)sizeof(((struct ldlm_resource_desc *)0)->lr_name) == 32, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_resource_desc *)0)->lr_name));
-
-        /* Checks for struct ldlm_lock_desc */
-        LASSERTF((int)sizeof(struct ldlm_lock_desc) == 80, " found %lld\n",
-                 (long long)(int)sizeof(struct ldlm_lock_desc));
-        LASSERTF((int)offsetof(struct ldlm_lock_desc, l_resource) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_lock_desc, l_resource));
-        LASSERTF((int)sizeof(((struct ldlm_lock_desc *)0)->l_resource) == 40, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_lock_desc *)0)->l_resource));
-        LASSERTF((int)offsetof(struct ldlm_lock_desc, l_req_mode) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_lock_desc, l_req_mode));
-        LASSERTF((int)sizeof(((struct ldlm_lock_desc *)0)->l_req_mode) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_lock_desc *)0)->l_req_mode));
-        LASSERTF((int)offsetof(struct ldlm_lock_desc, l_granted_mode) == 44, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_lock_desc, l_granted_mode));
-        LASSERTF((int)sizeof(((struct ldlm_lock_desc *)0)->l_granted_mode) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_lock_desc *)0)->l_granted_mode));
-        LASSERTF((int)offsetof(struct ldlm_lock_desc, l_policy_data) == 48, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_lock_desc, l_policy_data));
-        LASSERTF((int)sizeof(((struct ldlm_lock_desc *)0)->l_policy_data) == 32, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_lock_desc *)0)->l_policy_data));
-
-        /* Checks for struct ldlm_request */
-        LASSERTF((int)sizeof(struct ldlm_request) == 104, " found %lld\n",
-                 (long long)(int)sizeof(struct ldlm_request));
-        LASSERTF((int)offsetof(struct ldlm_request, lock_flags) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_request, lock_flags));
-        LASSERTF((int)sizeof(((struct ldlm_request *)0)->lock_flags) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_request *)0)->lock_flags));
-        LASSERTF((int)offsetof(struct ldlm_request, lock_padding) == 4, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_request, lock_padding));
-        LASSERTF((int)sizeof(((struct ldlm_request *)0)->lock_padding) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_request *)0)->lock_padding));
-        LASSERTF((int)offsetof(struct ldlm_request, lock_desc) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_request, lock_desc));
-        LASSERTF((int)sizeof(((struct ldlm_request *)0)->lock_desc) == 80, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_request *)0)->lock_desc));
-        LASSERTF((int)offsetof(struct ldlm_request, lock_handle1) == 88, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_request, lock_handle1));
-        LASSERTF((int)sizeof(((struct ldlm_request *)0)->lock_handle1) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_request *)0)->lock_handle1));
-        LASSERTF((int)offsetof(struct ldlm_request, lock_handle2) == 96, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_request, lock_handle2));
-        LASSERTF((int)sizeof(((struct ldlm_request *)0)->lock_handle2) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_request *)0)->lock_handle2));
-
-        /* Checks for struct ldlm_reply */
-        LASSERTF((int)sizeof(struct ldlm_reply) == 112, " found %lld\n",
-                 (long long)(int)sizeof(struct ldlm_reply));
-        LASSERTF((int)offsetof(struct ldlm_reply, lock_flags) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_reply, lock_flags));
-        LASSERTF((int)sizeof(((struct ldlm_reply *)0)->lock_flags) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_reply *)0)->lock_flags));
-        LASSERTF((int)offsetof(struct ldlm_request, lock_padding) == 4, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_request, lock_padding));
-        LASSERTF((int)sizeof(((struct ldlm_request *)0)->lock_padding) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_request *)0)->lock_padding));
-        LASSERTF((int)offsetof(struct ldlm_request, lock_desc) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_request, lock_desc));
-        LASSERTF((int)sizeof(((struct ldlm_request *)0)->lock_desc) == 80, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_request *)0)->lock_desc));
-        LASSERTF((int)offsetof(struct ldlm_reply, lock_handle) == 88, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_reply, lock_handle));
-        LASSERTF((int)sizeof(((struct ldlm_reply *)0)->lock_handle) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_reply *)0)->lock_handle));
-        LASSERTF((int)offsetof(struct ldlm_reply, lock_policy_res1) == 96, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_reply, lock_policy_res1));
-        LASSERTF((int)sizeof(((struct ldlm_reply *)0)->lock_policy_res1) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_reply *)0)->lock_policy_res1));
-        LASSERTF((int)offsetof(struct ldlm_reply, lock_policy_res2) == 104, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_reply, lock_policy_res2));
-        LASSERTF((int)sizeof(((struct ldlm_reply *)0)->lock_policy_res2) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_reply *)0)->lock_policy_res2));
-
-        /* Checks for struct ost_lvb */
-        LASSERTF((int)sizeof(struct ost_lvb) == 40, " found %lld\n",
-                 (long long)(int)sizeof(struct ost_lvb));
-        LASSERTF((int)offsetof(struct ost_lvb, lvb_size) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct ost_lvb, lvb_size));
-        LASSERTF((int)sizeof(((struct ost_lvb *)0)->lvb_size) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ost_lvb *)0)->lvb_size));
-        LASSERTF((int)offsetof(struct ost_lvb, lvb_mtime) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct ost_lvb, lvb_mtime));
-        LASSERTF((int)sizeof(((struct ost_lvb *)0)->lvb_mtime) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ost_lvb *)0)->lvb_mtime));
-        LASSERTF((int)offsetof(struct ost_lvb, lvb_atime) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct ost_lvb, lvb_atime));
-        LASSERTF((int)sizeof(((struct ost_lvb *)0)->lvb_atime) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ost_lvb *)0)->lvb_atime));
-        LASSERTF((int)offsetof(struct ost_lvb, lvb_ctime) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct ost_lvb, lvb_ctime));
-        LASSERTF((int)sizeof(((struct ost_lvb *)0)->lvb_ctime) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ost_lvb *)0)->lvb_ctime));
-        LASSERTF((int)offsetof(struct ost_lvb, lvb_blocks) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct ost_lvb, lvb_blocks));
-        LASSERTF((int)sizeof(((struct ost_lvb *)0)->lvb_blocks) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ost_lvb *)0)->lvb_blocks));
-
-        /* Checks for struct llog_logid */
-        LASSERTF((int)sizeof(struct llog_logid) == 20, " found %lld\n",
-                 (long long)(int)sizeof(struct llog_logid));
-        LASSERTF((int)offsetof(struct llog_logid, lgl_oid) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_logid, lgl_oid));
-        LASSERTF((int)sizeof(((struct llog_logid *)0)->lgl_oid) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_logid *)0)->lgl_oid));
-        LASSERTF((int)offsetof(struct llog_logid, lgl_ogr) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_logid, lgl_ogr));
-        LASSERTF((int)sizeof(((struct llog_logid *)0)->lgl_ogr) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_logid *)0)->lgl_ogr));
-        LASSERTF((int)offsetof(struct llog_logid, lgl_ogen) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_logid, lgl_ogen));
-        LASSERTF((int)sizeof(((struct llog_logid *)0)->lgl_ogen) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_logid *)0)->lgl_ogen));
-        CLASSERT(OST_SZ_REC == 274730752);
-        CLASSERT(OST_RAID1_REC == 274731008);
-        CLASSERT(MDS_UNLINK_REC == 274801668);
-        CLASSERT(MDS_SETATTR_REC == 274801665);
-        CLASSERT(OBD_CFG_REC == 274857984);
-        CLASSERT(PTL_CFG_REC == 274923520);
-        CLASSERT(LLOG_GEN_REC == 274989056);
-        CLASSERT(LLOG_JOIN_REC == 275054592);
-        CLASSERT(LLOG_HDR_MAGIC == 275010873);
-        CLASSERT(LLOG_LOGID_MAGIC == 275010875);
-
-        /* Checks for struct llog_catid */
-        LASSERTF((int)sizeof(struct llog_catid) == 32, " found %lld\n",
-                 (long long)(int)sizeof(struct llog_catid));
-        LASSERTF((int)offsetof(struct llog_catid, lci_logid) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_catid, lci_logid));
-        LASSERTF((int)sizeof(((struct llog_catid *)0)->lci_logid) == 20, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_catid *)0)->lci_logid));
-        LASSERTF((int)offsetof(struct llog_catid, lci_padding1) == 20, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_catid, lci_padding1));
-        LASSERTF((int)sizeof(((struct llog_catid *)0)->lci_padding1) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_catid *)0)->lci_padding1));
-        LASSERTF((int)offsetof(struct llog_catid, lci_padding2) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_catid, lci_padding2));
-        LASSERTF((int)sizeof(((struct llog_catid *)0)->lci_padding2) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_catid *)0)->lci_padding2));
-        LASSERTF((int)offsetof(struct llog_catid, lci_padding3) == 28, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_catid, lci_padding3));
-        LASSERTF((int)sizeof(((struct llog_catid *)0)->lci_padding3) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_catid *)0)->lci_padding3));
-
-        /* Checks for struct llog_rec_hdr */
-        LASSERTF((int)sizeof(struct llog_rec_hdr) == 16, " found %lld\n",
-                 (long long)(int)sizeof(struct llog_rec_hdr));
-        LASSERTF((int)offsetof(struct llog_rec_hdr, lrh_len) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_rec_hdr, lrh_len));
-        LASSERTF((int)sizeof(((struct llog_rec_hdr *)0)->lrh_len) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_rec_hdr *)0)->lrh_len));
-        LASSERTF((int)offsetof(struct llog_rec_hdr, lrh_index) == 4, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_rec_hdr, lrh_index));
-        LASSERTF((int)sizeof(((struct llog_rec_hdr *)0)->lrh_index) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_rec_hdr *)0)->lrh_index));
-        LASSERTF((int)offsetof(struct llog_rec_hdr, lrh_type) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_rec_hdr, lrh_type));
-        LASSERTF((int)sizeof(((struct llog_rec_hdr *)0)->lrh_type) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_rec_hdr *)0)->lrh_type));
-        LASSERTF((int)offsetof(struct llog_rec_hdr, padding) == 12, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_rec_hdr, padding));
-        LASSERTF((int)sizeof(((struct llog_rec_hdr *)0)->padding) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_rec_hdr *)0)->padding));
-
-        /* Checks for struct llog_rec_tail */
-        LASSERTF((int)sizeof(struct llog_rec_tail) == 8, " found %lld\n",
-                 (long long)(int)sizeof(struct llog_rec_tail));
-        LASSERTF((int)offsetof(struct llog_rec_tail, lrt_len) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_rec_tail, lrt_len));
-        LASSERTF((int)sizeof(((struct llog_rec_tail *)0)->lrt_len) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_rec_tail *)0)->lrt_len));
-        LASSERTF((int)offsetof(struct llog_rec_tail, lrt_index) == 4, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_rec_tail, lrt_index));
-        LASSERTF((int)sizeof(((struct llog_rec_tail *)0)->lrt_index) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_rec_tail *)0)->lrt_index));
-
-        /* Checks for struct llog_logid_rec */
-        LASSERTF((int)sizeof(struct llog_logid_rec) == 64, " found %lld\n",
-                 (long long)(int)sizeof(struct llog_logid_rec));
-        LASSERTF((int)offsetof(struct llog_logid_rec, lid_hdr) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_logid_rec, lid_hdr));
-        LASSERTF((int)sizeof(((struct llog_logid_rec *)0)->lid_hdr) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_logid_rec *)0)->lid_hdr));
-        LASSERTF((int)offsetof(struct llog_logid_rec, lid_id) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_logid_rec, lid_id));
-        LASSERTF((int)sizeof(((struct llog_logid_rec *)0)->lid_id) == 20, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_logid_rec *)0)->lid_id));
-        LASSERTF((int)offsetof(struct llog_logid_rec, padding1) == 36, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_logid_rec, padding1));
-        LASSERTF((int)sizeof(((struct llog_logid_rec *)0)->padding1) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_logid_rec *)0)->padding1));
-        LASSERTF((int)offsetof(struct llog_logid_rec, padding2) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_logid_rec, padding2));
-        LASSERTF((int)sizeof(((struct llog_logid_rec *)0)->padding2) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_logid_rec *)0)->padding2));
-        LASSERTF((int)offsetof(struct llog_logid_rec, padding3) == 44, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_logid_rec, padding3));
-        LASSERTF((int)sizeof(((struct llog_logid_rec *)0)->padding3) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_logid_rec *)0)->padding3));
-        LASSERTF((int)offsetof(struct llog_logid_rec, padding4) == 48, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_logid_rec, padding4));
-        LASSERTF((int)sizeof(((struct llog_logid_rec *)0)->padding4) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_logid_rec *)0)->padding4));
-        LASSERTF((int)offsetof(struct llog_logid_rec, padding5) == 52, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_logid_rec, padding5));
-        LASSERTF((int)sizeof(((struct llog_logid_rec *)0)->padding5) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_logid_rec *)0)->padding5));
-        LASSERTF((int)offsetof(struct llog_logid_rec, lid_tail) == 56, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_logid_rec, lid_tail));
-        LASSERTF((int)sizeof(((struct llog_logid_rec *)0)->lid_tail) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_logid_rec *)0)->lid_tail));
-
-        /* Checks for struct llog_create_rec */
-        LASSERTF((int)sizeof(struct llog_create_rec) == 56, " found %lld\n",
-                 (long long)(int)sizeof(struct llog_create_rec));
-        LASSERTF((int)offsetof(struct llog_create_rec, lcr_hdr) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_create_rec, lcr_hdr));
-        LASSERTF((int)sizeof(((struct llog_create_rec *)0)->lcr_hdr) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_create_rec *)0)->lcr_hdr));
-        LASSERTF((int)offsetof(struct llog_create_rec, lcr_fid) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_create_rec, lcr_fid));
-        LASSERTF((int)sizeof(((struct llog_create_rec *)0)->lcr_fid) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_create_rec *)0)->lcr_fid));
-        LASSERTF((int)offsetof(struct llog_create_rec, lcr_oid) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_create_rec, lcr_oid));
-        LASSERTF((int)sizeof(((struct llog_create_rec *)0)->lcr_oid) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_create_rec *)0)->lcr_oid));
-        LASSERTF((int)offsetof(struct llog_create_rec, lcr_ogen) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_create_rec, lcr_ogen));
-        LASSERTF((int)sizeof(((struct llog_create_rec *)0)->lcr_ogen) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_create_rec *)0)->lcr_ogen));
-        LASSERTF((int)offsetof(struct llog_create_rec, padding) == 44, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_create_rec, padding));
-        LASSERTF((int)sizeof(((struct llog_create_rec *)0)->padding) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_create_rec *)0)->padding));
-
-        /* Checks for struct llog_orphan_rec */
-        LASSERTF((int)sizeof(struct llog_orphan_rec) == 40, " found %lld\n",
-                 (long long)(int)sizeof(struct llog_orphan_rec));
-        LASSERTF((int)offsetof(struct llog_orphan_rec, lor_hdr) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_orphan_rec, lor_hdr));
-        LASSERTF((int)sizeof(((struct llog_orphan_rec *)0)->lor_hdr) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_orphan_rec *)0)->lor_hdr));
-        LASSERTF((int)offsetof(struct llog_orphan_rec, lor_oid) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_orphan_rec, lor_oid));
-        LASSERTF((int)sizeof(((struct llog_orphan_rec *)0)->lor_oid) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_orphan_rec *)0)->lor_oid));
-        LASSERTF((int)offsetof(struct llog_orphan_rec, lor_ogen) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_orphan_rec, lor_ogen));
-        LASSERTF((int)sizeof(((struct llog_orphan_rec *)0)->lor_ogen) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_orphan_rec *)0)->lor_ogen));
-        LASSERTF((int)offsetof(struct llog_orphan_rec, padding) == 28, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_orphan_rec, padding));
-        LASSERTF((int)sizeof(((struct llog_orphan_rec *)0)->padding) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_orphan_rec *)0)->padding));
-        LASSERTF((int)offsetof(struct llog_orphan_rec, lor_tail) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_orphan_rec, lor_tail));
-        LASSERTF((int)sizeof(((struct llog_orphan_rec *)0)->lor_tail) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_orphan_rec *)0)->lor_tail));
-
-        /* Checks for struct llog_unlink_rec */
-        LASSERTF((int)sizeof(struct llog_unlink_rec) == 40, " found %lld\n",
-                 (long long)(int)sizeof(struct llog_unlink_rec));
-        LASSERTF((int)offsetof(struct llog_unlink_rec, lur_hdr) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_unlink_rec, lur_hdr));
-        LASSERTF((int)sizeof(((struct llog_unlink_rec *)0)->lur_hdr) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_unlink_rec *)0)->lur_hdr));
-        LASSERTF((int)offsetof(struct llog_unlink_rec, lur_oid) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_unlink_rec, lur_oid));
-        LASSERTF((int)sizeof(((struct llog_unlink_rec *)0)->lur_oid) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_unlink_rec *)0)->lur_oid));
-        LASSERTF((int)offsetof(struct llog_unlink_rec, lur_ogen) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_unlink_rec, lur_ogen));
-        LASSERTF((int)sizeof(((struct llog_unlink_rec *)0)->lur_ogen) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_unlink_rec *)0)->lur_ogen));
-        LASSERTF((int)offsetof(struct llog_unlink_rec, padding) == 28, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_unlink_rec, padding));
-        LASSERTF((int)sizeof(((struct llog_unlink_rec *)0)->padding) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_unlink_rec *)0)->padding));
-        LASSERTF((int)offsetof(struct llog_unlink_rec, lur_tail) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_unlink_rec, lur_tail));
-        LASSERTF((int)sizeof(((struct llog_unlink_rec *)0)->lur_tail) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_unlink_rec *)0)->lur_tail));
-
-        /* Checks for struct llog_setattr_rec */
-        LASSERTF((int)sizeof(struct llog_setattr_rec) == 48, " found %lld\n",
-                 (long long)(int)sizeof(struct llog_setattr_rec));
-        LASSERTF((int)offsetof(struct llog_setattr_rec, lsr_hdr) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_setattr_rec, lsr_hdr));
-        LASSERTF((int)sizeof(((struct llog_setattr_rec *)0)->lsr_hdr) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_setattr_rec *)0)->lsr_hdr));
-        LASSERTF((int)offsetof(struct llog_setattr_rec, lsr_oid) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_setattr_rec, lsr_oid));
-        LASSERTF((int)sizeof(((struct llog_setattr_rec *)0)->lsr_oid) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_setattr_rec *)0)->lsr_oid));
-        LASSERTF((int)offsetof(struct llog_setattr_rec, lsr_ogen) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_setattr_rec, lsr_ogen));
-        LASSERTF((int)sizeof(((struct llog_setattr_rec *)0)->lsr_ogen) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_setattr_rec *)0)->lsr_ogen));
-        LASSERTF((int)offsetof(struct llog_setattr_rec, lsr_uid) == 28, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_setattr_rec, lsr_uid));
-        LASSERTF((int)sizeof(((struct llog_setattr_rec *)0)->lsr_uid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_setattr_rec *)0)->lsr_uid));
-        LASSERTF((int)offsetof(struct llog_setattr_rec, lsr_gid) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_setattr_rec, lsr_gid));
-        LASSERTF((int)sizeof(((struct llog_setattr_rec *)0)->lsr_gid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_setattr_rec *)0)->lsr_gid));
-        LASSERTF((int)offsetof(struct llog_setattr_rec, padding) == 36, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_setattr_rec, padding));
-        LASSERTF((int)sizeof(((struct llog_setattr_rec *)0)->padding) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_setattr_rec *)0)->padding));
-        LASSERTF((int)offsetof(struct llog_setattr_rec, lsr_tail) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_setattr_rec, lsr_tail));
-        LASSERTF((int)sizeof(((struct llog_setattr_rec *)0)->lsr_tail) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_setattr_rec *)0)->lsr_tail));
-
-        /* Checks for struct llog_size_change_rec */
-        LASSERTF((int)sizeof(struct llog_size_change_rec) == 48, " found %lld\n",
-                 (long long)(int)sizeof(struct llog_size_change_rec));
-        LASSERTF((int)offsetof(struct llog_size_change_rec, lsc_hdr) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_size_change_rec, lsc_hdr));
-        LASSERTF((int)sizeof(((struct llog_size_change_rec *)0)->lsc_hdr) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_size_change_rec *)0)->lsc_hdr));
-        LASSERTF((int)offsetof(struct llog_size_change_rec, lsc_fid) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_size_change_rec, lsc_fid));
-        LASSERTF((int)sizeof(((struct llog_size_change_rec *)0)->lsc_fid) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_size_change_rec *)0)->lsc_fid));
-        LASSERTF((int)offsetof(struct llog_size_change_rec, lsc_io_epoch) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_size_change_rec, lsc_io_epoch));
-        LASSERTF((int)sizeof(((struct llog_size_change_rec *)0)->lsc_io_epoch) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_size_change_rec *)0)->lsc_io_epoch));
-        LASSERTF((int)offsetof(struct llog_size_change_rec, padding) == 36, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_size_change_rec, padding));
-        LASSERTF((int)sizeof(((struct llog_size_change_rec *)0)->padding) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_size_change_rec *)0)->padding));
-        LASSERTF((int)offsetof(struct llog_size_change_rec, lsc_tail) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_size_change_rec, lsc_tail));
-        LASSERTF((int)sizeof(((struct llog_size_change_rec *)0)->lsc_tail) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_size_change_rec *)0)->lsc_tail));
-
-        /* Checks for struct llog_gen */
-        LASSERTF((int)sizeof(struct llog_gen) == 16, " found %lld\n",
-                 (long long)(int)sizeof(struct llog_gen));
-        LASSERTF((int)offsetof(struct llog_gen, mnt_cnt) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_gen, mnt_cnt));
-        LASSERTF((int)sizeof(((struct llog_gen *)0)->mnt_cnt) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_gen *)0)->mnt_cnt));
-        LASSERTF((int)offsetof(struct llog_gen, conn_cnt) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_gen, conn_cnt));
-        LASSERTF((int)sizeof(((struct llog_gen *)0)->conn_cnt) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_gen *)0)->conn_cnt));
-
-        /* Checks for struct llog_gen_rec */
-        LASSERTF((int)sizeof(struct llog_gen_rec) == 40, " found %lld\n",
-                 (long long)(int)sizeof(struct llog_gen_rec));
-        LASSERTF((int)offsetof(struct llog_gen_rec, lgr_hdr) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_gen_rec, lgr_hdr));
-        LASSERTF((int)sizeof(((struct llog_gen_rec *)0)->lgr_hdr) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_gen_rec *)0)->lgr_hdr));
-        LASSERTF((int)offsetof(struct llog_gen_rec, lgr_gen) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_gen_rec, lgr_gen));
-        LASSERTF((int)sizeof(((struct llog_gen_rec *)0)->lgr_gen) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_gen_rec *)0)->lgr_gen));
-        LASSERTF((int)offsetof(struct llog_gen_rec, lgr_tail) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_gen_rec, lgr_tail));
-        LASSERTF((int)sizeof(((struct llog_gen_rec *)0)->lgr_tail) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_gen_rec *)0)->lgr_tail));
-
-        /* Checks for struct llog_log_hdr */
-        LASSERTF((int)sizeof(struct llog_log_hdr) == 8192, " found %lld\n",
-                 (long long)(int)sizeof(struct llog_log_hdr));
-        LASSERTF((int)offsetof(struct llog_log_hdr, llh_hdr) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_log_hdr, llh_hdr));
-        LASSERTF((int)sizeof(((struct llog_log_hdr *)0)->llh_hdr) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_log_hdr *)0)->llh_hdr));
-        LASSERTF((int)offsetof(struct llog_log_hdr, llh_timestamp) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_log_hdr, llh_timestamp));
-        LASSERTF((int)sizeof(((struct llog_log_hdr *)0)->llh_timestamp) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_log_hdr *)0)->llh_timestamp));
-        LASSERTF((int)offsetof(struct llog_log_hdr, llh_count) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_log_hdr, llh_count));
-        LASSERTF((int)sizeof(((struct llog_log_hdr *)0)->llh_count) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_log_hdr *)0)->llh_count));
-        LASSERTF((int)offsetof(struct llog_log_hdr, llh_bitmap_offset) == 28, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_log_hdr, llh_bitmap_offset));
-        LASSERTF((int)sizeof(((struct llog_log_hdr *)0)->llh_bitmap_offset) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_log_hdr *)0)->llh_bitmap_offset));
-        LASSERTF((int)offsetof(struct llog_log_hdr, llh_size) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_log_hdr, llh_size));
-        LASSERTF((int)sizeof(((struct llog_log_hdr *)0)->llh_size) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_log_hdr *)0)->llh_size));
-        LASSERTF((int)offsetof(struct llog_log_hdr, llh_flags) == 36, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_log_hdr, llh_flags));
-        LASSERTF((int)sizeof(((struct llog_log_hdr *)0)->llh_flags) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_log_hdr *)0)->llh_flags));
-        LASSERTF((int)offsetof(struct llog_log_hdr, llh_cat_idx) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_log_hdr, llh_cat_idx));
-        LASSERTF((int)sizeof(((struct llog_log_hdr *)0)->llh_cat_idx) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_log_hdr *)0)->llh_cat_idx));
-        LASSERTF((int)offsetof(struct llog_log_hdr, llh_tgtuuid) == 44, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_log_hdr, llh_tgtuuid));
-        LASSERTF((int)sizeof(((struct llog_log_hdr *)0)->llh_tgtuuid) == 40, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_log_hdr *)0)->llh_tgtuuid));
-        LASSERTF((int)offsetof(struct llog_log_hdr, llh_reserved) == 84, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_log_hdr, llh_reserved));
-        LASSERTF((int)sizeof(((struct llog_log_hdr *)0)->llh_reserved) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_log_hdr *)0)->llh_reserved));
-        LASSERTF((int)offsetof(struct llog_log_hdr, llh_bitmap) == 88, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_log_hdr, llh_bitmap));
-        LASSERTF((int)sizeof(((struct llog_log_hdr *)0)->llh_bitmap) == 8096, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_log_hdr *)0)->llh_bitmap));
-        LASSERTF((int)offsetof(struct llog_log_hdr, llh_tail) == 8184, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_log_hdr, llh_tail));
-        LASSERTF((int)sizeof(((struct llog_log_hdr *)0)->llh_tail) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_log_hdr *)0)->llh_tail));
-
-        /* Checks for struct llog_cookie */
-        LASSERTF((int)sizeof(struct llog_cookie) == 32, " found %lld\n",
-                 (long long)(int)sizeof(struct llog_cookie));
-        LASSERTF((int)offsetof(struct llog_cookie, lgc_lgl) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_cookie, lgc_lgl));
-        LASSERTF((int)sizeof(((struct llog_cookie *)0)->lgc_lgl) == 20, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_cookie *)0)->lgc_lgl));
-        LASSERTF((int)offsetof(struct llog_cookie, lgc_subsys) == 20, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_cookie, lgc_subsys));
-        LASSERTF((int)sizeof(((struct llog_cookie *)0)->lgc_subsys) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_cookie *)0)->lgc_subsys));
-        LASSERTF((int)offsetof(struct llog_cookie, lgc_index) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_cookie, lgc_index));
-        LASSERTF((int)sizeof(((struct llog_cookie *)0)->lgc_index) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_cookie *)0)->lgc_index));
-        LASSERTF((int)offsetof(struct llog_cookie, lgc_padding) == 28, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_cookie, lgc_padding));
-        LASSERTF((int)sizeof(((struct llog_cookie *)0)->lgc_padding) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_cookie *)0)->lgc_padding));
-
-        /* Checks for struct llogd_body */
-        LASSERTF((int)sizeof(struct llogd_body) == 48, " found %lld\n",
-                 (long long)(int)sizeof(struct llogd_body));
-        LASSERTF((int)offsetof(struct llogd_body, lgd_logid) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llogd_body, lgd_logid));
-        LASSERTF((int)sizeof(((struct llogd_body *)0)->lgd_logid) == 20, " found %lld\n",
-                 (long long)(int)sizeof(((struct llogd_body *)0)->lgd_logid));
-        LASSERTF((int)offsetof(struct llogd_body, lgd_ctxt_idx) == 20, " found %lld\n",
-                 (long long)(int)offsetof(struct llogd_body, lgd_ctxt_idx));
-        LASSERTF((int)sizeof(((struct llogd_body *)0)->lgd_ctxt_idx) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llogd_body *)0)->lgd_ctxt_idx));
-        LASSERTF((int)offsetof(struct llogd_body, lgd_llh_flags) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct llogd_body, lgd_llh_flags));
-        LASSERTF((int)sizeof(((struct llogd_body *)0)->lgd_llh_flags) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llogd_body *)0)->lgd_llh_flags));
-        LASSERTF((int)offsetof(struct llogd_body, lgd_index) == 28, " found %lld\n",
-                 (long long)(int)offsetof(struct llogd_body, lgd_index));
-        LASSERTF((int)sizeof(((struct llogd_body *)0)->lgd_index) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llogd_body *)0)->lgd_index));
-        LASSERTF((int)offsetof(struct llogd_body, lgd_saved_index) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct llogd_body, lgd_saved_index));
-        LASSERTF((int)sizeof(((struct llogd_body *)0)->lgd_saved_index) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llogd_body *)0)->lgd_saved_index));
-        LASSERTF((int)offsetof(struct llogd_body, lgd_len) == 36, " found %lld\n",
-                 (long long)(int)offsetof(struct llogd_body, lgd_len));
-        LASSERTF((int)sizeof(((struct llogd_body *)0)->lgd_len) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llogd_body *)0)->lgd_len));
-        LASSERTF((int)offsetof(struct llogd_body, lgd_cur_offset) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct llogd_body, lgd_cur_offset));
-        LASSERTF((int)sizeof(((struct llogd_body *)0)->lgd_cur_offset) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llogd_body *)0)->lgd_cur_offset));
-        CLASSERT(LLOG_ORIGIN_HANDLE_CREATE == 501);
-        CLASSERT(LLOG_ORIGIN_HANDLE_NEXT_BLOCK == 502);
-        CLASSERT(LLOG_ORIGIN_HANDLE_READ_HEADER == 503);
-        CLASSERT(LLOG_ORIGIN_HANDLE_WRITE_REC == 504);
-        CLASSERT(LLOG_ORIGIN_HANDLE_CLOSE == 505);
-        CLASSERT(LLOG_ORIGIN_CONNECT == 506);
-        CLASSERT(LLOG_CATINFO == 507);
-        CLASSERT(LLOG_ORIGIN_HANDLE_PREV_BLOCK == 508);
-        CLASSERT(LLOG_ORIGIN_HANDLE_DESTROY == 509);
-
-        /* Checks for struct llogd_conn_body */
-        LASSERTF((int)sizeof(struct llogd_conn_body) == 40, " found %lld\n",
-                 (long long)(int)sizeof(struct llogd_conn_body));
-        LASSERTF((int)offsetof(struct llogd_conn_body, lgdc_gen) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llogd_conn_body, lgdc_gen));
-        LASSERTF((int)sizeof(((struct llogd_conn_body *)0)->lgdc_gen) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct llogd_conn_body *)0)->lgdc_gen));
-        LASSERTF((int)offsetof(struct llogd_conn_body, lgdc_logid) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct llogd_conn_body, lgdc_logid));
-        LASSERTF((int)sizeof(((struct llogd_conn_body *)0)->lgdc_logid) == 20, " found %lld\n",
-                 (long long)(int)sizeof(((struct llogd_conn_body *)0)->lgdc_logid));
-        LASSERTF((int)offsetof(struct llogd_conn_body, lgdc_ctxt_idx) == 36, " found %lld\n",
-                 (long long)(int)offsetof(struct llogd_conn_body, lgdc_ctxt_idx));
-        LASSERTF((int)sizeof(((struct llogd_conn_body *)0)->lgdc_ctxt_idx) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llogd_conn_body *)0)->lgdc_ctxt_idx));
-
-        /* Checks for struct llog_array_rec */
-        LASSERTF((int)sizeof(struct llog_array_rec) == 72, " found %lld\n",
-                 (long long)(int)sizeof(struct llog_array_rec));
-        LASSERTF((int)offsetof(struct llog_array_rec, lmr_hdr) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_array_rec, lmr_hdr));
-        LASSERTF((int)sizeof(((struct llog_array_rec *)0)->lmr_hdr) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_array_rec *)0)->lmr_hdr));
-        LASSERTF((int)offsetof(struct llog_array_rec, lmr_med) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_array_rec, lmr_med));
-        LASSERTF((int)sizeof(((struct llog_array_rec *)0)->lmr_med) == 48, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_array_rec *)0)->lmr_med));
-        LASSERTF((int)offsetof(struct llog_array_rec, lmr_tail) == 64, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_array_rec, lmr_tail));
-        LASSERTF((int)sizeof(((struct llog_array_rec *)0)->lmr_tail) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_array_rec *)0)->lmr_tail));
-
-        /* Checks for struct mds_extent_desc */
-        LASSERTF((int)sizeof(struct mds_extent_desc) == 48, " found %lld\n",
-                 (long long)(int)sizeof(struct mds_extent_desc));
-        LASSERTF((int)offsetof(struct mds_extent_desc, med_start) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_extent_desc, med_start));
-        LASSERTF((int)sizeof(((struct mds_extent_desc *)0)->med_start) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_extent_desc *)0)->med_start));
-        LASSERTF((int)offsetof(struct mds_extent_desc, med_len) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_extent_desc, med_len));
-        LASSERTF((int)sizeof(((struct mds_extent_desc *)0)->med_len) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_extent_desc *)0)->med_len));
-        LASSERTF((int)offsetof(struct mds_extent_desc, med_lmm) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_extent_desc, med_lmm));
-        LASSERTF((int)sizeof(((struct mds_extent_desc *)0)->med_lmm) == 32, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_extent_desc *)0)->med_lmm));
-
-        /* Checks for struct qunit_data */
-        LASSERTF((int)sizeof(struct qunit_data) == 16, " found %lld\n",
-                 (long long)(int)sizeof(struct qunit_data));
-        LASSERTF((int)offsetof(struct qunit_data, qd_id) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct qunit_data, qd_id));
-        LASSERTF((int)sizeof(((struct qunit_data *)0)->qd_id) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct qunit_data *)0)->qd_id));
-        LASSERTF((int)offsetof(struct qunit_data, qd_type) == 4, " found %lld\n",
-                 (long long)(int)offsetof(struct qunit_data, qd_type));
-        LASSERTF((int)sizeof(((struct qunit_data *)0)->qd_type) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct qunit_data *)0)->qd_type));
-        LASSERTF((int)offsetof(struct qunit_data, qd_count) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct qunit_data, qd_count));
-        LASSERTF((int)sizeof(((struct qunit_data *)0)->qd_count) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct qunit_data *)0)->qd_count));
-        LASSERTF((int)offsetof(struct qunit_data, qd_isblk) == 12, " found %lld\n",
-                 (long long)(int)offsetof(struct qunit_data, qd_isblk));
-        LASSERTF((int)sizeof(((struct qunit_data *)0)->qd_isblk) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct qunit_data *)0)->qd_isblk));
-}
-
-
-
-
-
index 53335f7..787074c 100644 (file)
@@ -45,13 +45,13 @@ int ptlrpc_ping(struct obd_import *imp)
         int rc = 0;
         ENTRY;
 
-        req = ptlrpc_prep_req(imp, LUSTRE_OBD_VERSION, OBD_PING, 0, NULL, NULL);
+        req = ptlrpc_prep_req(imp, LUSTRE_OBD_VERSION, OBD_PING, 1, NULL, NULL);
         if (req) {
                 DEBUG_REQ(D_INFO, req, "pinging %s->%s",
                           imp->imp_obd->obd_uuid.uuid,
                           obd2cli_tgt(imp->imp_obd));
                 req->rq_no_resend = req->rq_no_delay = 1;
-                req->rq_replen = lustre_msg_size(0, NULL);
+                ptlrpc_req_set_repsize(req, 1, NULL);
                 ptlrpcd_add_req(req);
         } else {
                 CERROR("OOM trying to ping %s->%s\n",
@@ -101,15 +101,14 @@ static int ptlrpc_pinger_main(void *arg)
                                 list_entry(iter, struct obd_import,
                                            imp_pinger_chain);
                         int force, level;
-                        unsigned long flags;
 
-                        spin_lock_irqsave(&imp->imp_lock, flags);
+                        spin_lock(&imp->imp_lock);
                         level = imp->imp_state;
                         force = imp->imp_force_verify;
                         imp->imp_force_verify = 0;
-                        spin_unlock_irqrestore(&imp->imp_lock, flags);
+                        spin_unlock(&imp->imp_lock);
 
-                        CDEBUG_EX(level == LUSTRE_IMP_FULL ? D_INFO : D_HA,
+                        CDEBUG(level == LUSTRE_IMP_FULL ? D_INFO : D_HA,
                                "level %s/%u force %u deactive %u pingable %u\n",
                                ptlrpc_import_state_name(level), level,
                                force, imp->imp_deactive, imp->imp_pingable);
@@ -373,23 +372,21 @@ static int ping_evictor_main(void *arg)
                 while (!list_empty(&obd->obd_exports_timed)) {
                         exp = list_entry(obd->obd_exports_timed.next,
                                          struct obd_export,exp_obd_chain_timed);
-
                         if (expire_time > exp->exp_last_request_time) {
                                 class_export_get(exp);
                                 spin_unlock(&obd->obd_dev_lock);
-                                LCONSOLE_WARN("%s: haven't heard from %s in %ld"
-                                              " seconds. Last request was at %ld. "
-                                              "I think it's dead, and I am evicting "
-                                              "it.\n", obd->obd_name,
+                                LCONSOLE_WARN("%s: haven't heard from client %s"
+                                              " (at %s) in %ld seconds. I think"
+                                              " it's dead, and I am evicting"
+                                              " it.\n", obd->obd_name,
+                                              obd_uuid2str(&exp->exp_client_uuid),
                                               obd_export_nid2str(exp),
                                               (long)(CURRENT_SECONDS -
-                                                     exp->exp_last_request_time),
-                                              exp->exp_last_request_time);
-
-
+                                                     exp->exp_last_request_time));
+                                CDEBUG(D_HA, "Last request was at %ld\n",
+                                       exp->exp_last_request_time);
                                 class_fail_export(exp);
                                 class_export_put(exp);
-
                                 spin_lock(&obd->obd_dev_lock);
                         } else {
                                 /* List is sorted, so everyone below is ok */
@@ -491,15 +488,14 @@ static int pinger_check_rpcs(void *arg)
                 struct obd_import *imp =
                         list_entry(iter, struct obd_import, imp_pinger_chain);
                 int generation, level;
-                unsigned long flags;
 
                 if (cfs_time_aftereq(pd->pd_this_ping, 
                                      imp->imp_next_ping - 5 * CFS_TICK)) {
                         /* Add a ping. */
-                        spin_lock_irqsave(&imp->imp_lock, flags);
+                        spin_lock(&imp->imp_lock);
                         generation = imp->imp_generation;
                         level = imp->imp_state;
-                        spin_unlock_irqrestore(&imp->imp_lock, flags);
+                        spin_unlock(&imp->imp_lock);
 
                         if (level != LUSTRE_IMP_FULL) {
                                 CDEBUG(D_HA,
@@ -509,13 +505,13 @@ static int pinger_check_rpcs(void *arg)
                         }
 
                         req = ptlrpc_prep_req(imp, LUSTRE_OBD_VERSION, OBD_PING,
-                                              0, NULL, NULL);
+                                              1, NULL, NULL);
                         if (!req) {
                                 CERROR("out of memory\n");
                                 break;
                         }
                         req->rq_no_resend = 1;
-                        req->rq_replen = lustre_msg_size(0, NULL);
+                        ptlrpc_req_set_repsize(req, 1, NULL);
                         req->rq_send_state = LUSTRE_IMP_FULL;
                         req->rq_phase = RQ_PHASE_RPC;
                         req->rq_import_generation = generation;
index 7497e2e..54abe7a 100644 (file)
@@ -34,6 +34,7 @@ struct ldlm_namespace;
 struct obd_import;
 struct ldlm_res_id;
 struct ptlrpc_request_set;
+extern int test_req_buffer_pressure;
 
 void ptlrpc_request_handle_notconn(struct ptlrpc_request *);
 void lustre_assert_wire_constants(void);
index aa23c90..c809437 100644 (file)
@@ -191,8 +191,10 @@ EXPORT_SYMBOL(lustre_shrink_reply);
 EXPORT_SYMBOL(lustre_free_reply_state);
 EXPORT_SYMBOL(lustre_msg_size);
 EXPORT_SYMBOL(lustre_unpack_msg);
+EXPORT_SYMBOL(lustre_unpack_ptlrpc_body);
 EXPORT_SYMBOL(lustre_msg_buf);
 EXPORT_SYMBOL(lustre_msg_string);
+EXPORT_SYMBOL(lustre_swab_ptlrpc_body);
 EXPORT_SYMBOL(lustre_swab_buf);
 EXPORT_SYMBOL(lustre_swab_reqbuf);
 EXPORT_SYMBOL(lustre_swab_repbuf);
@@ -232,6 +234,32 @@ EXPORT_SYMBOL(lustre_swab_ldlm_lock_desc);
 EXPORT_SYMBOL(lustre_swab_ldlm_request);
 EXPORT_SYMBOL(lustre_swab_ldlm_reply);
 EXPORT_SYMBOL(lustre_swab_qdata);
+EXPORT_SYMBOL(lustre_msg_get_flags);
+EXPORT_SYMBOL(lustre_msg_add_flags);
+EXPORT_SYMBOL(lustre_msg_set_flags);
+EXPORT_SYMBOL(lustre_msg_clear_flags);
+EXPORT_SYMBOL(lustre_msg_get_op_flags);
+EXPORT_SYMBOL(lustre_msg_add_op_flags);
+EXPORT_SYMBOL(lustre_msg_set_op_flags);
+EXPORT_SYMBOL(lustre_msg_get_handle );
+EXPORT_SYMBOL(lustre_msg_get_type);
+EXPORT_SYMBOL(lustre_msg_get_version);
+EXPORT_SYMBOL(lustre_msg_add_version);
+EXPORT_SYMBOL(lustre_msg_get_opc);
+EXPORT_SYMBOL(lustre_msg_get_last_xid);
+EXPORT_SYMBOL(lustre_msg_get_last_committed);
+EXPORT_SYMBOL(lustre_msg_get_transno);
+EXPORT_SYMBOL(lustre_msg_get_status);
+EXPORT_SYMBOL(lustre_msg_get_conn_cnt);
+EXPORT_SYMBOL(lustre_msg_get_magic);
+EXPORT_SYMBOL(lustre_msg_set_handle);
+EXPORT_SYMBOL(lustre_msg_set_type);
+EXPORT_SYMBOL(lustre_msg_set_opc);
+EXPORT_SYMBOL(lustre_msg_set_last_xid);
+EXPORT_SYMBOL(lustre_msg_set_last_committed);
+EXPORT_SYMBOL(lustre_msg_set_transno);
+EXPORT_SYMBOL(lustre_msg_set_status);
+EXPORT_SYMBOL(lustre_msg_set_conn_cnt);
 EXPORT_SYMBOL(lustre_swab_mgs_target_info);
 EXPORT_SYMBOL(lustre_swab_md_fld);
 EXPORT_SYMBOL(lustre_swab_generic_32s);
index fa315eb..9dce7f7 100644 (file)
@@ -92,21 +92,20 @@ static int ptlrpcd_check(struct ptlrpcd_ctl *pc)
 {
         struct list_head *tmp, *pos;
         struct ptlrpc_request *req;
-        unsigned long flags;
         int rc = 0;
         ENTRY;
 
         if (test_bit(LIOD_STOP, &pc->pc_flags))
                 RETURN(1);
 
-        spin_lock_irqsave(&pc->pc_set->set_new_req_lock, flags);
+        spin_lock(&pc->pc_set->set_new_req_lock);
         list_for_each_safe(pos, tmp, &pc->pc_set->set_new_requests) {
                 req = list_entry(pos, struct ptlrpc_request, rq_set_chain);
                 list_del_init(&req->rq_set_chain);
                 ptlrpc_set_add_req(pc->pc_set, req);
                 rc = 1; /* need to calculate its timeout */
         }
-        spin_unlock_irqrestore(&pc->pc_set->set_new_req_lock, flags);
+        spin_unlock(&pc->pc_set->set_new_req_lock);
 
         if (pc->pc_set->set_remaining) {
                 rc = rc | ptlrpc_check_set(pc->pc_set);
@@ -127,9 +126,9 @@ static int ptlrpcd_check(struct ptlrpcd_ctl *pc)
 
         if (rc == 0) {
                 /* If new requests have been added, make sure to wake up */
-                spin_lock_irqsave(&pc->pc_set->set_new_req_lock, flags);
+                spin_lock(&pc->pc_set->set_new_req_lock);
                 rc = !list_empty(&pc->pc_set->set_new_requests);
-                spin_unlock_irqrestore(&pc->pc_set->set_new_req_lock, flags);
+                spin_unlock(&pc->pc_set->set_new_req_lock);
         }
 
         RETURN(rc);
index 8ad20c6..30286fb 100644 (file)
@@ -64,9 +64,10 @@ static struct llog_commit_master *lcm = &lustre_lcm;
 static int llcd_alloc(void)
 {
         struct llog_canceld_ctxt *llcd;
-        int llcd_size = 0;
+        int llcd_size;
 
-        llcd_size = 4096 - lustre_msg_size(1, &llcd_size);
+        /* payload of lustre_msg V2 is bigger */
+        llcd_size = 4096 - lustre_msg_size(LUSTRE_MSG_MAGIC_V2, 1, NULL);
         OBD_ALLOC(llcd,
                   llcd_size + offsetof(struct llog_canceld_ctxt, llcd_cookies));
         if (llcd == NULL)
@@ -320,7 +321,9 @@ static int log_commit_thread(void *arg)
 
                 /* We are the only one manipulating our local list - no lock */
                 list_for_each_entry_safe(llcd,n, &lcd->lcd_llcd_list,llcd_list){
-                        char *bufs[1] = {(char *)llcd->llcd_cookies};
+                        int size[2] = { sizeof(struct ptlrpc_body),
+                                        llcd->llcd_cookiebytes };
+                        char *bufs[2] = { NULL, (char *)llcd->llcd_cookies };
 
                         list_del(&llcd->llcd_list);
                         if (llcd->llcd_cookiebytes == 0) {
@@ -349,9 +352,7 @@ static int log_commit_thread(void *arg)
                         }
 
                         request = ptlrpc_prep_req(import, LUSTRE_LOG_VERSION,
-                                                  OBD_LOG_CANCEL, 1,
-                                                  &llcd->llcd_cookiebytes,
-                                                  bufs);
+                                                  OBD_LOG_CANCEL, 2, size,bufs);
                         if (request == NULL) {
                                 rc = -ENOMEM;
                                 CERROR("error preparing commit: rc %d\n", rc);
@@ -368,7 +369,7 @@ static int log_commit_thread(void *arg)
                         request->rq_request_portal = LDLM_CANCEL_REQUEST_PORTAL;
                         request->rq_reply_portal = LDLM_CANCEL_REPLY_PORTAL;
 
-                        request->rq_replen = lustre_msg_size(0, NULL);
+                        ptlrpc_req_set_repsize(request, 1, NULL);
                         mutex_down(&llcd->llcd_ctxt->loc_sem);
                         if (llcd->llcd_ctxt->loc_imp == NULL) {
                                 mutex_up(&llcd->llcd_ctxt->loc_sem);
index cbbed63..1ca9a20 100644 (file)
@@ -78,19 +78,18 @@ void ptlrpc_run_recovery_over_upcall(struct obd_device *obd)
 void ptlrpc_run_failed_import_upcall(struct obd_import* imp)
 {
 #ifdef __KERNEL__
-        unsigned long flags;
         char *argv[7];
         char *envp[3];
         int rc;
         ENTRY;
 
-        spin_lock_irqsave(&imp->imp_lock, flags);
+        spin_lock(&imp->imp_lock);
         if (imp->imp_state == LUSTRE_IMP_CLOSED) {
-                spin_unlock_irqrestore(&imp->imp_lock, flags);
+                spin_unlock(&imp->imp_lock);
                 EXIT;
                 return;
         }
-        spin_unlock_irqrestore(&imp->imp_lock, flags);
+        spin_unlock(&imp->imp_lock);
 
         argv[0] = obd_lustre_upcall;
         argv[1] = "FAILED_IMPORT";
@@ -151,7 +150,6 @@ int ptlrpc_replay_next(struct obd_import *imp, int *inflight)
         int rc = 0;
         struct list_head *tmp, *pos;
         struct ptlrpc_request *req = NULL;
-        unsigned long flags;
         __u64 last_transno;
         ENTRY;
 
@@ -160,11 +158,11 @@ int ptlrpc_replay_next(struct obd_import *imp, int *inflight)
         /* It might have committed some after we last spoke, so make sure we
          * get rid of them now.
          */
-        spin_lock_irqsave(&imp->imp_lock, flags);
+        spin_lock(&imp->imp_lock);
         imp->imp_last_transno_checked = 0;
         ptlrpc_free_committed(imp);
         last_transno = imp->imp_last_replay_transno;
-        spin_unlock_irqrestore(&imp->imp_lock, flags);
+        spin_unlock(&imp->imp_lock);
 
         CDEBUG(D_HA, "import %p from %s committed "LPU64" last "LPU64"\n",
                imp, obd2cli_tgt(imp->imp_obd),
@@ -224,7 +222,6 @@ int ptlrpc_replay_next(struct obd_import *imp, int *inflight)
 int ptlrpc_resend(struct obd_import *imp)
 {
         struct ptlrpc_request *req, *next;
-        unsigned long flags;
 
         ENTRY;
 
@@ -234,12 +231,12 @@ int ptlrpc_resend(struct obd_import *imp)
          */
         /* Well... what if lctl recover is called twice at the same time?
          */
-        spin_lock_irqsave(&imp->imp_lock, flags);
+        spin_lock(&imp->imp_lock);
         if (imp->imp_state != LUSTRE_IMP_RECOVER) {
-                spin_unlock_irqrestore(&imp->imp_lock, flags);
+                spin_unlock(&imp->imp_lock);
                 RETURN(-1);
         }
-        spin_unlock_irqrestore(&imp->imp_lock, flags);
+        spin_unlock(&imp->imp_lock);
 
         list_for_each_entry_safe(req, next, &imp->imp_sending_list, rq_list) {
                 LASSERTF((long)req > PAGE_SIZE && req != LP_POISON,
@@ -253,31 +250,30 @@ int ptlrpc_resend(struct obd_import *imp)
 
 void ptlrpc_wake_delayed(struct obd_import *imp)
 {
-        unsigned long flags;
         struct list_head *tmp, *pos;
         struct ptlrpc_request *req;
 
-        spin_lock_irqsave(&imp->imp_lock, flags);
+        spin_lock(&imp->imp_lock);
         list_for_each_safe(tmp, pos, &imp->imp_delayed_list) {
                 req = list_entry(tmp, struct ptlrpc_request, rq_list);
 
                 DEBUG_REQ(D_HA, req, "waking (set %p):", req->rq_set);
                 ptlrpc_wake_client_req(req);
         }
-        spin_unlock_irqrestore(&imp->imp_lock, flags);
+        spin_unlock(&imp->imp_lock);
 }
 
 void ptlrpc_request_handle_notconn(struct ptlrpc_request *failed_req)
 {
         struct obd_import *imp = failed_req->rq_import;
-        unsigned long flags;
         ENTRY;
 
         CDEBUG(D_HA, "import %s of %s@%s abruptly disconnected: reconnecting\n",
                imp->imp_obd->obd_name, obd2cli_tgt(imp->imp_obd),
                imp->imp_connection->c_remote_uuid.uuid);
 
-        if (ptlrpc_set_import_discon(imp, failed_req->rq_reqmsg->conn_cnt)) {
+        if (ptlrpc_set_import_discon(imp,
+                              lustre_msg_get_conn_cnt(failed_req->rq_reqmsg))) {
                 if (!imp->imp_replayable) {
                         CDEBUG(D_HA, "import %s@%s for %s not replayable, "
                                "auto-deactivating\n",
@@ -293,10 +289,10 @@ void ptlrpc_request_handle_notconn(struct ptlrpc_request *failed_req)
 
         /* Wait for recovery to complete and resend. If evicted, then
            this request will be errored out later.*/
-        spin_lock_irqsave(&failed_req->rq_lock, flags);
+        spin_lock(&failed_req->rq_lock);
         if (!failed_req->rq_no_resend)
                 failed_req->rq_resend = 1;
-        spin_unlock_irqrestore(&failed_req->rq_lock, flags);
+        spin_unlock(&failed_req->rq_lock);
 
         EXIT;
 }
@@ -352,14 +348,13 @@ int ptlrpc_recover_import(struct obd_import *imp, char *new_uuid)
 
 int ptlrpc_import_in_recovery(struct obd_import *imp)
 {
-        unsigned long flags;
         int in_recovery = 1;
-        spin_lock_irqsave(&imp->imp_lock, flags);
+        spin_lock(&imp->imp_lock);
         if (imp->imp_state == LUSTRE_IMP_FULL ||
             imp->imp_state == LUSTRE_IMP_CLOSED ||
             imp->imp_state == LUSTRE_IMP_DISCON)
                 in_recovery = 0;
-        spin_unlock_irqrestore(&imp->imp_lock, flags);
+        spin_unlock(&imp->imp_lock);
         return in_recovery;
 }
 
@@ -367,17 +362,16 @@ static int ptlrpc_recover_import_no_retry(struct obd_import *imp,
                                           char *new_uuid)
 {
         int rc;
-        unsigned long flags;
         int in_recovery = 0;
         struct l_wait_info lwi;
         ENTRY;
 
-        spin_lock_irqsave(&imp->imp_lock, flags);
         /* Check if reconnect is already in progress */
+        spin_lock(&imp->imp_lock);
         if (imp->imp_state != LUSTRE_IMP_DISCON) {
                 in_recovery = 1;
         }
-        spin_unlock_irqrestore(&imp->imp_lock, flags);
+        spin_unlock(&imp->imp_lock);
 
         if (in_recovery == 1)
                 RETURN(-EALREADY);
index 83ce195..370ee76 100644 (file)
 #include <lnet/types.h>
 #include "ptlrpc_internal.h"
 
+int test_req_buffer_pressure = 0;
+CFS_MODULE_PARM(test_req_buffer_pressure, "i", int, 0444,
+                "set non-zero to put pressure on request buffer pools");
+
 /* forward ref */
 static int ptlrpc_server_post_idle_rqbds (struct ptlrpc_service *svc);
 
@@ -66,7 +70,6 @@ ptlrpc_free_request_buffer (char *ptr, int size)
 struct ptlrpc_request_buffer_desc *
 ptlrpc_alloc_rqbd (struct ptlrpc_service *svc)
 {
-        unsigned long                      flags;
         struct ptlrpc_request_buffer_desc *rqbd;
 
         OBD_ALLOC(rqbd, sizeof (*rqbd));
@@ -85,10 +88,10 @@ ptlrpc_alloc_rqbd (struct ptlrpc_service *svc)
                 return (NULL);
         }
 
-        spin_lock_irqsave (&svc->srv_lock, flags);
+        spin_lock(&svc->srv_lock);
         list_add(&rqbd->rqbd_list, &svc->srv_idle_rqbds);
         svc->srv_nbufs++;
-        spin_unlock_irqrestore (&svc->srv_lock, flags);
+        spin_unlock(&svc->srv_lock);
 
         return (rqbd);
 }
@@ -97,15 +100,14 @@ void
 ptlrpc_free_rqbd (struct ptlrpc_request_buffer_desc *rqbd)
 {
         struct ptlrpc_service *svc = rqbd->rqbd_service;
-        unsigned long          flags;
 
         LASSERT (rqbd->rqbd_refcount == 0);
         LASSERT (list_empty(&rqbd->rqbd_reqs));
 
-        spin_lock_irqsave(&svc->srv_lock, flags);
+        spin_lock(&svc->srv_lock);
         list_del(&rqbd->rqbd_list);
         svc->srv_nbufs--;
-        spin_unlock_irqrestore(&svc->srv_lock, flags);
+        spin_unlock(&svc->srv_lock);
 
         ptlrpc_free_request_buffer (rqbd->rqbd_buffer, svc->srv_buf_size);
         OBD_FREE (rqbd, sizeof (*rqbd));
@@ -143,8 +145,8 @@ ptlrpc_save_lock (struct ptlrpc_request *req,
         struct ptlrpc_reply_state *rs = req->rq_reply_state;
         int                        idx;
 
-        LASSERT (rs != NULL);
-        LASSERT (rs->rs_nlocks < RS_MAX_LOCKS);
+        LASSERT(rs != NULL);
+        LASSERT(rs->rs_nlocks < RS_MAX_LOCKS);
 
         idx = rs->rs_nlocks++;
         rs->rs_locks[idx] = *lock;
@@ -177,13 +179,12 @@ ptlrpc_commit_replies (struct obd_device *obd)
 {
         struct list_head   *tmp;
         struct list_head   *nxt;
-        unsigned long       flags;
 
         /* Find any replies that have been committed and get their service
          * to attend to complete them. */
 
         /* CAVEAT EMPTOR: spinlock ordering!!! */
-        spin_lock_irqsave (&obd->obd_uncommitted_replies_lock, flags);
+        spin_lock(&obd->obd_uncommitted_replies_lock);
 
         list_for_each_safe (tmp, nxt, &obd->obd_uncommitted_replies) {
                 struct ptlrpc_reply_state *rs =
@@ -201,22 +202,21 @@ ptlrpc_commit_replies (struct obd_device *obd)
                 }
         }
 
-        spin_unlock_irqrestore (&obd->obd_uncommitted_replies_lock, flags);
+        spin_unlock(&obd->obd_uncommitted_replies_lock);
 }
 
 static int
 ptlrpc_server_post_idle_rqbds (struct ptlrpc_service *svc)
 {
         struct ptlrpc_request_buffer_desc *rqbd;
-        unsigned long                      flags;
         int                                rc;
         int                                posted = 0;
 
         for (;;) {
-                spin_lock_irqsave(&svc->srv_lock, flags);
+                spin_lock(&svc->srv_lock);
 
                 if (list_empty (&svc->srv_idle_rqbds)) {
-                        spin_unlock_irqrestore(&svc->srv_lock, flags);
+                        spin_unlock(&svc->srv_lock);
                         return (posted);
                 }
 
@@ -229,7 +229,7 @@ ptlrpc_server_post_idle_rqbds (struct ptlrpc_service *svc)
                 svc->srv_nrqbd_receiving++;
                 list_add (&rqbd->rqbd_list, &svc->srv_active_rqbds);
 
-                spin_unlock_irqrestore(&svc->srv_lock, flags);
+                spin_unlock(&svc->srv_lock);
 
                 rc = ptlrpc_register_rqbd(rqbd);
                 if (rc != 0)
@@ -238,21 +238,16 @@ ptlrpc_server_post_idle_rqbds (struct ptlrpc_service *svc)
                 posted = 1;
         }
 
-        spin_lock_irqsave(&svc->srv_lock, flags);
+        spin_lock(&svc->srv_lock);
 
         svc->srv_nrqbd_receiving--;
         list_del(&rqbd->rqbd_list);
         list_add_tail(&rqbd->rqbd_list, &svc->srv_idle_rqbds);
 
-        if (svc->srv_nrqbd_receiving == 0) {
-                /* This service is off-air on this interface because all
-                 * its request buffers are busy.  Portals will have started
-                 * dropping incoming requests until more buffers get
-                 * posted */
-                CERROR("All %s request buffers busy\n", svc->srv_name);
-        }
+        /* Don't complain if no request buffers are posted right now; LNET
+         * won't drop requests because we set the portal lazy! */
 
-        spin_unlock_irqrestore (&svc->srv_lock, flags);
+        spin_unlock(&svc->srv_lock);
 
         return (-1);
 }
@@ -298,7 +293,7 @@ ptlrpc_init_svc(int nbufs, int bufsize, int max_req_size, int max_reply_size,
         CFS_INIT_LIST_HEAD(&service->srv_threads);
         cfs_waitq_init(&service->srv_waitq);
 
-        service->srv_nbuf_per_group = nbufs;
+        service->srv_nbuf_per_group = test_req_buffer_pressure ? 1 : nbufs;
         service->srv_max_req_size = max_req_size;
         service->srv_buf_size = bufsize;
         service->srv_rep_portal = rep_portal;
@@ -311,6 +306,9 @@ ptlrpc_init_svc(int nbufs, int bufsize, int max_req_size, int max_reply_size,
         service->srv_num_threads = num_threads;
         service->srv_ctx_tags = ctx_tags;
 
+        rc = LNetSetLazyPortal(service->srv_req_portal);
+        LASSERT (rc == 0);
+
         CFS_INIT_LIST_HEAD(&service->srv_request_queue);
         CFS_INIT_LIST_HEAD(&service->srv_idle_rqbds);
         CFS_INIT_LIST_HEAD(&service->srv_active_rqbds);
@@ -374,12 +372,11 @@ ptlrpc_server_free_request(struct ptlrpc_request *req)
 {
         struct ptlrpc_request_buffer_desc *rqbd = req->rq_rqbd;
         struct ptlrpc_service             *svc = rqbd->rqbd_service;
-        unsigned long                      flags;
         int                                refcount;
         struct list_head                  *tmp;
         struct list_head                  *nxt;
 
-        spin_lock_irqsave(&svc->srv_lock, flags);
+        spin_lock(&svc->srv_lock);
 
         svc->srv_n_active_reqs--;
         list_add(&req->rq_list, &rqbd->rqbd_reqs);
@@ -414,7 +411,7 @@ ptlrpc_server_free_request(struct ptlrpc_request *req)
                                 list_del(&req->rq_history_list);
                         }
 
-                        spin_unlock_irqrestore(&svc->srv_lock, flags);
+                        spin_unlock(&svc->srv_lock);
 
                         list_for_each_safe(tmp, nxt, &rqbd->rqbd_reqs) {
                                 req = list_entry(rqbd->rqbd_reqs.next,
@@ -423,7 +420,7 @@ ptlrpc_server_free_request(struct ptlrpc_request *req)
                                 __ptlrpc_server_free_request(req);
                         }
 
-                        spin_lock_irqsave(&svc->srv_lock, flags);
+                        spin_lock(&svc->srv_lock);
 
                         /* schedule request buffer for re-use.
                          * NB I can only do this after I've disposed of their
@@ -437,7 +434,7 @@ ptlrpc_server_free_request(struct ptlrpc_request *req)
                 __ptlrpc_server_free_request(req);
         }
 
-        spin_unlock_irqrestore(&svc->srv_lock, flags);
+        spin_unlock(&svc->srv_lock);
 
 }
 
@@ -525,7 +522,6 @@ ptlrpc_server_handle_request(struct ptlrpc_service *svc,
                              struct ptlrpc_thread *thread)
 {
         struct ptlrpc_request *request;
-        unsigned long          flags;
         struct timeval         work_start;
         struct timeval         work_end;
         long                   timediff;
@@ -534,14 +530,14 @@ ptlrpc_server_handle_request(struct ptlrpc_service *svc,
 
         LASSERT(svc);
 
-        spin_lock_irqsave (&svc->srv_lock, flags);
+        spin_lock(&svc->srv_lock);
         if (list_empty (&svc->srv_request_queue) ||
             (svc->srv_n_difficult_replies != 0 &&
              svc->srv_n_active_reqs >= (svc->srv_nthreads - 1))) {
                 /* If all the other threads are handling requests, I must
                  * remain free to handle any 'difficult' reply that might
                  * block them */
-                spin_unlock_irqrestore (&svc->srv_lock, flags);
+                spin_unlock(&svc->srv_lock);
                 RETURN(0);
         }
 
@@ -551,7 +547,7 @@ ptlrpc_server_handle_request(struct ptlrpc_service *svc,
         svc->srv_n_queued_reqs--;
         svc->srv_n_active_reqs++;
 
-        spin_unlock_irqrestore (&svc->srv_lock, flags);
+        spin_unlock(&svc->srv_lock);
 
         do_gettimeofday(&work_start);
         timediff = cfs_timeval_sub(&work_start, &request->rq_arrival_time,NULL);
@@ -568,7 +564,7 @@ ptlrpc_server_handle_request(struct ptlrpc_service *svc,
         /* Clear request swab mask; this is a new request */
         request->rq_req_swab_mask = 0;
 #endif
-        rc = lustre_unpack_msg (request->rq_reqmsg, request->rq_reqlen);
+        rc = lustre_unpack_msg(request->rq_reqmsg, request->rq_reqlen);
         if (rc != 0) {
                 CERROR ("error unpacking request: ptl %d from %s"
                         " xid "LPU64"\n", svc->srv_req_portal,
@@ -576,10 +572,18 @@ ptlrpc_server_handle_request(struct ptlrpc_service *svc,
                 goto out;
         }
 
+        rc = lustre_unpack_ptlrpc_body(request->rq_reqmsg);
+        if (rc) {
+                CERROR ("error unpacking ptlrpc body: ptl %d from %s"
+                        " xid "LPU64"\n", svc->srv_req_portal,
+                        libcfs_id2str(request->rq_peer), request->rq_xid);
+                goto out;
+        }
+
         rc = -EINVAL;
-        if (request->rq_reqmsg->type != PTL_RPC_MSG_REQUEST) {
+        if (lustre_msg_get_type(request->rq_reqmsg) != PTL_RPC_MSG_REQUEST) {
                 CERROR("wrong packet type received (type=%u) from %s\n",
-                       request->rq_reqmsg->type,
+                       lustre_msg_get_type(request->rq_reqmsg),
                        libcfs_id2str(request->rq_peer));
                 goto out;
         }
@@ -587,14 +591,15 @@ ptlrpc_server_handle_request(struct ptlrpc_service *svc,
         CDEBUG(D_NET, "got req "LPD64"\n", request->rq_xid);
 
         request->rq_svc_thread = thread;
-        request->rq_export = class_conn2export(&request->rq_reqmsg->handle);
+        request->rq_export = class_conn2export(
+                                     lustre_msg_get_handle(request->rq_reqmsg));
 
         if (request->rq_export) {
-                if (request->rq_reqmsg->conn_cnt <
+                if (lustre_msg_get_conn_cnt(request->rq_reqmsg) <
                     request->rq_export->exp_conn_cnt) {
                         DEBUG_REQ(D_ERROR, request,
                                   "DROPPING req from old connection %d < %d",
-                                  request->rq_reqmsg->conn_cnt,
+                                  lustre_msg_get_conn_cnt(request->rq_reqmsg),
                                   request->rq_export->exp_conn_cnt);
                         goto put_conn;
                 }
@@ -617,7 +622,8 @@ ptlrpc_server_handle_request(struct ptlrpc_service *svc,
          * REQ anyway (bug 1502) */
         if (timediff / 1000000 > (long)obd_timeout) {
                 CERROR("Dropping timed-out opc %d request from %s"
-                       ": %ld seconds old\n", request->rq_reqmsg->opc,
+                       ": %ld seconds old\n",
+                       lustre_msg_get_opc(request->rq_reqmsg),
                        libcfs_id2str(request->rq_peer),
                        timediff / 1000000);
                 goto put_conn;
@@ -631,9 +637,9 @@ ptlrpc_server_handle_request(struct ptlrpc_service *svc,
                 (char *)request->rq_export->exp_client_uuid.uuid : "0"),
                (request->rq_export ?
                 atomic_read(&request->rq_export->exp_refcount) : -99),
-               request->rq_reqmsg->status, request->rq_xid,
+               lustre_msg_get_status(request->rq_reqmsg), request->rq_xid,
                libcfs_id2str(request->rq_peer),
-               request->rq_reqmsg->opc);
+               lustre_msg_get_opc(request->rq_reqmsg));
 
         rc = svc->srv_handler(request);
 
@@ -645,9 +651,9 @@ ptlrpc_server_handle_request(struct ptlrpc_service *svc,
                 (char *)request->rq_export->exp_client_uuid.uuid : "0"),
                (request->rq_export ?
                 atomic_read(&request->rq_export->exp_refcount) : -99),
-               request->rq_reqmsg->status, request->rq_xid,
+               lustre_msg_get_status(request->rq_reqmsg), request->rq_xid,
                libcfs_id2str(request->rq_peer),
-               request->rq_reqmsg->opc);
+               lustre_msg_get_opc(request->rq_reqmsg));
 
 put_conn:
         if (request->rq_export != NULL)
@@ -661,25 +667,30 @@ put_conn:
         if (timediff / 1000000 > (long)obd_timeout)
                 CERROR("request "LPU64" opc %u from %s processed in %lds "
                        "trans "LPU64" rc %d/%d\n",
-                       request->rq_xid, request->rq_reqmsg->opc,
+                       request->rq_xid, lustre_msg_get_opc(request->rq_reqmsg),
                        libcfs_id2str(request->rq_peer),
                        cfs_timeval_sub(&work_end, &request->rq_arrival_time,
                                        NULL) / 1000000,
-                       request->rq_repmsg ? request->rq_repmsg->transno :
-                       request->rq_transno, request->rq_status,
-                       request->rq_repmsg ? request->rq_repmsg->status : -999);
+                       request->rq_repmsg ?
+                                lustre_msg_get_transno(request->rq_repmsg) :
+                                request->rq_transno, request->rq_status,
+                       request->rq_repmsg ?
+                                lustre_msg_get_status(request->rq_repmsg) :
+                                 -999);
         else
                 CDEBUG(D_HA, "request "LPU64" opc %u from %s processed in "
                        "%ldus (%ldus total) trans "LPU64" rc %d/%d\n",
-                       request->rq_xid, request->rq_reqmsg->opc,
+                       request->rq_xid, lustre_msg_get_opc(request->rq_reqmsg),
                        libcfs_id2str(request->rq_peer), timediff,
                        cfs_timeval_sub(&work_end, &request->rq_arrival_time,
                                        NULL),
                        request->rq_transno, request->rq_status,
-                       request->rq_repmsg ? request->rq_repmsg->status : -999);
+                       request->rq_repmsg ?
+                                lustre_msg_get_status(request->rq_repmsg) :
+                                -999);
 
         if (svc->srv_stats != NULL) {
-                int opc = opcode_offset(request->rq_reqmsg->opc);
+                int opc = opcode_offset(lustre_msg_get_opc(request->rq_reqmsg));
                 if (opc > 0) {
                         LASSERT(opc < LUSTRE_MAX_OPCODES);
                         lprocfs_counter_add(svc->srv_stats,
@@ -697,16 +708,15 @@ static int
 ptlrpc_server_handle_reply (struct ptlrpc_service *svc)
 {
         struct ptlrpc_reply_state *rs;
-        unsigned long              flags;
         struct obd_export         *exp;
         struct obd_device         *obd;
         int                        nlocks;
         int                        been_handled;
         ENTRY;
 
-        spin_lock_irqsave (&svc->srv_lock, flags);
+        spin_lock(&svc->srv_lock);
         if (list_empty (&svc->srv_reply_queue)) {
-                spin_unlock_irqrestore (&svc->srv_lock, flags);
+                spin_unlock(&svc->srv_lock);
                 RETURN(0);
         }
 
@@ -749,13 +759,12 @@ ptlrpc_server_handle_reply (struct ptlrpc_service *svc)
                       " o%d NID %s\n",
                       rs,
                       rs->rs_xid, rs->rs_transno,
-                      rs->rs_msg.opc,
+                      lustre_msg_get_opc(rs->rs_msg),
                       libcfs_nid2str(exp->exp_connection->c_peer.nid));
         }
 
-        if ((!been_handled && rs->rs_on_net) ||
-            nlocks > 0) {
-                spin_unlock_irqrestore(&svc->srv_lock, flags);
+        if ((!been_handled && rs->rs_on_net) || nlocks > 0) {
+                spin_unlock(&svc->srv_lock);
 
                 if (!been_handled && rs->rs_on_net) {
                         LNetMDUnlink(rs->rs_md_h);
@@ -767,7 +776,7 @@ ptlrpc_server_handle_reply (struct ptlrpc_service *svc)
                         ldlm_lock_decref(&rs->rs_locks[nlocks],
                                          rs->rs_modes[nlocks]);
 
-                spin_lock_irqsave(&svc->srv_lock, flags);
+                spin_lock(&svc->srv_lock);
         }
 
         rs->rs_scheduled = 0;
@@ -775,7 +784,7 @@ ptlrpc_server_handle_reply (struct ptlrpc_service *svc)
         if (!rs->rs_on_net) {
                 /* Off the net */
                 svc->srv_n_difficult_replies--;
-                spin_unlock_irqrestore(&svc->srv_lock, flags);
+                spin_unlock(&svc->srv_lock);
 
                 class_export_put (exp);
                 rs->rs_export = NULL;
@@ -785,7 +794,7 @@ ptlrpc_server_handle_reply (struct ptlrpc_service *svc)
         }
 
         /* still on the net; callback will schedule */
-        spin_unlock_irqrestore (&svc->srv_lock, flags);
+        spin_unlock(&svc->srv_lock);
         RETURN(1);
 }
 
@@ -840,14 +849,15 @@ void ptlrpc_daemonize(char *name)
         cfs_daemonize(name);
         exit_fs(cfs_current());
         current->fs = fs;
-        set_fs_pwd(current->fs, init_task.fs->pwdmnt, init_task.fs->pwd);
+        ll_set_fs_pwd(current->fs, init_task.fs->pwdmnt, init_task.fs->pwd);
 }
 
 static void
 ptlrpc_check_rqbd_pool(struct ptlrpc_service *svc)
 {
         int avail = svc->srv_nrqbd_receiving;
-        int low_water = svc->srv_nbuf_per_group/2;
+        int low_water = test_req_buffer_pressure ? 0 :
+                        svc->srv_nbuf_per_group/2;
 
         /* NB I'm not locking; just looking. */
 
@@ -880,7 +890,6 @@ static int ptlrpc_main(void *arg)
         struct ptlrpc_thread   *thread = data->thread;
         struct ptlrpc_reply_state *rs;
         struct lc_watchdog     *watchdog;
-        unsigned long           flags;
 #ifdef WITH_GROUP_INFO
         struct group_info *ginfo = NULL;
 #endif
@@ -946,13 +955,12 @@ static int ptlrpc_main(void *arg)
          */
         cfs_waitq_signal(&thread->t_ctl_waitq);
 
-        watchdog = lc_watchdog_add(svc->srv_watchdog_timeout,
-                                   LC_WATCHDOG_DEFAULT_CB, NULL);
+        watchdog = lc_watchdog_add(svc->srv_watchdog_timeout, NULL, NULL);
 
-        spin_lock_irqsave(&svc->srv_lock, flags);
+        spin_lock(&svc->srv_lock);
         svc->srv_nthreads++;
         list_add(&rs->rs_list, &svc->srv_free_rs_list);
-        spin_unlock_irqrestore(&svc->srv_lock, flags);
+        spin_unlock(&svc->srv_lock);
         cfs_waitq_signal(&svc->srv_free_rs_waitq);
 
         CDEBUG(D_NET, "service thread %d started\n", thread->t_id);
@@ -1003,6 +1011,8 @@ static int ptlrpc_main(void *arg)
                          * for a timeout (unless something else happens)
                          * before I try again */
                         svc->srv_rqbd_timeout = cfs_time_seconds(1)/10;
+                        CDEBUG(D_RPCTRACE,"Posted buffers: %d\n",
+                               svc->srv_nrqbd_receiving);
                 }
         }
 
@@ -1020,13 +1030,13 @@ out:
 
         CDEBUG(D_NET, "service thread %d exiting: rc %d\n", thread->t_id, rc);
 
-        spin_lock_irqsave(&svc->srv_lock, flags);
+        spin_lock(&svc->srv_lock);
         svc->srv_nthreads--;                    /* must know immediately */
         thread->t_id = rc;
         thread->t_flags = SVC_STOPPED;
 
         cfs_waitq_signal(&thread->t_ctl_waitq);
-        spin_unlock_irqrestore(&svc->srv_lock, flags);
+        spin_unlock(&svc->srv_lock);
 
         return rc;
 }
@@ -1035,39 +1045,37 @@ static void ptlrpc_stop_thread(struct ptlrpc_service *svc,
                                struct ptlrpc_thread *thread)
 {
         struct l_wait_info lwi = { 0 };
-        unsigned long      flags;
 
-        spin_lock_irqsave(&svc->srv_lock, flags);
+        spin_lock(&svc->srv_lock);
         thread->t_flags = SVC_STOPPING;
-        spin_unlock_irqrestore(&svc->srv_lock, flags);
+        spin_unlock(&svc->srv_lock);
 
         cfs_waitq_broadcast(&svc->srv_waitq);
         l_wait_event(thread->t_ctl_waitq, (thread->t_flags & SVC_STOPPED),
                      &lwi);
 
-        spin_lock_irqsave(&svc->srv_lock, flags);
+        spin_lock(&svc->srv_lock);
         list_del(&thread->t_link);
-        spin_unlock_irqrestore(&svc->srv_lock, flags);
+        spin_unlock(&svc->srv_lock);
 
         OBD_FREE(thread, sizeof(*thread));
 }
 
 void ptlrpc_stop_all_threads(struct ptlrpc_service *svc)
 {
-        unsigned long flags;
         struct ptlrpc_thread *thread;
 
-        spin_lock_irqsave(&svc->srv_lock, flags);
+        spin_lock(&svc->srv_lock);
         while (!list_empty(&svc->srv_threads)) {
                 thread = list_entry(svc->srv_threads.next,
                                     struct ptlrpc_thread, t_link);
 
-                spin_unlock_irqrestore(&svc->srv_lock, flags);
+                spin_unlock(&svc->srv_lock);
                 ptlrpc_stop_thread(svc, thread);
-                spin_lock_irqsave(&svc->srv_lock, flags);
+                spin_lock(&svc->srv_lock);
         }
 
-        spin_unlock_irqrestore(&svc->srv_lock, flags);
+        spin_unlock(&svc->srv_lock);
 }
 
 /* @base_name should be 11 characters or less - 3 will be added on */
@@ -1097,7 +1105,6 @@ int ptlrpc_start_thread(struct obd_device *dev, struct ptlrpc_service *svc,
         struct l_wait_info lwi = { 0 };
         struct ptlrpc_svc_data d;
         struct ptlrpc_thread *thread;
-        unsigned long flags;
         int rc;
         ENTRY;
 
@@ -1107,9 +1114,9 @@ int ptlrpc_start_thread(struct obd_device *dev, struct ptlrpc_service *svc,
         cfs_waitq_init(&thread->t_ctl_waitq);
         thread->t_id = id;
 
-        spin_lock_irqsave(&svc->srv_lock, flags);
+        spin_lock(&svc->srv_lock);
         list_add(&thread->t_link, &svc->srv_threads);
-        spin_unlock_irqrestore(&svc->srv_lock, flags);
+        spin_unlock(&svc->srv_lock);
 
         d.dev = dev;
         d.svc = svc;
@@ -1123,9 +1130,9 @@ int ptlrpc_start_thread(struct obd_device *dev, struct ptlrpc_service *svc,
         if (rc < 0) {
                 CERROR("cannot start thread '%s': rc %d\n", name, rc);
 
-                spin_lock_irqsave(&svc->srv_lock, flags);
+                spin_lock(&svc->srv_lock);
                 list_del(&thread->t_link);
-                spin_unlock_irqrestore(&svc->srv_lock, flags);
+                spin_unlock(&svc->srv_lock);
 
                 OBD_FREE(thread, sizeof(*thread));
                 RETURN(rc);
@@ -1141,7 +1148,6 @@ int ptlrpc_start_thread(struct obd_device *dev, struct ptlrpc_service *svc,
 int ptlrpc_unregister_service(struct ptlrpc_service *service)
 {
         int                   rc;
-        unsigned long         flags;
         struct l_wait_info    lwi;
         struct list_head     *tmp;
         struct ptlrpc_reply_state *rs, *t;
@@ -1161,6 +1167,9 @@ int ptlrpc_unregister_service(struct ptlrpc_service *service)
 
         CDEBUG(D_NET, "%s: tearing down\n", service->srv_name);
 
+        rc = LNetClearLazyPortal(service->srv_req_portal);
+        LASSERT (rc == 0);
+
         /* Unlink all the request buffers.  This forces a 'final' event with
          * its 'unlink' flag set for each posted rqbd */
         list_for_each(tmp, &service->srv_active_rqbds) {
@@ -1175,9 +1184,9 @@ int ptlrpc_unregister_service(struct ptlrpc_service *service)
         /* Wait for the network to release any buffers it's currently
          * filling */
         for (;;) {
-                spin_lock_irqsave(&service->srv_lock, flags);
+                spin_lock(&service->srv_lock);
                 rc = service->srv_nrqbd_receiving;
-                spin_unlock_irqrestore(&service->srv_lock, flags);
+                spin_unlock(&service->srv_lock);
 
                 if (rc == 0)
                         break;
@@ -1194,14 +1203,14 @@ int ptlrpc_unregister_service(struct ptlrpc_service *service)
         }
 
         /* schedule all outstanding replies to terminate them */
-        spin_lock_irqsave(&service->srv_lock, flags);
+        spin_lock(&service->srv_lock);
         while (!list_empty(&service->srv_active_replies)) {
                 struct ptlrpc_reply_state *rs =
                         list_entry(service->srv_active_replies.next,
                                    struct ptlrpc_reply_state, rs_list);
                 ptlrpc_schedule_difficult_reply(rs);
         }
-        spin_unlock_irqrestore(&service->srv_lock, flags);
+        spin_unlock(&service->srv_lock);
 
         /* purge the request queue.  NB No new replies (rqbds all unlinked)
          * and no service threads, so I'm the only thread noodling the
@@ -1269,13 +1278,12 @@ int ptlrpc_service_health_check(struct ptlrpc_service *svc)
         struct ptlrpc_request *request;
         struct timeval         right_now;
         long                   timediff, cutoff;
-        unsigned long          flags;
         int                    rc = 0;
 
         if (svc == NULL)
                 return 0;
 
-        spin_lock_irqsave(&svc->srv_lock, flags);
+        spin_lock(&svc->srv_lock);
 
         if (list_empty(&svc->srv_request_queue))
                 goto out;
@@ -1294,6 +1302,6 @@ int ptlrpc_service_health_check(struct ptlrpc_service *svc)
         }
 
  out:
-        spin_unlock_irqrestore(&svc->srv_lock, flags);
+        spin_unlock(&svc->srv_lock);
         return rc;
 }
diff --git a/lustre/ptlrpc/wirehdr.c b/lustre/ptlrpc/wirehdr.c
new file mode 100644 (file)
index 0000000..d287ba3
--- /dev/null
@@ -0,0 +1,10 @@
+#define DEBUG_SUBSYSTEM S_RPC
+#ifndef __KERNEL__
+# include <liblustre.h>
+#endif
+
+#include <obd_support.h>
+#include <obd_class.h>
+#include <lustre_net.h>
+#include <lustre_disk.h>
+
diff --git a/lustre/ptlrpc/wiretest.c b/lustre/ptlrpc/wiretest.c
new file mode 100644 (file)
index 0000000..b030804
--- /dev/null
@@ -0,0 +1,14 @@
+#define DEBUG_SUBSYSTEM S_RPC
+#ifndef __KERNEL__
+# include <liblustre.h>
+#endif
+
+#include <obd_support.h>
+#include <obd_class.h>
+#include <lustre_net.h>
+#include <lustre_disk.h>
+
+void lustre_assert_wire_constants(void)
+{
+}
+
index 6086088..1596b74 100644 (file)
@@ -49,18 +49,18 @@ static int target_quotacheck_callback(struct obd_export *exp,
 {
         struct ptlrpc_request *req;
         struct obd_quotactl *body;
-        int rc, size = sizeof(*oqctl);
+        int rc, size[2] = { sizeof(struct ptlrpc_body), sizeof(*oqctl) };
         ENTRY;
 
         req = ptlrpc_prep_req(exp->exp_imp_reverse, LUSTRE_OBD_VERSION,
-                              OBD_QC_CALLBACK, 1, &size, NULL);
+                              OBD_QC_CALLBACK, 2, size, NULL);
         if (!req)
                 RETURN(-ENOMEM);
 
-        body = lustre_msg_buf(req->rq_reqmsg, 0, sizeof(*body));
+        body = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, sizeof(*body));
         *body = *oqctl;
 
-        req->rq_replen = lustre_msg_size(0, NULL);
+        ptlrpc_req_set_repsize(req, 1, NULL);
 
         rc = ptlrpc_queue_wait(req);
         ptlrpc_req_finished(req);
@@ -153,29 +153,28 @@ int client_quota_check(struct obd_export *exp, struct obd_quotactl *oqctl)
         struct client_obd *cli = &exp->exp_obd->u.cli;
         struct ptlrpc_request *req;
         struct obd_quotactl *body;
-        int size = sizeof(*body), opc, version;
-        int rc;
+        int size[2] = { sizeof(struct ptlrpc_body), sizeof(*body) };
+        int ver, opc, rc;
         ENTRY;
 
         if (!strcmp(exp->exp_obd->obd_type->typ_name, LUSTRE_MDC_NAME)) {
-                version = LUSTRE_MDS_VERSION;
+                ver = LUSTRE_MDS_VERSION;
                 opc = MDS_QUOTACHECK;
         } else if (!strcmp(exp->exp_obd->obd_type->typ_name, LUSTRE_OSC_NAME)) {
-                version = LUSTRE_OST_VERSION;
+                ver = LUSTRE_OST_VERSION;
                 opc = OST_QUOTACHECK;
         } else {
                 RETURN(-EINVAL);
         }
 
-        req = ptlrpc_prep_req(class_exp2cliimp(exp), version, opc, 1, &size,
-                              NULL);
+        req = ptlrpc_prep_req(class_exp2cliimp(exp), ver, opc, 2, size, NULL);
         if (!req)
                 GOTO(out, rc = -ENOMEM);
 
-        body = lustre_msg_buf(req->rq_reqmsg, 0, sizeof(*body));
+        body = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, sizeof(*body));
         *body = *oqctl;
 
-        req->rq_replen = lustre_msg_size(0, NULL);
+        ptlrpc_req_set_repsize(req, 1, NULL);
 
         /* the next poll will find -ENODATA, that means quotacheck is
          * going on */
@@ -224,13 +223,13 @@ int lov_quota_check(struct obd_export *exp, struct obd_quotactl *oqctl)
         for (i = 0; i < lov->desc.ld_tgt_count; i++) {
                 int err;
 
-                if (!lov->tgts[i].active) {
+                if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_active) {
                         CERROR("lov idx %d inactive\n", i);
                         RETURN(-EIO);
                 }
 
-                err = obd_quotacheck(lov->tgts[i].ltd_exp, oqctl);
-                if (err && lov->tgts[i].active && !rc)
+                err = obd_quotacheck(lov->lov_tgts[i]->ltd_exp, oqctl);
+                if (err && lov->lov_tgts[i]->ltd_active && !rc)
                         rc = err;
         }
 
index 00b97db..47506c1 100644 (file)
@@ -432,9 +432,12 @@ static int dqacq_interpret(struct ptlrpc_request *req, void *data, int rc)
         struct qunit_data *qdata = NULL;
         ENTRY;
 
-        qdata = lustre_swab_repbuf(req, 0, sizeof(*qdata), lustre_swab_qdata);
-        if (rc == 0 && qdata == NULL)
+        qdata = lustre_swab_repbuf(req, REPLY_REC_OFF, sizeof(*qdata),
+                                   lustre_swab_qdata);
+        if (qdata == NULL) {
+                DEBUG_REQ(D_ERROR, req, "error unpacking qunit_data\n");
                 RETURN(-EPROTO);
+        }
 
         LASSERT(qdata->qd_id == qunit->lq_data.qd_id &&
                 qdata->qd_type == qunit->lq_data.qd_type &&
@@ -442,9 +445,11 @@ static int dqacq_interpret(struct ptlrpc_request *req, void *data, int rc)
                  qdata->qd_count == 0));
 
         QDATA_DEBUG(qdata, "%s interpret rc(%d).\n",
-                    req->rq_reqmsg->opc == QUOTA_DQACQ ? "DQACQ" : "DQREL", rc);
+                    lustre_msg_get_opc(req->rq_reqmsg) == QUOTA_DQACQ ?
+                    "DQACQ" : "DQREL", rc);
 
-        rc = dqacq_completion(obd, qctxt, qdata, rc, req->rq_reqmsg->opc);
+        rc = dqacq_completion(obd, qctxt, qdata, rc,
+                              lustre_msg_get_opc(req->rq_reqmsg));
 
         RETURN(rc);
 }
@@ -470,7 +475,7 @@ schedule_dqacq(struct obd_device *obd,
         struct ptlrpc_request *req;
         struct qunit_data *reqdata;
         struct dqacq_async_args *aa;
-        int size = sizeof(*reqdata);
+        int size[2] = { sizeof(struct ptlrpc_body), sizeof(*reqdata) };
         int rc = 0;
         ENTRY;
 
@@ -512,17 +517,17 @@ schedule_dqacq(struct obd_device *obd,
 
         /* build dqacq/dqrel request */
         LASSERT(qctxt->lqc_import);
-        req = ptlrpc_prep_req(qctxt->lqc_import, LUSTRE_MDS_VERSION, opc, 1,
-                              &size, NULL);
+        req = ptlrpc_prep_req(qctxt->lqc_import, LUSTRE_MDS_VERSION, opc, 2,
+                              size, NULL);
         if (!req) {
                 dqacq_completion(obd, qctxt, qdata, -ENOMEM, opc);
                 RETURN(-ENOMEM);
         }
 
-        reqdata = lustre_msg_buf(req->rq_reqmsg, 0, sizeof(*reqdata));
+        reqdata = lustre_msg_buf(req->rq_reqmsg, REPLY_REC_OFF,
+                                 sizeof(*reqdata));
         *reqdata = *qdata;
-        size = sizeof(*reqdata);
-        req->rq_replen = lustre_msg_size(1, &size);
+        ptlrpc_req_set_repsize(req, 2, size);
 
         CLASSERT(sizeof(*aa) <= sizeof(req->rq_async_args));
         aa = (struct dqacq_async_args *)&req->rq_async_args;
@@ -704,9 +709,9 @@ static int qslave_recovery_main(void *arg)
                 struct dquot_id *dqid, *tmp;
                 int ret;
 
-                down(&dqopt->dqonoff_sem);
+                LOCK_DQONOFF_MUTEX(dqopt);
                 if (!sb_has_quota_enabled(qctxt->lqc_sb, type)) {
-                        up(&dqopt->dqonoff_sem);
+                        UNLOCK_DQONOFF_MUTEX(dqopt);
                         break;
                 }
 
@@ -717,7 +722,7 @@ static int qslave_recovery_main(void *arg)
 #else
                 rc = fsfilt_qids(obd, NULL, dqopt->files[type], type, &id_list);
 #endif
-                up(&dqopt->dqonoff_sem);
+                UNLOCK_DQONOFF_MUTEX(dqopt);
                 if (rc)
                         CERROR("Get ids from quota file failed. (rc:%d)\n", rc);
 
@@ -743,7 +748,7 @@ static int qslave_recovery_main(void *arg)
                                 rc = 0;
 
                         if (rc)
-                                CDEBUG_EX(rc == -EBUSY ? D_QUOTA : D_ERROR,
+                                CDEBUG(rc == -EBUSY ? D_QUOTA : D_ERROR,
                                        "qslave recovery failed! (id:%d type:%d "
                                        " rc:%d)\n", dqid->di_id, type, rc);
 free:
index a8c4317..f761792 100644 (file)
@@ -181,33 +181,32 @@ int client_quota_ctl(struct obd_export *exp, struct obd_quotactl *oqctl)
 {
         struct ptlrpc_request *req;
         struct obd_quotactl *oqc;
-        int size = sizeof(*oqctl), opc, version;
-        int rc;
+        int size[2] = { sizeof(struct ptlrpc_body), sizeof(*oqctl) };
+        int ver, opc, rc;
         ENTRY;
 
         if (!strcmp(exp->exp_obd->obd_type->typ_name, LUSTRE_MDC_NAME)) {
+                ver = LUSTRE_MDS_VERSION,
                 opc = MDS_QUOTACTL;
-                version = LUSTRE_MDS_VERSION;
         } else if (!strcmp(exp->exp_obd->obd_type->typ_name, LUSTRE_OSC_NAME)) {
+                ver = LUSTRE_OST_VERSION,
                 opc = OST_QUOTACTL;
-                version = LUSTRE_OST_VERSION;
         } else {
                 RETURN(-EINVAL);
         }
 
-        req = ptlrpc_prep_req(class_exp2cliimp(exp), version, opc, 1, &size,
-                              NULL);
+        req = ptlrpc_prep_req(class_exp2cliimp(exp), ver, opc, 2, size, NULL);
         if (!req)
                 GOTO(out, rc = -ENOMEM);
 
-        oqc = lustre_msg_buf(req->rq_reqmsg, 0, sizeof (*oqctl));
+        oqc = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, sizeof(*oqctl));
         *oqc = *oqctl;
 
-        req->rq_replen = lustre_msg_size(1, &size);
+        ptlrpc_req_set_repsize(req, 2, size);
 
         rc = ptlrpc_queue_wait(req);
         if (!rc) {
-                oqc = lustre_swab_repbuf(req, 0, sizeof (*oqc),
+                oqc = lustre_swab_repbuf(req, REPLY_REC_OFF, sizeof(*oqc),
                                          lustre_swab_obd_quotactl);
                 if (oqc == NULL) {
                         CERROR ("Can't unpack obd_quotactl\n");
@@ -239,7 +238,7 @@ int lov_quota_ctl(struct obd_export *exp, struct obd_quotactl *oqctl)
         for (i = 0; i < lov->desc.ld_tgt_count; i++) {
                 int err;
 
-                if (!lov->tgts[i].active) {
+                if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_active) {
                         if (oqctl->qc_cmd == Q_GETOQUOTA) {
                                 CERROR("ost %d is inactive\n", i);
                                 rc = -EIO;
@@ -250,9 +249,9 @@ int lov_quota_ctl(struct obd_export *exp, struct obd_quotactl *oqctl)
                         }
                 }
 
-                err = obd_quotactl(lov->tgts[i].ltd_exp, oqctl);
+                err = obd_quotactl(lov->lov_tgts[i]->ltd_exp, oqctl);
                 if (err) {
-                        if (lov->tgts[i].active && !rc)
+                        if (lov->lov_tgts[i]->ltd_active && !rc)
                                 rc = err;
                         continue;
                 }
index 35a7f4a..b8a3516 100644 (file)
@@ -195,7 +195,7 @@ static int auto_quota_on(struct obd_device *obd, int type,
 local_quota:
         /* turn on local quota */
         rc = fsfilt_quotactl(obd, sb, oqctl);
-        CDEBUG_EX(rc ? D_ERROR : D_INFO, "auto-enable quota. rc=%d\n", rc);
+        CDEBUG(rc ? D_ERROR : D_INFO, "auto-enable quota. rc=%d\n", rc);
         if (rc && is_master)
                 mds_quota_off(obd, oqctl);
 out_pop:
index 97728eb..bf8de9d 100644 (file)
@@ -72,3 +72,5 @@ flock_test
 writemany
 random-reads
 chownmany
+llverdev
+llverfs
index 8713a35..12458c9 100644 (file)
@@ -4,22 +4,19 @@ AM_CFLAGS = $(LLCFLAGS)
 # LDADD = -lldap
 # LDADD := -lreadline -ltermcap # -lefence
 
-pkgexample_scripts = llmount.sh llmountcleanup.sh llecho.sh llechocleanup.sh
-pkgexample_scripts += local.sh echo.sh uml.sh lov.sh
 noinst_DATA =
-noinst_SCRIPTS = leak_finder.pl llecho.sh llmount.sh llmountcleanup.sh
+noinst_SCRIPTS = leak_finder.pl llecho.sh llmount.sh llmountcleanup.sh test-framework.sh
 noinst_SCRIPTS += runfailure-mds runvmstat runfailure-net
 noinst_SCRIPTS += runfailure-ost runiozone runregression-net.sh runtests
 noinst_SCRIPTS += sanity.sh rundbench
 
-EXTRA_DIST = $(pkgexample_scripts) $(noinst_SCRIPTS) $(noinst_DATA) \
+EXTRA_DIST = $(noinst_SCRIPTS) $(noinst_DATA) \
              sanity.sh rundbench \
              acl/run acl/make-tree acl/getfacl-noacl.test acl/cp.test \
              acl/setfacl.test acl/permissions.test acl/misc.test \
              acl/inheritance.test
 
 if TESTS
-pkgexample_SCRIPTS = $(pkgexample_scripts)
 noinst_PROGRAMS = openunlink testreq truncate directio openme writeme
 noinst_PROGRAMS += tchmod toexcl fsx test_brw openclose createdestroy
 noinst_PROGRAMS += stat createmany chownmany statmany multifstat createtest mlink utime
index a4bacc2..b1303c3 100755 (executable)
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 # script which _must_ complete successfully (at minimum) before checkins to
 # the CVS HEAD are allowed.
 set -vxe
@@ -6,13 +6,13 @@ set -vxe
 PATH=`dirname $0`/../utils:$PATH
 
 [ "$CONFIGS" ] || CONFIGS="local"  #"local lov"
-[ "$MAX_THREADS" ] || MAX_THREADS=10
+[ "$MAX_THREADS" ] || MAX_THREADS=20
+RAMKB=`awk '/MemTotal:/ { print $2 }' /proc/meminfo`
 if [ -z "$THREADS" ]; then
-       KB=`awk '/MemTotal:/ { print $2 }' /proc/meminfo`
-       THREADS=`expr $KB / 16384`
+       THREADS=$((RAMKB / 16384))
        [ $THREADS -gt $MAX_THREADS ] && THREADS=$MAX_THREADS
 fi
-[ "$SIZE" ] || SIZE=40960
+[ "$SIZE" ] || SIZE=$((RAMKB * 2))
 [ "$RSIZE" ] || RSIZE=512
 [ "$UID" ] || UID=1000
 [ "$MOUNT" ] || MOUNT=/mnt/lustre
@@ -29,18 +29,21 @@ LIBLUSTRETESTS=${LIBLUSTRETESTS:-$LIBLUSTRE/tests}
 LUSTRE=${LUSTRE:-`dirname $0`/..}
 . $LUSTRE/tests/test-framework.sh
 init_test_env $@
-. mountconf.sh
 
-SETUP=${SETUP:-mcsetup}
-FORMAT=${FORMAT:-mcformat}
-CLEANUP=${CLEANUP:-mcstopall}
+SETUP=${SETUP:-setupall}
+FORMAT=${FORMAT:-formatall}
+CLEANUP=${CLEANUP:-stopall}
+
+setup_if_needed() {
+    mount | grep $MOUNT || $FORMAT && $SETUP
+}
 
 for NAME in $CONFIGS; do
        export NAME MOUNT START CLEAN
        . $LUSTRE/tests/cfg/$NAME.sh
        
        assert_env mds_HOST MDS_MKFS_OPTS MDSDEV
-       assert_env ost_HOST ost2_HOST OST_MKFS_OPTS OSTDEV
+       assert_env ost_HOST OST_MKFS_OPTS OSTCOUNT
        assert_env FSNAME
 
        if [ "$RUNTESTS" != "no" ]; then
@@ -52,9 +55,9 @@ for NAME in $CONFIGS; do
        fi
 
        if [ "$DBENCH" != "no" ]; then
-               mount_client $MOUNT
+               setup_if_needed
                SPACE=`df -P $MOUNT | tail -n 1 | awk '{ print $4 }'`
-               DB_THREADS=`expr $SPACE / 50000`
+               DB_THREADS=$((SPACE / 50000))
                [ $THREADS -lt $DB_THREADS ] && DB_THREADS=$THREADS
 
                $DEBUG_OFF
@@ -74,24 +77,37 @@ for NAME in $CONFIGS; do
 
        chown $UID $MOUNT && chmod 700 $MOUNT
        if [ "$BONNIE" != "no" ]; then
-               mount_client $MOUNT
+               setup_if_needed
+               SPACE=`df -P $MOUNT | tail -n 1 | awk '{ print $4 }'`
+               [ $SPACE -lt $SIZE ] && SIZE=$((SPACE * 3 / 4))
                $DEBUG_OFF
-               bonnie++ -f -r 0 -s $(($SIZE / 1024)) -n 10 -u $UID -d $MOUNT
+               bonnie++ -f -r 0 -s $((SIZE / 1024)) -n 10 -u $UID -d $MOUNT
                $DEBUG_ON
                $CLEANUP
                $SETUP
        fi
 
-       IOZONE_OPTS="-i 0 -i 1 -i 2 -e -+d -r $RSIZE -s $SIZE"
-       IOZFILE="-f $MOUNT/iozone"
+       export O_DIRECT
        if [ "$IOZONE" != "no" ]; then
-               mount_client $MOUNT
+               setup_if_needed
+               SPACE=`df -P $MOUNT | tail -n 1 | awk '{ print $4 }'`
+               [ $SPACE -lt $SIZE ] && SIZE=$((SPACE * 3 / 4))
+               IOZONE_OPTS="-i 0 -i 1 -i 2 -e -+d -r $RSIZE -s $SIZE"
+               IOZFILE="-f $MOUNT/iozone"
                $DEBUG_OFF
                iozone $IOZONE_OPTS $IOZFILE
                $DEBUG_ON
                $CLEANUP
                $SETUP
 
+               # check if O_DIRECT support is implemented in kernel
+               if [ -z "$O_DIRECT" ]; then
+                       touch $MOUNT/f.iozone
+                       if ! ./directio write $MOUNT/f.iozone 0 1; then
+                               O_DIRECT=no
+                       fi
+                       rm -f $MOUNT/f.iozone
+               fi
                if [ "$O_DIRECT" != "no" -a "$IOZONE_DIR" != "no" ]; then
                        $DEBUG_OFF
                        iozone -I $IOZONE_OPTS $IOZFILE.odir
@@ -101,16 +117,16 @@ for NAME in $CONFIGS; do
                fi
 
                SPACE=`df -P $MOUNT | tail -n 1 | awk '{ print $4 }'`
-               IOZ_THREADS=`expr $SPACE / \( $SIZE + $SIZE / 512 \)`
+               IOZ_THREADS=$((SPACE / SIZE * 2 / 3 ))
                [ $THREADS -lt $IOZ_THREADS ] && IOZ_THREADS=$THREADS
-               IOZVER=`iozone -v|awk '/Revision:/ {print $3}'|tr -d .`
+               IOZVER=`iozone -v | awk '/Revision:/ {print $3}' | tr -d .`
                if [ "$IOZ_THREADS" -gt 1 -a "$IOZVER" -ge 3145 ]; then
                        $DEBUG_OFF
                        THREAD=1
                        IOZFILE="-F "
                        while [ $THREAD -le $IOZ_THREADS ]; do
                                IOZFILE="$IOZFILE $MOUNT/iozone.$THREAD"
-                               THREAD=`expr $THREAD + 1`
+                               THREAD=$((THREAD + 1))
                        done
                        iozone $IOZONE_OPTS -t $IOZ_THREADS $IOZFILE
                        $DEBUG_ON
@@ -123,7 +139,9 @@ for NAME in $CONFIGS; do
        fi
 
        if [ "$FSX" != "no" ]; then
-               mount | grep $MOUNT || $SETUP
+               setup_if_needed
+               SPACE=`df -P $MOUNT | tail -n 1 | awk '{ print $4 }'`
+               [ $SPACE -lt $SIZE ] && SIZE=$((SPACE * 3 / 4))
                $DEBUG_OFF
                ./fsx -c 50 -p 1000 -P $TMP -l $SIZE \
                        -N $(($COUNT * 100)) $MOUNT/fsxfile
@@ -144,7 +162,7 @@ for NAME in $CONFIGS; do
        esac
 
        if [ "$SANITYN" != "no" ]; then
-               mount_client $MOUNT
+               setup_if_needed
                $DEBUG_OFF
 
                if [ "$MDSNODE" -a "$MDSNAME" -a "$CLIENT" ]; then
@@ -162,7 +180,7 @@ for NAME in $CONFIGS; do
        fi
 
        if [ "$LIBLUSTRE" != "no" ]; then
-               mount_client $MOUNT
+               setup_if_needed
                export LIBLUSTRE_MOUNT_POINT=$MOUNT2
                export LIBLUSTRE_MOUNT_TARGET=$MDSNODE:/$MDSNAME/$CLIENT
                export LIBLUSTRE_TIMEOUT=`cat /proc/sys/lustre/timeout`
index e8d323e..e3f4087 100644 (file)
@@ -1,22 +1,26 @@
 FSNAME=lustre
+
+# facet hosts
 mds_HOST=${mds_HOST:-`hostname`}
-mgs_HOST=${mgs_HOST:-$mds_HOST}
 mdsfailover_HOST=${mdsfailover_HOST:-""}
-ost1_HOST=${ost1_HOST:-"`hostname`"}
-ost2_HOST=${ost2_HOST:-"`hostname`"}
-EXTRA_OSTS=${EXTRA_OSTS:-"`hostname`"}
-LIVE_CLIENT=${LIVE_CLIENT:-"`hostname`"}
+mgs_HOST=${mgs_HOST:-$mds_HOST}
+ost_HOST=${ost_HOST:-`hostname`}
+LIVE_CLIENT=${LIVE_CLIENT:-`hostname`}
 # This should always be a list, not a regexp
 FAIL_CLIENTS=${FAIL_CLIENTS:-""}
 
+TMP=${TMP:-/tmp}
 MDSDEV=${MDSDEV:-$TMP/${FSNAME}-mdt}
-MDSSIZE=${MDSSIZE:-10000} #50000000
-OSTDEV=${OSTDEV:-"$TMP/${FSNAME}-ost%d"}
-OSTSIZE=${OSTSIZE:=10000} #50000000
+MDSSIZE=${MDSSIZE:-100000}
+MDSOPT=${MDSOPT:-"--mountfsoptions=acl"}
+
+OSTCOUNT=${OSTCOUNT:-3}
+OSTDEVBASE=${OSTDEVBASE:-$TMP/${FSNAME}-ost}
+OSTSIZE=${OSTSIZE:-200000}
 
 NETTYPE=${NETTYPE:-tcp}
-MGSNID=`h2$NETTYPE $mgs_HOST`
-FSTYPE=${FSTYPE:-ext3}
+MGSNID=${MGSNID:-`h2$NETTYPE $mgs_HOST`}
+FSTYPE=${FSTYPE:-ldiskfs}
 STRIPE_BYTES=${STRIPE_BYTES:-1048576}
 STRIPES_PER_OBJ=${STRIPES_PER_OBJ:-0}
 TIMEOUT=${TIMEOUT:-30}
@@ -34,10 +38,10 @@ MOUNTOPT=""
 [ "x$mdsfailover_HOST" != "x" ] &&
     MOUNTOPT=$MOUNTOPT" --failnode=`h2$NETTYPE $mdsfailover_HOST`"
 [ "x$STRIPE_BYTES" != "x" ] &&
-    MOUNTOPT=$MOUNTOPT" --param default_stripe_size=$STRIPE_BYTES"
+    MOUNTOPT=$MOUNTOPT" --param lov.stripesize=$STRIPE_BYTES"
 [ "x$STRIPES_PER_OBJ" != "x" ] &&
-    MOUNTOPT=$MOUNTOPT" --param default_stripe_count=$STRIPES_PER_OBJ"
-MDS_MKFS_OPTS="--mgs --mdt --device-size=$MDSSIZE $MKFSOPT $MOUNTOPT $MDSOPT"
+    MOUNTOPT=$MOUNTOPT" --param lov.stripecount=$STRIPES_PER_OBJ"
+MDS_MKFS_OPTS="--mgs --mdt --fsname=$FSNAME --device-size=$MDSSIZE --param sys.timeout=$TIMEOUT $MKFSOPT $MOUNTOPT $MDSOPT"
 
 MKFSOPT=""
 MOUNTOPT=""
@@ -47,7 +51,7 @@ MOUNTOPT=""
     MKFSOPT="--mkfsoptions=\"$MKFSOPT\""
 [ "x$ostfailover_HOST" != "x" ] &&
     MOUNTOPT=$MOUNTOPT" --failnode=`h2$NETTYPE $ostfailover_HOST`"
-OST_MKFS_OPTS="--ost --device-size=$OSTSIZE --mgsnode=$MGSNID $MKFSOPT $MOUNTOPT $OSTOPT"
+OST_MKFS_OPTS="--ost --fsname=$FSNAME --device-size=$OSTSIZE --mgsnode=$MGSNID --param sys.timeout=$TIMEOUT $MKFSOPT $MOUNTOPT $OSTOPT"
 
 MDS_MOUNT_OPTS="-o loop"
 OST_MOUNT_OPTS="-o loop"
index ca7258e..adf0418 100644 (file)
@@ -1,31 +1,33 @@
-# oldstyle
-MDSNODE=${MDSNODE:-`hostname`}
-OSTNODE=${OSTNODE:-`hostname`}
-CLIENT=${CLIENT:-client}
-
 FSNAME=lustre
-mds_HOST=${mds_HOST:-$MDSNODE}
+
+# facet hosts
+mds_HOST=${mds_HOST:-`hostname`}
 mdsfailover_HOST=${mdsfailover_HOST}
 mgs_HOST=${mgs_HOST:-$mds_HOST}
-ost_HOST=${ost_HOST:-$OSTNODE}
+ost_HOST=${ost_HOST:-`hostname`}
 ostfailover_HOST=${ostfailover_HOST}
-ost2_HOST=${ost2_HOST:-$ost_HOST}
 
 TMP=${TMP:-/tmp}
+
 MDSDEV=${MDSDEV:-$TMP/${FSNAME}-mdt}
 MDSSIZE=${MDSSIZE:-100000}
 MDSOPT=${MDSOPT:-"--mountfsoptions=acl"}
-OSTDEV=${OSTDEV:-$TMP/${FSNAME}-ost0}
+
+OSTCOUNT=${OSTCOUNT:-2}
+OSTDEVBASE=${OSTDEVBASE:-$TMP/${FSNAME}-ost}
 OSTSIZE=${OSTSIZE:-200000}
-OSTDEV2=${OSTDEV2:-$TMP/${FSNAME}-ost1}
+OSTOPT=""
+# Can specify individual ost devs with
+# OSTDEV1="/dev/sda"
+# on specific hosts with
+# ost1_HOST="uml2"
 
 NETTYPE=${NETTYPE:-tcp}
-MGSNID=`h2$NETTYPE $mgs_HOST`
+MGSNID=${MGSNID:-`h2$NETTYPE $mgs_HOST`}
 FSTYPE=${FSTYPE:-ldiskfs}
 STRIPE_BYTES=${STRIPE_BYTES:-1048576}
 STRIPES_PER_OBJ=${STRIPES_PER_OBJ:-0}
 TIMEOUT=${TIMEOUT:-20}
-UPCALL=${UPCALL:-DEFAULT}
 PTLDEBUG=${PTLDEBUG:-0x33f0404}
 SUBSYSTEM=${SUBSYSTEM:- 0xffb7e3ff}
 
@@ -40,10 +42,10 @@ MOUNTOPT=""
 [ "x$mdsfailover_HOST" != "x" ] &&
     MOUNTOPT=$MOUNTOPT" --failnode=`h2$NETTYPE $mdsfailover_HOST`"
 [ "x$STRIPE_BYTES" != "x" ] &&
-    MOUNTOPT=$MOUNTOPT" --param default_stripe_size=$STRIPE_BYTES"
+    MOUNTOPT=$MOUNTOPT" --param lov.stripesize=$STRIPE_BYTES"
 [ "x$STRIPES_PER_OBJ" != "x" ] &&
-    MOUNTOPT=$MOUNTOPT" --param default_stripe_count=$STRIPES_PER_OBJ"
-MDS_MKFS_OPTS="--mgs --mdt --device-size=$MDSSIZE --param obd_timeout=$TIMEOUT $MKFSOPT $MOUNTOPT $MDSOPT"
+    MOUNTOPT=$MOUNTOPT" --param lov.stripecount=$STRIPES_PER_OBJ"
+MDS_MKFS_OPTS="--mgs --mdt --fsname=$FSNAME --device-size=$MDSSIZE --param sys.timeout=$TIMEOUT $MKFSOPT $MOUNTOPT $MDSOPT"
 
 MKFSOPT=""
 MOUNTOPT=""
@@ -53,20 +55,19 @@ MOUNTOPT=""
     MKFSOPT="--mkfsoptions=\"$MKFSOPT\""
 [ "x$ostfailover_HOST" != "x" ] &&
     MOUNTOPT=$MOUNTOPT" --failnode=`h2$NETTYPE $ostfailover_HOST`"
-OST_MKFS_OPTS="--ost --device-size=$OSTSIZE --mgsnode=$MGSNID --param obd_timeout=$TIMEOUT $MKFSOPT $MOUNTOPT $OSTOPT"
-OST2_MKFS_OPTS=${OST2_MKFS_OPTS:-${OST_MKFS_OPTS}}
+OST_MKFS_OPTS="--ost --fsname=$FSNAME --device-size=$OSTSIZE --mgsnode=$MGSNID --param sys.timeout=$TIMEOUT $MKFSOPT $MOUNTOPT $OSTOPT"
 
-MDS_MOUNT_OPTS="-o loop"
-OST_MOUNT_OPTS="-o loop"
-OST2_MOUNT_OPTS="-o loop"
+MDS_MOUNT_OPTS=${MDS_MOUNT_OPTS:-"-o loop"}
+OST_MOUNT_OPTS=${OST_MOUNT_OPTS:-"-o loop"}
 
+#client
 MOUNT=${MOUNT:-/mnt/${FSNAME}}
 MOUNT1=${MOUNT1:-$MOUNT}
 MOUNT2=${MOUNT2:-${MOUNT}2}
+MOUNTOPT=${MOUNTOPT:-"user_xattr,acl"}
 DIR=${DIR:-$MOUNT}
 DIR1=${DIR:-$MOUNT1}
 DIR2=${DIR2:-$MOUNT2}
-MOUNTOPT=${MOUNTOPT:-"user_xattr,acl"}
 
 PDSH=${PDSH:-no_dsh}
 FAILURE_MODE=${FAILURE_MODE:-SOFT} # or HARD
diff --git a/lustre/tests/cfg/lov.sh b/lustre/tests/cfg/lov.sh
new file mode 100644 (file)
index 0000000..56ca580
--- /dev/null
@@ -0,0 +1,69 @@
+FSNAME=lustre
+
+# facet hosts
+mds_HOST=${mds_HOST:-`hostname`}
+mdsfailover_HOST=${mdsfailover_HOST}
+mgs_HOST=${mgs_HOST:-$mds_HOST}
+ost_HOST=${ost_HOST:-`hostname`}
+ostfailover_HOST=${ostfailover_HOST}
+
+TMP=${TMP:-/tmp}
+MDSDEV=${MDSDEV:-$TMP/${FSNAME}-mdt}
+MDSSIZE=${MDSSIZE:-400000}
+MDSOPT=${MDSOPT:-"--mountfsoptions=user_xattr,acl,"}
+
+OSTCOUNT=${OSTCOUNT:-6}
+OSTDEVBASE=${OSTDEVBASE:-$TMP/${FSNAME}-ost}
+OSTSIZE=${OSTSIZE:-150000}
+
+NETTYPE=${NETTYPE:-tcp}
+MGSNID=${MGSNID:-`h2$NETTYPE $mgs_HOST`}
+FSTYPE=${FSTYPE:-ldiskfs}
+STRIPE_BYTES=${STRIPE_BYTES:-1048576}
+STRIPES_PER_OBJ=${STRIPES_PER_OBJ:-$((OSTCOUNT -1))}
+TIMEOUT=${TIMEOUT:-20}
+PTLDEBUG=${PTLDEBUG:-0x33f0404}
+SUBSYSTEM=${SUBSYSTEM:- 0xffb7e3ff}
+
+MKFSOPT=""
+MOUNTOPT=""
+[ "x$MDSJOURNALSIZE" != "x" ] &&
+    MKFSOPT=$MKFSOPT" -J size=$MDSJOURNALSIZE"
+[ "x$MDSISIZE" != "x" ] &&
+    MKFSOPT=$MKFSOPT" -i $MDSISIZE"
+[ "x$MKFSOPT" != "x" ] &&
+    MKFSOPT="--mkfsoptions=\"$MKFSOPT\""
+[ "x$mdsfailover_HOST" != "x" ] &&
+    MOUNTOPT=$MOUNTOPT" --failnode=`h2$NETTYPE $mdsfailover_HOST`"
+[ "x$STRIPE_BYTES" != "x" ] &&
+    MOUNTOPT=$MOUNTOPT" --param lov.stripesize=$STRIPE_BYTES"
+[ "x$STRIPES_PER_OBJ" != "x" ] &&
+    MOUNTOPT=$MOUNTOPT" --param lov.stripecount=$STRIPES_PER_OBJ"
+MDS_MKFS_OPTS="--mgs --mdt --fsname=$FSNAME --device-size=$MDSSIZE --param sys.timeout=$TIMEOUT $MKFSOPT $MOUNTOPT $MDSOPT"
+
+MKFSOPT=""
+MOUNTOPT=""
+[ "x$OSTJOURNALSIZE" != "x" ] &&
+    MKFSOPT=$MKFSOPT" -J size=$OSTJOURNALSIZE"
+[ "x$MKFSOPT" != "x" ] &&
+    MKFSOPT="--mkfsoptions=\"$MKFSOPT\""
+[ "x$ostfailover_HOST" != "x" ] &&
+    MOUNTOPT=$MOUNTOPT" --failnode=`h2$NETTYPE $ostfailover_HOST`"
+OST_MKFS_OPTS="--ost --fsname=$FSNAME --device-size=$OSTSIZE --mgsnode=$MGSNID --param sys.timeout=$TIMEOUT $MKFSOPT $MOUNTOPT $OSTOPT"
+
+MDS_MOUNT_OPTS="-o loop"
+OST_MOUNT_OPTS="-o loop"
+
+#client
+MOUNT=${MOUNT:-/mnt/${FSNAME}}
+MOUNT1=${MOUNT1:-$MOUNT}
+MOUNT2=${MOUNT2:-${MOUNT}2}
+MOUNTOPT=${MOUNTOPT:-"user_xattr,"}
+DIR=${DIR:-$MOUNT}
+DIR1=${DIR:-$MOUNT1}
+DIR2=${DIR2:-$MOUNT2}
+
+PDSH=${PDSH:-no_dsh}
+FAILURE_MODE=${FAILURE_MODE:-SOFT} # or HARD
+POWER_DOWN=${POWER_DOWN:-"powerman --off"}
+POWER_UP=${POWER_UP:-"powerman --on"}
index 23ea6ac..e903dbe 100644 (file)
 set -e
 
 ONLY=${ONLY:-"$*"}
-# bug number for skipped test:      mc mc mc mc mc mc  mc mc mc
-ALWAYS_EXCEPT=" $CONF_SANITY_EXCEPT 9  10 11 12 13 13b 14 15 18"
+
+# These tests don't apply to mountconf
+MOUNTCONFSKIP="9 10 11 12 13 13b 14 15 18"
+
+# bug number for skipped test:
+ALWAYS_EXCEPT=" $CONF_SANITY_EXCEPT $MOUNTCONFSKIP 23"
 # UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT!
 
 SRCDIR=`dirname $0`
 PATH=$PWD/$SRCDIR:$SRCDIR:$SRCDIR/../utils:$PATH
 
+PTLDEBUG=${PTLDEBUG:-1}
 LUSTRE=${LUSTRE:-`dirname $0`/..}
 RLUSTRE=${RLUSTRE:-$LUSTRE}
 MOUNTLUSTRE=${MOUNTLUSTRE:-/sbin/mount.lustre}
@@ -24,20 +29,11 @@ MKFSLUSTRE=${MKFSLUSTRE:-/usr/sbin/mkfs.lustre}
 HOSTNAME=`hostname`
 
 . $LUSTRE/tests/test-framework.sh
-
 init_test_env $@
-
 . ${CONFIG:=$LUSTRE/tests/cfg/local.sh}
 
 reformat() {
-        grep " $MOUNT " /proc/mounts && zconf_umount `hostname` $MOUNT
-       stop ost -f
-       stop ost2 -f
-       stop mds -f
-       echo Formatting mds, ost, ost2
-       add mds $MDS_MKFS_OPTS --reformat $MDSDEV  > /dev/null
-       add ost $OST_MKFS_OPTS --reformat $OSTDEV  > /dev/null
-       add ost2 $OST2_MKFS_OPTS --reformat $OSTDEV2  > /dev/null
+        formatall
 }
 
 gen_config() {
@@ -63,19 +59,19 @@ stop_mds() {
 }
 
 start_ost() {
-       echo "start ost service on `facet_active_host ost`"
-       start ost $OSTDEV $OST_MOUNT_OPTS || return 95
+       echo "start ost1 service on `facet_active_host ost1`"
+       start ost1 `ostdevname 1` $OST_MOUNT_OPTS || return 95
 }
 
 stop_ost() {
-       echo "stop ost service on `facet_active_host ost`"
+       echo "stop ost1 service on `facet_active_host ost1`"
        # These tests all use non-failover stop
-       stop ost -f  || return 98
+       stop ost1 -f  || return 98
 }
 
 start_ost2() {
        echo "start ost2 service on `facet_active_host ost2`"
-       start ost2 $OSTDEV2 $OST2_MOUNT_OPTS || return 92
+       start ost2 `ostdevname 2` $OST_MOUNT_OPTS || return 92
 }
 
 stop_ost2() {
@@ -90,6 +86,15 @@ mount_client() {
        zconf_mount `hostname` $MOUNTPATH  || return 96
 }
 
+remount_client() {
+       local SAVEMOUNTOPT=$MOUNTOPT
+       MOUNTOPT="remount,$1"
+       local MOUNTPATH=$2
+       echo "remount '$1' lustre on ${MOUNTPATH}....."
+       zconf_mount `hostname`  $MOUNTPATH  || return 96
+       MOUNTOPT=$SAVEMOUNTOPT
+}
+
 umount_client() {
        local MOUNTPATH=$1
        echo "umount lustre on ${MOUNTPATH}....."
@@ -166,7 +171,7 @@ test_1() {
        check_mount || return 42
        cleanup || return $?
 }
-run_test 1 "start up ost twice"
+run_test 1 "start up ost twice (should return errors)"
 
 test_2() {
        start_ost
@@ -177,7 +182,7 @@ test_2() {
        check_mount || return 43
        cleanup || return $?
 }
-run_test 2 "start up mds twice"
+run_test 2 "start up mds twice (should return err)"
 
 test_3() {
        setup
@@ -186,7 +191,7 @@ test_3() {
        check_mount || return 44
        cleanup || return $?
 }
-run_test 3 "mount client twice"
+run_test 3 "mount client twice (should return err)"
 
 test_4() {
        setup
@@ -251,19 +256,19 @@ test_5b() {
        cleanup_nocli || return $?
        return 0
 }
-run_test 5b "mds down, cleanup after failed mount (bug 2712)"
+run_test 5b "mds down, cleanup after failed mount (bug 2712) (should return errs)"
 
 test_5c() {
        start_ost
        start_mds
        [ -d $MOUNT ] || mkdir -p $MOUNT
        grep " $MOUNT " /etc/mtab && echo "test 5c: mtab before mount" && return 10
-       mount -t lustre `facet_nid mgs`:/wrong.$FSNAME $MOUNT || :
+       mount -t lustre $MGSNID:/wrong.$FSNAME $MOUNT || :
        grep " $MOUNT " /etc/mtab && echo "test 5c: mtab after failed mount" && return 11
        umount_client $MOUNT
        cleanup_nocli  || return $?
 }
-run_test 5c "cleanup after failed mount (bug 2712)"
+run_test 5c "cleanup after failed mount (bug 2712) (should return errs)"
 
 test_5d() {
        start_ost
@@ -589,7 +594,7 @@ test_14() {
         start_ost
         start_mds
         mount_client $MOUNT || return $?
-        if [ -z "`do_facet ost dumpe2fs -h $OSTDEV | grep label_conf_14`" ]; then
+        if [ -z "`do_facet ost1 dumpe2fs -h $OSTDEV | grep label_conf_14`" ]; then
                 echo "Error: the mkoptions not applied to mke2fs of ost."
                 return 1
         fi
@@ -626,7 +631,7 @@ test_15() {
        # load llite module on the client if it isn't in /lib/modules
        do_facet client "$LCONF --nosetup --node client_facet $XMLCONFIG"
        do_facet client "mount -t lustre -o $MOUNTOPT \
-               `facet_nid mds`:/mds_svc/client_facet $MOUNT" ||return $?
+               $MGSNID:/$FSNAME $MOUNT" ||return $?
        echo "mount lustre on $MOUNT with $MOUNTLUSTRE: success"
        [ -d /r ] && $LCTL modules > /r/tmp/ogdb-`hostname`
        check_mount || return 41
@@ -635,7 +640,7 @@ test_15() {
        [ -f "$MOUNTLUSTRE" ] && rm -f $MOUNTLUSTRE
        echo "mount lustre on ${MOUNT} without $MOUNTLUSTRE....."
        do_node `hostname` mount -t lustre -o nettype=$NETTYPE,$MOUNTOPT \
-               `facet_nid mds`:/mds_svc/client_facet $MOUNT &&return $?
+               $MGSNID:/$FSNAME $MOUNT &&return $?
        echo "mount lustre on $MOUNT without $MOUNTLUSTRE failed as expected"
        cleanup || return $?
        cleanup_15
@@ -653,10 +658,10 @@ test_16() {
         fi
 
         echo "change the mode of $MDSDEV/OBJECTS,LOGS,PENDING to 555"
-        do_facet mds "[ -d $TMPMTPT ] || mkdir -p $TMPMTPT;
-                      mount -o loop -t ext3 $MDSDEV $TMPMTPT || return \$?;
-                      chmod 555 $TMPMTPT/{OBJECTS,LOGS,PENDING} || return \$?;
-                      umount -d $TMPMTPT || return \$?" || return $?
+        do_facet mds "mkdir -p $TMPMTPT &&
+                      mount -o loop -t ext3 $MDSDEV $TMPMTPT &&
+                      chmod 555 $TMPMTPT/{OBJECTS,LOGS,PENDING} &&
+                      umount $TMPMTPT" || return $?
 
         echo "mount Lustre to change the mode of OBJECTS/LOGS/PENDING, then umount Lustre"
        setup
@@ -706,7 +711,7 @@ test_17() {
        start_mds && return 42
        gen_config
 }
-run_test 17 "Verify failed mds_postsetup won't fail assertion (2936)"
+run_test 17 "Verify failed mds_postsetup won't fail assertion (2936) (should return errs)"
 
 test_18() {
         [ -f $MDSDEV ] && echo "remove $MDSDEV" && rm -f $MDSDEV
@@ -749,23 +754,44 @@ test_19b() {
 }
 run_test 19b "start/stop OSTs without MDS"
 
-test_20a() {
+test_20() {
+       # first format the ost/mdt
+       start_ost
+       start_mds
+       mount_client $MOUNT
+       check_mount || return 43
+       rm -f $DIR/$tfile
+       remount_client ro $MOUNT || return 44
+       touch $DIR/$tfile && echo "$DIR/$tfile created incorrectly" && return 45
+       [ -e $DIR/$tfile ] && echo "$DIR/$tfile exists incorrectly" && return 46
+       remount_client rw $MOUNT || return 47
+       touch $DIR/$tfile
+       [ ! -f $DIR/$tfile ] && echo "$DIR/$tfile missing" && return 48
+       MCNT=`grep -c $MOUNT /etc/mtab`
+       [ "$MCNT" -ne 1 ] && echo "$MOUNT in /etc/mtab $MCNT times" && return 49
+       umount_client $MOUNT
+       stop_mds
+       stop_ost
+}
+run_test 20 "remount ro,rw mounts work and doesn't break /etc/mtab"
+
+test_21a() {
         start_mds
        start_ost
        stop_ost
        stop_mds
 }
-run_test 20a "start mds before ost, stop ost first"
+run_test 21a "start mds before ost, stop ost first"
 
-test_20b() {
+test_21b() {
         start_ost
        start_mds
        stop_mds
        stop_ost
 }
-run_test 20b "start ost before mds, stop mds first"
+run_test 21b "start ost before mds, stop mds first"
 
-test_20c() {
+test_21c() {
         start_ost
        start_mds
        start_ost2
@@ -773,9 +799,9 @@ test_20c() {
        stop_ost2
        stop_mds
 }
-run_test 20c "start mds between two osts, stop mds last"
+run_test 21c "start mds between two osts, stop mds last"
 
-test_21() {
+test_22() {
         reformat
        start_mds
        echo Client mount before any osts are in the logs
@@ -800,8 +826,34 @@ test_21() {
 
        cleanup
 }
-run_test 21 "start a client before osts"
+run_test 22 "start a client before osts (should return errs)"
 
+test_23() {
+        setup
+        # fail mds
+       stop mds   
+       # force down client so that recovering mds waits for reconnect
+       zconf_umount `hostname` $MOUNT -f
+       # enter recovery on mds
+       start_mds
+       # try to start a new client
+       mount_client $MOUNT &
+       MOUNT_PID=$!
+       sleep 5
+       MOUNT_LUSTRE_PID=`ps -ef | grep mount.lustre | grep -v grep | awk '{print $2}'`
+       echo mount pid is ${MOUNT_PID}, mount.lustre pid is ${MOUNT_LUSTRE_PID}
+       ps --ppid $MOUNT_PID
+       ps --ppid $MOUNT_LUSTRE_PID
+       # why o why can't I kill these? Manual "ctrl-c" works...
+       kill -TERM $MOUNT_PID
+       echo "waiting for mount to finish"
+       ps -ef | grep mount
+       wait $MOUNT_PID
+
+       stop_mds
+       stop_ost
+}
+run_test 23 "interrupt client during recovery mount delay"
 
 umount_client $MOUNT   
 cleanup_nocli
index cec369b..b5b7c2b 100644 (file)
@@ -45,8 +45,7 @@ static int be_verbose(int verbose, struct timeval *next_time,
                 gettimeofday(&now, NULL);
 
         /* A positive verbosity means to print every X iterations */
-        if (verbose > 0 &&
-            (next_num == NULL || num >= *next_num || num >= num_total)) {
+        if (verbose > 0 && (num >= *next_num || num >= num_total)) {
                 *next_num += verbose;
                 if (next_time) {
                         next_time->tv_sec = now.tv_sec - verbose;
@@ -59,8 +58,7 @@ static int be_verbose(int verbose, struct timeval *next_time,
         if (verbose < 0 && next_time != NULL && difftime(&now, next_time) >= 0){
                 next_time->tv_sec = now.tv_sec - verbose;
                 next_time->tv_usec = now.tv_usec;
-                if (next_num)
-                        *next_num = num;
+                *next_num = num;
                 return 1;
         }
 
index d399036..83f6564 100755 (executable)
@@ -19,19 +19,9 @@ UPCALL=${UPCALL:-DEFAULT}
 build_test_filter
 
 assert_env mds_HOST MDS_MKFS_OPTS MDSDEV
-assert_env ost1_HOST ost2_HOST OST_MKFS_OPTS OSTDEV
+assert_env ost_HOST OST_MKFS_OPTS OSTCOUNT
 assert_env LIVE_CLIENT FSNAME
 
-####
-# Initialize all the ostN_HOST 
-NUMOST=2
-if [ "$EXTRA_OSTS" ]; then
-    for host in $EXTRA_OSTS; do
-       NUMOST=$((NUMOST + 1))
-       OST=ost$NUMOST
-       eval ${OST}_HOST=$host
-    done
-fi
 
 # This can be a regexp, to allow more clients
 CLIENTS=${CLIENTS:-"`comma_list $LIVE_CLIENT $FAIL_CLIENTS $EXTRA_CLIENTS`"}
@@ -114,25 +104,14 @@ reintegrate_clients() {
 }
 
 start_ost() {
-    local dev=`printf $OSTDEV $1`
-    start ost$1 $dev $OST_MOUNT_OPTS
+    start ost$1 `ostdevname $1` $OST_MOUNT_OPTS
 }
 
 setup() {
     cleanup
     rm -rf logs/*
-    wait_for mds
-    add mds $MDS_MKFS_OPTS --reformat $MDSDEV >> /dev/null
-    start mds $MDSDEV $MDS_MOUNT_OPTS
-    for i in `seq $NUMOST`; do
-       local dev=`printf $OSTDEV $i`
-       local index=$((i - 1))
-       wait_for ost$i
-       echo Adding ost$i at index $index dev $dev
-       add ost$i $OST_MKFS_OPTS --reformat --index=$index $dev >> /dev/null
-       start ost$i $dev $OST_MOUNT_OPTS
-    done
-    [ "$DAEMONFILE" ] && $LCTL debug_daemon start $DAEMONFILE $DAEMONSIZE
+    formatall
+    setupall
 
     while ! do_node $CLIENTS "ls -d $LUSTRE" > /dev/null; do sleep 5; done
     grep " $MOUNT " /proc/mounts || zconf_mount $CLIENTS $MOUNT
@@ -140,10 +119,8 @@ setup() {
 
 cleanup() {
     zconf_umount $CLIENTS $MOUNT
-    stop mds -f
-    for i in `seq $NUMOST`; do
-        stop ost$i -f
-    done
+    cleanupall
+    cleanup_check
 }
 
 trap exit INT
@@ -183,21 +160,6 @@ clients_recover_osts() {
 #    do_node $CLIENTS "$LCTL "'--device %OSC_`hostname`_'"${facet}_svc_MNT_client_facet recover"
 }
 
-node_to_ost() {
-    node=$1
-    retvar=$2
-    for i in `seq $NUMOST`; do
-       ostvar="ost${i}_HOST"
-       if [ "${!ostvar}" == $node ]; then
-           eval $retvar=ost${i}
-           return 0
-       fi
-    done
-    echo "No ost found for node; $node"
-    return 1
-}
-
-
 if [ "$ONLY" == "cleanup" ]; then
     $CLEANUP
     exit
@@ -222,11 +184,11 @@ test_0() {
     echo "Waiting for df pid: $DFPID"
     wait $DFPID || { echo "df returned $?" && return 1; }
 
-    facet_failover ost1
+    facet_failover ost1 || return 4
     echo "Waiting for df pid: $DFPID"
     wait $DFPID || { echo "df returned $?" && return 2; }
 
-    facet_failover ost2
+    facet_failover ost2 || return 5
     echo "Waiting for df pid: $DFPID"
     wait $DFPID || { echo "df returned $?" && return 3; }
     return 0
@@ -262,10 +224,10 @@ test_2() {
     echo "Reintegrating OST"
     reboot_facet ost1
     wait_for ost1
-    start_ost 1
+    start_ost 1 || return 2
 
     wait_for mds
-    start mds $MDSDEV $MDS_MOUNT_OPTS
+    start mds $MDSDEV $MDS_MOUNT_OPTS || return $?
 
     #Check FS
     wait $DFPID
diff --git a/lustre/tests/lfscktest.sh b/lustre/tests/lfscktest.sh
new file mode 100755 (executable)
index 0000000..35078e0
--- /dev/null
@@ -0,0 +1,226 @@
+#!/bin/bash
+#set -vx
+set -e
+
+TESTNAME="lfscktest"
+TMP=${TMP:-/tmp}
+MDSDB=${MDSDB:-$TMP/mdsdb}
+OSTDB=${OSTDB:-$TMP/ostdb}
+LOG=${LOG:-"$TMP/lfscktest.log"}
+L2FSCK_PATH=${L2FSCK_PATH:-""}
+NUMFILES=${NUMFILES:-10}
+NUMDIRS=${NUMDIRS:-4}
+LFIND=${LFIND:-"lfs find"}
+GETFATTR=${GETFATTR:-getfattr}
+SETFATTR=${SETFATTR:-setfattr}
+MAX_ERR=1
+
+case `uname -r` in
+2.4.*) FSTYPE=${FSTYPE:-ext3} ;;
+2.6.*) FSTYPE=${FSTYPE:-ldiskfs} ;;
+*)     echo "unhandled kernel `uname -r`"; exit 4;;
+esac
+
+export PATH=$LFSCK_PATH:`dirname $0`:`dirname $0`/../utils:$PATH
+
+[ -z "`which $GETFATTR`" ] && echo "$0: $GETFATTR not found" && exit 5
+[ -z "`which $SETFATTR`" ] && echo "$0: $SETFATTR not found" && exit 6
+
+export NAME=${NAME:-lov}
+. $NAME.sh $NAME.xml
+
+mounted_lustre_filesystems() {
+       awk '($3 ~ "lustre") { print $2 }' /proc/mounts
+}
+
+MOUNT="`mounted_lustre_filesystems`"
+WAS_MOUNTED=$MOUNT
+if [ -z "$MOUNT" ]; then
+       sh llmount.sh
+       MOUNT="`mounted_lustre_filesystems`"
+       [ -z "$MOUNT" ] && echo "$NAME not mounted" && exit 2
+fi
+
+DIR=${DIR:-$MOUNT/$TESTNAME}
+[ -z "`echo $DIR | grep $MOUNT`" ] && echo "$DIR not in $MOUNT" && exit 3
+
+if [ "$WAS_MOUNTED" ]; then
+       LFSCK_SETUP=no
+       MAX_ERR=4               # max expected error from e2fsck
+fi
+
+if [ "$LFSCK_SETUP" != "no" ]; then
+       #Create test directory 
+       rm -rf $DIR
+       mkdir -p $DIR
+       OSTCOUNT=`$LFIND $MOUNT | grep -c "^[0-9]*: "`
+
+       # Create some files on the filesystem
+       for d in `seq -f d%g $NUMDIRS`; do
+               echo "creating files in $DIR/$d"
+               for e in `seq -f d%g $NUMDIRS`; do
+                       mkdir -p  $DIR/$d/$e
+                       for f in `seq -f test%g $NUMDIRS`; do
+                               cp /etc/fstab $DIR/$d/$e/$f ||exit 5
+                       done
+               done
+       done
+
+       # Create Files to be modified
+       for f in `seq -f $DIR/testfile.%g $((NUMFILES * 3))`; do
+               echo "creating $f"
+               cp /etc/termcap $f || exit 10
+       done
+
+       #Create some more files
+       for d in `seq -f d%g $((NUMDIRS * 2 + 1)) $((NUMDIRS * 2 + 3))`; do
+               echo "creating files in $DIR/$d"
+               for e in `seq -f d%g $NUMDIRS`; do
+                       mkdir -p  $DIR/$d/$e
+                       for f in `seq -f test%g $NUMDIRS`; do
+                               cp /etc/hosts $DIR/$d/$e/$f ||exit 15
+                       done
+               done
+       done
+
+       # these should NOT be taken as duplicates
+       for f in `seq -f $DIR/$d/linkfile.%g $NUMFILES`; do
+               echo "linking files in $DIR/$d"
+               cp /etc/hosts $f
+               ln $f $f.link
+       done
+
+       # Get objids for a file on the OST
+       OST_FILES=`seq -f $DIR/testfile.%g $NUMFILES`
+       OST_REMOVE=`$LFIND $OST_FILES | awk '$1 == 0 { print $2 }' | head -n $NUMFILES`
+
+       export MDS_DUPE=""
+       for f in `seq -f testfile.%g $((NUMFILES + 1)) $((NUMFILES * 2))`; do
+               TEST_FILE=$DIR/$f
+               echo "DUPLICATING MDS file $TEST_FILE"
+               $LFIND -v $TEST_FILE >> $LOG || exit 20
+               MDS_DUPE="$MDS_DUPE $TEST_FILE"
+       done
+       MDS_DUPE=`echo $MDS_DUPE | sed "s#$MOUNT/##g"`
+
+       export MDS_REMOVE=""
+       for f in `seq -f testfile.%g $((NUMFILES * 2 + 1)) $((NUMFILES * 3))`; do
+               TEST_FILE=$DIR/$f
+               echo "REMOVING MDS file $TEST_FILE which has info:"
+               $LFIND -v $TEST_FILE >> $LOG || exit 30
+               MDS_REMOVE="$MDS_REMOVE $TEST_FILE"
+       done
+       MDS_REMOVE=`echo $MDS_REMOVE | sed "s#$MOUNT/##g"`
+
+       OSTDEVS=`cat /proc/fs/lustre/obdfilter/*/mntdev`
+       sh llmountcleanup.sh || exit 40
+
+       # Remove objects associated with files
+       echo "removing objects: `echo $OST_REMOVE`"
+       DEBUGTMP=`mktemp $TMP/debugfs.XXXXXXXXXX`
+       for i in $OST_REMOVE; do
+               echo "rm O/0/d$((i % 32))/$i" >> $DEBUGTMP
+       done
+       debugfs -w -f $DEBUGTMP `echo $OSTDEVS | cut -d' ' -f 1`
+       RET=$?
+       rm $DEBUGTMP
+       [ $RET -ne 0 ] && exit 50
+
+       SAVE_PWD=$PWD
+       mount -t $FSTYPE -o loop $MDSDEV $MOUNT || exit 60
+       do_umount() {
+               trap 0
+               cd $SAVE_PWD
+               umount -f $MOUNT
+       }
+       trap do_umount EXIT
+
+       #Remove files from mds
+       for f in $MDS_REMOVE; do
+               rm $MOUNT/ROOT/$f || exit 70
+       done
+
+       #Create EAs on files so objects are referenced from different files
+       ATTRTMP=`mktemp $TMP/setfattr.XXXXXXXXXX`
+       cd $MOUNT/ROOT || exit 78
+       for f in $MDS_DUPE; do
+               touch $f.bad || exit 74
+               getfattr -n trusted.lov $f | sed "s#$f#&.bad#" > $ATTRTMP
+               setfattr --restore $ATTRTMP || exit 80
+       done
+       cd $SAVE_PWD
+       rm $ATTRTMP
+
+       do_umount
+else
+       OSTDEVS=`cat /proc/fs/lustre/obdfilter/*/mntdev`
+       OSTCOUNT=`$LFIND $MOUNT | grep -c "^[0-9]*: "`
+fi # LFSCK_SETUP
+
+# Run e2fsck to get mds and ost info
+# a return status of 1 indicates e2fsck successfuly fixed problems found
+set +e
+
+echo "e2fsck -d -v -fn --mdsdb $MDSDB $MDSDEV"
+e2fsck -d -v -fn --mdsdb $MDSDB $MDSDEV
+RET=$?
+[ $RET -gt $MAX_ERR ] && echo "e2fsck returned $RET" && exit 90 || true
+
+export OSTDB_LIST=""
+i=0
+for OSTDEV in $OSTDEVS; do
+       e2fsck -d -v -fn --mdsdb $MDSDB --ostdb $OSTDB-$i $OSTDEV
+       RET=$?
+       [ $RET -gt $MAX_ERR ] && echo "e2fsck returned $RET" && exit 100
+       OSTDB_LIST="$OSTDB_LIST $OSTDB-$i"
+       i=$((i + 1))
+done
+
+#Remount filesystem
+MOUNT="`mounted_lustre_filesystems`"
+if [ -z "$MOUNT" ]; then
+       sh llrmount.sh --old-conf || exit 109
+       MOUNT="`mounted_lustre_filesystems`"
+       [ -z "$MOUNT" ] && echo "$NAME not mounted" && exit 2
+fi
+
+# need to turn off shell error detection to get proper error return
+# lfsck will return 1 if the filesystem had errors fixed
+echo "LFSCK TEST 1"
+echo "lfsck -c -l --mdsdb $MDSDB --ostdb $OSTDB_LIST $MOUNT"
+lfsck -c -l --mdsdb $MDSDB --ostdb $OSTDB_LIST $MOUNT
+RET=$?
+[ $RET -eq 0 ] && echo "clean after first check" && exit 0
+echo "LFSCK TEST 1 - finished with rc=$RET"
+[ $RET -gt $MAX_ERR ] && exit 110 || true
+
+# make sure everything gets to the backing store
+sync; sleep 2; sync
+
+echo "LFSCK TEST 2"
+echo "e2fsck -d -v -fn --mdsdb $MDSDB $MDSDEV"
+e2fsck -d -v -fn --mdsdb $MDSDB $MDSDEV
+RET=$?
+[ $RET -gt $MAX_ERR ] && echo "e2fsck returned $RET" && exit 123 || true
+
+i=0
+export OSTDB_LIST=""
+for OSTDEV in $OSTDEVS; do
+       e2fsck -d -v -fn --mdsdb $MDSDB --ostdb $OSTDB-$i $OSTDEV
+       RET=$?
+       [ $RET -gt $MAX_ERR ] && echo "e2fsck returned $RET" && exit 124
+       OSTDB_LIST="$OSTDB_LIST $OSTDB-$i"
+       i=$((i + 1))
+done
+
+echo "LFSCK TEST 2"
+echo "lfsck -c -l --mdsdb $MDSDB --ostdb $OSTDB_LIST $MOUNT"
+lfsck -c -l --mdsdb $MDSDB --ostdb $OSTDB_LIST $MOUNT
+RET=$?
+echo "LFSCK TEST 2 - finished with rc=$RET"
+[ $RET -ne 0 ] && exit 125 || true
+sh llmountcleanup.sh || exit 120
+
+#Cleanup 
+rm -f $MDSDB $OSTDB-* || true
+
index aa1ed8c..85685a6 100644 (file)
 
 #define MAX_LOV_UUID_COUNT      1000
 
+/* Returns bytes read on success and a negative value on failure.
+ * If zero bytes are read it will be treated as failure as such
+ * zero cannot be returned from this function.
+ */
 int read_proc_entry(char *proc_path, char *buf, int len)
 {
-        int rcnt = -2, fd;
+        int rc, fd;
+
+        memset(buf, 0, len);
 
-        if ((fd = open(proc_path, O_RDONLY)) == -1) {
+        fd = open(proc_path, O_RDONLY);
+        if (fd == -1) {
                 fprintf(stderr, "open('%s') failed: %s\n",
                         proc_path, strerror(errno));
-                rcnt = -3;
-        } else if ((rcnt = read(fd, buf, len)) <= 0) {
+                return -2;
+        }
+
+        rc = read(fd, buf, len - 1);
+        if (rc < 0) {
                 fprintf(stderr, "read('%s') failed: %s\n",
                         proc_path, strerror(errno));
-        } else {
-                buf[rcnt - 1] = '\0';
+                rc = -3;
+        } else if (rc == 0) {
+                fprintf(stderr, "read('%s') zero bytes\n", proc_path);
+                rc = -4;
+        } else if (/* rc > 0 && */ buf[rc - 1] == '\n') {
+                buf[rc - 1] = '\0'; /* Remove trailing newline */
         }
+        close(fd);
 
-        if (fd >= 0)
-                close(fd);
-
-        return (rcnt);
+        return (rc);
 }
 
 int compare(struct lov_user_md *lum_dir, struct lov_user_md *lum_file1,
@@ -59,19 +71,27 @@ int compare(struct lov_user_md *lum_dir, struct lov_user_md *lum_file1,
         char buf[128];
         char lov_path[PATH_MAX];
         char tmp_path[PATH_MAX];
-        int i, rc;
-
-        rc = read_proc_entry("/proc/fs/lustre/llite/fs0/lov/common_name",
-                             buf, sizeof(buf)) <= 0;
-        if (rc < 0)
-                return -rc;
-
-        snprintf(lov_path, sizeof(lov_path) - 1, "/proc/fs/lustre/lov/%s", buf);
+        int i;
+        FILE *fp;
+
+        fp = popen("\\ls -d  /proc/fs/lustre/lov/*clilov*", "r");
+        if (!fp) {
+                fprintf(stderr, "open(lustre/lov/*clilov*) failed: %s\n", 
+                        strerror(errno));
+                return 2;
+        }
+        if (fscanf(fp, "%s", lov_path) < 1) { 
+                fprintf(stderr, "read(lustre/lov/*clilov*) failed: %s\n",
+                        strerror(errno));
+                pclose(fp);
+                return 3;
+        }
+        pclose(fp);
 
         if (lum_dir == NULL) {
                 snprintf(tmp_path, sizeof(tmp_path) - 1, "%s/stripecount",
                          lov_path);
-                if (read_proc_entry(tmp_path, buf, sizeof(buf)) <= 0)
+                if (read_proc_entry(tmp_path, buf, sizeof(buf)) < 0)
                         return 5;
 
                 stripe_count = atoi(buf);
@@ -82,7 +102,7 @@ int compare(struct lov_user_md *lum_dir, struct lov_user_md *lum_file1,
                 stripe_count = 1;
 
         snprintf(tmp_path, sizeof(tmp_path) - 1, "%s/numobd", lov_path);
-        if (read_proc_entry(tmp_path, buf, sizeof(buf)) <= 0)
+        if (read_proc_entry(tmp_path, buf, sizeof(buf)) < 0)
                 return 6;
 
         ost_count = atoi(buf);
@@ -99,7 +119,7 @@ int compare(struct lov_user_md *lum_dir, struct lov_user_md *lum_file1,
         if (stripe_size == 0) {
                 snprintf(tmp_path, sizeof(tmp_path) - 1, "%s/stripesize",
                          lov_path);
-                if (read_proc_entry(tmp_path, buf, sizeof(buf)) <= 0)
+                if (read_proc_entry(tmp_path, buf, sizeof(buf)) < 0)
                         return 5;
 
                 stripe_size = atoi(buf);
@@ -149,12 +169,13 @@ int main(int argc, char **argv)
         if (argc < 3) {
                 fprintf(stderr, "Usage: %s <dirname> <filename1> [filename2]\n",
                         argv[0]);
-                exit(1);
+                return 1;
         }
 
         dir = opendir(argv[1]);
         if (dir == NULL) {
-                fprintf(stderr, "%s opendir failed\n", argv[1]);
+                fprintf(stderr, "%s opendir failed: %s\n", argv[1], 
+                        strerror(errno));
                 return errno;
         }
 
@@ -184,7 +205,7 @@ int main(int argc, char **argv)
         fname = strrchr(argv[2], '/');
         fname++;
         strncpy((char *)lum_file1, fname, lum_size);
-        rc = ioctl(dirfd(dir), IOC_MDC_GETSTRIPE, lum_file1);
+        rc = ioctl(dirfd(dir), IOC_MDC_GETFILESTRIPE, lum_file1);
         if (rc) {
                 rc = errno;
                 goto cleanup;
@@ -202,7 +223,7 @@ int main(int argc, char **argv)
                 fname = strrchr(argv[3], '/');
                 fname++;
                 strncpy((char *)lum_file2, fname, lum_size);
-                rc = ioctl(dirfd(dir), IOC_MDC_GETSTRIPE, lum_file2);
+                rc = ioctl(dirfd(dir), IOC_MDC_GETFILESTRIPE, lum_file2);
                 if (rc) {
                         rc = errno;
                         goto cleanup;
index 80fa2b3..d234d5e 100755 (executable)
@@ -1,44 +1,11 @@
 #!/bin/sh
-# suggested boilerplate for test script
 
 export PATH=`dirname $0`/../utils:$PATH
 
-LCONF=${LCONF:-lconf}
-NAME=${NAME:-local}
-LLMOUNT=${LLMOUNT:-llmount}
+LUSTRE=${LUSTRE:-`dirname $0`/..}
+. $LUSTRE/tests/test-framework.sh
+init_test_env $@
+. ${CONFIG:=$LUSTRE/tests/cfg/local.sh}
 
-config=$NAME.xml
-mkconfig=$NAME.sh
-
-if [ "$PORTALS" ]; then
-    portals_opt="--portals=$PORTALS"
-fi
-
-if [ "$LUSTRE" ]; then
-    lustre_opt="--lustre=$LUSTRE"
-fi
-
-if [ "$LDAPURL" ]; then
-    conf_opt="--ldapurl $LDAPURL --config $NAME"
-else
-    sh $mkconfig $config || exit 1
-    conf_opt="$config"
-fi    
-
-[ "$NODE" ] && node_opt="--node $NODE"
-[ "$DEBUG" ] && debug_opt="--ptldebug=$DEBUG"
-[ "$PTLDEBUG" ] && debug_opt="--ptldebug=$PTLDEBUG"
-
-echo llmount: FIXME replace llmount.sh with ". mountconf.sh" and "$SETUP"
-
-exit 1
-
-#${LCONF} $NOMOD $portals_opt $lustre_opt $debug_opt $node_opt ${REFORMAT:---reformat} $@ $conf_opt  || {
-    # maybe acceptor error, dump tcp port usage
-#    netstat -tpn
-#    exit 2
-#}
-
-#if [ "$MOUNT2" ]; then
-#      $LLMOUNT -v -o user_xattr,acl `hostname`:/mds1/client $MOUNT2 || exit 3
-#fi
+[ -z "$NOFORMAT" ] && formatall
+[ -z "$NOSETUP" ] && setupall
index 7d8eda9..417a436 100755 (executable)
@@ -2,57 +2,9 @@
 
 export PATH=`dirname $0`/../utils:$PATH
 
-LCONF=${LCONF:-lconf}
-NAME=${NAME:-local}
-TMP=${TMP:-/tmp}
+LUSTRE=${LUSTRE:-`dirname $0`/..}
+. $LUSTRE/tests/test-framework.sh
+init_test_env $@
+. ${CONFIG:=$LUSTRE/tests/cfg/local.sh}
 
-config=$NAME.xml
-mkconfig=$NAME.sh
-
-if [ "$PORTALS" ]; then
-  portals_opt="--portals=$PORTALS"
-fi
-
-if [ "$LUSTRE" ]; then
-  lustre_opt="--lustre=$LUSTRE"
-fi
-
-if [ "$LDAPURL" ]; then
-    conf_opt="--ldapurl $LDAPURL --config $NAME"
-else
-    if [ ! -f $config ]; then
-       sh $mkconfig $config || exit 1
-    fi
-    conf_opt="$config"
-fi    
-
-[ "$NODE" ] && node_opt="--node $NODE"
-
-[ "$MOUNT2" ] && umount $MOUNT2
-
-#${LCONF} $NOMOD $portals_opt $lustre_opt $node_opt --cleanup $@ \
-    --dump $TMP/debug $conf_opt
-
-echo FIXME llmountcleanup should be replaced with $CLEANUP
-exit 1
-
-rc=$?
-echo "lconf DONE"
-BUSY=`dmesg | grep -i destruct`
-if [ "$BUSY" ]; then
-       echo "$BUSY" 1>&2
-       mv $TMP/debug $TMP/debug-busy.`date +%s`
-       exit 255
-fi
-LEAK_LUSTRE=`dmesg | tail -n 30 | grep "obd mem.*leaked"`
-LEAK_PORTALS=`dmesg | tail -n 20 | grep "Portals memory leaked"`
-if [ "$LEAK_LUSTRE" -o "$LEAK_PORTALS" ]; then
-       echo "$LEAK_LUSTRE" 1>&2
-       echo "$LEAK_PORTALS" 1>&2
-       mv $TMP/debug $TMP/debug-leak.`date +%s`
-       echo "Memory leaks detected"
-       exit 254
-fi
-lsmod | grep lnet && echo "modules still loaded" && exit 1
-
-exit $rc
+cleanupall
index 98b8d12..01b4e17 100644 (file)
@@ -33,6 +33,7 @@ cleanup() {
     zconf_umount `hostname` $MOUNT
     stop mds ${FORCE} $MDSLCONFARGS
     stop ost ${FORCE} --dump $TMP/replay-ost-single-`hostname`.log
+    cleanup_check
 }
 
 if [ "$ONLY" == "cleanup" ]; then
diff --git a/lustre/tests/local.sh b/lustre/tests/local.sh
deleted file mode 100755 (executable)
index fb19ac6..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-#!/bin/bash
-
-export PATH=`dirname $0`/../utils:$PATH
-
-config=${1:-`basename $0 .sh`.xml}
-
-LMC=echo 
-TMP=${TMP:-/tmp}
-
-FSNAME=lustre
-HOSTNAME=`hostname`
-MDSDEV=${MDSDEV:-$TMP/mdt-${FSNAME}}
-MDSSIZE=${MDSSIZE:-400000}
-MOUNT=${MOUNT:-/mnt/${FSNAME}}
-MOUNT2=${MOUNT2:-${MOUNT}2}
-NETTYPE=${NETTYPE:-tcp}
-[ "$ACCEPTOR_PORT" ] && PORT_OPT="--port $ACCEPTOR_PORT"
-
-OSTDEV=${OSTDEV:-$TMP/ost0-${FSNAME}}
-OSTSIZE=${OSTSIZE:-400000}
-OSTDEV2=${OSTDEV2:-$TMP/ost1-${FSNAME}}
-
-MDS_MOUNT_OPTS="user_xattr,acl,${MDS_MOUNT_OPTS:-""}"
-CLIENTOPT="user_xattr,acl,${CLIENTOPT:-""}"
-
-# specific journal size for the ost, in MB
-JSIZE=${JSIZE:-0}
-[ "$JSIZE" -gt 0 ] && OST_MKFS_OPTS=$OST_MKFS_OPTS" -J size=$JSIZE"
-MDSISIZE=${MDSISIZE:-0}
-[ "$MDSISIZE" -gt 0 ] && MDS_MKFS_OPTS=$MDS_MKFS_OPTS" -i $MDSISIZE"
-
-STRIPE_BYTES=${STRIPE_BYTES:-1048576}
-STRIPES_PER_OBJ=1      # 0 means stripe over all OSTs
-
-rm -f $config
-
-h2tcp () {
-       case $1 in
-       client) echo '\*' ;;
-       *) echo $1 ;;
-       esac
-}
-
-h2elan () {
-       case $1 in
-       client) echo '\*' ;;
-       *) echo $1 | sed "s/[^0-9]*//" ;;
-       esac
-}
-
-h2gm () {
-       echo `gmlndnid -n$1`
-}
-
-h2iib () {
-       case $1 in
-       client) echo '\*' ;;
-       *) echo $1 | sed "s/[^0-9]*//" ;;
-       esac
-}
-
-MGSNID=`h2$NETTYPE $HOSTNAME`
-
-# configure mds server
-[ "x$MDS_MOUNT_OPTS" != "x" ] &&
-    MDS_MOUNT_OPTS="--mountfsoptions=$MDS_MOUNT_OPTS"
-[ "x$MDS_MKFS_OPTS" != "x" ] &&
-    MDS_MOUNT_OPTS="--mkfsoptions=\"$MDS_MOUNT_OPTS\""
-[ "x$QUOTA_OPTS" != "x" ] &&
-    QUOTA_OPTS="--quota $QUOTA_OPTS"
-[ ! -z "$mdsfailover_HOST" ] && MDS_FAIL_OPT="--failnode=$mdsfailover_HOST"    
-
-MDS_OPTS="--mgs $MDS_FAIL_OPT --device-size=$MDSSIZE $MDS_MOUNT_OPTS $MDS_MKFS_OPTS"
-echo mkfs.lustre --mdt $MDS_OPTS --reformat $MDSDEV
-
-[ "x$OST_MOUNT_OPTS" != "x" ] &&
-    OST_MOUNT_OPTS="--mountfsoptions=$OST_MOUNT_OPTS"
-[ "x$OST_MKFS_OPTS" != "x" ] &&
-    OST_MOUNT_OPTS="--mkfsoptions=\"$OST_MOUNT_OPTS\""
-
-OST_OPTS="--mgsnode=`h2$NETTYPE $HOSTNAME` $OST_FAIL_OPT --device-size=$OSTSIZE $OST_MOUNT_OPTS $OST_MKFS_OPTS"
-echo mkfs.lustre --ost $OST_OPTS --reformat $OSTDEV
-
-OST2_OPTS="--mgsnode=`h2$NETTYPE $HOSTNAME` $OST_FAIL_OPT --device-size=$OSTSIZE $OST_MOUNT_OPTS $OST_MKFS_OPTS"
-echo mkfs.lustre --ost $OST2_OPTS --reformat $OSTDEV2
-
diff --git a/lustre/tests/lov.sh b/lustre/tests/lov.sh
deleted file mode 100755 (executable)
index 62c3b14..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-#!/bin/bash
-
-set -e
-
-export PATH=`dirname $0`/../utils:$PATH
-
-config=${1:-`basename $0 .sh`.xml}
-
-LMC="${LMC:-lmc} -m $config"
-TMP=${TMP:-/tmp}
-
-HOSTNAME=`hostname`
-MDSDEV=${MDSDEV:-$TMP/mds1-`hostname`}
-MDSSIZE=${MDSSIZE:-400000}
-FSTYPE=${FSTYPE:-ext3}
-MOUNT=${MOUNT:-/mnt/lustre}
-MOUNT2=${MOUNT2:-${MOUNT}2}
-NETTYPE=${NETTYPE:-tcp}
-[ "$ACCEPTOR_PORT" ] && PORT_OPT="--port $ACCEPTOR_PORT"
-
-OSTCOUNT=${OSTCOUNT:-5}
-# OSTDEVn will still override the device for OST n
-
-OSTSIZE=${OSTSIZE:-150000}
-# 1 to config an echo client instead of llite
-ECHO_CLIENT=${ECHO_CLIENT:-}
-
-STRIPE_BYTES=${STRIPE_BYTES:-1048576}
-STRIPES_PER_OBJ=${STRIPES_PER_OBJ:-$((OSTCOUNT -1))}
-
-MDS_MOUNT_OPTS="user_xattr,acl,${MDS_MOUNT_OPTS:-""}"
-CLIENTOPT="user_xattr,acl,${CLIENTOPT:-""}"
-
-# specific journal size for the ost, in MB
-JSIZE=${JSIZE:-0}
-JARG=""
-[ "$JSIZE" -gt 0 ] && JARG="--journal_size $JSIZE"
-
-rm -f $config
-
-# create nodes
-${LMC} --add node --node $HOSTNAME || exit 10
-${LMC} --add net --node $HOSTNAME --nid $HOSTNAME \
-    --nettype $NETTYPE $PORT_OPT || exit 11
-${LMC} --add net --node client --nid '*' --nettype $NETTYPE $PORT_OPT || exit 12
-
-[ "x$QUOTA_OPTS" != "x" ] &&
-    QUOTA_OPTS="--quota $QUOTA_OPTS"
-
-# configure mds server
-[ "x$MDS_MOUNT_OPTS" != "x" ] &&
-    MDS_MOUNT_OPTS="--mountfsoptions $MDS_MOUNT_OPTS"
-
-${LMC} --format --add mds --node $HOSTNAME --mds mds1 --fstype $FSTYPE \
-       --dev $MDSDEV $MDS_MOUNT_OPTS $QUOTA_OPTS --size $MDSSIZE $MDSOPT || exit 20
-
-# configure ost
-${LMC} --add lov --lov lov1 --mds mds1 --stripe_sz $STRIPE_BYTES \
-       --stripe_cnt $STRIPES_PER_OBJ --stripe_pattern 0 $LOVOPT || exit 20
-
-for num in `seq $OSTCOUNT`; do
-    OST=ost$num
-    DEVPTR=OSTDEV$num
-    eval $DEVPTR=${!DEVPTR:=$TMP/$OST-`hostname`}
-    ${LMC} --add ost --node $HOSTNAME --lov lov1 --ost $OST --fstype $FSTYPE \
-       --dev ${!DEVPTR} --size $OSTSIZE $JARG $OSTOPT $QUOTA_OPTS|| exit 30
-done
-
-
-if [ -z "$ECHO_CLIENT" ]; then
-       # create client config
-       [ "x$CLIENTOPT" != "x" ] && CLIENTOPT="--clientoptions $CLIENTOPT"
-       ${LMC} --add mtpt --node $HOSTNAME --path $MOUNT \
-               --mds mds1 --lov lov1 $CLIENTOPT || exit 40
-       ${LMC} --add mtpt --node client --path $MOUNT2 \
-               --mds mds1 --lov lov1 $CLIENTOPT || exit 41
-else
-       ${LMC} --add echo_client --node $HOSTNAME --ost lov1 || exit 42
-fi
index 91b6a2f..cfa4caf 100644 (file)
@@ -472,7 +472,7 @@ static int mmap_tst5(char *mnt)
         memset(ptr, 'a', region);
 
         /* cancel unused locks */
-        cancel_lru_locks("osc");
+        rc = cancel_lru_locks("osc");
         if (rc)
                 goto out_unmap;
 
@@ -538,7 +538,7 @@ static int mmap_tst6(char *mnt)
                 goto out;
         }
 
-        cancel_lru_locks("osc");
+        rc = cancel_lru_locks("osc");
         if (rc)
                 goto out;
 
diff --git a/lustre/tests/mountconf.sh b/lustre/tests/mountconf.sh
deleted file mode 100755 (executable)
index 0d71f75..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/bin/sh
-
-#set -vx
-
-# mountconf setup of MDS and two OSTs
-
-#export PATH=`dirname $0`/../utils:$PATH
-#LUSTRE=${LUSTRE:-`dirname $0`/..}
-#. $LUSTRE/tests/test-framework.sh
-#init_test_env $@
-
-mcstopall() {
-    # make sure we are using the primary server, so test-framework will
-    # be able to clean up properly.
-    activemds=`facet_active mds`
-    if [ $activemds != "mds" ]; then
-        fail mds
-    fi
-
-    grep " $MOUNT " /proc/mounts && zconf_umount `hostname` $MOUNT $*
-    stop ost -f
-    stop ost2 -f
-    stop mds -f
-    return 0
-}
-
-mccleanup() {
-    echo "mountconf cleanup $*"
-    mcstopall $*
-    unload_modules
-}
-
-mcformat() {
-    mcstopall
-    echo Formatting mds, ost, ost2
-    add mds $MDS_MKFS_OPTS --reformat $MDSDEV    > /dev/null || exit 10
-    add ost $OST_MKFS_OPTS --reformat $OSTDEV    > /dev/null || exit 10
-    add ost2 $OST2_MKFS_OPTS --reformat $OSTDEV2 > /dev/null || exit 10
-}
-export MCFORMAT=${MCFORMAT:-"mcformat"}
-
-mount_client() {
-    grep " $1 " /proc/mounts || zconf_mount `hostname` $*
-}
-
-mcsetup() {
-    echo Setup mds, ost, ost2
-    start mds $MDSDEV $MDS_MOUNT_OPTS
-    start ost $OSTDEV $OST_MOUNT_OPTS
-    start ost2 $OSTDEV2 $OST2_MOUNT_OPTS
-    [ "$DAEMONFILE" ] && $LCTL debug_daemon start $DAEMONFILE $DAEMONSIZE
-
-    mount_client $MOUNT
-    sleep 5
-}
-
-export MCSETUP=${MCSETUP:-"mcsetup"}
-export MCCLEANUP=${MCCLEANUP:-"mccleanup"}
-
index 572bef0..db33465 100644 (file)
@@ -50,7 +50,7 @@ qos_test_1() {
 
        # set stripe number to 1
        $LFS setstripe $QOSFILE 65536 -1 1
-       FULLOST=`$LFS find -q $QOSFILE | awk '/\s*\d*/ {print $1}'`
+       FULLOST=`$LFS getstripe -q $QOSFILE | awk '/\s*\d*/ {print $1}'`
        
        # floodfill the FULLOST
        echo "$TAB fill the OST $FULLOST to almost fullness..."
@@ -62,7 +62,7 @@ qos_test_1() {
        for i in `seq 10`; do
                rm -f $MOUNT/file-$i
                $LFS setstripe $MOUNT/file-$i 65536 -1 1
-               idx=`$LFS find -q $MOUNT/file-$i | awk '/\s*\d*/ {print $1}'`
+               idx=`$LFS getstripe -q $MOUNT/file-$i | awk '/\s*\d*/ {print $1}'`
                if [ $idx -eq $FULLOST ]; then
                        echo "$TAB ERROR: create object on full OST $FULLOST"
                        return 1
@@ -109,14 +109,14 @@ qos_test_2 () {
        echo "$TAB done"
 
        # the objects created on OST 0 should be 1/4 of on other OSTs'
-       CNT0=`$LFS find -q /mnt/lustre | awk '/\s*\d*/ {print $1}'| grep -c 0`
+       CNT0=`$LFS getstripe -q /mnt/lustre | awk '/\s*\d*/ {print $1}'| grep -c 0`
        CNT0=$(($CNT0 - 1))
        echo "$TAB object created on OST 0: $CNT0"
        
        # the object count of other osts must be greater than 2 times 
        CNT0=$(($CNT0 * 2))
        for i in `seq $(($OSTCOUNT - 1))`; do
-               CNT=`$LFS find -q /mnt/lustre | awk '/\s*\d*/ {print $1}'| grep -c $i`
+               CNT=`$LFS getstripe -q /mnt/lustre | awk '/\s*\d*/ {print $1}'| grep -c $i`
                echo "$TAB object created on OST $i: $CNT"
                if [ $CNT0 -gt $CNT ] ; then
                        echo "$TAB ERROR: too much objects created on OST 0"
index 36e90f3..9f9b8e4 100755 (executable)
@@ -2,14 +2,10 @@
 
 set -e
 
-#         bug  2986 5494 7288
-ALWAYS_EXCEPT="20b  24   27 $RECOVERY_SMALL_EXCEPT"
-
-# Tests that always fail with mountconf -- FIXME
-# 16 fails with 1, not evicted
-EXCEPT="$EXCEPT 16"
-
+#         bug  5494 7288
+ALWAYS_EXCEPT="24   27 $RECOVERY_SMALL_EXCEPT"
 
+PTLDEBUG=${PTLDEBUG:-1}
 LUSTRE=${LUSTRE:-`dirname $0`/..}
 . $LUSTRE/tests/test-framework.sh
 init_test_env $@
@@ -22,16 +18,13 @@ build_test_filter
 SETUP=${SETUP:-"setup"}
 CLEANUP=${CLEANUP:-"cleanup"}
 
-# for MCSETUP and MCCLEANUP
-. mountconf.sh
-
 setup() {
-    $MCFORMAT
-    $MCSETUP
+    formatall
+    setupall
 }
 
 cleanup() {
-       $MCCLEANUP > /dev/null || { echo "FAILed to clean up"; exit 20; }
+       cleanupall || { echo "FAILed to clean up"; exit 20; }
 }
 
 if [ ! -z "$EVAL" ]; then
@@ -201,21 +194,21 @@ test_16() {
     stop_read_ahead
 
 #define OBD_FAIL_PTLRPC_BULK_PUT_NET 0x504 | OBD_FAIL_ONCE
-    do_facet ost sysctl -w lustre.fail_loc=0x80000504
+    do_facet ost1 sysctl -w lustre.fail_loc=0x80000504
     cancel_lru_locks osc
-    # will get evicted here
-    do_facet client "cmp /etc/termcap $MOUNT/termcap"  && return 1
+    # OST bulk will time out here, client resends
+    do_facet client "cmp /etc/termcap $MOUNT/termcap" || return 1
     sysctl -w lustre.fail_loc=0
     # give recovery a chance to finish (shouldn't take long)
     sleep $TIMEOUT
-    do_facet client "cmp /etc/termcap $MOUNT/termcap"  || return 2
+    do_facet client "cmp /etc/termcap $MOUNT/termcap" || return 2
     start_read_ahead
 }
-run_test 16 "timeout bulk put, evict client (2732)"
+run_test 16 "timeout bulk put, don't evict client (2732)"
 
 test_17() {
     # OBD_FAIL_PTLRPC_BULK_GET_NET 0x0503 | OBD_FAIL_ONCE
-    # client will get evicted here
+    # OST bulk will time out here, client retries
     sysctl -w lustre.fail_loc=0x80000503
     # need to ensure we send an RPC
     do_facet client cp /etc/termcap $DIR/$tfile
@@ -224,14 +217,16 @@ test_17() {
     sleep $TIMEOUT
     sysctl -w lustre.fail_loc=0
     do_facet client "df $DIR"
-    # expect cmp to fail
-    do_facet client "cmp /etc/termcap $DIR/$tfile"  && return 3
+    # expect cmp to succeed, client resent bulk
+    do_facet client "cmp /etc/termcap $DIR/$tfile" || return 3
     do_facet client "rm $DIR/$tfile" || return 4
     return 0
 }
 run_test 17 "timeout bulk get, evict client (2732)"
 
 test_18a() {
+    [ -z ${ost2_svc} ] && echo Skipping, needs 2 osts && return 0
+
     do_facet client mkdir -p $MOUNT/$tdir
     f=$MOUNT/$tdir/$tfile
 
@@ -269,12 +264,7 @@ test_18b() {
 
     do_facet client cp /etc/termcap $f
     sync
-    # just use this write to trigger the client's eviction from the ost
-# OBD_FAIL_PTLRPC_BULK_GET_NET|OBD_FAIL_ONCE
-    sysctl -w lustre.fail_loc=0x80000503
-    do_facet client dd if=/dev/zero of=$f2 bs=4k count=1
-    sync
-    sysctl -w lustre.fail_loc=0
+    ost_evict_client
     # allow recovery to complete
     sleep $((TIMEOUT + 2))
     # my understanding is that there should be nothing in the page
@@ -319,7 +309,7 @@ test_20a() {        # bug 2983 - ldlm_handle_enqueue cleanup
        sleep 1
        cancel_lru_locks osc
 #define OBD_FAIL_LDLM_ENQUEUE_EXTENT_ERR 0x308
-       do_facet ost sysctl -w lustre.fail_loc=0x80000308
+       do_facet ost1 sysctl -w lustre.fail_loc=0x80000308
        kill -USR1 $MULTI_PID
        wait $MULTI_PID
        rc=$?
@@ -332,22 +322,239 @@ test_20b() {     # bug 2986 - ldlm_handle_enqueue error during open
        touch $DIR/$tdir/${tfile}
        cancel_lru_locks osc
 #define OBD_FAIL_LDLM_ENQUEUE_EXTENT_ERR 0x308
-       do_facet ost sysctl -w lustre.fail_loc=0x80000308
+       do_facet ost1 sysctl -w lustre.fail_loc=0x80000308
        dd if=/etc/hosts of=$DIR/$tdir/$tfile && \
                error "didn't fail open enqueue" || true
 }
 run_test 20b "ldlm_handle_enqueue error (should return error)"
 
-#b_cray run_test 21a "drop close request while close and open are both in flight"
-#b_cray run_test 21b "drop open request while close and open are both in flight"
-#b_cray run_test 21c "drop both request while close and open are both in flight"
-#b_cray run_test 21d "drop close reply while close and open are both in flight"
-#b_cray run_test 21e "drop open reply while close and open are both in flight"
-#b_cray run_test 21f "drop both reply while close and open are both in flight"
-#b_cray run_test 21g "drop open reply and close request while close and open are both in flight"
-#b_cray run_test 21h "drop open request and close reply while close and open are both in flight"
-#b_cray run_test 22 "drop close request and do mknod"
-#b_cray run_test 23 "client hang when close a file after mds crash"
+test_21a() {
+       mkdir -p $DIR/$tdir-1
+       mkdir -p $DIR/$tdir-2
+       multiop $DIR/$tdir-1/f O_c &
+       close_pid=$!
+
+       do_facet mds "sysctl -w lustre.fail_loc=0x80000129"
+       multiop $DIR/$tdir-2/f Oc &
+       open_pid=$!
+       sleep 1
+       do_facet mds "sysctl -w lustre.fail_loc=0"
+
+       do_facet mds "sysctl -w lustre.fail_loc=0x80000115"
+       kill -USR1 $close_pid
+       cancel_lru_locks mdc
+       wait $close_pid || return 1
+       wait $open_pid || return 2
+       do_facet mds "sysctl -w lustre.fail_loc=0"
+
+       $CHECKSTAT -t file $DIR/$tdir-1/f || return 3
+       $CHECKSTAT -t file $DIR/$tdir-2/f || return 4
+
+       rm -rf $DIR/$tdir-*
+}
+run_test 21a "drop close request while close and open are both in flight"
+
+test_21b() {
+       mkdir -p $DIR/$tdir-1
+       mkdir -p $DIR/$tdir-2
+       multiop $DIR/$tdir-1/f O_c &
+       close_pid=$!
+
+       do_facet mds "sysctl -w lustre.fail_loc=0x80000107"
+       mcreate $DIR/$tdir-2/f &
+       open_pid=$!
+       sleep 1
+       do_facet mds "sysctl -w lustre.fail_loc=0"
+
+       kill -USR1 $close_pid
+       cancel_lru_locks mdc
+       wait $close_pid || return 1
+       wait $open_pid || return 3
+
+       $CHECKSTAT -t file $DIR/$tdir-1/f || return 4
+       $CHECKSTAT -t file $DIR/$tdir-2/f || return 5
+       rm -rf $DIR/$tdir-*
+}
+run_test 21b "drop open request while close and open are both in flight"
+
+test_21c() {
+       mkdir -p $DIR/$tdir-1
+       mkdir -p $DIR/$tdir-2
+       multiop $DIR/$tdir-1/f O_c &
+       close_pid=$!
+
+       do_facet mds "sysctl -w lustre.fail_loc=0x80000107"
+       mcreate $DIR/$tdir-2/f &
+       open_pid=$!
+       sleep 3
+       do_facet mds "sysctl -w lustre.fail_loc=0"
+
+       do_facet mds "sysctl -w lustre.fail_loc=0x80000115"
+       kill -USR1 $close_pid
+       cancel_lru_locks mdc
+       wait $close_pid || return 1
+       wait $open_pid || return 2
+
+       do_facet mds "sysctl -w lustre.fail_loc=0"
+
+       $CHECKSTAT -t file $DIR/$tdir-1/f || return 2
+       $CHECKSTAT -t file $DIR/$tdir-2/f || return 3
+       rm -rf $DIR/$tdir-*
+}
+run_test 21c "drop both request while close and open are both in flight"
+
+test_21d() {
+       mkdir -p $DIR/$tdir-1
+       mkdir -p $DIR/$tdir-2
+       multiop $DIR/$tdir-1/f O_c &
+       pid=$!
+
+       do_facet mds "sysctl -w lustre.fail_loc=0x80000129"
+       multiop $DIR/$tdir-2/f Oc &
+       sleep 1
+       do_facet mds "sysctl -w lustre.fail_loc=0"
+
+       do_facet mds "sysctl -w lustre.fail_loc=0x80000122"
+       kill -USR1 $pid
+       cancel_lru_locks mdc
+       wait $pid || return 1
+       do_facet mds "sysctl -w lustre.fail_loc=0"
+
+       $CHECKSTAT -t file $DIR/$tdir-1/f || return 2
+       $CHECKSTAT -t file $DIR/$tdir-2/f || return 3
+
+       rm -rf $DIR/$tdir-*
+}
+run_test 21d "drop close reply while close and open are both in flight"
+
+test_21e() {
+       mkdir -p $DIR/$tdir-1
+       mkdir -p $DIR/$tdir-2
+       multiop $DIR/$tdir-1/f O_c &
+       pid=$!
+
+       do_facet mds "sysctl -w lustre.fail_loc=0x80000119"
+       touch $DIR/$tdir-2/f &
+       sleep 1
+       do_facet mds "sysctl -w lustre.fail_loc=0"
+
+       kill -USR1 $pid
+       cancel_lru_locks mdc
+       wait $pid || return 1
+
+       sleep $TIMEOUT
+       $CHECKSTAT -t file $DIR/$tdir-1/f || return 2
+       $CHECKSTAT -t file $DIR/$tdir-2/f || return 3
+       rm -rf $DIR/$tdir-*
+}
+run_test 21e "drop open reply while close and open are both in flight"
+
+test_21f() {
+       mkdir -p $DIR/$tdir-1
+       mkdir -p $DIR/$tdir-2
+       multiop $DIR/$tdir-1/f O_c &
+       pid=$!
+
+       do_facet mds "sysctl -w lustre.fail_loc=0x80000119"
+       touch $DIR/$tdir-2/f &
+       sleep 1
+       do_facet mds "sysctl -w lustre.fail_loc=0"
+
+       do_facet mds "sysctl -w lustre.fail_loc=0x80000122"
+       kill -USR1 $pid
+       cancel_lru_locks mdc
+       wait $pid || return 1
+       do_facet mds "sysctl -w lustre.fail_loc=0"
+
+       $CHECKSTAT -t file $DIR/$tdir-1/f || return 2
+       $CHECKSTAT -t file $DIR/$tdir-2/f || return 3
+       rm -rf $DIR/$tdir-*
+}
+run_test 21f "drop both reply while close and open are both in flight"
+
+test_21g() {
+       mkdir -p $DIR/$tdir-1
+       mkdir -p $DIR/$tdir-2
+       multiop $DIR/$tdir-1/f O_c &
+       pid=$!
+
+       do_facet mds "sysctl -w lustre.fail_loc=0x80000119"
+       touch $DIR/$tdir-2/f &
+       sleep 1
+       do_facet mds "sysctl -w lustre.fail_loc=0"
+
+       do_facet mds "sysctl -w lustre.fail_loc=0x80000115"
+       kill -USR1 $pid
+       cancel_lru_locks mdc
+       wait $pid || return 1
+       do_facet mds "sysctl -w lustre.fail_loc=0"
+
+       $CHECKSTAT -t file $DIR/$tdir-1/f || return 2
+       $CHECKSTAT -t file $DIR/$tdir-2/f || return 3
+       rm -rf $DIR/$tdir-*
+}
+run_test 21g "drop open reply and close request while close and open are both in flight"
+
+test_21h() {
+       mkdir -p $DIR/$tdir-1
+       mkdir -p $DIR/$tdir-2
+       multiop $DIR/$tdir-1/f O_c &
+       pid=$!
+
+       do_facet mds "sysctl -w lustre.fail_loc=0x80000107"
+       touch $DIR/$tdir-2/f &
+       touch_pid=$!
+       sleep 1
+       do_facet mds "sysctl -w lustre.fail_loc=0"
+
+       do_facet mds "sysctl -w lustre.fail_loc=0x80000122"
+       cancel_lru_locks mdc
+       kill -USR1 $pid
+       wait $pid || return 1
+       do_facet mds "sysctl -w lustre.fail_loc=0"
+
+       wait $touch_pid || return 2
+
+       $CHECKSTAT -t file $DIR/$tdir-1/f || return 3
+       $CHECKSTAT -t file $DIR/$tdir-2/f || return 4
+       rm -rf $DIR/$tdir-*
+}
+run_test 21h "drop open request and close reply while close and open are both in flight"
+
+# bug 3462 - multiple MDC requests
+test_22() {
+    f1=$DIR/${tfile}-1
+    f2=$DIR/${tfile}-2
+    
+    do_facet mds "sysctl -w lustre.fail_loc=0x80000115"
+    multiop $f2 Oc &
+    close_pid=$!
+
+    sleep 1
+    multiop $f1 msu || return 1
+
+    cancel_lru_locks mdc
+    do_facet mds "sysctl -w lustre.fail_loc=0"
+
+    wait $close_pid || return 2
+    rm -rf $f2 || return 4
+}
+run_test 22 "drop close request and do mknod"
+
+test_23() { #b=4561
+    multiop $DIR/$tfile O_c &
+    pid=$!
+    # give a chance for open
+    sleep 5
+
+    # try the close
+    drop_request "kill -USR1 $pid"
+
+    fail mds
+    wait $pid || return 1
+    return 0
+}
+run_test 23 "client hang when close a file after mds crash"
 
 test_24() {    # bug 2248 - eviction fails writeback but app doesn't see it
        mkdir -p $DIR/$tdir
@@ -355,8 +562,7 @@ test_24() { # bug 2248 - eviction fails writeback but app doesn't see it
        multiop $DIR/$tdir/$tfile Owy_wyc &
        MULTI_PID=$!
        usleep 500
-# OBD_FAIL_PTLRPC_BULK_GET_NET|OBD_FAIL_ONCE
-       sysctl -w lustre.fail_loc=0x80000503
+       ost_evict_client
        usleep 500
        kill -USR1 $MULTI_PID
        wait $MULTI_PID
@@ -373,8 +579,8 @@ test_26() {      # bug 5921 - evict dead exports by pinger
            echo "skipping test 26 (local OST)" && return
        [ "`lsmod | grep mds`" ] && \
            echo "skipping test 26 (local MDS)" && return
-       OST_FILE=$LPROC/obdfilter/ost_svc/num_exports
-        OST_EXP="`do_facet ost cat $OST_FILE`"
+       OST_FILE=$LPROC/obdfilter/${ost1_svc}/num_exports
+        OST_EXP="`do_facet ost1 cat $OST_FILE`"
        OST_NEXP1=`echo $OST_EXP | cut -d' ' -f2`
        echo starting with $OST_NEXP1 OST exports
 # OBD_FAIL_PTLRPC_DROP_RPC 0x505
@@ -384,7 +590,7 @@ test_26() {      # bug 5921 - evict dead exports by pinger
        # might have to wait for the next ping.
        echo Waiting for $(($TIMEOUT * 4)) secs
        sleep $(($TIMEOUT * 4))
-        OST_EXP="`do_facet ost cat $OST_FILE`"
+        OST_EXP="`do_facet ost1 cat $OST_FILE`"
        OST_NEXP2=`echo $OST_EXP | cut -d' ' -f2`
        echo ending with $OST_NEXP2 OST exports
        do_facet client sysctl -w lustre.fail_loc=0x0
@@ -397,8 +603,8 @@ test_26b() {      # bug 10140 - evict dead exports by pinger
        zconf_mount `hostname` $MOUNT2
        MDS_FILE=$LPROC/mds/${mds_svc}/num_exports
         MDS_NEXP1="`do_facet mds cat $MDS_FILE | cut -d' ' -f2`"
-       OST_FILE=$LPROC/obdfilter/${ost_svc}/num_exports
-        OST_NEXP1="`do_facet ost cat $OST_FILE | cut -d' ' -f2`"
+       OST_FILE=$LPROC/obdfilter/${ost1_svc}/num_exports
+        OST_NEXP1="`do_facet ost1 cat $OST_FILE | cut -d' ' -f2`"
        echo starting with $OST_NEXP1 OST and $MDS_NEXP1 MDS exports
        zconf_umount `hostname` $MOUNT2 -f
        # evictor takes up to 2.25x to evict.  But if there's a 
@@ -406,7 +612,7 @@ test_26b() {      # bug 10140 - evict dead exports by pinger
        # might have to wait for the next ping.
        echo Waiting for $(($TIMEOUT * 4)) secs
        sleep $(($TIMEOUT * 4))
-        OST_NEXP2="`do_facet ost cat $OST_FILE | cut -d' ' -f2`"
+        OST_NEXP2="`do_facet ost1 cat $OST_FILE | cut -d' ' -f2`"
         MDS_NEXP2="`do_facet mds cat $MDS_FILE | cut -d' ' -f2`"
        echo ending with $OST_NEXP2 OST and $MDS_NEXP2 MDS exports
         [ $OST_NEXP1 -le $OST_NEXP2 ] && error "client not evicted from OST"
@@ -511,7 +717,7 @@ test_52_guts() {
        echo writemany pid $CLIENT_PID
        sleep 10
        FAILURE_MODE="SOFT"
-       fail ost
+       fail ost1
        rc=0
        wait $CLIENT_PID || rc=$?
        # active client process should see an EIO for down OST
index 05dfdde..ea56524 100755 (executable)
@@ -5,6 +5,7 @@ set -e
 # bug number:  6088 10124
 ALWAYS_EXCEPT="8    15c   $REPLAY_DUAL_EXCEPT"
 
+PTLDEBUG=${PTLDEBUG:-1}
 LUSTRE=${LUSTRE:-`dirname $0`/..}
 . $LUSTRE/tests/test-framework.sh
 
@@ -18,18 +19,7 @@ CLEANUP=${CLEANUP:-"cleanup"}
 build_test_filter
 
 cleanup() {
-    # make sure we are using the primary server, so test-framework will
-    # be able to clean up properly.
-    activemds=`facet_active mds`
-    if [ $activemds != "mds" ]; then
-        fail mds
-    fi
-
-    grep " $MOUNT " /proc/mounts && zconf_umount `hostname` $MOUNT
-    grep " $MOUNT2 " /proc/mounts && zconf_umount `hostname` $MOUNT2
-    stop mds -f
-    stop ost2 -f
-    stop ost -f
+    stopall
 }
 
 if [ "$ONLY" == "cleanup" ]; then
@@ -40,16 +30,9 @@ fi
 
 setup() {
     cleanup
-    add mds $MDS_MKFS_OPTS --reformat $MDSDEV
-    add ost $OST_MKFS_OPTS --reformat $OSTDEV
-    add ost2 $OST2_MKFS_OPTS --reformat $OSTDEV2
-    start mds $MDSDEV $MDS_MOUNT_OPTS
-    start ost $OSTDEV $OST_MOUNT_OPTS
-    start ost2 $OSTDEV2 $OST2_MOUNT_OPTS
-    # client actions will get EIO until MDT contacts OSTs, so give it a sec
-    sleep 5
-    zconf_mount `hostname` $MOUNT
-    zconf_mount `hostname` $MOUNT2
+    formatall
+    setupall
+    mount_client $MOUNT2
 }
 
 $SETUP
@@ -362,11 +345,11 @@ test_15b() {
     echo "data" > "$MOUNT2/${tfile}-m2"
     umount $MOUNT2
 
-    do_facet ost "sysctl -w lustre.fail_loc=0x80000802"
+    do_facet ost1 "sysctl -w lustre.fail_loc=0x80000802"
     facet_failover mds
 
     df $MOUNT || return 1
-    do_facet ost "sysctl -w lustre.fail_loc=0"
+    do_facet ost1 "sysctl -w lustre.fail_loc=0"
     
     zconf_mount `hostname` $MOUNT2
     return 0
@@ -413,12 +396,12 @@ test_17() {
     createmany -o $MOUNT2/$tfile-2- 1
 
     # Make sure the disconnect is lost
-    replay_barrier ost
+    replay_barrier ost1
     umount $MOUNT2
 
-    facet_failover ost
+    facet_failover ost1
     sleep $TIMEOUT
-    facet_failover ost
+    facet_failover ost1
     df $MOUNT || return 1
 
     unlinkmany $MOUNT1/$tfile- 25 || return 2
index f74e4f4..1c40ea2 100755 (executable)
@@ -2,46 +2,31 @@
 
 set -e
 
+PTLDEBUG=${PTLDEBUG:-1}
 LUSTRE=${LUSTRE:-`dirname $0`/..}
 . $LUSTRE/tests/test-framework.sh
-
 init_test_env $@
-
 . ${CONFIG:=$LUSTRE/tests/cfg/local.sh}
 
 ostfailover_HOST=${ostfailover_HOST:-$ost_HOST}
 #failover= must be defined in OST_MKFS_OPTIONS if ostfailover_HOST != ost_HOST
 
 # Skip these tests
-# BUG NUMBER: 2766?
-ALWAYS_EXCEPT="5 $REPLAY_OST_SINGLE_EXCEPT"
+# BUG NUMBER: 
+ALWAYS_EXCEPT="$REPLAY_OST_SINGLE_EXCEPT"
+
+# It is replay-ost-single, after all
+OSTCOUNT=1
 
 gen_config() {
-    grep " $MOUNT " /proc/mounts && zconf_umount `hostname` $MOUNT
-    stop ost -f
-    stop ost2 -f
-    stop mds -f
-    echo Formatting mds, ost
-    add mds $MDS_MKFS_OPTS --reformat $MDSDEV
-    add ost $OST_MKFS_OPTS --reformat $OSTDEV
+    formatall
 }
 
 cleanup() {
-    # make sure we are using the primary server, so test-framework will
-    # be able to clean up properly.
-    activeost=`facet_active ost`
-    if [ $activeost != "ost" ]; then
-        fail ost
-    fi
-
-    zconf_umount `hostname` $MOUNT
-    stop mds
-    stop ost
-    unload_modules
+    cleanupall
 }
 
 if [ "$ONLY" == "cleanup" ]; then
-    sysctl -w lnet.debug=0
     cleanup
     exit
 fi
@@ -54,14 +39,14 @@ CLEANUP=${CLEANUP:-"cleanup"}
 setup() {
     gen_config
     start mds $MDSDEV $MDS_MOUNT_OPTS
-    start ost $OSTDEV $OST_MOUNT_OPTS
+    start ost1 `ostdevname 1` $OST_MOUNT_OPTS
     [ "$DAEMONFILE" ] && $LCTL debug_daemon start $DAEMONFILE $DAEMONSIZE
 
     if [ -z "`grep " $MOUNT " /proc/mounts`" ]; then
        # test "-1" needed during initial client->OST connection
        log "== test 00: target handle mismatch (bug 5317) === `date +%H:%M:%S`"
        #define OBD_FAIL_OST_ALL_REPLY_NET       0x211
-       do_facet ost "sysctl -w lustre.fail_loc=0x80000211"
+       do_facet ost1 "sysctl -w lustre.fail_loc=0x80000211"
        zconf_mount `hostname` $MOUNT && df $MOUNT && pass || error "mount fail"
     fi
 }
@@ -71,7 +56,7 @@ mkdir -p $DIR
 $SETUP
 
 test_0() {
-    fail ost
+    fail ost1
     cp /etc/profile  $DIR/$tfile
     sync
     diff /etc/profile $DIR/$tfile
@@ -81,7 +66,7 @@ run_test 0 "empty replay"
 
 test_1() {
     date > $DIR/$tfile
-    fail ost
+    fail ost1
     $CHECKSTAT -t file $DIR/$tfile || return 1
     rm -f $DIR/$tfile
 }
@@ -91,7 +76,7 @@ test_2() {
     for i in `seq 10`; do
         echo "tag-$i" > $DIR/$tfile-$i
     done 
-    fail ost
+    fail ost1
     for i in `seq 10`; do
       grep -q "tag-$i" $DIR/$tfile-$i || error "f2-$i"
     done 
@@ -104,7 +89,7 @@ test_3() {
     dd if=/dev/urandom bs=4096 count=1280 | tee $verify > $DIR/$tfile &
     ddpid=$!
     sync &
-    fail ost
+    fail ost1
     wait $ddpid || return 1
     cmp $verify $DIR/$tfile || return 2
     rm -f $verify $DIR/$tfile
@@ -120,13 +105,14 @@ test_4() {
     done
     cmp $verify $DIR/$tfile &
     cmppid=$!
-    fail ost
+    fail ost1
     wait $cmppid || return 1
     rm -f $verify $DIR/$tfile
 }
 run_test 4 "Fail OST during read, with verification"
 
 test_5() {
+    [ -z "`which iozone 2> /dev/null`" ] && log "iozone missing" && return
     FREE=`df -P -h $DIR | tail -n 1 | awk '{ print $3 }'`
     case $FREE in
     *T|*G) FREE=1G;;
@@ -136,7 +122,7 @@ test_5() {
     PID=$!
     
     sleep 8
-    fail ost
+    fail ost1
     wait $PID || return 1
     rm -f $DIR/$tfile
 }
@@ -151,17 +137,18 @@ test_6() {
     rm -f $f
     sync && sleep 2 && sync    # wait for delete thread
     before=`kbytesfree`
-    dd if=/dev/urandom bs=4096 count=1280 of=$f
+    dd if=/dev/urandom bs=4096 count=1280 of=$f || return 28
     lfs getstripe $f
 #define OBD_FAIL_MDS_REINT_NET_REP       0x119
     do_facet mds "sysctl -w lustre.fail_loc=0x80000119"
     sync
     sleep 1                                    # ensure we have a fresh statfs
+    sync
     after_dd=`kbytesfree`
     log "before: $before after_dd: $after_dd"
     (( $before > $after_dd )) || return 1
     rm -f $f
-    fail ost
+    fail ost1
     $CHECKSTAT -t file $f && return 2 || true
     sync
     # let the delete happen
@@ -183,9 +170,9 @@ test_7() {
     after_dd=`kbytesfree`
     log "before: $before after_dd: $after_dd"
     (( $before > $after_dd )) || return 1
-    replay_barrier ost
+    replay_barrier ost1
     rm -f $f
-    fail ost
+    fail ost1
     $CHECKSTAT -t file $f && return 2 || true
     sync
     # let the delete happen
index 513766c..35c4961 100755 (executable)
@@ -9,11 +9,9 @@ set -e
 
 LUSTRE=${LUSTRE:-`dirname $0`/..}
 . $LUSTRE/tests/test-framework.sh
-
 init_test_env $@
-
 . ${CONFIG:=$LUSTRE/tests/cfg/local.sh}
-. mountconf.sh 
+
 
 # Skip these tests
 # bug number: 2766
@@ -22,7 +20,7 @@ ALWAYS_EXCEPT="0b   $REPLAY_SINGLE_EXCEPT"
 build_test_filter
 
 SETUP=${SETUP:-"setup"}
-CLEANUP=${CLEANUP:-"mcstopall"}
+CLEANUP=${CLEANUP:-"stopall"}
 
 if [ "$ONLY" == "cleanup" ]; then
     sysctl -w lnet.debug=0 || true
@@ -31,8 +29,8 @@ if [ "$ONLY" == "cleanup" ]; then
 fi
 
 setup() {
-    mcformat
-    mcsetup
+    formatall
+    setupall
 }
 
 $SETUP
@@ -52,7 +50,7 @@ run_test 0 "empty replay"
 test_0b() {
     # this test attempts to trigger a race in the precreation code, 
     # and must run before any other objects are created on the filesystem
-    fail ost
+    fail ost1
     createmany -o $DIR/$tfile 20 || return 1
     unlinkmany $DIR/$tfile 20 || return 2
 }
@@ -68,7 +66,7 @@ test_1() {
 run_test 1 "simple create"
 
 test_1a() {
-    do_facet ost "sysctl -w lustre.fail_loc=0"
+    do_facet ost1 "sysctl -w lustre.fail_loc=0"
 
     rm -fr $DIR/$tfile
     local old_last_id=`cat $LPROC/obdfilter/*/last_id`
@@ -93,7 +91,7 @@ test_1a() {
     rm -fr $DIR/$tfile
 
 #define OBD_FAIL_OST_CROW_EIO | OBD_FAIL_ONCE
-    do_facet ost "sysctl -w lustre.fail_loc=0x80000801"
+    do_facet ost1 "sysctl -w lustre.fail_loc=0x80000801"
 
     rm -fr $DIR/1a1
     old_last_id=`cat $LPROC/obdfilter/*/last_id`
@@ -107,7 +105,7 @@ test_1a() {
     
     rm -fr $DIR/1a1
     
-    do_facet ost "sysctl -w lustre.fail_loc=0"
+    do_facet ost1 "sysctl -w lustre.fail_loc=0"
 }
 #CROW run_test 1a "CROW object create (check OST last_id)"
 
@@ -848,11 +846,11 @@ run_test 41 "read from a valid osc while other oscs are invalid"
 test_42() {
     blocks=`df -P $MOUNT | tail -n 1 | awk '{ print $2 }'`
     createmany -o $DIR/$tfile-%d 800
-    replay_barrier ost
+    replay_barrier ost1
     unlinkmany $DIR/$tfile-%d 0 400
     DEBUG42=`sysctl -n lnet.debug`
     sysctl -w lnet.debug=-1
-    facet_failover ost
+    facet_failover ost1
     
     # osc is evicted, fs is smaller (but only with failout OSTs (bug 7287)
     #blocks_after=`df -P $MOUNT | tail -n 1 | awk '{ print $2 }'`
@@ -870,10 +868,10 @@ test_43() { # bug 2530
     replay_barrier mds
 
     # OBD_FAIL_OST_CREATE_NET 0x204
-    do_facet ost "sysctl -w lustre.fail_loc=0x80000204"
+    do_facet ost1 "sysctl -w lustre.fail_loc=0x80000204"
     fail mds
     sleep 10
-    do_facet ost "sysctl -w lustre.fail_loc=0"
+    do_facet ost1 "sysctl -w lustre.fail_loc=0"
 
     return 0
 }
@@ -952,8 +950,8 @@ test_47() { # bug 2824
     createmany -o $DIR/$tfile 20  || return 1
 
     # OBD_FAIL_OST_CREATE_NET 0x204
-    fail ost
-    do_facet ost "sysctl -w lustre.fail_loc=0x80000204"
+    fail ost1
+    do_facet ost1 "sysctl -w lustre.fail_loc=0x80000204"
     df $MOUNT || return 2
 
     # let the MDS discover the OST failure, attempt to recover, fail
@@ -964,7 +962,7 @@ test_47() { # bug 2824
     createmany -o $DIR/$tfile 20 || return 3
     unlinkmany $DIR/$tfile 20 || return 4
 
-    do_facet ost "sysctl -w lustre.fail_loc=0"
+    do_facet ost1 "sysctl -w lustre.fail_loc=0"
     return 0
 }
 run_test 47 "MDS->OSC failure during precreate cleanup (2824)"
@@ -974,19 +972,19 @@ test_48() {
     createmany -o $DIR/$tfile 20  || return 1
     # OBD_FAIL_OST_EROFS 0x216
     fail mds
-    do_facet ost "sysctl -w lustre.fail_loc=0x80000216"
+    do_facet ost1 "sysctl -w lustre.fail_loc=0x80000216"
     df $MOUNT || return 2
 
     createmany -o $DIR/$tfile 20 20 || return 2
     unlinkmany $DIR/$tfile 40 || return 3
 
-    do_facet ost "sysctl -w lustre.fail_loc=0"
+    do_facet ost1 "sysctl -w lustre.fail_loc=0"
     return 0
 }
 run_test 48 "MDS->OSC failure during precreate cleanup (2824)"
 
 test_50() {
-    local oscdev=`grep ${ost_svc}-osc- $LPROC/devices | awk '{print $1}'`
+    local oscdev=`grep ${ost1_svc}-osc- $LPROC/devices | awk '{print $1}'`
     [ "$oscdev" ] || return 1
     $LCTL --device $oscdev recover &&  $LCTL --device $oscdev recover
     # give the mds_lov_sync threads a chance to run
index fe80594..9c5371b 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/sh
-MNT=${MNT:-/mnt/lustre}
-DIR=${DIR:-$MNT/`hostname`}
+MOUNT=${MOUNT:-/mnt/lustre}
+DIR=${DIR:-$MOUNT/`hostname`}
 #[ -e /proc/sys/lnet/debug ] && echo 0 > /proc/sys/lnet/debug 
 mkdir -p $DIR
 TGT=$DIR/client.txt
index 7071490..a9f8e23 100755 (executable)
@@ -11,11 +11,10 @@ export PATH=/sbin:/usr/sbin:$SRCDIR:$SRCDIR/../utils:$PATH
 . $LUSTRE/tests/test-framework.sh
 init_test_env $@
 . ${CONFIG:=$LUSTRE/tests/cfg/local.sh}
-. mountconf.sh
 
-SETUP=${SETUP:-mcsetup}
-FORMAT=${FORMAT:-mcformat}
-CLEANUP=${CLEANUP:-mcstopall}
+SETUP=${SETUP:-setupall}
+FORMAT=${FORMAT:-formatall}
+CLEANUP=${CLEANUP:-stopall}
 
 fail() { 
        echo "ERROR: $1" 1>&2
@@ -92,7 +91,7 @@ mkdir $DST || fail "can't mkdir $DST" 10
 # haven't changed in the last day (hopefully they don't change during test)
 FILES=`find $SRC -type f -mtime +1 -ctime +1 | head -n $COUNT`
 log "copying files from $SRC to $DST$SRC at `date`"
-tar cf - $FILES | tar xvf - -C $DST || fail "copying $SRC" 11
+tar cf - $FILES | tar xvf - -C $DST > /dev/null || fail "copying $SRC" 11
 
 log "comparing newly copied files at `date`"
 for f in $FILES; do
index d8e887a..8a5a7df 100755 (executable)
@@ -1,17 +1,23 @@
 #!/bin/sh
+DELAY=1
 null() {
        :
 }
 
-if [ "$1" == "-q" ]; then
-       echo "echo off"
+case "$1" in
+-q)    echo "echo off"
        ECHO="null"
-       shift
-else
+       shift ;;
+[1-9]*)
+       DELAY=$1
+       ECHO=echo
+       shift ;;
+*)
        echo "echo on"
        ECHO=echo
-fi
-vmstat 1 | while read LINE ; do
+esac
+
+vmstat $DELAY | while read LINE ; do
        LINE="`date +%s`: $LINE"
        $ECHO "$LINE"
        [ "$1" ] && echo "$LINE" >> $1
index b30fc42..ef1467a 100644 (file)
@@ -25,7 +25,7 @@ TMP=${TMP:-/tmp}
 
 LFS=${LFS:-lfs}
 LCTL=${LCTL:-lctl}
-LSTRIPE=${LSTRIPE:-"$LFS setstripe"}
+SETSTRIPE=${SETSTRIPE:-"$LFS setstripe"}
 TSTID=${TSTID:-60000}
 RUNAS=${RUNAS:-"runas -u $TSTID"}
 TSTUSR=${TSTUSR:-"quota_usr"}
index 0a5c246..af04e8d 100644 (file)
@@ -22,7 +22,7 @@ EXCEPT="$EXCEPT 76 99"
 
 case `uname -r` in
 2.4*) FSTYPE=${FSTYPE:-ext3};    ALWAYS_EXCEPT="$ALWAYS_EXCEPT 76" ;;
-2.6*) FSTYPE=${FSTYPE:-ldiskfs}; ALWAYS_EXCEPT="$ALWAYS_EXCEPT 60 69" ;;
+2.6*) FSTYPE=${FSTYPE:-ldiskfs}; ALWAYS_EXCEPT="$ALWAYS_EXCEPT " ;;
 *) error "unsupported kernel" ;;
 esac
 
@@ -34,8 +34,8 @@ TMP=${TMP:-/tmp}
 CHECKSTAT=${CHECKSTAT:-"checkstat -v"}
 CREATETEST=${CREATETEST:-createtest}
 LFS=${LFS:-lfs}
-LSTRIPE=${LSTRIPE:-"$LFS setstripe"}
-LFIND=${LFIND:-"$LFS find"}
+SETSTRIPE=${SETSTRIPE:-"$LFS setstripe"}
+GETSTRIPE=${GETSTRIPE:-"$LFS getstripe"}
 LVERIFY=${LVERIFY:-ll_dirstripe_verify}
 LCTL=${LCTL:-lctl}
 MCREATE=${MCREATE:-mcreate}
@@ -55,18 +55,18 @@ ACCEPTOR_PORT=${ACCEPTOR_PORT:-988}
 UMOUNT=${UMOUNT:-"umount -d"}
 
 if [ $UID -ne 0 ]; then
-    echo "Warning: running as non-root uid $UID"
+       echo "Warning: running as non-root uid $UID"
        RUNAS_ID="$UID"
        RUNAS=""
 else
        RUNAS_ID=${RUNAS_ID:-500}
        RUNAS=${RUNAS:-"runas -u $RUNAS_ID"}
 
-    # $RUNAS_ID may get set incorrectly somewhere else
-    if [ $RUNAS_ID -eq 0 ]; then
-       echo "Error: \$RUNAS_ID set to 0, but \$UID is also 0!"
-       exit 1
-    fi
+       # $RUNAS_ID may get set incorrectly somewhere else
+       if [ $RUNAS_ID -eq 0 ]; then
+               echo "Error: \$RUNAS_ID set to 0, but \$UID is also 0!"
+               exit 1
+       fi
 fi
 
 SANITYLOG=${SANITYLOG:-/tmp/sanity.log}
@@ -75,24 +75,24 @@ export NAME=${NAME:-local}
 
 SAVE_PWD=$PWD
 
-# for MCSETUP and MCCLEANUP
 LUSTRE=${LUSTRE:-`dirname $0`/..}
 . $LUSTRE/tests/test-framework.sh
 init_test_env $@
 . ${CONFIG:=$LUSTRE/tests/cfg/local.sh}
-. mountconf.sh
 
 cleanup() {
        echo -n "cln.."
-       $MCCLEANUP ${FORCE} $* || { echo "FAILed to clean up"; exit 20; }
+       cleanupall ${FORCE} $* || { echo "FAILed to clean up"; exit 20; }
 }
 CLEANUP=${CLEANUP:-:}
 
 setup() {
        echo -n "mnt.."
-       $MCSETUP || exit 10
+        load_modules
+       setupall || exit 10
        echo "done"
 }
+
 SETUP=${SETUP:-:}
 
 log() {
@@ -218,8 +218,8 @@ mounted_lustre_filesystems() {
 
 MOUNTED="`mounted_lustre_filesystems`"
 if [ -z "$MOUNTED" ]; then
-        $MCFORMAT
-       $MCSETUP
+        formatall
+       setupall
        MOUNTED="`mounted_lustre_filesystems`"
        [ -z "$MOUNTED" ] && error "NAME=$NAME not mounted"
        I_MOUNTED=yes
@@ -880,7 +880,7 @@ run_test 26f "rm -r of a directory which has recursive symlink ="
 test_27a() {
        echo '== stripe sanity =============================================='
        mkdir $DIR/d27
-       $LSTRIPE $DIR/d27/f0 65536 0 1 || error "lstripe failed"
+       $SETSTRIPE $DIR/d27/f0 65536 0 1 || error "lstripe failed"
        $CHECKSTAT -t file $DIR/d27/f0 || error "checkstat failed"
        pass
        log "== test_27b: write to one stripe file ========================="
@@ -891,8 +891,8 @@ run_test 27a "one stripe file =================================="
 test_27c() {
        [ "$OSTCOUNT" -lt "2" ] && echo "skipping 2-stripe test" && return
        mkdir -p $DIR/d27
-       $LSTRIPE $DIR/d27/f01 65536 0 2 || error "lstripe failed"
-       [ `$LFIND $DIR/d27/f01 | grep -A 10 obdidx | wc -l` -eq 4 ] ||
+       $SETSTRIPE $DIR/d27/f01 65536 0 2 || error "lstripe failed"
+       [ `$GETSTRIPE $DIR/d27/f01 | grep -A 10 obdidx | wc -l` -eq 4 ] ||
                error "two-stripe file doesn't have two stripes"
        pass
        log "== test_27d: write to two stripe file file f01 ================"
@@ -902,7 +902,7 @@ run_test 27c "create two stripe file f01 ======================="
 
 test_27d() {
        mkdir -p $DIR/d27
-       $LSTRIPE $DIR/d27/fdef 0 -1 0 || error "lstripe failed"
+       $SETSTRIPE $DIR/d27/fdef 0 -1 0 || error "lstripe failed"
        $CHECKSTAT -t file $DIR/d27/fdef || error "checkstat failed"
        dd if=/dev/zero of=$DIR/d27/fdef bs=4k count=4 || error
 }
@@ -910,17 +910,17 @@ run_test 27d "create file with default settings ================"
 
 test_27e() {
        mkdir -p $DIR/d27
-       $LSTRIPE $DIR/d27/f12 65536 0 2 || error "lstripe failed"
-       $LSTRIPE $DIR/d27/f12 65536 0 2 && error "lstripe succeeded twice"
+       $SETSTRIPE $DIR/d27/f12 65536 0 2 || error "lstripe failed"
+       $SETSTRIPE $DIR/d27/f12 65536 0 2 && error "lstripe succeeded twice"
        $CHECKSTAT -t file $DIR/d27/f12 || error "checkstat failed"
 }
 run_test 27e "lstripe existing file (should return error) ======"
 
 test_27f() {
        mkdir -p $DIR/d27
-       $LSTRIPE $DIR/d27/fbad 100 0 1 && error "lstripe failed"
+       $SETSTRIPE $DIR/d27/fbad 100 0 1 && error "lstripe failed"
        dd if=/dev/zero of=$DIR/d27/f12 bs=4k count=4 || error "dd failed"
-       $LFIND $DIR/d27/fbad || error "lfind failed"
+       $GETSTRIPE $DIR/d27/fbad || error "lfs getstripe failed"
 }
 run_test 27f "lstripe with bad stripe size (should return error)"
 
@@ -928,18 +928,18 @@ test_27g() {
        mkdir -p $DIR/d27
        $MCREATE $DIR/d27/fnone || error "mcreate failed"
        pass
-       log "== test 27h: lfind with no objects ============================"
-       $LFIND $DIR/d27/fnone 2>&1 | grep "no stripe info" || error "has object"
+       log "== test 27h: lfs getstripe with no objects ===================="
+       $GETSTRIPE $DIR/d27/fnone 2>&1 | grep "no stripe info" || error "has object"
        pass
-       log "== test 27i: lfind with some objects =========================="
+       log "== test 27i: lfs getstripe with some objects =================="
        touch $DIR/d27/fsome || error "touch failed"
-       $LFIND $DIR/d27/fsome | grep obdidx || error "missing objects"
+       $GETSTRIPE $DIR/d27/fsome | grep obdidx || error "missing objects"
 }
-run_test 27g "test lfind ======================================="
+run_test 27g "test lfs getstripe ==========================================="
 
 test_27j() {
        mkdir -p $DIR/d27
-       $LSTRIPE $DIR/d27/f27j 65536 $OSTCOUNT 1 && error "lstripe failed"||true
+       $SETSTRIPE $DIR/d27/f27j 65536 $OSTCOUNT 1 && error "lstripe failed"||true
 }
 run_test 27j "lstripe with bad stripe offset (should return error)"
 
@@ -948,7 +948,7 @@ test_27k() { # bug 2844
        FILE=$DIR/d27/f27k
        LL_MAX_BLKSIZE=$((4 * 1024 * 1024))
        [ ! -d $DIR/d27 ] && mkdir -p $DIR/d27
-       $LSTRIPE $FILE 67108864 -1 0 || error "lstripe failed"
+       $SETSTRIPE $FILE 67108864 -1 0 || error "lstripe failed"
        BLKSIZE=`stat $FILE | awk '/IO Block:/ { print $7 }'`
        [ $BLKSIZE -le $LL_MAX_BLKSIZE ] || error "$BLKSIZE > $LL_MAX_BLKSIZE"
        dd if=/dev/zero of=$FILE bs=4k count=1
@@ -960,7 +960,7 @@ run_test 27k "limit i_blksize for broken user apps ============="
 test_27l() {
        mkdir -p $DIR/d27
        mcreate $DIR/f27l || error "creating file"
-       $RUNAS $LSTRIPE $DIR/f27l 65536 -1 1 && \
+       $RUNAS $SETSTRIPE $DIR/f27l 65536 -1 1 && \
                error "lstripe should have failed" || true
 }
 run_test 27l "check setstripe permissions (should return error)"
@@ -972,21 +972,21 @@ test_27m() {
                return
        fi
        mkdir -p $DIR/d27
-       $LSTRIPE $DIR/d27/f27m_1 0 0 1
+       $SETSTRIPE $DIR/d27/f27m_1 0 0 1
        dd if=/dev/zero of=$DIR/d27/f27m_1 bs=1024 count=$MAXFREE && \
                error "dd should fill OST0"
        i=2
-       while $LSTRIPE $DIR/d27/f27m_$i 0 0 1 ; do
+       while $SETSTRIPE $DIR/d27/f27m_$i 0 0 1 ; do
                i=`expr $i + 1`
                [ $i -gt 256 ] && break
        done
        i=`expr $i + 1`
        touch $DIR/d27/f27m_$i
-       [ `$LFIND $DIR/d27/f27m_$i | grep -A 10 obdidx | awk '{print $1}'| grep -w "0"` ] && \
+       [ `$GETSTRIPE $DIR/d27/f27m_$i | grep -A 10 obdidx | awk '{print $1}'| grep -w "0"` ] && \
                error "OST0 was full but new created file still use it"
        i=`expr $i + 1`
        touch $DIR/d27/f27m_$i
-       [ `$LFIND $DIR/d27/f27m_$i | grep -A 10 obdidx | awk '{print $1}'| grep -w "0"` ] && \
+       [ `$GETSTRIPE $DIR/d27/f27m_$i | grep -A 10 obdidx | awk '{print $1}'| grep -w "0"` ] && \
                error "OST0 was full but new created file still use it"
        rm -r $DIR/d27
 }
@@ -1009,7 +1009,7 @@ exhaust_precreations() {
        next_id=$(cat $LPROC/osc/${OST}-osc/prealloc_next_id)
 
        mkdir -p $DIR/d27/${OST}
-       $LSTRIPE $DIR/d27/${OST} 0 $OSTIDX 1
+       $SETSTRIPE $DIR/d27/${OST} 0 $OSTIDX 1
 #define OBD_FAIL_OST_ENOSPC              0x215
        sysctl -w lustre.fail_loc=0x215
        echo "Creating to objid $last_id on ost $OST..."
@@ -1097,7 +1097,7 @@ test_27r() {
        rm -f $DIR/d27/f27r
        exhaust_precreations 0 0x80000215
 
-       $LSTRIPE $DIR/d27/f27r 0 0 2 # && error
+       $SETSTRIPE $DIR/d27/f27r 0 0 2 # && error
 
        reset_enospc
 }
@@ -1109,13 +1109,6 @@ test_28() {
 }
 run_test 28 "create/mknod/mkdir with bad file types ============"
 
-cancel_lru_locks() {
-       for d in $LPROC/ldlm/namespaces/*-$1-*; do
-               echo clear > $d/lru_size
-       done
-       grep "[0-9]" $LPROC/ldlm/namespaces/*-$1-*/lock_unused_count /dev/null
-}
-
 test_29() {
        cancel_lru_locks mdc
        mkdir $DIR/d29
@@ -1285,32 +1278,27 @@ test_32f() {
 run_test 32f "open d32f/symlink->tmp/symlink->lustre-subdir ===="
 
 test_32g() {
-       [ -e $DIR/d32g ] && rm -fr $DIR/d32g
-       [ -e $DIR/test_dir ] && rm -fr $DIR/test_dir
-       mkdir -p $DIR/test_dir 
-       mkdir -p $DIR/d32g/tmp    
-       TMP_DIR=$DIR/d32g/tmp       
-       ln -s $DIR/test_dir $TMP_DIR/symlink12 
+       TMP_DIR=$DIR/$tdir/tmp       
+       mkdir -p $TMP_DIR $DIR/${tdir}2
+       ln -s $DIR/${tdir}2 $TMP_DIR/symlink12 
        ln -s $TMP_DIR/symlink12 $TMP_DIR/../symlink02 
-       $CHECKSTAT -t link $DIR/d32g/tmp/symlink12 || error
-       $CHECKSTAT -t link $DIR/d32g/symlink02 || error
-       $CHECKSTAT -t dir -f $DIR/d32g/tmp/symlink12 || error
-       $CHECKSTAT -t dir -f $DIR/d32g/symlink02 || error
+       $CHECKSTAT -t link $TMP_DIR/symlink12 || error
+       $CHECKSTAT -t link $DIR/$tdir/symlink02 || error
+       $CHECKSTAT -t dir -f $TMP_DIR/symlink12 || error
+       $CHECKSTAT -t dir -f $DIR/$tdir/symlink02 || error
 }
-run_test 32g "stat d32g/symlink->tmp/symlink->lustre-subdir/test_dir"
+run_test 32g "stat d32g/symlink->tmp/symlink->lustre-subdir/${tdir}2"
 
 test_32h() {
-       [ -e $DIR/d32h ] && rm -fr $DIR/d32h
-       [ -e $DIR/test_dir ] && rm -fr $DIR/test_dir
-       mkdir -p $DIR/test_dir 
-       mkdir -p $DIR/d32h/tmp    
-       TMP_DIR=$DIR/d32h/tmp       
-       ln -s $DIR/test_dir $TMP_DIR/symlink12 
+       rm -fr $DIR/$tdir $DIR/${tdir}2
+       TMP_DIR=$DIR/$tdir/tmp       
+       mkdir -p $TMP_DIR $DIR/${tdir}2 
+       ln -s $DIR/${tdir}2 $TMP_DIR/symlink12 
        ln -s $TMP_DIR/symlink12 $TMP_DIR/../symlink02 
-       ls $DIR/d32h/tmp/symlink12 || error
-       ls $DIR/d32h/symlink02  || error
+       ls $TMP_DIR/symlink12 || error
+       ls $DIR/$tdir/symlink02  || error
 }
-run_test 32h "open d32h/symlink->tmp/symlink->lustre-subdir/test_dir"
+run_test 32h "open d32h/symlink->tmp/symlink->lustre-subdir/${tdir}2"
 
 test_32i() {
        [ -e $DIR/d32i ] && rm -fr $DIR/d32i
@@ -1377,33 +1365,32 @@ test_32n() {
 run_test 32n "open d32n/symlink->tmp/symlink->lustre-root ======"
 
 test_32o() {
-       rm -fr $DIR/d32o
-       rm -f $DIR/test_file
-       touch $DIR/test_file 
+       rm -fr $DIR/d32o $DIR/$tfile
+       touch $DIR/$tfile 
        mkdir -p $DIR/d32o/tmp    
        TMP_DIR=$DIR/d32o/tmp       
-       ln -s $DIR/test_file $TMP_DIR/symlink12 
+       ln -s $DIR/$tfile $TMP_DIR/symlink12 
        ln -s $TMP_DIR/symlink12 $TMP_DIR/../symlink02 
        $CHECKSTAT -t link $DIR/d32o/tmp/symlink12 || error
        $CHECKSTAT -t link $DIR/d32o/symlink02 || error
        $CHECKSTAT -t file -f $DIR/d32o/tmp/symlink12 || error
        $CHECKSTAT -t file -f $DIR/d32o/symlink02 || error
 }
-run_test 32o "stat d32o/symlink->tmp/symlink->lustre-root/test_file"
+run_test 32o "stat d32o/symlink->tmp/symlink->lustre-root/$tfile"
 
 test_32p() {
     log 32p_1
        rm -fr $DIR/d32p
     log 32p_2
-       rm -f $DIR/test_file
+       rm -f $DIR/$tfile
     log 32p_3
-       touch $DIR/test_file 
+       touch $DIR/$tfile 
     log 32p_4
        mkdir -p $DIR/d32p/tmp    
     log 32p_5
        TMP_DIR=$DIR/d32p/tmp       
     log 32p_6
-       ln -s $DIR/test_file $TMP_DIR/symlink12 
+       ln -s $DIR/$tfile $TMP_DIR/symlink12 
     log 32p_7
        ln -s $TMP_DIR/symlink12 $TMP_DIR/../symlink02 
     log 32p_8
@@ -1412,7 +1399,7 @@ test_32p() {
        cat $DIR/d32p/symlink02 || error
     log 32p_10
 }
-run_test 32p "open d32p/symlink->tmp/symlink->lustre-root/test_file"
+run_test 32p "open d32p/symlink->tmp/symlink->lustre-root/$tfile"
 
 test_32q() {
        [ -e $DIR/d32q ] && rm -fr $DIR/d32q
@@ -1459,9 +1446,9 @@ TEST_34_SIZE=${TEST_34_SIZE:-2000000000000}
 test_34a() {
        rm -f $DIR/f34
        $MCREATE $DIR/f34 || error
-       $LFIND $DIR/f34 2>&1 | grep -q "no stripe info" || error
+       $GETSTRIPE $DIR/f34 2>&1 | grep -q "no stripe info" || error
        $TRUNCATE $DIR/f34 $TEST_34_SIZE || error
-       $LFIND $DIR/f34 2>&1 | grep -q "no stripe info" || error
+       $GETSTRIPE $DIR/f34 2>&1 | grep -q "no stripe info" || error
        $CHECKSTAT -s $TEST_34_SIZE $DIR/f34 || error
 }
 run_test 34a "truncate file that has not been opened ==========="
@@ -1470,7 +1457,7 @@ test_34b() {
        [ ! -f $DIR/f34 ] && test_34a
        $CHECKSTAT -s $TEST_34_SIZE $DIR/f34 || error
        $OPENFILE -f O_RDONLY $DIR/f34
-       $LFIND $DIR/f34 2>&1 | grep -q "no stripe info" || error
+       $GETSTRIPE $DIR/f34 2>&1 | grep -q "no stripe info" || error
        $CHECKSTAT -s $TEST_34_SIZE $DIR/f34 || error
 }
 run_test 34b "O_RDONLY opening file doesn't create objects ====="
@@ -1479,7 +1466,7 @@ test_34c() {
        [ ! -f $DIR/f34 ] && test_34a 
        $CHECKSTAT -s $TEST_34_SIZE $DIR/f34 || error
        $OPENFILE -f O_RDWR $DIR/f34
-       $LFIND $DIR/f34 2>&1 | grep -q "no stripe info" && error
+       $GETSTRIPE $DIR/f34 2>&1 | grep -q "no stripe info" && error
        $CHECKSTAT -s $TEST_34_SIZE $DIR/f34 || error
 }
 run_test 34c "O_RDWR opening file-with-size works =============="
@@ -1554,12 +1541,54 @@ run_test 36d "non-root OST utime check (open, utime) ==========="
 
 test_36e() {
        [ $RUNAS_ID -eq $UID ] && echo "skipping $TESTNAME" && return
-       [ ! -d $DIR/d36 ] && mkdir $DIR/d36
-       touch $DIR/d36/f36e
-       $RUNAS utime $DIR/d36/f36e && error "utime worked, want failure" || true
+       mkdir -p $DIR/$tdir
+       touch $DIR/$tdir/$tfile
+       $RUNAS utime $DIR/$tdir/$tfile && \
+               error "utime worked, expected failure" || true
 }
 run_test 36e "utime on non-owned file (should return error) ===="
 
+test_36f() {
+       export LANG=C LC_LANG=C # for date language
+
+       DATESTR="Dec 20  2000"
+       mkdir -p $DIR/$tdir
+       #define OBD_FAIL_OST_BRW_PAUSE_BULK 0x214
+        sysctl -w lustre.fail_loc=0x80000214
+       date; date +%s
+       cp /etc/hosts $DIR/$tdir/$tfile
+       sync & # write RPC generated with "current" inode timestamp, but delayed
+       sleep 1
+       touch --date="$DATESTR" $DIR/$tdir/$tfile # setattr timestamp in past
+       LS_BEFORE="`ls -l $DIR/d36/$tfile`" # "old" timestamp from client cache
+       cancel_lru_locks osc
+       LS_AFTER="`ls -l $DIR/d36/$tfile`"  # timestamp from OST object
+       date; date +%s
+       [ "$LS_BEFORE" != "$LS_AFTER" ] && \
+               echo "BEFORE: $LS_BEFORE" && \
+               echo "AFTER : $LS_AFTER" && \
+               echo "WANT  : $DATESTR" && \
+               error "$DIR/d36/$tfile timestamps changed" || true
+}
+run_test 36f "utime on file racing with OST BRW write =========="
+
+if [ -d $LPROC/obdfilter ]; then
+export FMD_MAX_AGE=`cat $LPROC/obdfilter/*/client_cache_seconds | head -n 1`
+
+test_36g() {
+       FMD_BEFORE="`awk '/ll_fmd_cache/ { print $2 }' /proc/slabinfo`"
+       touch $DIR/d36/$tfile
+       sleep $((FMD_MAX_AGE + 12))
+       FMD_AFTER="`awk '/ll_fmd_cache/ { print $2 }' /proc/slabinfo`"
+       [ "$FMD_AFTER" -gt "$FMD_BEFORE" ] && \
+               echo "AFTER : $FMD_AFTER > BEFORE $FMD_BEFORE" && \
+               error "fmd didn't expire after ping" || true
+}
+run_test 36g "filter mod data cache expiry ====================="
+else
+       log "skipping test_36g because of non-local OST"
+fi # [ -d $LPROC/obdfilter ]
+
 test_37() {
        mkdir -p $DIR/dextra
        echo f > $DIR/dextra/fbugfile
@@ -1571,7 +1600,7 @@ test_37() {
 run_test 37 "ls a mounted file system to check old content ====="
 
 test_38() {
-       o_directory $DIR/test38
+       o_directory $DIR/$tfile
 }
 run_test 38 "open a regular file with O_DIRECTORY =============="
 
@@ -2006,23 +2035,18 @@ run_test 50 "special situations: /proc symlinks  ==============="
 
 test_51() {
        # bug 1516 - create an empty entry right after ".." then split dir
-       echo "*****************************************"
-       echo "why we can not list so big a directory!!"
-       echo "skipped this by huanghua@clusterfs.com"
-       echo "please restore it when ready"
-       return
-       mkdir $DIR/d49
-       touch $DIR/d49/foo
-       $MCREATE $DIR/d49/bar
-       rm $DIR/d49/foo
-       createmany -m $DIR/d49/longfile 201
+       mkdir $DIR/d51
+       touch $DIR/d51/foo
+       $MCREATE $DIR/d51/bar
+       rm $DIR/d51/foo
+       createmany -m $DIR/d51/longfile 201
        FNUM=202
-       while [ `ls -sd $DIR/d49 | awk '{ print $1 }'` -le 4 ]; do
-               $MCREATE $DIR/d49/longfile$FNUM
+       while [ `ls -sd $DIR/d51 | awk '{ print $1 }'` -eq 4 ]; do
+               $MCREATE $DIR/d51/longfile$FNUM
                FNUM=$(($FNUM + 1))
                echo -n "+"
        done
-       ls -l $DIR/d49 > /dev/null || error
+       ls -l $DIR/d51 > /dev/null || error
 }
 run_test 51 "special situations: split htree with empty entry =="
 
@@ -2052,6 +2076,34 @@ test_51c() {
 }
 run_test 51c "rmdir .../t-0 --- .../t-$NUMTEST ===================="
 
+test_51d() {
+        [  "$OSTCOUNT" -lt "3" ] && echo "skipping test with few OSTs" && return
+        mkdir -p $DIR/d51d
+        createmany -o $DIR/d51d/t- 1000
+        $LFS getstripe $DIR/d51d > $TMP/files
+        for N in `seq 0 $((OSTCOUNT - 1))`; do
+           OBJS[$N]=`awk -vobjs=0 '($1 == '$N') { objs += 1 } END { print objs;}' $TMP/files`
+           OBJS0[$N]=`grep -A 1 idx $TMP/files | awk -vobjs=0 '($1 == '$N') { objs += 1 } END { print objs;}'`
+           log "OST$N has ${OBJS[$N]} objects, ${OBJS0[$N]} are index 0"
+        done
+        unlinkmany $DIR/d51d/t- 1000
+
+        NLAST=0
+        for N in `seq 1 $((OSTCOUNT - 1))`; do
+           [ ${OBJS[$N]} -lt $((${OBJS[$NLAST]} - 20)) ] && \
+               error "OST $N has less objects vs OST $NLAST (${OBJS[$N]} < ${OBJS[$NLAST]}"
+           [ ${OBJS[$N]} -gt $((${OBJS[$NLAST]} + 20)) ] && \
+               error "OST $N has less objects vs OST $NLAST (${OBJS[$N]} < ${OBJS[$NLAST]}"
+           
+           [ ${OBJS0[$N]} -lt $((${OBJS0[$NLAST]} - 20)) ] && \
+               error "OST $N has less #0 objects vs OST $NLAST (${OBJS0[$N]} < ${OBJS0[$NLAST]}"
+           [ ${OBJS0[$N]} -gt $((${OBJS0[$NLAST]} + 20)) ] && \
+               error "OST $N has less #0 objects vs OST $NLAST (${OBJS0[$N]} < ${OBJS0[$NLAST]}"
+           NLAST=$N
+        done
+}
+run_test 51d "check object distribution ===================="
+
 test_52a() {
        [ -f $DIR/d52a/foo ] && chattr -a $DIR/d52a/foo
        mkdir -p $DIR/d52a
@@ -2198,7 +2250,7 @@ run_test 55 "check iopen_connect_dentry() ======================"
 
 test_56() {
         rm -rf $DIR/d56
-        $LSTRIPE -d $DIR
+        $SETSTRIPE -d $DIR
         mkdir $DIR/d56
         mkdir $DIR/d56/dir
         NUMFILES=3
@@ -2208,45 +2260,45 @@ test_56() {
                 touch $DIR/d56/dir/file$i
         done
 
-        # test lfs find with --recursive
-        FILENUM=`$LFIND --recursive $DIR/d56 | grep -c obdidx`
+        # test lfs getstripe with --recursive
+        FILENUM=`$GETSTRIPE --recursive $DIR/d56 | grep -c obdidx`
         [ $FILENUM -eq $NUMFILESx2 ] || error \
-                "lfs find --recursive $DIR/d56 wrong: found $FILENUM, expected $NUMFILESx2"
-        FILENUM=`$LFIND $DIR/d56 | grep -c obdidx`
+                "lfs getstripe --recursive $DIR/d56 wrong: found $FILENUM, expected $NUMFILESx2"
+        FILENUM=`$GETSTRIPE $DIR/d56 | grep -c obdidx`
         [ $FILENUM -eq $NUMFILES ] || error \
-                "lfs find $DIR/d56 without --recursive wrong: found $FILENUM, expected $NUMFILES"
-        echo "lfs find --recursive passed."
+                "lfs getstripe $DIR/d56 without --recursive wrong: found $FILENUM, expected $NUMFILES"
+        echo "lfs getstripe --recursive passed."
 
-        # test lfs find with file instead of dir
-        FILENUM=`$LFIND $DIR/d56/file1 | grep -c obdidx`
+        # test lfs getstripe with file instead of dir
+        FILENUM=`$GETSTRIPE $DIR/d56/file1 | grep -c obdidx`
         [ $FILENUM  -eq 1 ] || error \
-                 "lfs find $DIR/d56/file1 wrong:found $FILENUM, expected 1"
-        echo "lfs find file passed."
+                 "lfs getstripe $DIR/d56/file1 wrong:found $FILENUM, expected 1"
+        echo "lfs getstripe file passed."
 
-        #test lfs find with --verbose
-        [ `$LFIND --verbose $DIR/d56 | grep -c lmm_magic` -eq $NUMFILES ] ||\
-                error "lfs find --verbose $DIR/d56 wrong: should find $NUMFILES lmm_magic info"
-        [ `$LFIND $DIR/d56 | grep -c lmm_magic` -eq 0 ] || error \
-                "lfs find $DIR/d56 without --verbose wrong: should not show lmm_magic info"
-        echo "lfs find --verbose passed."
+        #test lfs getstripe with --verbose
+        [ `$GETSTRIPE --verbose $DIR/d56 | grep -c lmm_magic` -eq $NUMFILES ] ||\
+                error "lfs getstripe --verbose $DIR/d56 wrong: should find $NUMFILES lmm_magic info"
+        [ `$GETSTRIPE $DIR/d56 | grep -c lmm_magic` -eq 0 ] || error \
+                "lfs getstripe $DIR/d56 without --verbose wrong: should not show lmm_magic info"
+        echo "lfs getstripe --verbose passed."
 
-        #test lfs find with --obd
-        $LFIND --obd wrong_uuid $DIR/d56 2>&1 | grep -q "unknown obduuid" || \
-                error "lfs find --obd wrong_uuid should return error message"
+        #test lfs getstripe with --obd
+        $GETSTRIPE --obd wrong_uuid $DIR/d56 2>&1 | grep -q "unknown obduuid" || \
+                error "lfs getstripe --obd wrong_uuid should return error message"
 
         [  "$OSTCOUNT" -lt 2 ] && \
-                echo "skipping other lfs find --obd test" && return
-        FILENUM=`$LFIND --recursive $DIR/d56 | sed -n '/^[      ]*1[    ]/p' | wc -l`
-        OBDUUID=`$LFIND --recursive $DIR/d56 | sed -n '/^[      ]*1:/p' | awk '{print $2}'`
-        FOUND=`$LFIND -r --obd $OBDUUID $DIR/d56 | wc -l`
+                echo "skipping other lfs getstripe --obd test" && return
+        FILENUM=`$GETSTRIPE --recursive $DIR/d56 | sed -n '/^[  ]*1[    ]/p' | wc -l`
+        OBDUUID=`$GETSTRIPE --recursive $DIR/d56 | sed -n '/^[  ]*1:/p' | awk '{print $2}'`
+        FOUND=`$GETSTRIPE -r --obd $OBDUUID $DIR/d56 | wc -l`
         [ $FOUND -eq $FILENUM ] || \
-                error "lfs find --obd wrong: found $FOUND, expected $FILENUM"
-        [ `$LFIND -r -v --obd $OBDUUID $DIR/d56 | sed '/^[      ]*1[    ]/d' |\
+                error "lfs getstripe --obd wrong: found $FOUND, expected $FILENUM"
+        [ `$GETSTRIPE -r -v --obd $OBDUUID $DIR/d56 | sed '/^[  ]*1[    ]/d' |\
                 sed -n '/^[     ]*[0-9][0-9]*[  ]/p' | wc -l` -eq 0 ] || \
-                error "lfs find --obd wrong: should not show file on other obd"
-        echo "lfs find --obd passed."
+                error "lfs getstripe --obd wrong: should not show file on other obd"
+        echo "lfs getstripe --obd passed."
 }
-run_test 56 "check lfs find ===================================="
+run_test 56 "check lfs getstripe ===================================="
 
 test_57a() {
        # note test will not do anything if MDS is not local
@@ -2272,8 +2324,8 @@ test_57b() {
                error "creating files in $DIR/d57b"
 
        # verify that files do not have EAs yet
-       $LFIND $FILE1 2>&1 | grep -q "no stripe" || error "$FILE1 has an EA"
-       $LFIND $FILEN 2>&1 | grep -q "no stripe" || error "$FILEN has an EA"
+       $GETSTRIPE $FILE1 2>&1 | grep -q "no stripe" || error "$FILE1 has an EA"
+       $GETSTRIPE $FILEN 2>&1 | grep -q "no stripe" || error "$FILEN has an EA"
 
        MDSFREE="`cat $LPROC/mds/*/kbytesfree`"
        MDCFREE="`cat $LPROC/mdc/*/kbytesfree`"
@@ -2283,8 +2335,8 @@ test_57b() {
        done
 
        # verify that files have EAs now
-       $LFIND $FILE1 | grep -q "obdidx" || error "$FILE1 missing EA"
-       $LFIND $FILEN | grep -q "obdidx" || error "$FILEN missing EA"
+       $GETSTRIPE $FILE1 | grep -q "obdidx" || error "$FILE1 missing EA"
+       $GETSTRIPE $FILEN | grep -q "obdidx" || error "$FILEN missing EA"
 
        sleep 1 # make sure we get new statfs data
 #      MDSFREE2="`cat $LPROC/mds/*/kbytesfree`"
@@ -2302,7 +2354,8 @@ test_57b() {
 run_test 57b "default LOV EAs are stored inside large inodes ==="
 
 test_58() {
-       wiretest
+    [ -z "$(which wiretest 2>/dev/null)" ] && echo "skipping $TESTNAME (could not find wiretest)" && return
+    wiretest
 }
 run_test 58 "verify cross-platform wire constants =============="
 
@@ -2386,7 +2439,7 @@ test_63b() {
                $LCTL dk /tmp/test63b.debug && \
                sysctl -w lnet.debug=$DBG_SAVE && \
                error "sync didn't return ENOMEM"
-       grep -q locked $LPROC/llite/fs*/dump_page_cache && \
+       grep -q locked $LPROC/llite/*/dump_page_cache && \
                $LCTL dk /tmp/test63b.debug && \
                sysctl -w lnet.debug=$DBG_SAVE && \
                error "locked page left in cache after async error" || true
@@ -2415,7 +2468,7 @@ run_test 65a "directory with no stripe info ===================="
 
 test_65b() {
        mkdir -p $DIR/d65
-       $LSTRIPE $DIR/d65 $(($STRIPESIZE * 2)) 0 1 || error "setstripe"
+       $SETSTRIPE $DIR/d65 $(($STRIPESIZE * 2)) 0 1 || error "setstripe"
        touch $DIR/d65/f2
        $LVERIFY $DIR/d65 $DIR/d65/f2 || error "lverify failed"
 }
@@ -2424,7 +2477,7 @@ run_test 65b "directory setstripe $(($STRIPESIZE * 2)) 0 1 ==============="
 test_65c() {
        if [ $OSTCOUNT -gt 1 ]; then
                mkdir -p $DIR/d65
-               $LSTRIPE $DIR/d65 $(($STRIPESIZE * 4)) 1 \
+               $SETSTRIPE $DIR/d65 $(($STRIPESIZE * 4)) 1 \
                        $(($OSTCOUNT - 1)) || error "setstripe"
                touch $DIR/d65/f3
                $LVERIFY $DIR/d65 $DIR/d65/f3 || error "lverify failed"
@@ -2436,7 +2489,7 @@ run_test 65c "directory setstripe $(($STRIPESIZE * 4)) 1 $(($OSTCOUNT - 1))"
 
 test_65d() {
        mkdir -p $DIR/d65
-       $LSTRIPE $DIR/d65 $STRIPESIZE -1 $sc || error "setstripe"
+       $SETSTRIPE $DIR/d65 $STRIPESIZE -1 $sc || error "setstripe"
        touch $DIR/d65/f4 $DIR/d65/f5
        $LVERIFY $DIR/d65 $DIR/d65/f4 $DIR/d65/f5 || error "lverify failed"
 }
@@ -2445,8 +2498,8 @@ run_test 65d "directory setstripe $STRIPESIZE -1 $sc =============="
 test_65e() {
        mkdir -p $DIR/d65
 
-       $LSTRIPE $DIR/d65 0 -1 0 || error "setstripe"
-        $LFS find -v $DIR/d65 | grep "has no stripe info" || error "no stripe info failed"
+       $SETSTRIPE $DIR/d65 0 -1 0 || error "setstripe"
+        $GETSTRIPE -v $DIR/d65 | grep "has no stripe info" || error "no stripe info failed"
        touch $DIR/d65/f6
        $LVERIFY $DIR/d65 $DIR/d65/f6 || error "lverify failed"
 }
@@ -2454,32 +2507,32 @@ run_test 65e "directory setstripe 0 -1 0 ======================="
 
 test_65f() {
        mkdir -p $DIR/d65f
-       $RUNAS $LSTRIPE $DIR/d65f 0 -1 0 && error "setstripe succeeded" || true
+       $RUNAS $SETSTRIPE $DIR/d65f 0 -1 0 && error "setstripe succeeded" || true
 }
 run_test 65f "dir setstripe permission (should return error) ==="
 
 test_65g() {
         mkdir -p $DIR/d65
-        $LSTRIPE $DIR/d65 $(($STRIPESIZE * 2)) 0 1 || error "setstripe"
-        $LSTRIPE -d $DIR/d65 || error "setstripe"
-        $LFS find -v $DIR/d65 | grep "has no stripe info" || \
+        $SETSTRIPE $DIR/d65 $(($STRIPESIZE * 2)) 0 1 || error "setstripe"
+        $SETSTRIPE -d $DIR/d65 || error "setstripe"
+        $GETSTRIPE -v $DIR/d65 | grep "has no stripe info" || \
                error "delete default stripe failed"
 }
 run_test 65g "directory setstripe -d ==========================="
 
 test_65h() {
         mkdir -p $DIR/d65
-        $LSTRIPE $DIR/d65 $(($STRIPESIZE * 2)) 0 1 || error "setstripe"
+        $SETSTRIPE $DIR/d65 $(($STRIPESIZE * 2)) 0 1 || error "setstripe"
         mkdir -p $DIR/d65/dd1
-        [ "`$LFS find -v $DIR/d65 | grep "^count"`" == \
-          "`$LFS find -v $DIR/d65/dd1 | grep "^count"`" ] || error "stripe info inherit failed"
+        [ "`$GETSTRIPE -v $DIR/d65 | grep "^count"`" == \
+          "`$GETSTRIPE -v $DIR/d65/dd1 | grep "^count"`" ] || error "stripe info inherit failed"
 }
 run_test 65h "directory stripe info inherit ===================="
  
 test_65i() { # bug6367
-        $LSTRIPE $MOUNT 65536 -1 -1
+        $SETSTRIPE $MOUNT 65536 -1 -1
 }
-run_test 65i "set default striping on root directory (bug 6367)="
+run_test 65i "set non-default striping on root directory (bug 6367)="
 
 test_65j() { # bug6367
        return
@@ -2488,9 +2541,9 @@ test_65j() { # bug6367
                cleanup -f || error "failed to unmount"
                setup || error "failed to remount"
        fi
-       $LSTRIPE -d $MOUNT || true
+       $SETSTRIPE -d $MOUNT || true
 }
-run_test 65j "get default striping on root directory (bug 6367)="
+run_test 65j "set default striping on root directory (bug 6367)="
 
 # bug 2543 - update blocks count on client
 test_66() {
@@ -2575,9 +2628,14 @@ test_69() {
        [ -z "`lsmod|grep obdfilter`" ] &&
                echo "skipping $TESTNAME (remote OST)" && return
 
-       f="$DIR/f69"
+       f="$DIR/$tfile"
        touch $f
 
+       if ! $DIRECTIO write ${f}.2 0 1; then
+               echo "skipping $TESTNAME - O_DIRECT not implemented"
+               return 0
+       fi
+
        sysctl -w lustre.fail_loc=0x217
        truncate $f 1 # vmtruncate() will ignore truncate() error.
        $DIRECTIO write $f 0 2 && error "write succeeded, expect -ENOENT"
@@ -2641,7 +2699,35 @@ test_72() { # bug 5695 - Test that on 2.6 remove_suid works properly
 }
 run_test 72 "Test that remove suid works properly (bug5695) ===="
 
-#b_cray run_test 73 "multiple MDC requests (should not deadlock)"
+# bug 3462 - multiple simultaneous MDC requests
+test_73() {
+       mkdir $DIR/d73-1 
+       mkdir $DIR/d73-2
+       multiop $DIR/d73-1/f73-1 O_c &
+       pid1=$!
+       #give multiop a chance to open
+       usleep 500
+
+       echo 0x80000129 > /proc/sys/lustre/fail_loc
+       multiop $DIR/d73-1/f73-2 Oc &
+       sleep 1
+       echo 0 > /proc/sys/lustre/fail_loc
+
+       multiop $DIR/d73-2/f73-3 Oc &
+       pid3=$!
+
+       kill -USR1 $pid1
+       wait $pid1 || return 1
+
+       sleep 25
+
+       $CHECKSTAT -t file $DIR/d73-1/f73-1 || return 4
+       $CHECKSTAT -t file $DIR/d73-1/f73-2 || return 5 
+       $CHECKSTAT -t file $DIR/d73-2/f73-3 || return 6 
+
+       rm -rf $DIR/d73-*
+}
+run_test 73 "multiple MDC requests (should not deadlock)"
 
 test_74() { # bug 6149, 6184
        #define OBD_FAIL_LDLM_ENQUEUE_OLD_EXPORT 0x30e
@@ -2704,7 +2790,7 @@ test_75() {
        $CHECKSTAT -a ${FHEAD}_tmp || error "${FHEAD}_tmp exist after join"
        $CHECKSTAT -a ${FTAIL} || error "tail ${FTAIL} exist after join (2)"
 
-       rm -rf ${FHEAD} || "delete join file error"
+       rm -rf ${FHEAD} || error "delete join file error"
        cp -p ${F128k} ${F}_join_10_compare
        cp -p ${F128k} ${F}_join_10
        for ((i = 0; i < 10; i++)); do
@@ -2721,7 +2807,7 @@ test_75() {
 
        ls -l $F*
 }
-run_test 75 "TEST join file"
+run_test 75 "TEST join file ===================================="
 
 num_inodes() {
        awk '/lustre_inode_cache|^inode_cache/ {print $2; exit}' /proc/slabinfo
@@ -2736,11 +2822,11 @@ test_76() { # bug 1443
        done
        AFTER_INODES=`num_inodes`
        echo "after inodes: $AFTER_INODES"
-       [ $AFTER_INODES -gt $((BEFORE_INODES + 10)) ] && \
+       [ $AFTER_INODES -gt $((BEFORE_INODES + 32)) ] && \
                error "inode slab grew from $BEFORE_INODES to $AFTER_INODES"
        true
 }
-run_test 76 "destroy duplicate inodes in client inode cache"
+run_test 76 "destroy duplicate inodes in client inode cache ===="
 
 test_77() {
        sh qos.sh
@@ -2852,13 +2938,14 @@ test_101() {
        local s
        local discard
        local nreads=10000
+       [ "$CPU" = "UML" ] && nreads=1000
        local cache_limit=32
 
        for s in $LPROC/osc/*-osc*/rpc_stats; do
                echo 0 > $s
        done
        trap cleanup_101 EXIT
-       for s in $LPROC/llite/fs*; do
+       for s in $LPROC/llite/*; do
                echo 0 > $s/read_ahead_stats
                echo $cache_limit > $s/max_cached_mb
        done
@@ -2870,7 +2957,7 @@ test_101() {
        $RANDOM_READS -f $DIR/$tfile -s$((cache_limit * 3192 * 1024)) -b65536 -C -n$nreads -t 180
 
        discard=0
-       for s in $LPROC/llite/fs*; do
+       for s in $LPROC/llite/*; do
                discard=$(($discard + $(cat $s/read_ahead_stats | get_named_value 'read but discarded')))
        done
        cleanup_101
@@ -2936,15 +3023,14 @@ run_acl_subtest()
 }
 
 test_103 () {
+    [ "$UID" != 0 ] && echo "skipping $TESTNAME (must run as root)" && return
+    [ -z "$(grep acl $LPROC/mdc/*-mdc-*/connect_flags)" ] && echo "skipping $TESTNAME (must have acl enabled)" && return
+    [ -z "$(which setfacl 2>/dev/null)" ] && echo "skipping $TESTNAME (could not find setfacl)" && return
+
     SAVE_UMASK=`umask`
     umask 0022
     cd $DIR
 
-    [ "$UID" != 0 ] && echo "skipping $TESTNAME (must run as root)" && return
-    [ -z "`mount | grep " $DIR .*\<acl\>"`" ] && echo "skipping $TESTNAME (must have acl)" && return
-    [ -z "`grep acl $LPROC/mdc/*-mdc-*/connect_flags`" ] && echo "skipping $TESTNAME (must have acl)" && return
-    $(which setfacl 2>/dev/null) || echo "skipping $TESTNAME (could not find setfacl)" && return
-
     echo "performing cp ..."
     run_acl_subtest cp || error
     echo "performing getfacl-noacl..."
@@ -2964,7 +3050,7 @@ test_103 () {
     run_acl_subtest inheritance || error
     rm -f make-tree
 
-    cd $SAVED_PWD
+    cd $SAVE_PWD
     umask $SAVE_UMASK
 }
 run_test 103 "acl test ========================================="
@@ -2995,7 +3081,7 @@ if [ "`mount | grep ^$NAME`" ]; then
     rm -rf $DIR/[Rdfs][1-9]*
 fi
 if [ "$I_MOUNTED" = "yes" ]; then
-    $MCCLEANUP -f || error "cleanup failed"
+    cleanupall -f || error "cleanup failed"
 fi
 
 
index a32f2b6..a3fffce 100644 (file)
@@ -16,8 +16,8 @@ PATH=$PWD/$SRCDIR:$SRCDIR:$SRCDIR/../utils:$PATH
 SIZE=${SIZE:-40960}
 CHECKSTAT=${CHECKSTAT:-"checkstat -v"}
 CREATETEST=${CREATETEST:-createtest}
-LFIND=${LFIND:-lfind}
-LSTRIPE=${LSTRIPE:-lstripe}
+GETSTRIPE=${GETSTRIPE:-lfs getstripe}
+SETSTRIPE=${SETSTRIPE:-lstripe}
 LCTL=${LCTL:-lctl}
 MCREATE=${MCREATE:-mcreate}
 OPENFILE=${OPENFILE:-openfile}
@@ -36,23 +36,21 @@ fi
 
 SAVE_PWD=$PWD
 
-# for MCSETUP and MCCLEANUP
 LUSTRE=${LUSTRE:-`dirname $0`/..}
 . $LUSTRE/tests/test-framework.sh
 init_test_env $@
 . ${CONFIG:=$LUSTRE/tests/cfg/local.sh}
-. mountconf.sh
 
 cleanup() {
        echo -n "cln.."
        grep " $MOUNT2 " /proc/mounts && zconf_umount `hostname` $MOUNT2 ${FORCE}
-       $MCCLEANUP ${FORCE} > /dev/null || { echo "FAILed to clean up"; exit 20; }
+       cleanupall ${FORCE} > /dev/null || { echo "FAILed to clean up"; exit 20; }
 }
 CLEANUP=${CLEANUP:-:}
 
 setup() {
        echo -n "mnt.."
-       $MCSETUP || exit 10
+       setupall || exit 10
        echo "done"
 }
 SETUP=${SETUP:-:}
@@ -71,6 +69,8 @@ trace() {
 }
 TRACE=${TRACE:-""}
 
+LPROC=/proc/fs/lustre
+
 run_one() {
        if ! grep -q $DIR /proc/mounts; then
                $SETUP
@@ -179,8 +179,8 @@ mounted_lustre_filesystems() {
 }
 MOUNTED="`mounted_lustre_filesystems`"
 if [ -z "$MOUNTED" ]; then
-    $MCFORMAT
-    $MCSETUP
+    formatall
+    setupall
     mount_client $MOUNT2
     MOUNTED="`mounted_lustre_filesystems`"
     [ -z "$MOUNTED" ] && error "NAME=$NAME not mounted"
@@ -487,12 +487,12 @@ test_19() { # bug3811
 test_20() {
        mkdir $DIR1/d20
        cancel_lru_locks osc
-       CNT=$((`cat /proc/fs/lustre/llite/fs0/dump_page_cache | wc -l`))
+       CNT=$((`cat /proc/fs/lustre/llite/*/dump_page_cache | wc -l`))
        multiop $DIR1/f20 Ow8190c
        multiop $DIR2/f20 Oz8194w8190c
        multiop $DIR1/f20 Oz0r8190c
        cancel_lru_locks osc
-       CNTD=$((`cat /proc/fs/lustre/llite/fs0/dump_page_cache | wc -l` - $CNT))
+       CNTD=$((`cat /proc/fs/lustre/llite/*/dump_page_cache | wc -l` - $CNT))
        [ $CNTD -gt 0 ] && \
            error $CNTD" page left in cache after lock cancel" || true
 }
@@ -571,7 +571,7 @@ test_24() {
        lfs df $DIR1/$tfile || error "lfs df $DIR1/$tfile failed"
        lfs df -ih $DIR2/$tfile || error "lfs df -ih $DIR2/$tfile failed"
        
-       OSC=`lctl dl | awk '/OSC.*MNT/ {print $4}' | head -n 1`
+       OSC=`lctl dl | awk '/-osc-/ {print $4}' | head -n 1`
        lctl --device %$OSC deactivate
        lfs df -i || error "lfs df -i with deactivated OSC failed"
        lctl --device %$OSC recover
@@ -580,8 +580,7 @@ test_24() {
 run_test 24 "lfs df [-ih] [path] test ========================="
 
 test_25() {
-       [ -z "`mount | grep " $DIR1 .*\<acl\>"`" ] && echo "skipping $TESTNAME ($DIR1 must have acl)" && return
-       [ -z "`mount | grep " $DIR2 .*\<acl\>"`" ] && echo "skipping $TESTNAME ($DIR2 must have acl)" && return
+       [ `cat $LPROC/mdc/*-mdc-*/connect_flags | grep -c acl` -lt 2 ] && echo "skipping $TESTNAME (must have acl)" && return
 
        mkdir $DIR1/d25 || error
        touch $DIR1/d25/f1 || error
@@ -601,6 +600,26 @@ test_25() {
 }
 run_test 25 "change ACL on one mountpoint be seen on another ==="
 
+test_26a() {
+        utime $DIR1/f26a -s $DIR2/f26a || error
+}
+run_test 26a "allow mtime to get older"
+
+test_26b() {
+        touch $DIR1/$tfile
+        sleep 1
+        echo "aaa" >> $DIR1/$tfile
+        sleep 1
+        chmod a+x $DIR2/$tfile
+        mt1=`stat -c %Y $DIR1/$tfile`
+        mt2=`stat -c %Y $DIR2/$tfile`
+        
+        if [ x"$mt1" != x"$mt2" ]; then 
+                error "not equal mtime, client1: "$mt1", client2: "$mt2"."
+        fi
+}
+run_test 26b "sync mtime between ost and mds"
+
 log "cleanup: ======================================================"
 rm -rf $DIR1/[df][0-9]* $DIR1/lnk || true
 if [ "$I_MOUNTED" = "yes" ]; then
index ebbb2b3..442d0fd 100644 (file)
@@ -7,42 +7,44 @@
 #include <stdlib.h>
 #include <string.h>
 
+#define GOTO(label, rc)   do { rc; goto label; } while (0)
+
 int main (int argc, char **argv) {
-       int fd, i, rc;
+       int fd, i, rc = 0;
        unsigned long bytes, lbytes;
        struct stat st;
        char *str, *str2, *readbuf;
 
        if (argc != 3) {
                fprintf(stderr, "usage: %s <filename> <bytes>\n", argv[0]);
-               return 1;
+               GOTO(out, rc = 1);
        }
 
        bytes = strtoul(argv[2], NULL, 10);
        if (!bytes) {
                printf("No bytes!\n");
-               return 1;
+               GOTO(out, rc = 2);
        }
        if (bytes % 2) {
                printf("Need an even number of bytes!\n");
-               return 1;
+               GOTO(out, rc = 3);
        }
        lbytes = 3*bytes/2;
 
        str = malloc(bytes+1);
        if (!str) {
                printf("No enough memory for %lu bytes.\n", bytes);
-               return 1;
+               GOTO(out, rc = 4);
        }
        str2 = malloc(lbytes+1);
-       if (!str) {
+       if (!str2) {
                printf("No enough memory for %lu bytes.\n", lbytes);
-               return 1;
+               GOTO(out_str, rc = 5);
        }
        readbuf = malloc(bytes*2);
-       if (!str) {
+       if (!readbuf) {
                printf("No enough memory for %lu bytes.\n", bytes*2);
-               return 1;
+               GOTO(out_str2, rc = 6);
        }
 
        for(i=0; i < bytes; i++)
@@ -59,13 +61,13 @@ int main (int argc, char **argv) {
        fd = open(argv[1], O_CREAT|O_RDWR|O_TRUNC, 0700);
        if (fd == -1) {
                printf("Could not open file %s.\n", argv[1]);
-               return 1;
+               GOTO(out_readbuf, rc = 7);
        }
 
        rc = write(fd, str, bytes);
        if (rc != bytes) {
                printf("Write failed!\n");
-               return 1;
+               GOTO(out_fd, rc = 8);
        }
 
        sleep(1);
@@ -74,19 +76,19 @@ int main (int argc, char **argv) {
                printf("bad file %lu size first write %lu != %lu: rc %d\n",
                       (unsigned long)st.st_ino, (unsigned long)st.st_size,
                        bytes, rc);
-               return 1;
+               GOTO(out_fd, rc = 9);
        }
 
        rc = lseek(fd, bytes / 2, SEEK_SET);
        if (rc != bytes / 2) {
                printf("Seek failed!\n");
-               return 1;
+               GOTO(out_fd, rc = 10);
        }
 
        rc = write(fd, str, bytes);
        if (rc != bytes) {
                printf("Write failed!\n");
-               return 1;
+               GOTO(out_fd, rc = 11);
        }
 
        rc = fstat(fd, &st);
@@ -94,13 +96,13 @@ int main (int argc, char **argv) {
                printf("bad file %lu size second write %lu != %lu: rc %d\n",
                       (unsigned long)st.st_ino, (unsigned long)st.st_size,
                        bytes, rc);
-               return 1;
+               GOTO(out_fd, rc = 12);
        }
 
        rc = lseek(fd, 0, SEEK_SET);
        if (rc != 0) {
                printf("Seek failed!\n");
-               return 1;
+               GOTO(out_fd, rc = 13);
        }
 
        rc = read(fd, readbuf, bytes * 2);
@@ -115,23 +117,29 @@ int main (int argc, char **argv) {
                        printf("bad file size after read %lu != %lu: rc %d\n",
                               (unsigned long)st.st_size, bytes + bytes / 2,
                                rc);
-                       return 1;
+                       GOTO(out_fd, rc = 14);
                }
 
-               return 1;
+               GOTO(out_fd, rc = 15);
        }
-
-       fd = close(fd);
-       if (fd == -1)
-               return 1;
+       rc = 0;
 
        if (bytes < 320)
                printf("%s\n%s\n", readbuf, str2);
        if (strcmp(readbuf, str2)) {
                printf("No match!\n");
-               return 1;
+               GOTO(out_fd, rc = 16);
        }
 
        printf("Pass!\n");
-       return 0;
+out_fd:
+       close(fd);
+out_readbuf:
+        free(readbuf);
+out_str2:
+        free(str2);
+out_str:
+        free(str);
+out:
+        return rc;
 }
index f27957d..9963650 100644 (file)
@@ -85,6 +85,7 @@ void print_human_fstype(struct statfs *statfsbuf)
          break;
        case S_MAGIC_MINIX:
          type = strdup("minix");
+          break;
        case S_MAGIC_MINIX_30:
          type = strdup("minix (30 char.)");
          break;
index 8ca56d9..d2f002e 100644 (file)
@@ -2,20 +2,23 @@
 # vim:expandtab:shiftwidth=4:softtabstop=4:tabstop=4:
 
 set -e
+trap 'echo "test-framework exiting on error"' ERR
 #set -vx
 
+
 export REFORMAT=""
 export VERBOSE=false
 export GMNALNID=${GMNALNID:-/usr/sbin/gmlndnid}
+export CATASTROPHE=${CATASTROPHE:-/proc/sys/lnet/catastrophe}
 
 # eg, assert_env LUSTRE MDSNODES OSTNODES CLIENTS
 assert_env() {
     local failed=""
     for name in $@; do
-      if [ -z "${!name}" ]; then
-         echo "$0: $name must be set"
-          failed=1
-      fi
+        if [ -z "${!name}" ]; then
+            echo "$0: $name must be set"
+            failed=1
+        fi
     done
     [ $failed ] && exit 1 || true
 }
@@ -30,7 +33,6 @@ usage() {
 init_test_env() {
     export LUSTRE=`absolute_path $LUSTRE`
     export TESTSUITE=`basename $0 .sh`
-    export XMLCONFIG=${XMLCONFIG:-${TESTSUITE}.xml}
     export LTESTDIR=${LTESTDIR:-$LUSTRE/../ltest}
 
     [ -d /r ] && export ROOT=${ROOT:-/r}
@@ -54,39 +56,97 @@ init_test_env() {
     # command line
     
     while getopts "rvf:" opt $*; do 
-       case $opt in
-           f) CONFIG=$OPTARG;;
-           r) REFORMAT=--reformat;;
-           v) VERBOSE=true;;
-           \?) usage;;
-       esac
+        case $opt in
+            f) CONFIG=$OPTARG;;
+            r) REFORMAT=--reformat;;
+            v) VERBOSE=true;;
+            \?) usage;;
+        esac
     done
 
     shift $((OPTIND - 1))
     ONLY=${ONLY:-$*}
+}
+
+load_module() {
+    EXT=".ko"
+    module=$1
+    shift
+    BASE=`basename $module $EXT`
+    lsmod | grep -q ${BASE} || \
+      if [ -f ${LUSTRE}/${module}${EXT} ]; then
+        insmod ${LUSTRE}/${module}${EXT} $@
+    else
+        # must be testing a "make install" or "rpm" installation
+        modprobe $BASE $@
+    fi
+}
 
-    # save the name of the config file for the upcall
-    echo "XMLCONFIG=$LUSTRE/tests/$XMLCONFIG"  > $LUSTRE/tests/XMLCONFIG
-#    echo "CONFIG=`canonical_path $CONFIG`"  > $LUSTRE/tests/CONFIG
+load_modules() {
+    if [ -n "$MODPROBE" ]; then
+        # use modprobe
+       return 0
+    fi
+    if [ "$HAVE_MODULES" = true ]; then
+       # we already loaded
+        return 0
+    fi
+    HAVE_MODULES=true
+
+    echo Loading modules from $LUSTRE
+    load_module ../lnet/libcfs/libcfs
+    # note that insmod will ignore anything in modprobe.conf
+    load_module ../lnet/lnet/lnet $LNETOPTS
+    LNETLND=${LNETLND:-"socklnd/ksocklnd"}
+    load_module ../lnet/klnds/$LNETLND
+    load_module lvfs/lvfs
+    load_module obdclass/obdclass
+    load_module ptlrpc/ptlrpc
+    load_module mdc/mdc
+    load_module osc/osc
+    load_module lov/lov
+    load_module mds/mds
+    load_module ldiskfs/ldiskfs
+    load_module lvfs/fsfilt_ldiskfs
+    load_module ost/ost
+    load_module obdfilter/obdfilter
+    load_module llite/lustre
+    load_module mgc/mgc
+    load_module mgs/mgs
+    rm -f $TMP/ogdb-`hostname`
+    $LCTL modules > $TMP/ogdb-`hostname`
+    # 'mount' doesn't look in $PATH, just sbin
+    [ -f $LUSTRE/utils/mount.lustre ] && cp $LUSTRE/utils/mount.lustre /sbin/. || true
 }
 
 unload_modules() {
-    lsmod | grep lnet > /dev/null && $LCTL dk $TMP/debug
-    local MODULES=`$LCTL modules | awk '{ print $2 }'`
-    rmmod $MODULES >/dev/null 2>&1 
+    lsmod | grep lnet > /dev/null && $LCTL dl && $LCTL dk $TMP/debug
+    local MODULES=$($LCTL modules | awk '{ print $2 }')
+    rmmod $MODULES >/dev/null 2>&1 || true
      # do it again, in case we tried to unload ksocklnd too early
-    lsmod | grep lnet > /dev/null && rmmod $MODULES >/dev/null 2>&1 
-    lsmod | grep lnet && echo "modules still loaded" && return 1
+    MODULES=$($LCTL modules | awk '{ print $2 }')
+    [ -n "$MODULES" ] && rmmod $MODULES >/dev/null && sleep 2 || true
+    MODULES=$($LCTL modules | awk '{ print $2 }')
+    if [ -n "$MODULES" ]; then
+       echo "modules still loaded"
+       echo $MODULES 
+       cat $LPROC/devices || true
+       lsmod
+       return 2
+    fi
+    HAVE_MODULES=false
 
-    LEAK_LUSTRE=`dmesg | tail -n 30 | grep "obd mem.*leaked"`
-    LEAK_PORTALS=`dmesg | tail -n 20 | grep "Portals memory leaked"`
+    LEAK_LUSTRE=$(dmesg | tail -n 30 | grep "obd mem.*leaked" || true)
+    LEAK_PORTALS=$(dmesg | tail -n 20 | grep "Portals memory leaked" || true)
     if [ "$LEAK_LUSTRE" -o "$LEAK_PORTALS" ]; then
-       echo "$LEAK_LUSTRE" 1>&2
-       echo "$LEAK_PORTALS" 1>&2
-       mv $TMP/debug $TMP/debug-leak.`date +%s`
-       echo "Memory leaks detected"
-       return 254
+        echo "$LEAK_LUSTRE" 1>&2
+        echo "$LEAK_PORTALS" 1>&2
+        mv $TMP/debug $TMP/debug-leak.`date +%s`
+        echo "Memory leaks detected"
+        return 254
     fi
+    echo "modules unloaded."
+    return 0
 }
 
 # Facet functions
@@ -96,40 +156,41 @@ start() {
     shift
     device=$1
     shift
-    echo "Starting ${facet}: $@ ${device} /mnt/${facet}"
-    do_facet ${facet} mkdir -p /mnt/${facet}
-    do_facet ${facet} mount -t lustre $@ ${device} /mnt/${facet} 
-    #do_facet $facet $LCONF --select ${facet}_svc=${active}_facet \
-    #    --node ${active}_facet  --ptldebug $PTLDEBUG --subsystem $SUBSYSTEM \
-    #    $@ $XMLCONFIG
+    echo "Starting ${facet}: $@ ${device} ${MOUNT%/*}/${facet}"
+    do_facet ${facet} mkdir -p ${MOUNT%/*}/${facet}
+    do_facet ${facet} mount -t lustre $@ ${device} ${MOUNT%/*}/${facet} 
     RC=${PIPESTATUS[0]}
     if [ $RC -ne 0 ]; then
-       echo mount -t lustre $@ ${device} /mnt/${facet} 
+        echo mount -t lustre $@ ${device} ${MOUNT%/*}/${facet} 
         echo Start of ${device} on ${facet} failed ${RC}
     else 
-       do_facet ${facet} sync
-       # need the awk in case running with -v 
-       label=`do_facet ${facet} "e2label ${device}" | awk '{print $(NF)}'`
-       eval export ${facet}_svc=${label}
-       eval export ${facet}_dev=${device}
-       eval export ${facet}_opt=\"$@\"
-       echo Started ${label}
+        do_facet ${facet} sync
+        label=`do_facet ${facet} "e2label ${device}" | grep -v "CMD: "`
+        [ -z "$label" ] && echo no label for ${device} && exit 1
+        eval export ${facet}_svc=${label}
+        eval export ${facet}_dev=${device}
+        eval export ${facet}_opt=\"$@\"
+        echo Started ${label}
     fi
     return $RC
 }
 
 stop() {
+    local running
     facet=$1
     shift
-    # the following line fails with VERBOSE set 
-    local running=`do_facet ${facet} "grep -c /mnt/${facet}' ' /proc/mounts" | awk '{print $(NF)}'`
-    if [ $running -ne 0 ]; then
-       echo "Stopping /mnt/${facet} (opts:$@)"
-       do_facet ${facet} umount -d $@ /mnt/${facet}
+    HOST=`facet_active_host $facet`
+    [ -z $HOST ] && echo stop: no host for $facet && return 0
+
+    running=`do_facet ${facet} "grep -c ${MOUNT%/*}/${facet}' ' /proc/mounts" | grep -v "CMD: "`
+    if [ ${running} -ne 0 ]; then
+        echo "Stopping ${MOUNT%/*}/${facet} (opts:$@)"
+        do_facet ${facet} umount -d $@ ${MOUNT%/*}/${facet}
     fi
-    #do_facet ${facet} umount -d $@ /mnt/${facet} >> /dev/null 2>&1 || :
-    [ -e /proc/fs/lustre ] && grep "ST " /proc/fs/lustre/devices && echo "service didn't stop" && exit 1
+
+    [ -e /proc/fs/lustre ] && grep "ST " $LPROC/devices && echo "service didn't stop" && exit 1
     return 0
+
 }
 
 zconf_mount() {
@@ -140,10 +201,10 @@ zconf_mount() {
     if [ -n "$MOUNTOPT" ]; then
         OPTIONS="-o $MOUNTOPT"
     fi
-    local device=`facet_nid mgs`:/$FSNAME
+    local device=$MGSNID:/$FSNAME
     if [ -z "$mnt" -o -z "$FSNAME" ]; then
-       echo Bad zconf mount command: opt=$OPTIONS dev=$device mnt=$mnt
-       exit 1
+        echo Bad zconf mount command: opt=$OPTIONS dev=$device mnt=$mnt
+        exit 1
     fi
 
     echo "Starting client: $OPTIONS $device $mnt" 
@@ -159,55 +220,85 @@ zconf_umount() {
     client=$1
     mnt=$2
     [ "$3" ] && force=-f
-    local running=`do_node $client "grep -c $mnt' ' /proc/mounts" | awk '{print $(NF)}'`
+    local running=`do_node $client "grep -c $mnt' ' /proc/mounts" | grep -v "CMD: "`
     if [ $running -ne 0 ]; then
-       echo "Stopping client $mnt (opts:$force)"
-       do_node $client umount $force $mnt
+        echo "Stopping client $mnt (opts:$force)"
+        do_node $client umount $force $mnt
     fi
 }
 
 shutdown_facet() {
     facet=$1
     if [ "$FAILURE_MODE" = HARD ]; then
-       $POWER_DOWN `facet_active_host $facet`
-       sleep 2 
+        $POWER_DOWN `facet_active_host $facet`
+        sleep 2 
     elif [ "$FAILURE_MODE" = SOFT ]; then
-       stop $facet
+        stop $facet
     fi
 }
 
 reboot_facet() {
     facet=$1
     if [ "$FAILURE_MODE" = HARD ]; then
-       $POWER_UP `facet_active_host $facet`
+        $POWER_UP `facet_active_host $facet`
     else
-       sleep 10
+        sleep 10
+    fi
+}
+
+# verify that lustre actually cleaned up properly
+cleanup_check() {
+    [ -e $CATASTROPHE -a "`cat $CATASTROPHE`" = "1" ] && echo "LBUG" && exit 206
+    BUSY=`dmesg | grep -i destruct || true`
+    if [ "$BUSY" ]; then
+        echo "$BUSY" 1>&2
+        [ -e $TMP/debug ] && mv $TMP/debug $TMP/debug-busy.`date +%s`
+        exit 205
     fi
+    LEAK_LUSTRE=`dmesg | tail -n 30 | grep "obd mem.*leaked" || true`
+    LEAK_PORTALS=`dmesg | tail -n 20 | grep "Portals memory leaked" || true`
+    if [ "$LEAK_LUSTRE" -o "$LEAK_PORTALS" ]; then
+        echo "$0: $LEAK_LUSTRE" 1>&2
+        echo "$0: $LEAK_PORTALS" 1>&2
+        echo "$0: Memory leak(s) detected..." 1>&2
+        mv $TMP/debug $TMP/debug-leak.`date +%s`
+        exit 204
+    fi
+
+    [ "`lctl dl 2> /dev/null | wc -l`" -gt 0 ] && lctl dl && \
+        echo "$0: lustre didn't clean up..." 1>&2 && return 202 || true
+
+    if [ "`/sbin/lsmod 2>&1 | egrep 'lnet|libcfs'`" ]; then
+        echo "$0: modules still loaded..." 1>&2
+        /sbin/lsmod 1>&2
+        return 203
+    fi
+    return 0
 }
 
 wait_for_host() {
-   HOST=$1
-   check_network "$HOST" 900
-   while ! do_node $HOST "ls -d $LUSTRE " > /dev/null; do sleep 5; done
+    HOST=$1
+    check_network "$HOST" 900
+    while ! do_node $HOST "ls -d $LUSTRE " > /dev/null; do sleep 5; done
 }
 
 wait_for() {
-   facet=$1
-   HOST=`facet_active_host $facet`
-   wait_for_host $HOST
+    facet=$1
+    HOST=`facet_active_host $facet`
+    wait_for_host $HOST
 }
 
 client_df() {
     # not every config has many clients
     if [ ! -z "$CLIENTS" ]; then
-       $PDSH $CLIENTS "df $MOUNT" > /dev/null
+        $PDSH $CLIENTS "df $MOUNT" > /dev/null
     fi
 }
 
 client_reconnect() {
     uname -n >> $MOUNT/recon
     if [ ! -z "$CLIENTS" ]; then
-       $PDSH $CLIENTS "df $MOUNT; uname -n >> $MOUNT/recon" > /dev/null
+        $PDSH $CLIENTS "df $MOUNT; uname -n >> $MOUNT/recon" > /dev/null
     fi
     echo Connected clients:
     cat $MOUNT/recon
@@ -248,7 +339,7 @@ replay_barrier() {
 }
 
 replay_barrier_nodf() {
-    local facet=$1
+    local facet=$1    echo running=${running}
     do_facet $facet sync
     local svc=${facet}_svc
     echo Replay barrier on ${!svc}
@@ -259,10 +350,15 @@ replay_barrier_nodf() {
 }
 
 mds_evict_client() {
-    UUID=`cat /proc/fs/lustre/mdc/*_MNT_*/uuid`
+    UUID=`cat /proc/fs/lustre/mdc/${mds_svc}-mdc-*/uuid`
     do_facet mds "echo $UUID > /proc/fs/lustre/mds/${mds_svc}/evict_client"
 }
 
+ost_evict_client() {
+    UUID=`cat /proc/fs/lustre/osc/${ost1_svc}-osc-*/uuid`
+    do_facet ost1 "echo $UUID > /proc/fs/lustre/obdfilter/${ost1_svc}/evict_client"
+}
+
 fail() {
     facet_failover $*
     df $MOUNT || error "post-failover df: $?"
@@ -288,53 +384,48 @@ do_lmc() {
 }
 
 h2gm () {
-   if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
-       ID=`$PDSH $1 $GMNALNID -l | cut -d\  -f2`
-       echo $ID"@gm"
-   fi
+    if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
+        ID=`$PDSH $1 $GMNALNID -l | cut -d\  -f2`
+        echo $ID"@gm"
+    fi
 }
 
 h2tcp() {
-   if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
-   echo $1"@tcp" 
-   fi
+    if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
+        echo $1"@tcp" 
+    fi
 }
 declare -fx h2tcp
 
 h2elan() {
-   if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
-   ID=`echo $1 | sed 's/[^0-9]*//g'`
-   echo $ID"@elan"
-   fi
+    if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
+        if type __h2elan >/dev/null 2>&1; then
+            ID=$(__h2elan $1)
+        else
+            ID=`echo $1 | sed 's/[^0-9]*//g'`
+        fi
+        echo $ID"@elan"
+    fi
 }
 declare -fx h2elan
 
 h2openib() {
-   if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
-   ID=`echo $1 | sed 's/[^0-9]*//g'`
-   echo $ID"@openib"
-   fi
+    if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
+        ID=`echo $1 | sed 's/[^0-9]*//g'`
+        echo $ID"@openib"
+    fi
 }
 declare -fx h2openib
 
 facet_host() {
-   local facet=$1
-   varname=${facet}_HOST
-   echo -n ${!varname}
-}
-
-facet_nid() {
-   facet=$1
-   HOST=`facet_host $facet`
-   if [ -z "$HOST" ]; then
-           echo "The env variable ${facet}_HOST must be set."
-           exit 1
-   fi
-   if [ -z "$NETTYPE" ]; then
-           echo "The env variable NETTYPE must be set."
-           exit 1
-   fi
-   echo `h2$NETTYPE $HOST`
+    local facet=$1
+    varname=${facet}_HOST
+    if [ -z "${!varname}" ]; then
+        if [ "${facet:0:3}" == "ost" ]; then
+            eval ${facet}_HOST=${ost_HOST}
+        fi
+    fi
+    echo -n ${!varname}
 }
 
 facet_active() {
@@ -347,9 +438,9 @@ facet_active() {
 
     active=${!activevar}
     if [ -z "$active" ] ; then 
-       echo -n ${facet}
+        echo -n ${facet}
     else
-       echo -n ${active}
+        echo -n ${active}
     fi
 }
 
@@ -357,9 +448,9 @@ facet_active_host() {
     local facet=$1
     local active=`facet_active $facet`
     if [ "$facet" == client ]; then
-       hostname
+        hostname
     else
-       echo `facet_host $active`
+        echo `facet_host $active`
     fi
 }
 
@@ -397,16 +488,88 @@ do_facet() {
     facet=$1
     shift
     HOST=`facet_active_host $facet`
+    [ -z $HOST ] && echo No host defined for facet ${facet} && exit 1
     do_node $HOST $@
 }
 
 add() {
     local facet=$1
     shift
-    # failsafe
+    # make sure its not already running
     stop ${facet} -f
     rm -f ${facet}active
-    $MKFS $*
+    do_facet ${facet} $MKFS $*
+}
+
+ostdevname() {
+    num=$1
+    DEVNAME=OSTDEV$num
+    #if $OSTDEVn isn't defined, default is $OSTDEVBASE + num
+    eval DEVPTR=${!DEVNAME:=${OSTDEVBASE}${num}}
+    echo -n $DEVPTR
+}
+
+########
+## MountConf setup
+
+stopall() {
+    # make sure we are using the primary server, so test-framework will
+    # be able to clean up properly.
+    activemds=`facet_active mds`
+    if [ $activemds != "mds" ]; then
+        fail mds
+    fi
+    
+    # assume client mount is local 
+    grep " $MOUNT " /proc/mounts && zconf_umount `hostname` $MOUNT $*
+    grep " $MOUNT2 " /proc/mounts && zconf_umount `hostname` $MOUNT2 $*
+    stop mds -f
+    for num in `seq $OSTCOUNT`; do
+        stop ost$num -f
+    done
+    return 0
+}
+
+cleanupall() {
+    stopall $*
+    unload_modules
+}
+
+formatall() {
+    stopall
+    # We need ldiskfs here, may as well load them all
+    load_modules
+    echo Formatting mds, osts
+    if $VERBOSE; then
+        add mds $MDS_MKFS_OPTS --reformat $MDSDEV || exit 10
+    else
+        add mds $MDS_MKFS_OPTS --reformat $MDSDEV > /dev/null || exit 10
+    fi
+
+    for num in `seq $OSTCOUNT`; do
+        if $VERBOSE; then
+            add ost$num $OST_MKFS_OPTS --reformat `ostdevname $num` || exit 10
+        else
+            add ost$num $OST_MKFS_OPTS --reformat `ostdevname $num` > /dev/null || exit 10
+        fi
+    done
+}
+
+mount_client() {
+    grep " $1 " /proc/mounts || zconf_mount `hostname` $*
+}
+
+setupall() {
+    load_modules
+    echo Setup mdt, osts
+    start mds $MDSDEV $MDS_MOUNT_OPTS
+    for num in `seq $OSTCOUNT`; do
+        DEVNAME=`ostdevname $num`
+        start ost$num $DEVNAME $OST_MOUNT_OPTS
+    done
+    [ "$DAEMONFILE" ] && $LCTL debug_daemon start $DAEMONFILE $DAEMONSIZE
+    mount_client $MOUNT
+    sleep 5
 }
 
 
@@ -414,33 +577,33 @@ add() {
 # General functions
 
 check_network() {
-   local NETWORK=0
-   local WAIT=0
-   local MAX=$2
-   while [ $NETWORK -eq 0 ]; do
-      ping -c 1 -w 3 $1 > /dev/null
-      if [ $? -eq 0 ]; then
-         NETWORK=1
-      else
-         WAIT=$((WAIT + 5))
-        echo "waiting for $1, $((MAX - WAIT)) secs left"
-         sleep 5
-      fi
-      if [ $WAIT -gt $MAX ]; then
-         echo "Network not available"
-         exit 1
-      fi
-   done
+    local NETWORK=0
+    local WAIT=0
+    local MAX=$2
+    while [ $NETWORK -eq 0 ]; do
+        ping -c 1 -w 3 $1 > /dev/null
+        if [ $? -eq 0 ]; then
+            NETWORK=1
+        else
+            WAIT=$((WAIT + 5))
+            echo "waiting for $1, $((MAX - WAIT)) secs left"
+            sleep 5
+        fi
+        if [ $WAIT -gt $MAX ]; then
+            echo "Network not available"
+            exit 1
+        fi
+    done
 }
 check_port() {
-   while( !($DSH2 $1 "netstat -tna | grep -q $2") ) ; do
-      sleep 9
-   done
+    while( !($DSH2 $1 "netstat -tna | grep -q $2") ) ; do
+        sleep 9
+    done
 }
 
 no_dsh() {
-   shift
-   eval $@
+    shift
+    eval $@
 }
 
 comma_list() {
@@ -450,7 +613,7 @@ comma_list() {
 }
 
 absolute_path() {
-   (cd `dirname $1`; echo $PWD/`basename $1`)
+    (cd `dirname $1`; echo $PWD/`basename $1`)
 }
 
 ##################################
@@ -486,10 +649,10 @@ drop_reint_reply() {
 pause_bulk() {
 #define OBD_FAIL_OST_BRW_PAUSE_BULK      0x214
     RC=0
-    do_facet ost sysctl -w lustre.fail_loc=0x214
+    do_facet ost1 sysctl -w lustre.fail_loc=0x214
     do_facet client "$1" || RC=$?
     do_facet client "sync"
-    do_facet ost sysctl -w lustre.fail_loc=0
+    do_facet ost1 sysctl -w lustre.fail_loc=0
     return $RC
 }
 
@@ -521,12 +684,12 @@ clear_failloc() {
 
 cancel_lru_locks() {
     $LCTL mark "cancel_lru_locks start"
-    for d in /proc/fs/lustre/ldlm/namespaces/$1*; do
-       if [ -f $d/lru_size ]; then
-           echo clear > $d/lru_size
-           grep "[0-9]" $d/lock_unused_count
+    for d in $LPROC/ldlm/namespaces/*-$1-*; do
+        if [ -f $d/lru_size ]; then
+           echo clear >> $d/lru_size
        fi
     done
+    grep "[0-9]" $LPROC/ldlm/namespaces/*-$1-*/lock_unused_count /dev/null
     $LCTL mark "cancel_lru_locks stop"
 }
 
@@ -534,9 +697,9 @@ cancel_lru_locks() {
 pgcache_empty() {
     for a in /proc/fs/lustre/llite/*/dump_page_cache; do
         if [ `wc -l $a | awk '{print $1}'` -gt 1 ]; then
-                echo there is still data in page cache $a ?
-                cat $a;
-                return 1;
+            echo there is still data in page cache $a ?
+            cat $a;
+            return 1;
         fi
     done
     return 0
@@ -545,22 +708,22 @@ pgcache_empty() {
 ##################################
 # Test interface 
 error() {
-       sysctl -w lustre.fail_loc=0 2> /dev/null || true
-       echo "${TESTSUITE}: **** FAIL:" $@
-       log "FAIL: $@"
-       exit 1
+    sysctl -w lustre.fail_loc=0 2> /dev/null || true
+    echo "${TESTSUITE}: **** FAIL:" $@
+    log "FAIL: $@"
+    exit 1
 }
 
 build_test_filter() {
-        [ "$ONLY" ] && log "only running test `echo $ONLY`"
-        for O in $ONLY; do
-            eval ONLY_${O}=true
-        done
-        [ "$EXCEPT$ALWAYS_EXCEPT" ] && \
-               log "skipping tests: `echo $EXCEPT $ALWAYS_EXCEPT`"
-        for E in $EXCEPT $ALWAYS_EXCEPT; do
-            eval EXCEPT_${E}=true
-        done
+    [ "$ONLY" ] && log "only running test `echo $ONLY`"
+    for O in $ONLY; do
+        eval ONLY_${O}=true
+    done
+    [ "$EXCEPT$ALWAYS_EXCEPT" ] && \
+        log "skipping tests: `echo $EXCEPT $ALWAYS_EXCEPT`"
+    for E in $EXCEPT $ALWAYS_EXCEPT; do
+        eval EXCEPT_${E}=true
+    done
 }
 
 _basetest() {
@@ -572,53 +735,53 @@ basetest() {
 }
 
 run_test() {
-        export base=`basetest $1`
-        if [ ! -z "$ONLY" ]; then
-                 testname=ONLY_$1
-                 if [ ${!testname}x != x ]; then
-                     run_one $1 "$2"
-                     return $?
-                 fi
-                 testname=ONLY_$base
-                 if [ ${!testname}x != x ]; then
-                     run_one $1 "$2"
-                     return $?
-                 fi
-                 echo -n "."
-                 return 0
-        fi
-        testname=EXCEPT_$1
+    export base=`basetest $1`
+    if [ ! -z "$ONLY" ]; then
+        testname=ONLY_$1
         if [ ${!testname}x != x ]; then
-                 echo "skipping excluded test $1"
-                 return 0
+            run_one $1 "$2"
+            return $?
         fi
-        testname=EXCEPT_$base
+        testname=ONLY_$base
         if [ ${!testname}x != x ]; then
-                 echo "skipping excluded test $1 (base $base)"
-                 return 0
+            run_one $1 "$2"
+            return $?
         fi
-        run_one $1 "$2"
-
-        return $?
+        echo -n "."
+        return 0
+    fi
+    testname=EXCEPT_$1
+    if [ ${!testname}x != x ]; then
+        echo "skipping excluded test $1"
+        return 0
+    fi
+    testname=EXCEPT_$base
+    if [ ${!testname}x != x ]; then
+        echo "skipping excluded test $1 (base $base)"
+        return 0
+    fi
+    run_one $1 "$2"
+    
+    return $?
 }
 
 EQUALS="======================================================================"
 equals_msg() {
-   msg="$@"
+    msg="$@"
 
-   local suffixlen=$((${#EQUALS} - ${#msg}))
-   [ $suffixlen -lt 5 ] && suffixlen=5
-   printf '===== %s %.*s\n' "$msg" $suffixlen $EQUALS
+    local suffixlen=$((${#EQUALS} - ${#msg}))
+    [ $suffixlen -lt 5 ] && suffixlen=5
+    printf '===== %s %.*s\n' "$msg" $suffixlen $EQUALS
 }
 
 log() {
-       echo "$*"
-       lsmod | grep lnet > /dev/null || modprobe lnet
-       $LCTL mark "$*" 2> /dev/null || true
+    echo "$*"
+    lsmod | grep lnet > /dev/null || load_modules
+    $LCTL mark "$*" 2> /dev/null || true
 }
 
 pass() {
-       echo PASS $@
+    echo PASS $@
 }
 
 check_mds() {
@@ -641,10 +804,12 @@ run_one() {
     #check_mds
     test_${testnum} || error "test_$testnum failed with $?"
     #check_mds
+    [ -f $CATASTROPHE ] && [ `cat $CATASTROPHE` -ne 0 ] && \
+        error "LBUG/LASSERT detected"
     pass "($((`date +%s` - $BEFORE))s)"
 }
 
 canonical_path() {
-   (cd `dirname $1`; echo $PWD/`basename $1`)
+    (cd `dirname $1`; echo $PWD/`basename $1`)
 }
 
diff --git a/lustre/tests/uml.sh b/lustre/tests/uml.sh
deleted file mode 100644 (file)
index e887a9f..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-#!/bin/bash
-
-export PATH=`dirname $0`/../utils:$PATH
-
-config=${1:-`basename $0 .sh`.xml}
-LMC=${LMC:-lmc}
-TMP=${TMP:-/tmp}
-
-MDSDEV=${MDSDEV:-$TMP/mds1-`hostname`}
-MDSSIZE=${MDSSIZE:-100000}
-
-OSTDEVBASE=$TMP/ost
-#OSTDEV1=${OSTDEV1:-${OSTDEVBASE}1}
-#OSTDEV2=${OSTDEV2:-${OSTDEVBASE}2}
-#etc
-OSTSIZE=${OSTSIZE:-100000}
-STRIPECNT=${STRIPECNT:-1}
-STRIPE_BYTES=${STRIPE_BYTES:-1048576}
-OSDTYPE=${OSDTYPE:-obdfilter}
-OSTFAILOVER=${OSTFAILOVER:-}
-
-MOUNT=${MOUNT:-/mnt/lustre}
-FSTYPE=${FSTYPE:-ext3}
-
-MDS_MOUNT_OPTS="user_xattr,acl,${MDS_MOUNT_OPTS:-""}"
-CLIENTOPT="user_xattr,acl,${CLIENTOPT:-""}"
-
-NETTYPE=${NETTYPE:-tcp}
-NIDTYPE=${NIDTYPE:-$NETTYPE}
-[ "$ACCEPTOR_PORT" ] && PORT_OPT="--port $ACCEPTOR_PORT"
-
-# NOTE - You can't have different MDS/OST nodes and also have clients on the
-#        MDS/OST nodes without using --endlevel and --startlevel during lconf.
-#        You can put both MDS/OST on one node and client can be there too.
-#        CLIENTS is a space-separated list of client nodes.
-#
-#        The rule is that both the MDS and the OST must be set up before any
-#        of the clients can be started, so plan accordingly.
-
-# Three separate systems
-MDSNODE=${MDSNODE:-uml1}
-OSTNODES=${OSTNODES:-"uml2 uml2"}
-CLIENTS=${CLIENTS:-"uml3"}
-
-# Single system with additional clients
-#MDSNODE=uml1
-#OSTNODES="uml1 uml1"
-#CLIENTS="$MDSNODE client"
-
-# Two systems with client on MDS, and additional clients (set up OST first)
-#MDSNODE=uml1
-#OSTNODES="uml2 uml2"
-#CLIENTS="$MDSNODE client"
-
-# Two systems with client on OST, and additional clients (set up MDS first)
-#MDSNODE=uml1
-#OSTNODES="uml2 uml2"
-#CLIENTS="$OSTNODES client"
-
-rm -f $config
-
-h2tcp () {
-       case $1 in
-       client) echo '\*' ;;
-       *) echo $1 ;;
-       esac
-}
-
-h2elan () {
-       case $1 in
-       client) echo '\*' ;;
-       *) echo $1 | sed "s/[^0-9]*//" ;;
-       esac
-}
-
-h2gm () {
-       echo `gmlndnid -n$1`
-}
-
-h2iib () {
-       case $1 in
-       client) echo '\*' ;;
-       *) echo $1 | sed "s/[^0-9]*//" ;;
-       esac
-}
-
-# create nodes
-echo -n "adding NET for:"
-for NODE in `echo $MDSNODE $OSTNODES $CLIENTS | tr -s " " "\n" | sort -u`; do
-       echo -n " $NODE"
-       ${LMC} -m $config --add net --node $NODE --nid `h2$NIDTYPE $NODE` \
-    --nettype $NETTYPE $PORT_OPT || exit 1
-done
-
-# configure mds server
-[ "x$MDS_MOUNT_OPTS" != "x" ] &&
-    MDS_MOUNT_OPTS="--mountfsoptions $MDS_MOUNT_OPTS"
-
-echo; echo "adding MDS on: $MDSNODE"
-${LMC} -m $config --add mds --node $MDSNODE --mds mds1 --fstype $FSTYPE \
-       --dev $MDSDEV $MDS_MOUNT_OPTS --size $MDSSIZE $MDSOPT || exit 10
-
-# configure ost
-${LMC} -m $config --add lov --lov lov1 --mds mds1 --stripe_sz $STRIPE_BYTES \
-       --stripe_cnt $STRIPECNT --stripe_pattern 0 $LOVOPT || exit 20
-COUNT=1
-echo -n "adding OST on:"
-for NODE in $OSTNODES; do
-       eval OSTDEV=\$OSTDEV$COUNT
-       echo -n " $NODE"
-       OSTDEV=${OSTDEV:-$OSTDEVBASE$COUNT-`hostname`}
-       case "$OSDTYPE" in
-               obdfilter)
-                       OSTARGS="--fstype $FSTYPE --dev $OSTDEV --size $OSTSIZE"
-                       ;;
-               obdecho)
-                       OSTARGS="--osdtype=obdecho"
-                       ;;
-       esac
-        ${LMC} -m $config --add ost --node $NODE --lov lov1 $OSTARGS \
-               $OSTFAILOVER $OSTOPT || exit 21
-       COUNT=`expr $COUNT + 1`
-done
-
-# create client config(s)
-[ "x$CLIENTOPT" != "x" ] && CLIENTOPT="--clientoptions $CLIENTOPT"
-echo; echo -n "adding CLIENT on:"
-for NODE in $CLIENTS; do
-       echo -n " $NODE"
-       ${LMC} -m $config --add mtpt --node $NODE --path $MOUNT --mds mds1 \
-               --lov lov1 $CLIENTOPT || exit 30
-done
-echo
index be94e55..8d8cd08 100644 (file)
@@ -14,7 +14,7 @@
 
 void usage(char *prog)
 {
-       fprintf(stderr, "usage: %s <filename>\n", prog);
+       fprintf(stderr, "usage: %s <filename> [-s <filename>]\n", prog);
        exit(1);
 }
 
@@ -22,15 +22,26 @@ int main(int argc, char *argv[])
 {
        long before_mknod, after_mknod;
        const char *prog = argv[0];
-       const char *filename = argv[1];
+        const char *filename = argv[1];
+        char *secname = NULL;
         struct utimbuf utb;
-       struct stat st;
+       struct stat st, st2;
        int rc;
+        int c;
 
-       utb.actime = 0x47114711;
-       utb.modtime = 0x11471147;
+       utb.actime = 200000;
+       utb.modtime = 100000;
 
-       if (argc != 2)
+        while ((c = getopt(argc, argv, "s:")) != -1) {
+                switch(c) {
+                case 's':
+                        secname = optarg;
+                        break;
+                default:
+                       usage(argv[0]);
+                }
+        }
+       if (optind + 1 > argc)
                usage(argv[0]);
 
        /* Adjust the before time back one second, because the kernel's
@@ -62,10 +73,33 @@ int main(int argc, char *argv[])
                        return 4;
                }
 
-               printf("%s: good mknod times %lu%s <= %lu <= %lu\n",
+               printf("%s: good mknod times %lu%s <= %lu <= %lu for %s\n",
                       prog, before_mknod, before_mknod == st.st_mtime ? "*":"",
-                      st.st_mtime, after_mknod);
+                      st.st_mtime, after_mknod, filename);
 
+                if (secname) {
+                        sleep(1);
+                        rc = stat(secname, &st2);
+                        if (rc) {
+                                fprintf(stderr, "%s: stat(%s) failed: rc %d: "
+                                        "%s\n", prog, secname, errno,
+                                        strerror(errno));
+                                return 5;
+                        }
+
+                        if (st2.st_mtime < before_mknod || 
+                            st2.st_mtime > after_mknod) {
+                                fprintf(stderr, "%s: bad mknod times %lu <= %lu"
+                                        " <= %lu false\n", prog, before_mknod,
+                                        st2.st_mtime, after_mknod);
+                                return 6;
+                        }
+
+                        printf("%s: good mknod times %lu%s <= %lu <= %lu "
+                               "for %s\n", prog, before_mknod, 
+                               before_mknod == st.st_mtime ? "*":"", 
+                               st2.st_mtime, after_mknod, secname);
+                }
        }
 
        /* See above */
@@ -73,30 +107,55 @@ int main(int argc, char *argv[])
        if (rc) {
                fprintf(stderr, "%s: utime(%s) failed: rc %d: %s\n",
                        prog, filename, errno, strerror(errno));
-               return 5;
+               return 7;
        }
-
+        
        rc = stat(filename, &st);
        if (rc) {
                fprintf(stderr, "%s: second stat(%s) failed: rc %d: %s\n",
                        prog, filename, errno, strerror(errno));
-               return 6;
+               return 8;
        }
 
        if (st.st_mtime != utb.modtime ) {
                fprintf(stderr, "%s: bad utime mtime %lu should be  %lu\n",
                        prog, st.st_mtime, utb.modtime);
-               return 7;
+               return 9;
        }
 
        if (st.st_atime != utb.actime ) {
                fprintf(stderr, "%s: bad utime atime %lu should be  %lu\n",
                        prog, st.st_atime, utb.actime);
-               return 8;
+               return 10;
        }
 
        printf("%s: good utime mtimes %lu, atime %lu\n",
               prog, utb.modtime, utb.actime);
 
+        if (secname == NULL)
+                return 0;
+        
+        /* Checking that times in past get updated on another client. */
+       rc = stat(secname, &st2);
+        if (rc) {
+               fprintf(stderr, "%s: second stat(%s) failed: rc %d: %s\n",
+                       prog, secname, errno, strerror(errno));
+               return 12;
+       }
+
+       if (st2.st_mtime != st.st_mtime) {
+               fprintf(stderr, "%s: not synced mtime between clients: %lu "
+                        "should be  %lu\n", prog, st2.st_mtime, st.st_mtime);
+               return 13;
+       }
+
+       if (st2.st_ctime != st.st_ctime) {
+               fprintf(stderr, "%s: not synced ctime between clients: %lu "
+                        " should be  %lu\n", prog, st2.st_ctime, st.st_ctime);
+               return 14;
+       }
+       
+        printf("%s: updated times for %s\n", prog, secname);
+        
        return 0;
 }
index 23be7e4..03b48fb 100644 (file)
@@ -42,13 +42,17 @@ struct kid_list_t {
 
 struct kid_list_t *head = NULL;
 
-void push_kid(pid_t kid)
+int push_kid(pid_t kid)
 {
         struct kid_list_t *new;
         new = (struct kid_list_t *)malloc(sizeof(struct kid_list_t));
+        if (new == NULL)
+                return 1;
+
         new->kid = kid;
         new->next = head;
         head = new;
+        return 0;
 }
 
 void kill_kids(void)
@@ -258,7 +262,11 @@ int main(int argc, char *argv[])
                         return (run_one_child(directory, i, duration));
                 } else {
                         /* parent */
-                        push_kid(rc);
+                        rc = push_kid(rc);
+                        if (rc != 0) {
+                                kill_kids();
+                                exit(3);
+                        }
                 }
         }
         /* parent process */
index d730e27..f1f7030 100644 (file)
@@ -28,3 +28,5 @@ wiretest
 llog_reader
 .*.cmd
 .*.d
+llverfs
+llverdev
index 9d7444c..5648aee 100644 (file)
@@ -1,31 +1,29 @@
 # Administration utilities Makefile
 
-SUBDIRS = Lustre
-
 AM_CFLAGS=$(LLCFLAGS)
 AM_CPPFLAGS=$(LLCPPFLAGS) -DLUSTRE_UTILS=1
 AM_LDFLAGS := -L$(top_builddir)/lnet/utils
 
 LIBPTLCTL := $(top_builddir)/lnet/utils/libptlctl.a
 
-sbin_scripts = llanalyze llstat.pl llobdstat.pl lactive lrun 
-bin_scripts = lfind lstripe
+sbin_scripts = llstat.pl llobdstat.pl lrun 
 
 if UTILS
+noinst_PROGRAMS = mount_lustre mkfs_lustre tunefs_lustre \
+       llog_reader lr_reader wirecheck wiretest lload obdio obdbarrier
 # mount only finds helpers in /sbin
 rootsbin_PROGRAMS = mount.lustre
-sbin_PROGRAMS = lctl obdio obdbarrier lload wirecheck wiretest \
-       mount_lustre mkfs_lustre mkfs.lustre \
-       tunefs_lustre tunefs.lustre l_getgroups
-bin_PROGRAMS = lfs llog_reader req_layout
-lib_LIBRARIES = liblustreapi.a libiam.a
+sbin_PROGRAMS = mkfs.lustre tunefs.lustre lctl \
+       l_getgroups llverfs llverdev
+bin_PROGRAMS = lfs req_layout
 sbin_SCRIPTS = $(sbin_scripts)
-bin_SCRIPTS = $(bin_scripts)
 endif # UTILS
 
+lib_LIBRARIES = liblustreapi.a libiam.a
+
 lctl_SOURCES = parser.c obd.c lustre_cfg.c lctl.c parser.h obdctl.h platform.h
-lctl_LDADD := $(LIBREADLINE) $(LIBPTLCTL) 
-lctl_DEPENDENCIES := $(LIBPTLCTL) 
+lctl_LDADD := $(LIBREADLINE) $(LIBPTLCTL)
+lctl_DEPENDENCIES := $(LIBPTLCTL)
 
 lfs_SOURCES = lfs.c parser.c obd.c
 lfs_LDADD := $(LIBREADLINE) liblustreapi.a $(LIBPTLCTL)
@@ -35,6 +33,24 @@ lload_SOURCES = lload.c
 lload_LDADD := $(LIBREADLINE) $(LIBPTLCTL)
 lload_DEPENDENCIES := $(LIBPTLCTL)
 
+if EXT2FS_DEVEL
+EXT2FSLIB = -lext2fs
+E2PLIB = -le2p
+else
+E2PLIB = 
+EXT2FSLIB =
+endif
+
+if BLKID
+BLKIDLIB = -lblkid
+else
+BLKIDLIB =
+endif
+
+llverfs_LDADD := $(EXT2FSLIB) $(E2PLIB)
+
+llverdev_LDADD := $(EXT2FSLIB) $(BLKIDLIB)
+
 liblustreapi_a_SOURCES = liblustreapi.c
 libiam_a_SOURCES = libiam.c
 
@@ -51,6 +67,8 @@ llog_reader_SOURCES = llog_reader.c
 llog_reader_LDADD := $(LIBPTLCTL)
 llog_reader_DEPENDENCIES := $(LIBPTLCTL)
 
+lr_reader_SOURCES = lr_reader.c
+
 mount_lustre_SOURCES = mount_lustre.c 
 mount_lustre_LDADD := $(LIBPTLCTL)
 mount_lustre_DEPENDENCIES := $(LIBPTLCTL)
@@ -65,12 +83,14 @@ tunefs_lustre_CPPFLAGS = -DTUNEFS $(AM_CPPFLAGS)
 tunefs_lustre_LDADD := $(mkfs_lustre_LDADD)
 tunefs_lustre_DEPENDENCIES := $(mkfs_lustre_DEPENDENCIES)
 
-EXTRA_DIST = $(bin_scripts) $(sbin_scripts)
+EXTRA_DIST = $(sbin_scripts)
 
 # NOTE: this should only be run on i386.
 newwiretest: wirehdr.c wirecheck
        cp wirehdr.c wiretest.c
        ./wirecheck >> wiretest.c
+       cp ../ptlrpc/wirehdr.c ../ptlrpc/wiretest.c
+       ./wirecheck >> ../ptlrpc/wiretest.c
 
 # Apparently I can't use .'s in automake names
 mount.lustre$(EXEEXT): mount_lustre
diff --git a/lustre/utils/cluster_scripts/1uml.csv b/lustre/utils/cluster_scripts/1uml.csv
deleted file mode 100644 (file)
index d6f23a4..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-# combo mdt/mgs
-uml1,options lnet networks=tcp,/r/tmp/mdt,mdt|mgs,,,,--device-size=10240
-# ost0
-uml1,options lnet networks=tcp,/r/tmp/ost0,ost,,"uml1@tcp0",,--device-size=10240
-
diff --git a/lustre/utils/cluster_scripts/cluster_config.sh b/lustre/utils/cluster_scripts/cluster_config.sh
deleted file mode 100755 (executable)
index 818d884..0000000
+++ /dev/null
@@ -1,705 +0,0 @@
-#!/bin/bash
-#
-# cluster_config.sh - configure multiple lustre servers from a csv file
-#
-# This script is used to parse each line of a spreadsheet (csv file) and 
-# execute remote pdsh commands to format (mkfs.lustre) every Lustre target 
-# that will be part of the Lustre cluster.
-# 
-# In addition, it can also verify the network connectivity and hostnames in 
-# the cluster and produce High-Availability software configurations for
-# Heartbeat or CluManager
-#
-################################################################################
-
-# Usage
-usage() {
-       cat >&2 <<EOF
-
-Usage: `basename $0` [-t HAtype] [-n] [-f] [-h] [-v] <csv file>
-
-       -t HAtype       produce High-Availability software configurations
-
-                       The argument following -t is used to indicate the High-
-                       Availability software type. The HA software types which 
-                       are currently supported are: hbv1 (Heartbeat v1), hbv2 
-                       (Heartbeat v2) and clumanager (CluManager).
-       -n              don't verify network connectivity and hostnames in the 
-                       cluster
-       -f              force-format the Lustre targets using --reformat option
-       -h              help and examples
-       -v              verbose mode
-       csv file        a spreadsheet that contains configuration parameters
-                        (separated by commas) for each target in a Lustre cl-
-                        uster
-EOF
-       exit 1
-}
-
-# Samples 
-sample() {
-       cat >&2 <<EOF
-
-Each line in the csv file represents one Lustre target.
-The format is:
-hostname,module_opts,device name,device type,fsname,mgs nids,index,
-format options,mkfs options,mount options,failover nids,heartbeat channels,
-service address,heartbeat options
-
-Items left blank will be set to defaults.
-
-Sample 1 for csv file (Simple one without HA software configuration options):
--------------------------------------------------------------------------------
-# combo mdt/mgs
-lustre-mgs,options lnet networks=tcp,/r/tmp/mgs,mdt|mgs,,,,--device-size=10240
-
-# ost0
-lustre-ost,options lnet networks=tcp,/r/tmp/ost0,ost,,lustre-mgs@tcp0,,
---device-size=10240
--------------------------------------------------------------------------------
-
-Sample 2 for csv file (Complex one without HA software configuration options):
--------------------------------------------------------------------------------
-# mgs
-lustre-mgs1,options lnet 'networks="tcp,elan"',/r/tmp/mgs,mgs,,,,
---device-size=10240,-J size=4,,"lustre-mgs2,2@elan"
-
-# mdt
-lustre-mdt1,options lnet 'networks="tcp,elan"',/r/tmp/mdt,mdt,,
-"lustre-mgs1,1@elan:lustre-mgs2,2@elan",,--device-size=10240,
--J size=4,,lustre-mdt2
-
-# ost
-lustre-ost1,options lnet 'networks="tcp,elan"',/r/tmp/ost,ost,,
-"lustre-mgs1,1@elan:lustre-mgs2,2@elan",,--device-size=10240,
--J size=4,"extents,mballoc",lustre-ost2
--------------------------------------------------------------------------------
-
-Sample 3 for csv file (with Heartbeat version 1 configuration options):
--------------------------------------------------------------------------------
-# mgs
-lustre-mgs1,options lnet networks=tcp,/r/tmp/mgs,mgs,,,,--device-size=10240,,,
-lustre-mgs2,serial /dev/ttyS0:bcast eth1,192.168.1.170,auto_failback off:
-ping 192.168.1.169:respawn hacluster /usr/lib/heartbeat/ipfail
-
-# mdt
-lustre-mdt1,options lnet networks=tcp,/r/tmp/mdt,mdt,,"lustre-mgs1:lustre-mgs2",
-,--device-size=10240,,,lustre-mdt2,bcast eth1,192.168.1.173,auto_failback off
-
-# ost
-lustre-ost1,options lnet networks=tcp,/r/tmp/ost,ost,,"lustre-mgs1:lustre-mgs2",
-,--device-size=10240,,,lustre-ost2,bcast eth1,192.168.1.171,auto_failback on
--------------------------------------------------------------------------------
-
-Sample 4 for csv file (with Heartbeat version 2 configuration options):
--------------------------------------------------------------------------------
-# combo mdt/mgs
-lustre-mgs1,options lnet networks=tcp,/r/tmp/mgs,mgs|mdt,,,,--device-size=10240,
-,,"lustre-mgs2:lustre-mgs3",bcast eth1,192.168.1.170,auto_failback off
-
-# ost
-lustre-ost1,options lnet networks=tcp,/r/tmp/ost,ost,,"lustre-mgs1:lustre-mgs2:
-lustre-mgs3",,--device-size=10240,,,lustre-ost2,bcast eth1,192.168.1.171,
-auto_failback on:crm yes
--------------------------------------------------------------------------------
-
-Sample 5 for csv file (with Red Hat's Cluster Manager configuration options):
--------------------------------------------------------------------------------
-# mgs
-lustre-mgs1,options lnet networks=tcp,/r/tmp/mgs,mgs,,,,--device-size=10240,,,
-lustre-mgs2,broadcast,192.168.1.170,--clumembd--interval=1000000 --tko_count=20
-
-# mdt
-lustre-mdt1,options lnet networks=tcp,/r/tmp/mdt,mdt,,"lustre-mgs1:lustre-mgs2",
-,--device-size=10240,,,lustre-mdt2,multicast225.0.0.12,192.168.1.173,
-
-# ost
-lustre-ost1,options lnet networks=tcp,/r/tmp/ost,ost,,"lustre-mgs1:lustre-mgs2",
-,--device-size=10240,,,lustre-ost2,,192.168.1.171:192.168.1.172,
--------------------------------------------------------------------------------
-
-EOF
-       exit 1
-}
-
-# Global variables
-PDSH=${PDSH:-"pdsh -R ssh"}
-export PDSH
-
-CMD_PATH=${CMD_PATH:-"/sbin/"}
-
-# Some scripts to be called
-SCRIPTS_PATH=${CLUSTER_SCRIPTS_PATH:-"./"}
-MODULE_CONFIG=${SCRIPTS_PATH}$"module_config.sh"
-VERIFY_CLUSTER_NET=${SCRIPTS_PATH}$"verify_cluster_net.sh"
-GEN_HB_CONFIG=${SCRIPTS_PATH}$"gen_hb_config.sh"
-GEN_CLUMGR_CONFIG=${SCRIPTS_PATH}$"gen_clumanager_config.sh"
-
-HATYPE_HBV1=$"hbv1"                    # Heartbeat version 1
-HATYPE_HBV2=$"hbv2"                    # Heartbeat version 2
-HATYPE_CLUMGR=$"clumanager"            # Cluster Manager
-
-HB_TMP_DIR=$"/tmp/heartbeat/"          # Temporary directory
-CLUMGR_TMP_DIR=$"/tmp/clumanager/"
-TMP_DIRS=$"${HB_TMP_DIR} ${CLUMGR_TMP_DIR}"
-
-declare -a CONFIG_ITEM                 # fields in each line of the csv file
-declare -a NODE_NAMES                  # node names in the failover group
-
-# Get and check the positional parameters
-while getopts "t:nfhv" OPTION; do
-       case $OPTION in
-       t) 
-               HATYPE_OPT=$OPTARG
-               if [ "${HATYPE_OPT}" != "${HATYPE_HBV1}" ] \
-               && [ "${HATYPE_OPT}" != "${HATYPE_HBV2}" ] \
-               && [ "${HATYPE_OPT}" != "${HATYPE_CLUMGR}" ]; then
-                       echo >&2 $"`basename $0`: Invalid HA software type" \
-                                 "- ${HATYPE_OPT}!"
-                       usage
-               fi
-               ;;
-        n) 
-               VERIFY_CONNECT=$"no"
-               ;;
-        f) 
-               REFORMAT_OPTION=$"--reformat "
-               ;;
-        h) 
-               sample  
-               ;;
-       v) 
-               VERBOSE_OPT=$" -v"
-               ;;
-        ?) 
-               usage 
-       esac
-done
-
-# Toss out the parameters we've already processed
-shift  `expr $OPTIND - 1`
-
-# Here we expect the csv file
-if [ $# -eq 0 ]; then
-       echo >&2 $"`basename $0`: Missing csv file!"
-       usage
-fi
-
-# Output verbose informations
-verbose_output() {
-       if [ -n "${VERBOSE_OPT}" ]; then
-               echo "`basename $0`: $*"
-       fi
-       return 0
-}
-
-# Check the csv file
-check_file() {
-        # Check argument
-        if [ $# -eq 0 ]; then
-                echo >&2 $"`basename $0`: check_file() error: Lack argument"\
-                         "for function check_file()!"
-                return 1
-        fi
-
-       CSV_FILE=$1
-       if [ ! -s ${CSV_FILE} ]; then
-                echo >&2 $"`basename $0`: check_file() error: ${CSV_FILE}"\
-                         "does not exist or is empty!"
-                return 1
-        fi
-
-        return 0
-}
-
-# Parse a line in the csv file
-parse_line() {
-        # Check argument
-        if [ $# -eq 0 ]; then
-                echo >&2 $"`basename $0`: parse_line() error: Lack argument"\
-                         "for function parse_line()!"
-                return 1
-        fi
-
-       declare -i i=0
-       declare -i length=0 
-       declare -i idx=0
-       declare -i s_quote_flag=0 
-       declare -i d_quote_flag=0
-       local TMP_LETTER LINE
-       LINE=$*
-
-       # Initialize the CONFIG_ITEM array
-       for ((i = 0; i < ${#CONFIG_ITEM[@]}; i++)); do
-               CONFIG_ITEM[i]=$""
-       done
-
-       # Get the length of the line
-        length=${#LINE}
-
-       i=0
-       while [ ${idx} -lt ${length} ]; do
-               # Get a letter from the line
-               TMP_LETTER=${LINE:${idx}:1}
-
-               case "${TMP_LETTER}" in
-               ",")
-                               if [ ${s_quote_flag} -eq 1 ] || [ ${d_quote_flag} -eq 1 ]; then
-                                       CONFIG_ITEM[i]=${CONFIG_ITEM[i]}${TMP_LETTER}
-                               else
-                               i=$i+1
-                               fi
-                               idx=${idx}+1
-                       continue
-                       ;;
-               "'")
-                               if [ ${s_quote_flag} -eq 0 ]; then
-                                       s_quote_flag=1
-                               else
-                                       s_quote_flag=0
-                               fi
-                       ;;
-               "\"")
-                               if [ ${d_quote_flag} -eq 0 ]; then
-                                       d_quote_flag=1
-                               else
-                                       d_quote_flag=0
-                               fi
-
-                               if [ ${i} -eq 1 ]; then
-                               CONFIG_ITEM[i]=${CONFIG_ITEM[i]}$"\\"${TMP_LETTER}
-                               idx=${idx}+1
-                               continue
-                       fi
-                       ;;
-               "\r")
-                               idx=${idx}+1
-                       continue
-                       ;;
-               *)
-                       ;;
-               esac
-                CONFIG_ITEM[i]=${CONFIG_ITEM[i]}${TMP_LETTER}
-                idx=${idx}+1
-               done
-       return 0
-}
-
-# Check the elements required for OSTs, MDTs and MGS
-#
-# When formatting an OST, the following elements: hostname, module_opts,
-# device name, device type and mgs nids, cannot have null value.
-#
-# When formatting an MDT or MGS, the following elements: hostname,
-# module_opts, device name and device type, cannot have null value.
-check_element() {
-        # Check hostname, module_opts, device name and device type
-        if [ -z "${HOST_NAME}" ]||[ -z "${MODULE_OPTS}" ]||[ -z "${DEVICE_NAME}" ]\
-          ||[ -z "${DEVICE_TYPE}" ]; then
-                echo >&2 $"`basename $0`: check_element() error: Some required"\
-                         "element has null value! Check hostname, module_opts,"\
-                         "device name and device type!"
-                return 1
-        fi
-
-        # Check mgs nids
-        if [ "${DEVICE_TYPE}" = "ost" ]&&[ -z "${MGS_NIDS}" ]; then
-                echo >&2 $"`basename $0`: check_element() error: OST's mgs nids"\
-                         "element has null value!"
-                return 1
-        fi
-
-        return 0
-}
-
-# Check the elements required for HA configuration
-check_ha_element() {
-       if [ -z "${HATYPE_OPT}" ]; then
-               return 0
-       fi
-
-       # Check service IP element
-       if [ -z "${SRV_IPADDRS}" ]; then
-                echo >&2 $"`basename $0`: check_ha_element() error: Service IP"\
-                         "element has null value!"
-                return 1
-        fi
-
-       # Check heartbeat channel element
-       if [ "${HATYPE_OPT}" != "${HATYPE_CLUMGR}" -a -z "${HB_CHANNELS}" ]
-       then
-                echo >&2 $"`basename $0`: check_ha_element() error: Heartbeat"\
-                         "channel element has null value!"
-                return 1
-        fi
-
-       return 0
-}
-
-# Check the number of MGS.
-# There should be no more than one MGS specified in the entire csv file.
-check_mgs() {
-       # Check the number of explicit MGS
-       if [ "${DEVICE_TYPE#*mgs*}" != "${DEVICE_TYPE}" ]; then 
-               if [ "${EXP_MGS}" = "${HOST_NAME}" ]; then
-                       echo >&2 $"`basename $0`: check_mgs() error: More than"\
-                                 "one explicit MGS in the csv file!"
-                       return 1
-               fi
-
-               if [ -z "${EXP_MGS}" ]; then
-                       EXP_MGS=${HOST_NAME}
-               fi
-
-               if [ "${EXP_MGS}" != "${HOST_NAME}" ]; then
-                       if [ "${FAILOVERS#*$EXP_MGS*}" = "${FAILOVERS}" ]; then
-                               echo >&2 $"`basename $0`: check_mgs() error:"\
-                                         "More than one explicit MGS in the"\
-                                         "csv file!"
-                       else
-                               echo >&2 $"`basename $0`: check_mgs() error:"\
-                                         "There should not be two entries for"\
-                                         "a server and its failover partner"\
-                                         "in the csv file!"
-                       fi
-                       return 1
-               fi
-       fi
-
-       # Check the number of implicit MGS
-        if [ "${DEVICE_TYPE}" = "mdt" ]&&[ -z "${MGS_NIDS}" ]; then
-               if [ "${IMP_MGS}" = "${HOST_NAME}" ]; then
-                       echo >&2 $"`basename $0`: check_mgs() error: More than"\
-                                 "one implicit MGS in the csv file!"
-                       return 1
-               fi
-
-               if [ -z "${IMP_MGS}" ]; then
-                       IMP_MGS=${HOST_NAME}
-               fi
-
-               if [ "${IMP_MGS}" != "${HOST_NAME}" ]; then
-                       if [ "${FAILOVERS#*$IMP_MGS*}" = "${FAILOVERS}" ]; then
-                               echo >&2 $"`basename $0`: check_mgs() error:"\
-                                         "More than one implicit MGS in the"\
-                                         "csv file!"
-                       else
-                               echo >&2 $"`basename $0`: check_mgs() error:"\
-                                         "There should not be two entries for"\
-                                         "a server and its failover partner"\
-                                         "in the csv file!"
-                       fi
-                       return 1
-               fi
-       fi
-
-       if [ -n "${EXP_MGS}" -a -n "${IMP_MGS}" ]; then
-               echo >&2 $"`basename $0`: check_mgs() error: More than one"\
-                         "MGS in the csv file!"
-               return 1
-       fi
-       
-       return 0
-}
-
-# Construct the command line of mkfs.lustre
-construct_mkfs_cmdline() {
-       MKFS_CMD=${CMD_PATH}$"mkfs.lustre "
-       MKFS_CMD=${MKFS_CMD}${REFORMAT_OPTION}
-
-       case "${DEVICE_TYPE}" in
-       "ost")
-               MKFS_CMD=${MKFS_CMD}$"--ost "
-               ;;
-       "mdt")
-               MKFS_CMD=${MKFS_CMD}$"--mdt "
-               ;;
-       "mgs")
-               MKFS_CMD=${MKFS_CMD}$"--mgs "
-               ;;
-       "mdt|mgs")
-               MKFS_CMD=${MKFS_CMD}$"--mdt --mgs "
-               ;;
-       "mgs|mdt")
-               MKFS_CMD=${MKFS_CMD}$"--mdt --mgs "
-               ;;
-       *)
-               echo >&2 $"`basename $0`: construct_mkfs_cmdline() error:"\
-                         "Invalid device type - \"${DEVICE_TYPE}\""
-               return 1
-               ;;
-       esac
-
-       if [ -n "${FS_NAME}" ]; then
-               MKFS_CMD=${MKFS_CMD}$"--fsname="${FS_NAME}$" "
-       fi
-
-       if [ -n "${MGS_NIDS}" ]; then
-               MGS_NIDS=`echo "${MGS_NIDS}" | sed 's/^"//' | sed 's/"$//'`
-               MKFS_CMD=${MKFS_CMD}$"--mgsnode="${MGS_NIDS}$" "
-       fi
-
-       if [ -n "${INDEX}" ]; then
-               MKFS_CMD=${MKFS_CMD}$"--index="${INDEX}$" "
-       fi
-
-       if [ -n "${FORMAT_OPTIONS}" ]; then
-               FORMAT_OPTIONS=`echo "${FORMAT_OPTIONS}" | sed 's/^"//' | sed 's/"$//'`
-               MKFS_CMD=${MKFS_CMD}${FORMAT_OPTIONS}$" "
-       fi
-
-       if [ -n "${MKFS_OPTIONS}" ]; then
-               MKFS_OPTIONS=`echo "${MKFS_OPTIONS}" | sed 's/^"//' | sed 's/"$//'`
-               MKFS_CMD=${MKFS_CMD}$"--mkfsoptions="$"\""${MKFS_OPTIONS}$"\""$" "
-       fi
-
-       if [ -n "${MOUNT_OPTIONS}" ]; then
-               MOUNT_OPTIONS=`echo "${MOUNT_OPTIONS}" | sed 's/^"//' | sed 's/"$//'`
-               MKFS_CMD=${MKFS_CMD}$"--mountfsoptions="$"\""${MOUNT_OPTIONS}$"\""$" "
-       fi
-
-       if [ -n "${FAILOVERS}" ]; then
-               FAILOVERS=`echo "${FAILOVERS}" | sed 's/^"//' | sed 's/"$//'`
-               MKFS_CMD=${MKFS_CMD}$"--failnode="${FAILOVERS}$" "
-       fi
-
-       MKFS_CMD=${MKFS_CMD}${DEVICE_NAME}
-       return 0
-} 
-
-# Get all the node names in this failover group
-get_nodenames() {
-        declare -i idx
-        local failover_nids failover_nid first_nid
-
-       NODE_NAMES[0]=${HOST_NAME}
-
-        failover_nids=`echo ${FAILOVERS}|awk '{split($FAILOVERS, a, ":")}\
-                       END {for (i in a) print a[i]}'`
-
-       # XXX: Suppose the first nid of one failover node contains the node name
-       idx=1
-        for failover_nid in ${failover_nids}
-        do
-               first_nid=`echo ${failover_nid} | awk -F, '{print $1}'`
-                NODE_NAMES[idx]=${first_nid%@*}
-                idx=$idx+1
-        done
-
-        return 0
-}
-
-# Produce HA software's configuration files
-gen_ha_config() {
-        local  cmd_line
-        declare -i idx
-
-       if [ -z "${HATYPE_OPT}" ]; then
-               return 0
-       fi
-
-       # Prepare parameters
-       # Hostnames option
-       HOSTNAME_OPT=${HOST_NAME}
-
-       if ! get_nodenames; then
-               return 1
-       fi
-
-        for ((idx = 1; idx < ${#NODE_NAMES[@]}; idx++)); do
-                HOSTNAME_OPT=${HOSTNAME_OPT}$":"${NODE_NAMES[idx]}
-        done
-
-       # Target device option
-       TARGET_TYPE=${DEVICE_TYPE}
-       if [ "${TARGET_TYPE}" = "mdt|mgs" -o "${TARGET_TYPE}" = "mgs|mdt" ]
-       then
-               TARGET_TYPE=$"mgs_mdt"
-       fi
-       TARGET_OPT=${DEVICE_NAME}:${TARGET_TYPE}
-
-       # Service IP address option
-       SRVADDR_OPT=${SRV_IPADDRS}
-
-       # Heartbeat channels option
-       HBCHANNEL_OPT=$"\""${HB_CHANNELS}$"\""
-
-       # Heartbeat options option
-       HBOPT_OPT=$"\""${HB_OPTIONS}$"\""
-
-       # Construct the generation script command line
-       case "${HATYPE_OPT}" in
-       "${HATYPE_HBV1}"|"${HATYPE_HBV2}")      # Heartbeat 
-               cmd_line=${GEN_HB_CONFIG}$" -r ${HATYPE_OPT} -n ${HOSTNAME_OPT}"
-               cmd_line=${cmd_line}$" -d ${TARGET_OPT} -c ${HBCHANNEL_OPT}"
-               cmd_line=${cmd_line}$" -s ${SRVADDR_OPT}"${VERBOSE_OPT}
-
-               if [ -n "${HB_OPTIONS}" ]; then
-                       cmd_line=${cmd_line}$" -o ${HBOPT_OPT}"
-               fi
-               ;;
-        "${HATYPE_CLUMGR}")                    # CluManager
-               cmd_line=${GEN_CLUMGR_CONFIG}$" -n ${HOSTNAME_OPT}"
-               cmd_line=${cmd_line}$" -d ${TARGET_OPT} -s ${SRVADDR_OPT}"
-               cmd_line=${cmd_line}${VERBOSE_OPT}
-
-               if [ -n "${HBCHANNEL_OPT}" ]; then
-                       cmd_line=${cmd_line}$" -c ${HBCHANNEL_OPT}"
-               fi
-
-               if [ -n "${HB_OPTIONS}" ]; then
-                       cmd_line=${cmd_line}$" -o ${HBOPT_OPT}"
-               fi
-               ;;
-       esac
-       
-       # Execute script to generate HA software's configuration files
-       verbose_output "${cmd_line}"
-       eval $(echo "${cmd_line}")
-       if [ $? -ne 0 ]; then
-               return 1
-       fi
-       
-       return 0
-}
-
-# Execute pdsh commands to add lnet options lines to remote nodes'
-# modprobe.conf/modules.conf and format(mkfs.lustre) Lustre targets
-#
-# If -t option exists, then also to produce the HA software's 
-# configuration files
-mass_config() {
-       # Check argument
-        if [ $# -eq 0 ]; then
-                echo >&2 $"`basename $0`: mass_config() error: Lack argument"\
-                         "for function mass_config()!"
-                return 1
-        fi
-
-        CSV_FILE=$1
-       local LINE COMMAND
-       declare -a PDSH_PID 
-       declare -a PDSH_CMD 
-       declare -i line_num=1
-       declare -i pid_num=0
-
-       while read -r LINE; do
-               # Get rid of the empty line
-               if [ -z "`echo ${LINE} | awk '/[[:alnum:]]/{print $0}'`" ]; then
-                       line_num=${line_num}+1
-                       continue
-               fi
-
-               # Get rid of the comment line
-               if [ -z "`echo \"${LINE}\" | egrep -v \"([[:space:]]|^)#\"`" ]; then
-                       line_num=${line_num}+1
-                       continue
-               fi
-
-               # Parse the config line into CONFIG_ITEM
-               if ! parse_line $LINE; then
-                       return 1        
-               fi
-
-               HOST_NAME=${CONFIG_ITEM[0]}
-               MODULE_OPTS=${CONFIG_ITEM[1]}
-               DEVICE_NAME=${CONFIG_ITEM[2]}
-               DEVICE_TYPE=${CONFIG_ITEM[3]}
-               FS_NAME=${CONFIG_ITEM[4]}
-               MGS_NIDS=${CONFIG_ITEM[5]}
-               INDEX=${CONFIG_ITEM[6]}
-               FORMAT_OPTIONS=${CONFIG_ITEM[7]}
-               MKFS_OPTIONS=${CONFIG_ITEM[8]}
-               MOUNT_OPTIONS=${CONFIG_ITEM[9]}
-               FAILOVERS=${CONFIG_ITEM[10]}
-
-               HB_CHANNELS=${CONFIG_ITEM[11]}
-               SRV_IPADDRS=${CONFIG_ITEM[12]}
-               HB_OPTIONS=${CONFIG_ITEM[13]}
-
-               # Check some required elements for formatting target
-               if ! check_element; then
-                       echo >&2 $"`basename $0`: check_element() error:"\
-                                 "Occurred on line ${line_num} in ${CSV_FILE}"
-                       return 1        
-               fi
-               
-               # Check the number of MGS
-               if ! check_mgs; then
-                       echo >&2 $"`basename $0`: check_mgs() error:"\
-                                 "Occurred on line ${line_num} in ${CSV_FILE}"
-                       return 1
-               fi
-               
-               # Construct the command line of mkfs.lustre
-               if ! construct_mkfs_cmdline; then
-                       echo >&2 $"`basename $0`: construct_mkfs_cmdline() error:"\
-                                 "Occurred on line ${line_num} in ${CSV_FILE}"
-                       return 1        
-               fi
-
-               # Produce HA software's configuration files
-               if ! gen_ha_config; then
-                       return 1
-               fi
-
-               # Execute pdsh command to add lnet options lines to 
-               # modprobe.conf/modules.conf
-               COMMAND=$"echo \"${MODULE_OPTS}\"|${MODULE_CONFIG}"
-               verbose_output "Adding module options to ${HOST_NAME}"
-               verbose_output ${COMMAND}
-               ${PDSH} -w ${HOST_NAME} ${COMMAND} >&2 &
-               PDSH_PID[${pid_num}]=$!
-               PDSH_CMD[${pid_num}]="${PDSH} -w ${HOST_NAME} ${COMMAND}"
-               pid_num=${pid_num}+1
-
-               # Execute pdsh command to format Lustre target
-               verbose_output "Formatting Lustre target on ${HOST_NAME}..."
-               verbose_output "Format command line is: ${MKFS_CMD}"
-               ${PDSH} -w ${HOST_NAME} ${MKFS_CMD} >&2 &  
-               PDSH_PID[${pid_num}]=$!
-               PDSH_CMD[${pid_num}]="${PDSH} -w ${HOST_NAME} ${MKFS_CMD}"
-               pid_num=${pid_num}+1
-
-               line_num=${line_num}+1
-       done < ${CSV_FILE}
-
-       # Wait for the exit status of the background pdsh command
-       verbose_output "Waiting for the return of the pdsh command..."
-       for ((pid_num = 0; pid_num < ${#PDSH_PID[@]}; pid_num++)); do
-               wait ${PDSH_PID[${pid_num}]}
-               if [ $? -ne 0 ]; then
-                       echo >&2 "`basename $0`: mass_config() error:"\
-                                "Fail to execute \"${PDSH_CMD[${pid_num}]}\"!"
-               fi
-       done    
-
-       rm -rf ${TMP_DIRS}
-       return 0
-}
-
-# Main flow
-# Check the csv file
-if ! check_file $1; then
-       exit 1  
-fi
-
-if [ "${VERIFY_CONNECT}" != "no" ]; then
-# Check the network connectivity and hostnames
-       verbose_output "Checking the network connectivity and hostnames..."
-       if ! ${VERIFY_CLUSTER_NET} ${VERBOSE_OPT} ${CSV_FILE}; then
-               exit 1
-       fi
-       verbose_output "Check the network connectivity and hostnames OK!"
-fi
-
-# Configure the Lustre cluster
-verbose_output "******** Lustre cluster configuration START ********"
-if ! mass_config ${CSV_FILE}; then
-       rm -rf ${TMP_DIRS}
-       exit 1
-fi
-verbose_output "******** Lustre cluster configuration END **********"
-
-exit 0
diff --git a/lustre/utils/cluster_scripts/gen_clumanager_config.sh b/lustre/utils/cluster_scripts/gen_clumanager_config.sh
deleted file mode 100755 (executable)
index 8469f7d..0000000
+++ /dev/null
@@ -1,379 +0,0 @@
-#!/bin/bash
-#
-# gen_clumanager_config.sh - script for generating the Red Hat's Cluster Manager
-#                           HA software's configuration files
-#
-################################################################################
-
-# Usage
-usage() {
-       cat >&2 <<EOF
-
-Usage:  `basename $0` <-n hostnames> <-d target device> <-s service addresses> 
-                     [-c heartbeat channels] [-o heartbeat options] [-v]
-
-       -n hostnames            the nodenames of the primary node and its fail-
-                               overs
-                               Multiple nodenames are separated by colon (:)
-                               delimeter. The first one is the nodename of the 
-                               primary node, the others are failover nodenames.
-       -d target device        the target device name and type
-                               The name and type are separated by colon (:)
-                               delimeter. The type values are: mgs, mdt, ost or
-                               mgs_mdt.
-       -s service addresses    the IP addresses to failover
-                               Multiple addresses are separated by colon (:)
-                               delimeter.
-       -c heartbeat channels   the methods to send/rcv heartbeats on
-                               The default method is multicast, and multicast_
-                               ipaddress is "225.0.0.11".
-       -o heartbeat options    a "catchall" for other heartbeat configuration 
-                               options
-       -v                      verbose mode
-
-EOF
-       exit 1
-}
-
-# Global variables
-SCRIPTS_PATH=${CLUSTER_SCRIPTS_PATH:-"./"}
-SCRIPT_VERIFY_SRVIP=${SCRIPTS_PATH}$"verify_serviceIP.sh"
-
-LUSTRE_SRV_SCRIPT=$"/etc/rc.d/init.d/lustre"   # service script for lustre
-
-TMP_DIR=$"/tmp/clumanager/"            # temporary directory
-CLUMGR_DIR=$"/etc/"                    # CluManager configuration directory
-
-CONFIG_CMD=$"redhat-config-cluster-cmd"
-
-declare -a NODE_NAMES                  # node names in the failover group
-declare -a SRV_IPADDRS                 # service IP addresses
-
-# Get and check the positional parameters
-while getopts "n:d:s:c:o:v" OPTION; do
-       case $OPTION in
-        n)
-               HOSTNAME_OPT=$OPTARG 
-               HOSTNAME_NUM=`echo ${HOSTNAME_OPT} | awk -F":" '{print NF}'`
-               if [ ${HOSTNAME_NUM} -lt 2 ]; then
-                       echo >&2 $"`basename $0`: Lack failover nodenames!"
-                       usage
-               fi
-               ;;
-        d)
-               DEVICE_OPT=$OPTARG 
-               TARGET_DEV=`echo ${DEVICE_OPT} | awk -F":" '{print $1}'`
-               TARGET_TYPE=`echo ${DEVICE_OPT} | awk -F":" '{print $2}'`
-               if [ -z "${TARGET_TYPE}" ]; then
-                       echo >&2 $"`basename $0`: Lack target device type!"
-                       usage
-               fi
-               if [ "${TARGET_TYPE}" != "mgs" ]&&[ "${TARGET_TYPE}" != "mdt" ]\
-               &&[ "${TARGET_TYPE}" != "ost" ]&&[ "${TARGET_TYPE}" != "mgs_mdt" ]
-               then
-                       echo >&2 $"`basename $0`: Invalid target device type" \
-                                 "- ${TARGET_TYPE}!"
-                       usage
-               fi
-               ;;
-        s)
-               SRVADDR_OPT=$OPTARG 
-               ;;
-        c)
-               HBCHANNEL_OPT=$OPTARG
-               HBCHANNEL_OPT=`echo "${HBCHANNEL_OPT}" | sed 's/^"//' \
-                               | sed 's/"$//'` 
-               if [ -n "${HBCHANNEL_OPT}" ] \
-               && [ "${HBCHANNEL_OPT}" = "${HBCHANNEL_OPT#*broadcast*}" ] \
-               && [ "${HBCHANNEL_OPT}" = "${HBCHANNEL_OPT#*multicast*}" ]; then
-                       echo >&2 $"`basename $0`: Invalid Heartbeat channel" \
-                                 "- ${HBCHANNEL_OPT}!"
-                       usage
-               fi
-               ;;
-        o)
-               HBOPT_OPT=$OPTARG 
-               HBOPT_OPT=`echo "${HBOPT_OPT}" | sed 's/^"//' | sed 's/"$//'`
-               ;;
-       v) 
-               VERBOSE_OPT=$"yes"
-               ;;
-        ?) 
-               usage 
-       esac
-done
-
-# Check the required parameters
-if [ -z "${HOSTNAME_OPT}" ]; then
-       echo >&2 $"`basename $0`: Lack -n option!"
-       usage
-fi
-
-if [ -z "${DEVICE_OPT}" ]; then
-       echo >&2 $"`basename $0`: Lack -d option!"
-       usage
-fi
-
-if [ -z "${SRVADDR_OPT}" ]; then
-       echo >&2 $"`basename $0`: Lack -s option!"
-       usage
-fi
-
-# Output verbose informations
-verbose_output() {
-       if [ "${VERBOSE_OPT}" = "yes" ]; then
-               echo "`basename $0`: $*"
-       fi
-       return 0
-}
-
-# get_nodenames
-#
-# Get all the node names in this failover group
-get_nodenames() {
-       PRIM_NODENAME=`echo ${HOSTNAME_OPT} | awk -F":" '{print $1}'`
-
-       declare -i idx
-       local nodename_str nodename
-
-       nodename_str=`echo ${HOSTNAME_OPT}|awk '{split($HOSTNAME_OPT, a, ":")}\
-                     END {for (i in a) print a[i]}'`
-       idx=0
-       for nodename in ${nodename_str}
-        do
-               NODE_NAMES[idx]=${nodename}
-               idx=$idx+1
-        done
-
-       return 0
-}
-
-# get_check_srvIPaddrs
-#
-# Get and check all the service IP addresses in this failover group
-get_check_srvIPaddrs() {
-       declare -i idx
-       declare -i i
-       local srvIPaddr_str srvIPaddr
-
-       srvIPaddr_str=`echo ${SRVADDR_OPT}|awk '{split($SRVADDR_OPT, a, ":")}\
-                     END {for (i in a) print a[i]}'`
-       idx=0
-       for srvIPaddr in ${srvIPaddr_str}
-        do
-               SRV_IPADDRS[idx]=${srvIPaddr}
-               idx=$idx+1
-        done
-
-       for ((idx = 0; idx < ${#SRV_IPADDRS[@]}; idx++)); do
-         for ((i = 0; i < ${#NODE_NAMES[@]}; i++)); do
-           # Check service IP address
-           verbose_output "Verifying service IP ${SRV_IPADDRS[idx]} and" \
-                          "real IP of host ${NODE_NAMES[i]} are in the" \
-                          "same subnet..."
-           if ! ${SCRIPT_VERIFY_SRVIP} ${SRV_IPADDRS[idx]} ${NODE_NAMES[i]}
-           then
-             return 1
-           fi
-           verbose_output "OK"
-         done
-       done
-
-       return 0
-}
-
-# stop_clumanager
-#
-# Run pdsh command to stop each node's clumanager service
-stop_clumanager() {
-       declare -i idx
-       local nodename_str=${PRIM_NODENAME}
-
-       for ((idx = 1; idx < ${#NODE_NAMES[@]}; idx++)); do
-               nodename_str=${nodename_str}$","${NODE_NAMES[idx]}
-       done
-
-       ${PDSH} -w ${nodename_str} /sbin/service clumanager stop
-       if [ $? -ne 0 ]; then
-               echo >&2 "`basename $0`: stop_clumanager() error:"\
-                        "Fail to execute pdsh command!"
-               return 1
-       fi
-
-       return 0
-}
-
-# check_retval retval
-#
-# Check the return value of redhat-config-cluster-cmd
-check_retval() {
-       if [ $1 -ne 0 ]; then
-               echo >&2 "`basename $0`: Fail to run ${CONFIG_CMD}!"
-               return 1
-       fi
-
-       return 0
-}
-
-# gen_cluster_xml
-#
-# Run redhat-config-cluster-cmd to create the cluster.xml file
-gen_cluster_xml() {
-       declare -i idx
-       local mcast_IPaddr
-       local hbopt_str hbopt
-
-       # Run redhat-config-cluster-cmd to generate cluster.xml
-       # Add clumembd tag
-       if [ "${HBCHANNEL_OPT}" != "${HBCHANNEL_OPT#*broadcast*}" ]; then
-               ${CONFIG_CMD} --clumembd --broadcast=yes
-               if ! check_retval $?; then
-                       return 1
-               fi
-       elif [ "${HBCHANNEL_OPT}" != "${HBCHANNEL_OPT#*multicast*}" ]; then
-               mcast_IPaddr=`echo ${HBCHANNEL_OPT} | awk '{print $2}'`
-               if [ -n "${mcast_IPaddr}" ]; then
-                       ${CONFIG_CMD} --clumembd --multicast=yes\
-                                     --multicast_ipaddress=${mcast_IPaddr}
-                       if ! check_retval $?; then
-                               return 1
-                       fi
-               fi
-       fi
-
-       # Add cluster tag
-       ${CONFIG_CMD} --cluster --name='${TARGET_TYPE} failover group'
-       if ! check_retval $?; then
-               return 1
-       fi
-
-       # Add member tag
-       for ((idx = 0; idx < ${#NODE_NAMES[@]}; idx++)); do
-               ${CONFIG_CMD} --add_member --name=${NODE_NAMES[idx]}
-               if ! check_retval $?; then
-                       return 1
-               fi
-       done
-
-       # Add failoverdomain tag
-       ${CONFIG_CMD} --add_failoverdomain --name=${TARGET_TYPE}-domain
-       if ! check_retval $?; then
-               return 1
-       fi
-
-       for ((idx = 0; idx < ${#NODE_NAMES[@]}; idx++)); do
-               ${CONFIG_CMD} --failoverdomain=${TARGET_TYPE}-domain\
-                       --add_failoverdomainnode --name=${NODE_NAMES[idx]}
-               if ! check_retval $?; then
-                       return 1
-               fi
-       done
-
-       # Add service tag
-       ${CONFIG_CMD} --add_service --name=${TARGET_TYPE}-service
-       if ! check_retval $?; then
-               return 1
-       fi
-
-       ${CONFIG_CMD} --service=${TARGET_TYPE}-service \
-               --userscript=${LUSTRE_SRV_SCRIPT}
-       if ! check_retval $?; then
-               return 1
-       fi
-
-       ${CONFIG_CMD} --service=${TARGET_TYPE}-service \
-               --failoverdomain=${TARGET_TYPE}-domain
-       if ! check_retval $?; then
-               return 1
-       fi
-
-       for ((idx = 0; idx < ${#SRV_IPADDRS[@]}; idx++)); do
-               ${CONFIG_CMD} --service=mgs-service \
-                       --add_service_ipaddress --ipaddress=${SRV_IPADDRS[idx]}
-               if ! check_retval $?; then
-                       return 1
-               fi
-       done
-
-       # Add other tags
-       if [ -n "${HBOPT_OPT}"]; then
-               hbopt_str=`echo ${HBOPT_OPT}|awk '{split($HBOPT_OPT, a, ":")}\
-                         END {for (i in a) print a[i]}'`
-               idx=0
-               for hbopt in ${hbopt_str}
-               do
-                       ${CONFIG_CMD} ${hbopt}
-                       if ! check_retval $?; then
-                               return 1
-                       fi
-                       idx=$idx+1
-               done
-       fi
-
-       return 0
-}
-
-# create_config
-#
-# Create the cluster.xml file and scp it to the each node's /etc/
-create_config() {
-       CONFIG_PRIMNODE=${TMP_DIR}$"cluster.xml."${PRIM_NODENAME}
-       declare -i idx
-
-       if [ -e ${CONFIG_PRIMNODE} ]; then
-               verbose_output "${CONFIG_PRIMNODE} already exists."
-               return 0
-       fi
-
-       # Run redhat-config-cluster-cmd to generate cluster.xml
-       verbose_output "Creating cluster.xml file for" \
-                      "${PRIM_NODENAME} failover group hosts..."
-       if ! gen_cluster_xml; then
-               return 1
-       fi
-       verbose_output "OK"
-
-       /bin/cp -f ${CLUMGR_DIR}cluster.xml ${CONFIG_PRIMNODE}
-
-       # scp the cluster.xml file to all the nodes
-       verbose_output "Remote copying cluster.xml file to" \
-                      "${PRIM_NODENAME} failover group hosts..."
-       for ((idx = 0; idx < ${#NODE_NAMES[@]}; idx++)); do
-               touch ${TMP_DIR}$"cluster.xml."${NODE_NAMES[idx]}
-               scp ${CONFIG_PRIMNODE} ${NODE_NAMES[idx]}:${CLUMGR_DIR}cluster.xml
-               if [ $? -ne 0 ]; then
-                       echo >&2 "`basename $0`: Fail to scp cluster.xml file"\
-                                "to node ${NODE_NAMES[idx]}!"
-                       return 1
-               fi
-       done
-       verbose_output "OK"
-
-       return 0
-}
-
-# Main flow
-# Get all the node names
-if ! get_nodenames; then
-       exit 1
-fi
-
-# Get and check all the service IP addresses
-if ! get_check_srvIPaddrs; then
-       exit 1
-fi
-
-# Stop clumanager services
-verbose_output "Stopping clumanager service in the ${PRIM_NODENAME}"\
-              "failover group hosts..."
-if ! stop_clumanager; then
-       exit 1
-fi
-verbose_output "OK"
-
-# Generate configuration files
-if ! create_config; then
-       exit 1
-fi
-
-exit 0
diff --git a/lustre/utils/cluster_scripts/gen_hb_config.sh b/lustre/utils/cluster_scripts/gen_hb_config.sh
deleted file mode 100755 (executable)
index bf66368..0000000
+++ /dev/null
@@ -1,591 +0,0 @@
-#!/bin/bash
-#
-# gen_hb_config.sh - script for generating the Heartbeat HA software's
-#                   configuration files
-#
-###############################################################################
-
-# Usage
-usage() {
-       cat >&2 <<EOF
-
-Usage:  `basename $0` <-r HBver> <-n hostnames> <-d target device>
-                     <-c heartbeat channels> <-s service address>
-                     [-o heartbeat options] [-v]
-
-       -r HBver                the version of Heartbeat software
-                               The Heartbeat software versions which are curr-
-                               ently supported are: hbv1 (Heartbeat version 1) 
-                               and hbv2 (Heartbeat version 2).
-       -n hostnames            the nodenames of the primary node and its fail-
-                               overs
-                               Multiple nodenames are separated by colon (:)
-                               delimeter. The first one is the nodename of the 
-                               primary node, the others are failover nodenames.
-       -d target device        the target device name and type
-                               The name and type are separated by colon (:)
-                               delimeter. The type values are: mgs, mdt, ost or
-                               mgs_mdt.
-       -c heartbeat channels   the methods and devices to send/rcv heartbeats on
-       -s service address      the IP address to failover
-       -o heartbeat options    a "catchall" for other heartbeat configuration 
-                               options
-       -v                      verbose mode
-
-EOF
-       exit 1
-}
-
-# Global variables
-SCRIPTS_PATH=${CLUSTER_SCRIPTS_PATH:-"./"}
-SCRIPT_VERIFY_SRVIP=${SCRIPTS_PATH}$"verify_serviceIP.sh"
-
-LUSTRE_SRV_SCRIPT=$"lustre"            # service script for lustre
-MON_SRV_SCRIPT=$"mon"                  # service script for mon
-LUSTRE_MON_SCRIPT=$"simple.health_check.monitor"
-LUSTRE_ALERT_SCRIPT=$"fail_lustre.alert"
-CIB_GEN_SCRIPT=$"/usr/lib/heartbeat/cts/haresources2cib.py"
-
-TMP_DIR=$"/tmp/heartbeat/"             # temporary directory
-HACF_TEMP=${TMP_DIR}$"ha.cf.temp"
-AUTHKEYS_TEMP=${TMP_DIR}$"authkeys.temp"
-MONCF_TEMP=${TMP_DIR}$"mon.cf.temp"
-
-HA_DIR=$"/etc/ha.d/"                   # Heartbeat configuration directory
-MON_DIR=$"/etc/mon/"                   # mon configuration directory
-CIB_DIR=$"/var/lib/heartbeat/crm/"     # cib.xml directory
-
-HBVER_HBV1=$"hbv1"                     # Heartbeat version 1
-HBVER_HBV2=$"hbv2"                     # Heartbeat version 2
-
-declare -a NODE_NAMES                  # node names in the failover group
-
-# Get and check the positional parameters
-while getopts "r:n:d:c:s:o:v" OPTION; do
-       case $OPTION in
-       r) 
-               HBVER_OPT=$OPTARG
-               if [ "${HBVER_OPT}" != "${HBVER_HBV1}" ] \
-               && [ "${HBVER_OPT}" != "${HBVER_HBV2}" ]; then
-                       echo >&2 $"`basename $0`: Invalid Heartbeat software" \
-                                 "version - ${HBVER_OPT}!"
-                       usage
-               fi
-               ;;
-        n)
-               HOSTNAME_OPT=$OPTARG 
-               HOSTNAME_NUM=`echo ${HOSTNAME_OPT} | awk -F":" '{print NF}'`
-               if [ ${HOSTNAME_NUM} -lt 2 ]; then
-                       echo >&2 $"`basename $0`: Lack failover nodenames!"
-                       usage
-               fi
-               ;;
-        d)
-               DEVICE_OPT=$OPTARG 
-               TARGET_DEV=`echo ${DEVICE_OPT} | awk -F":" '{print $1}'`
-               TARGET_TYPE=`echo ${DEVICE_OPT} | awk -F":" '{print $2}'`
-               if [ -z "${TARGET_TYPE}" ]; then
-                       echo >&2 $"`basename $0`: Lack target device type!"
-                       usage
-               fi
-               if [ "${TARGET_TYPE}" != "mgs" ]&&[ "${TARGET_TYPE}" != "mdt" ]\
-               &&[ "${TARGET_TYPE}" != "ost" ]&&[ "${TARGET_TYPE}" != "mgs_mdt" ]
-               then
-                       echo >&2 $"`basename $0`: Invalid target device type" \
-                                 "- ${TARGET_TYPE}!"
-                       usage
-               fi
-               ;;
-        c)
-               HBCHANNEL_OPT=$OPTARG 
-               HBCHANNEL_OPT=`echo "${HBCHANNEL_OPT}" | sed 's/^"//' \
-                              | sed 's/"$//'`
-               if [ "${HBCHANNEL_OPT}" = "${HBCHANNEL_OPT#*serial*}" ] \
-               && [ "${HBCHANNEL_OPT}" = "${HBCHANNEL_OPT#*bcast*}" ] \
-               && [ "${HBCHANNEL_OPT}" = "${HBCHANNEL_OPT#*ucast*}" ] \
-               && [ "${HBCHANNEL_OPT}" = "${HBCHANNEL_OPT#*mcast*}" ]; then
-                       echo >&2 $"`basename $0`: Invalid Heartbeat channel" \
-                                 "- ${HBCHANNEL_OPT}!"
-                       usage
-               fi
-               ;;
-        s)
-               SRVADDR_OPT=$OPTARG 
-               ;;
-        o)
-               HBOPT_OPT=$OPTARG 
-               HBOPT_OPT=`echo "${HBOPT_OPT}" | sed 's/^"//' | sed 's/"$//'`
-               ;;
-       v) 
-               VERBOSE_OPT=$"yes"
-               ;;
-        ?) 
-               usage 
-       esac
-done
-
-# Check the required parameters
-if [ -z "${HBVER_OPT}" ]; then
-       echo >&2 $"`basename $0`: Lack -r option!"
-       usage
-fi
-
-if [ -z "${HOSTNAME_OPT}" ]; then
-       echo >&2 $"`basename $0`: Lack -n option!"
-       usage
-fi
-
-if [ -z "${DEVICE_OPT}" ]; then
-       echo >&2 $"`basename $0`: Lack -d option!"
-       usage
-fi
-
-if [ -z "${HBCHANNEL_OPT}" ]; then
-       echo >&2 $"`basename $0`: Lack -c option!"
-       usage
-fi
-
-if [ -z "${SRVADDR_OPT}" ]; then
-       echo >&2 $"`basename $0`: Lack -s option!"
-       usage
-fi
-
-if [ "${HBVER_OPT}" = "${HBVER_HBV1}" -a ${HOSTNAME_NUM} -gt 2 ]; then
-       echo >&2 $"`basename $0`: Heartbeat version 1 can only support 2 nodes!"
-       usage
-fi
-
-# Output verbose informations
-verbose_output() {
-       if [ "${VERBOSE_OPT}" = "yes" ]; then
-               echo "`basename $0`: $*"
-       fi
-       return 0
-}
-
-# get_nodenames
-#
-# Get all the node names in this failover group
-get_nodenames() {
-       PRIM_NODENAME=`echo ${HOSTNAME_OPT} | awk -F":" '{print $1}'`
-
-       declare -i idx
-       local nodename_str nodename
-
-       nodename_str=`echo ${HOSTNAME_OPT}|awk '{split($HOSTNAME_OPT, a, ":")}\
-                     END {for (i in a) print a[i]}'`
-       idx=0
-       for nodename in ${nodename_str}
-        do
-               NODE_NAMES[idx]=${nodename}
-               idx=$idx+1
-        done
-
-       return 0
-}
-
-# check_srvIPaddr
-#
-# Check service IP address in this failover group
-check_srvIPaddr() {
-       declare -i idx
-
-       for ((idx = 0; idx < ${#NODE_NAMES[@]}; idx++)); do
-               # Check service IP address
-               verbose_output "Verifying service IP ${SRVADDR_OPT} and" \
-                          "real IP of host ${NODE_NAMES[idx]} are in the" \
-                          "same subnet..."
-               if ! ${SCRIPT_VERIFY_SRVIP} ${SRVADDR_OPT} ${NODE_NAMES[idx]}
-               then
-                       return 1
-               fi
-               verbose_output "OK"
-       done
-
-       return 0
-}
-
-# stop_heartbeat
-#
-# Run pdsh command to stop each node's heartbeat service
-stop_heartbeat() {
-       declare -i idx
-       local nodename_str=${PRIM_NODENAME}
-
-       for ((idx = 1; idx < ${#NODE_NAMES[@]}; idx++)); do
-               nodename_str=${nodename_str}$","${NODE_NAMES[idx]}
-       done
-
-       ${PDSH} -w ${nodename_str} /sbin/service heartbeat stop
-       if [ $? -ne 0 ]; then
-               echo >&2 "`basename $0`: stop_heartbeat() error:"\
-                        "Fail to execute pdsh command!"
-               return 1
-       fi
-
-       return 0
-}
-
-# create_template
-#
-# Create the templates for ha.cf, authkeys and mon.cf files
-create_template() {
-       /bin/mkdir -p ${TMP_DIR}
-
-       # Create the template for ha.cf
-       if [ "${HBVER_OPT}" = "${HBVER_HBV1}" ]; then
-               cat >${HACF_TEMP} <<EOF
-debugfile /var/log/ha-debug
-logfile /var/log/ha-log
-logfacility     local0
-keepalive 2
-deadtime 15
-warntime 10
-initdead 120
-
-EOF
-       elif [ "${HBVER_OPT}" = "${HBVER_HBV2}" ]; then
-               cat >${HACF_TEMP} <<EOF
-logfacility     daemon
-use_logd        yes
-keepalive 2
-deadtime 15
-warntime 10
-initdead 120
-
-EOF
-       fi
-
-       # Create the template for authkeys
-       if [ ! -s ${AUTHKEYS_TEMP} ]; then
-               cat >${AUTHKEYS_TEMP} <<EOF
-auth 1
-1 sha1 HelloLustre!
-EOF
-       fi
-
-       # Create the template for mon.cf 
-       if [ ! -s ${MONCF_TEMP} ]; then
-               cat >${MONCF_TEMP} <<EOF
-cfbasedir   = /etc/mon
-alertdir   = /usr/lib/mon/alert.d
-mondir     = /usr/lib/mon/mon.d
-statedir    = /usr/lib/mon/state.d
-logdir    = /usr/lib/mon/log.d
-dtlogfile    = /usr/lib/mon/log.d/downtime.log
-maxprocs    = 20
-histlength  = 100
-randstart   = 60s
-
-authtype = getpwnam
-
-EOF
-       fi
-
-       return 0
-}
-
-# gen_udpport
-#
-# Generate the UDP port number for Heartbeat bcast/ucast communication
-# The default value for udpport option in ha.cf is 694. If there are multiple 
-# bcast failover groups on the same subnet, this value should be different for 
-# each of the failover groups.
-gen_udpport() {
-       local port_file
-       declare -i default_port=694
-       declare -i dynamic_port=49152
-       declare -i port=0
-       declare -i tmp_port
-       declare -i idx
-
-       UDPPORT_PRIMNODE=${TMP_DIR}$"udpport."${PRIM_NODENAME}
-
-       if [ -s ${UDPPORT_PRIMNODE} ]; then
-               cat ${UDPPORT_PRIMNODE}
-               return 0
-       fi
-
-       # Get the current maximum UDP port number in the cluster
-       for port_file in `ls ${TMP_DIR}udpport.*`
-       do
-               if [ $? -ne 0 ]; then
-                       break
-               fi
-               tmp_port=$(cat ${port_file})
-               if [ $? -ne 0 ]; then
-                       break
-               fi
-               
-               if [ ${tmp_port} -gt ${port} ]; then
-                       port=${tmp_port}
-               fi
-       done
-
-       # Generate and check a new UDP port number
-       if [ ${port} -eq 0 ]; then
-               port=${default_port}
-       elif [ ${port} -eq ${default_port} ]; then
-               port=${dynamic_port}
-       else
-               port=${port}+1
-               if [ ${port} -gt 65535 ]; then
-                       echo >&2 $"`basename $0`: Invalid UDP port" \
-                                 "- ${port}!"
-                       return 1
-               fi
-       fi
-
-        # Add the UDP port number into each failover node's udpport file
-        for ((idx = 0; idx < ${#NODE_NAMES[@]}; idx++)); do
-                UDPPORT_NODE=${TMP_DIR}$"udpport."${NODE_NAMES[idx]}
-               echo ${port} > ${UDPPORT_NODE}
-        done
-
-       echo ${port}
-       return 0
-}
-
-# create_hacf
-#
-# Create the ha.cf file and scp it to each node's /etc/ha.d/
-create_hacf() {
-       HACF_PRIMNODE=${TMP_DIR}$"ha.cf."${PRIM_NODENAME}
-
-       declare -i idx
-
-       if [ -s ${HACF_PRIMNODE} ]; then
-               # The ha.cf file for the primary node has already existed.
-               verbose_output "${HACF_PRIMNODE} already exists."
-               return 0
-       fi
-
-       /bin/cp -f ${HACF_TEMP} ${HACF_PRIMNODE}
-
-       if [ "${HBCHANNEL_OPT}" != "${HBCHANNEL_OPT#*bcast*}" ] \
-       || [ "${HBCHANNEL_OPT}" != "${HBCHANNEL_OPT#*ucast*}" ]; then
-               UDPPORT_OPT=$(gen_udpport)
-               if [ $? -ne 0 ]; then
-                       return 1
-               fi      
-               echo "udpport ${UDPPORT_OPT}" >> ${HACF_PRIMNODE}
-       fi
-
-       if [ "${HBCHANNEL_OPT}" != "${HBCHANNEL_OPT#*serial*}" ]; then
-               echo "baud    19200" >> ${HACF_PRIMNODE}
-       fi
-
-       echo ${HBCHANNEL_OPT} | awk '{split($HBCHANNEL_OPT, a, ":")} \
-       END {for (i in a) print a[i]}' >> ${HACF_PRIMNODE}
-
-        for ((idx = 0; idx < ${#NODE_NAMES[@]}; idx++)); do
-               echo "node    ${NODE_NAMES[idx]}" >> ${HACF_PRIMNODE}
-        done
-
-       echo ${HBOPT_OPT} | awk '{split($HBOPT_OPT, a, ":")} \
-       END {for (i in a) print a[i]}' >> ${HACF_PRIMNODE}
-
-       # scp ha.cf file to all the nodes
-       for ((idx = 0; idx < ${#NODE_NAMES[@]}; idx++)); do
-               touch ${TMP_DIR}$"ha.cf."${NODE_NAMES[idx]}
-               scp ${HACF_PRIMNODE} ${NODE_NAMES[idx]}:${HA_DIR}ha.cf
-               if [ $? -ne 0 ]; then
-                       echo >&2 "`basename $0`: Fail to scp ha.cf file"\
-                                "to node ${NODE_NAMES[idx]}!"
-                       return 1
-               fi
-       done
-
-       return 0
-}
-
-# create_haresources
-#
-# Create the haresources file and scp it to the each node's /etc/ha.d/
-create_haresources() {
-       HARES_PRIMNODE=${TMP_DIR}$"haresources."${PRIM_NODENAME}
-       declare -i idx
-
-       if [ -s ${HARES_PRIMNODE} ]; then
-               # The haresources file for the primary node has already existed
-               verbose_output "${HARES_PRIMNODE} already exists."
-               return 0
-       fi
-               
-       # Add the resource group line into the haresources file
-       echo "${PRIM_NODENAME} ${SRVADDR_OPT} "\
-            "${LUSTRE_SRV_SCRIPT}::${TARGET_TYPE}::${TARGET_DEV} "\
-            "${MON_SRV_SCRIPT}" > ${HARES_PRIMNODE}
-
-       # Generate the cib.xml file
-       if [ "${HBVER_OPT}" = "${HBVER_HBV2}" ]; then
-               CIB_PRIMNODE=${TMP_DIR}$"cib.xml."${PRIM_NODENAME}
-               python ${CIB_GEN_SCRIPT} ${HARES_PRIMNODE} > ${CIB_PRIMNODE}
-               if [ $? -ne 0 ]; then
-                       echo >&2 "`basename $0`: Fail to generate cib.xml file"\
-                                "for node ${PRIM_NODENAME}!"
-                       return 1
-               fi
-       fi
-
-       # scp the haresources file or cib.xml file
-       for ((idx = 0; idx < ${#NODE_NAMES[@]}; idx++)); do
-               touch ${TMP_DIR}$"haresources."${NODE_NAMES[idx]}
-               if [ "${HBVER_OPT}" = "${HBVER_HBV2}" ]; then
-                       scp ${CIB_PRIMNODE} ${NODE_NAMES[idx]}:${CIB_DIR}cib.xml
-               else
-                       scp ${HARES_PRIMNODE} ${NODE_NAMES[idx]}:${HA_DIR}haresources
-               fi
-
-               if [ $? -ne 0 ]; then
-                       echo >&2 "`basename $0`: Fail to scp haresources file"\
-                                "to node ${NODE_NAMES[idx]}!"
-                       return 1
-               fi
-       done
-
-       return 0
-}
-
-# create_authkeys
-#
-# Create the authkeys file and scp it to the each node's /etc/ha.d/
-create_authkeys() {
-       AUTHKEYS_PRIMNODE=${TMP_DIR}$"authkeys."${PRIM_NODENAME}
-       declare -i idx
-
-       if [ -e ${AUTHKEYS_PRIMNODE} ]; then
-               verbose_output "${AUTHKEYS_PRIMNODE} already exists."
-               return 0
-       fi
-
-       # scp the authkeys file to all the nodes
-       for ((idx = 0; idx < ${#NODE_NAMES[@]}; idx++)); do
-               touch ${TMP_DIR}$"authkeys."${NODE_NAMES[idx]}
-               scp ${AUTHKEYS_TEMP} ${NODE_NAMES[idx]}:${HA_DIR}authkeys
-               if [ $? -ne 0 ]; then
-                       echo >&2 "`basename $0`: Fail to scp authkeys file"\
-                                "to node ${NODE_NAMES[idx]}!"
-                       return 1
-               fi
-       done
-
-       return 0
-}
-
-# create_moncf
-#
-# Create the mon.cf file and scp it to the each node's /etc/mon/
-create_moncf() {
-       MONCF_PRIMNODE=${TMP_DIR}$"mon.cf."${PRIM_NODENAME}
-       declare -i idx
-       local hostgroup_str=$"hostgroup ${TARGET_TYPE}-group"
-
-       if [ -e ${MONCF_PRIMNODE} ]; then
-               verbose_output "${MONCF_PRIMNODE} already exists."
-               return 0
-       fi
-
-       /bin/cp -f ${MONCF_TEMP} ${MONCF_PRIMNODE}
-
-       for ((idx = 0; idx < ${#NODE_NAMES[@]}; idx++)); do
-               hostgroup_str=${hostgroup_str}$" "${NODE_NAMES[idx]}
-       done
-
-       echo ${hostgroup_str} >> ${MONCF_PRIMNODE}
-
-       cat >>${MONCF_PRIMNODE} <<EOF
-
-watch ${TARGET_TYPE}-group
-    service ${LUSTRE_SRV_SCRIPT}
-        description Lustre health check
-        interval 1m
-        monitor ${LUSTRE_MON_SCRIPT} -o ${TARGET_TYPE}
-        period wd {Sat-Sun}
-            alert ${LUSTRE_ALERT_SCRIPT}
-
-EOF
-       # scp the mon.cf file to all the nodes
-       for ((idx = 0; idx < ${#NODE_NAMES[@]}; idx++)); do
-               touch ${TMP_DIR}$"mon.cf."${NODE_NAMES[idx]}
-               scp ${MONCF_PRIMNODE} ${NODE_NAMES[idx]}:${MON_DIR}mon.cf
-               if [ $? -ne 0 ]; then
-                       echo >&2 "`basename $0`: Fail to scp mon.cf file"\
-                                "to node ${NODE_NAMES[idx]}!"
-                       return 1
-               fi
-       done
-
-       return 0
-}
-
-# generate_config
-#
-# Generate the configuration files for Heartbeat and scp them to all the nodes
-generate_config() {
-       if ! create_template; then
-               return 1
-       fi
-
-       verbose_output "Creating and remote copying ha.cf file to"\
-                      "${PRIM_NODENAME} failover group hosts..." 
-       if ! create_hacf; then
-               return 1
-       fi
-       verbose_output "OK"
-
-       if [ "${HBVER_OPT}" = "${HBVER_HBV1}" ]; then
-               verbose_output "Creating and remote copying haresources file"\
-                              "to ${PRIM_NODENAME} failover group hosts..."
-       else
-               verbose_output "Creating and remote copying cib.xml file"\
-                              "to ${PRIM_NODENAME} failover group hosts..."
-       fi
-
-       if ! create_haresources; then
-               return 1
-       fi
-       verbose_output "OK"
-
-       verbose_output "Creating and remote copying authkeys file to" \
-                      "${PRIM_NODENAME} failover group hosts..."
-       if ! create_authkeys; then
-               return 1
-       fi
-       verbose_output "OK"
-
-       verbose_output "Creating and remote copying mon.cf file to" \
-                      "${PRIM_NODENAME} failover group hosts..."
-       if ! create_moncf; then
-               return 1
-       fi
-       verbose_output "OK"
-
-       return 0
-}
-
-# Main flow
-# Get all the node names
-if ! get_nodenames; then
-       exit 1
-fi
-
-# Check service IP address
-if ! check_srvIPaddr; then
-       exit 1
-fi
-
-# Stop heartbeat services
-verbose_output "Stopping heartbeat service in the ${PRIM_NODENAME}"\
-              "failover group hosts..."
-if ! stop_heartbeat; then
-       exit 1
-fi
-verbose_output "OK"
-
-# Generate configuration files
-if ! generate_config; then
-       exit 1
-fi
-
-exit 0
diff --git a/lustre/utils/cluster_scripts/module_config.sh b/lustre/utils/cluster_scripts/module_config.sh
deleted file mode 100755 (executable)
index baff1eb..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-#!/bin/bash
-#
-# module_config.sh - add lustre options lines into modprobe.conf or 
-#   modules.conf
-#
-#################################################################################
-
-# Check the kernel version
-KERNEL_VERSION=`uname -r`
-KERNEL_VERSION=${KERNEL_VERSION:0:3}
-
-if [ "${KERNEL_VERSION}" = "2.4" ]; then
-       MODULE_CONF=/etc/modules.conf
-else
-       MODULE_CONF=/etc/modprobe.conf
-fi
-
-read -r NETWORKS
-MODLINES_FILE=/tmp/modlines$$.txt
-START_MARKER=$"# start lustre config"
-END_MARKER=$"# end lustre config"
-
-# Generate a temp file contains lnet options lines 
-generate_lnet_lines() {
-       local LNET_LINE TMP_LINE
-
-       TMP_LINE="${NETWORKS}"
-
-       echo ${START_MARKER} > ${MODLINES_FILE}
-       while true; do
-               LNET_LINE=${TMP_LINE%%\\n*}
-               echo ${LNET_LINE} >> ${MODLINES_FILE}
-
-               TMP_LINE=${TMP_LINE#*\\n}
-
-               if [ "${TMP_LINE}" == "${LNET_LINE}" ]; then
-                       break
-               fi
-       done
-       echo ${END_MARKER} >> ${MODLINES_FILE}
-
-       #echo "--------------${MODLINES_FILE}--------------"
-       #cat ${MODLINES_FILE}
-       #echo -e "------------------------------------------\n"
-
-       return 0
-}
-
-if ! generate_lnet_lines; then
-       exit 1  
-fi
-
-# Add lnet options lines to the module configuration file
-if [ -e ${MODULE_CONF} ]; then
-       # Delete the old options
-       sed -i "/${START_MARKER}/,/${END_MARKER}/d" ${MODULE_CONF}
-fi
-
-cat ${MODLINES_FILE} >> ${MODULE_CONF}
-rm -f ${MODLINES_FILE}
-exit 0
diff --git a/lustre/utils/cluster_scripts/verify_cluster_net.sh b/lustre/utils/cluster_scripts/verify_cluster_net.sh
deleted file mode 100755 (executable)
index f5f59c4..0000000
+++ /dev/null
@@ -1,296 +0,0 @@
-#!/bin/bash
-#
-# verify_cluster_net.sh - script for Lustre cluster network verification
-#
-###############################################################################
-
-# Usage
-usage() {
-       cat >&2 <<EOF
-
-Usage: `basename $0` [-v] <csv file>
-
-       -v              verbose mode
-       csv file        a spreadsheet that contains configuration parameters 
-                       (separated by commas) for each target in a Lustre cl-
-                       uster, the first field of each line is the host name 
-                       of the cluster node
-
-EOF
-       exit 1
-}
-
-# Get and check the positional parameters
-while getopts "v" OPTION; do
-       case $OPTION in
-       v) 
-               VERBOSE_OPT=$"yes"
-               ;;
-        ?) 
-               usage 
-       esac
-done
-
-# Toss out the parameters we've already processed
-shift  `expr $OPTIND - 1`
-
-# Here we expect the csv file
-if [ $# -eq 0 ]; then
-       echo >&2 $"`basename $0`: Lack csv file!"
-       usage
-fi
-
-# Global variables
-CSV_FILE=$1
-declare -a HOST_NAMES
-declare -a HOST_IPADDRS
-
-# Output verbose informations
-verbose_output() {
-       if [ "${VERBOSE_OPT}" = "yes" ]; then
-               echo "`basename $0`: $*"
-       fi
-       return 0
-}
-
-# Check the csv file
-check_file() {
-       if [ ! -s ${CSV_FILE} ]; then
-                echo >&2 $"`basename $0`: check_file() error: ${CSV_FILE}" \
-                         "does not exist or is empty!"
-                return 1
-        fi
-
-        return 0
-}
-
-# Get the host names from the csv file
-get_hostnames() {
-       local NAME CHECK_STR
-       declare -i i
-
-       # Initialize the HOST_NAMES array
-       for ((i = 0; i < ${#HOST_NAMES[@]}; i++)); do
-               HOST_NAMES[i]=$""
-       done
-
-       CHECK_STR=`egrep -v "([[:space:]]|^)#" ${CSV_FILE} | awk -F, \
-                 '/[[:alnum:]]/{if ($1 !~/[[:alnum:]]/) print $0}'`
-       if [ -n "${CHECK_STR}" ]; then
-                echo >&2 $"`basename $0`: get_hostnames() error: Lack hostname"\
-                         "field in the line - ${CHECK_STR}"
-               return 1
-       fi
-
-       i=0
-       for NAME in `egrep -v "([[:space:]]|^)#" ${CSV_FILE}\
-                   | awk -F, '/[[:alnum:]]/{print $1}'`
-       do
-               HOST_NAMES[i]=${NAME}
-               i=$i+1
-       done
-
-       return 0
-}
-
-# Check whether the host name matches the name in the local /etc/hosts table
-# and whether the IP address according to the host name is correct
-local_check() {
-       # Check argument
-        if [ $# -ne 2 ]; then
-                echo >&2 $"`basename $0`: local_check() error: Lack argument" \
-                         "for function local_check()!"
-                return 1
-        fi
-
-       local RET_STR REAL_NAME
-
-       # Get the IP address according to the host name from /etc/hosts table
-       # of the current host 
-       HOST_IPADDRS[$2]=`egrep "[[:space:]]$1([[:space:]]|$)" /etc/hosts \
-                    | awk '{print $1}'`
-       if [ -z "${HOST_IPADDRS[$2]}" ]; then
-               echo >&2 "`basename $0`: local_check() error: $1 does not" \
-                        "exist in the local /etc/hosts table!"
-               return 1
-       fi
-
-       if [ ${#HOST_IPADDRS[$2]} -gt 15 ]; then
-               echo >&2 "`basename $0`: local_check() error: More than one" \
-                        "IP address line according to $1 in the local" \
-                        "/etc/hosts table!"
-               return 1
-       fi
-
-       # Execute pdsh command to get the real host name
-       RET_STR=`${PDSH} -w ${HOST_IPADDRS[$2]} hostname 2>&1`
-       if [ $? -ne 0 ] || [ "${RET_STR}" != "${RET_STR#*connect:*}" ]; then
-               echo >&2 "`basename $0`: local_check() error: pdsh error:" \
-                        "${RET_STR}"
-               return 1
-       fi
-
-       if [ -z "${RET_STR}" ]; then
-               echo >&2 "`basename $0`: local_check() error: pdsh error:" \
-                        "No results from pdsh! Check the network connectivity"\
-                        "between the local host and ${HOST_IPADDRS[$2]}" \
-                        "or check the two hosts' rcmd module!"
-               return 1
-       fi
-
-       REAL_NAME=`echo ${RET_STR} | awk '{print $2}'`
-       if [ "$1" != "${REAL_NAME}" ]; then
-               echo >&2 "`basename $0`: local_check() error: The real hostname"\
-                        "according to ${HOST_IPADDRS[$2]} is ${REAL_NAME}," \
-                        "not $1! Check the local /etc/hosts table!"
-               return 1
-       fi
-
-       return 0
-}
-
-# Check whether the correct host name and IP address pair matches 
-# the one in the remote /etc/hosts tables
-remote_check() {
-       # Check argument
-        if [ $# -ne 2 ]; then
-                echo >&2 $"`basename $0`: remote_check() error: Lack argument"\
-                         "for function remote_check()!"
-                return 1
-        fi
-
-       declare -i i
-       local RET_STR COMMAND IP_ADDR
-
-       COMMAND=$"egrep \"[[:space:]]$1([[:space:]]|$)\" /etc/hosts"
-
-       # Execute pdsh command to check remote /etc/hosts tables
-       for ((i = 0; i < ${#HOST_NAMES[@]}; i++)); do
-               RET_STR=`${PDSH} -w ${HOST_NAMES[i]} ${COMMAND} 2>&1`
-               if [ $? -ne 0 ] || [ "${RET_STR}" != "${RET_STR#*connect:*}" ]
-               then
-                       echo >&2 "`basename $0`: remote_check() error:" \
-                                "pdsh error: ${RET_STR}"
-                       return 1
-               fi
-
-               IP_ADDR=`echo ${RET_STR} | awk '{print $2}'`
-               if [ -z "${IP_ADDR}" ]; then
-                       echo >&2 "`basename $0`: remote_check() error:" \
-                                "$1 does not exist in the ${HOST_NAMES[i]}'s"\
-                                "/etc/hosts table!"
-                       return 1
-               fi
-
-               if [ "${IP_ADDR}" != "${HOST_IPADDRS[$2]}" ]; then
-                       echo >&2 "`basename $0`: remote_check() error:" \
-                                "IP address ${IP_ADDR} of $1 in the" \
-                                "${HOST_NAMES[i]}'s /etc/hosts is incorrect!"
-                       return 1
-               fi
-               
-       done
-
-       return 0
-}
-
-# Verify forward and reverse network connectivity of the Lustre cluster
-network_check () {
-       # Check argument
-        if [ $# -eq 0 ]; then
-                echo >&2 $"`basename $0`: network_check() error: Lack argument" \
-                         "for function network_check()!"
-                return 1
-        fi
-
-       declare -i i
-       local RET_STR COMMAND REAL_NAME
-
-       # Execute pdsh command to check network connectivity
-       for ((i = 0; i < ${#HOST_NAMES[@]}; i++)); do
-               COMMAND=$"${PDSH} -w ${HOST_NAMES[i]} hostname"
-               RET_STR=`${PDSH} -w $1 ${COMMAND} 2>&1`
-               if [ $? -ne 0 ] || [ "${RET_STR}" != "${RET_STR#*connect:*}" ]
-               then
-                       echo >&2 "`basename $0`: network_check() error:" \
-                                "pdsh error: ${RET_STR}"
-                       return 1
-               fi
-
-               if [ -z "${RET_STR}" ]; then
-                       echo >&2 "`basename $0`: network_check() error:" \
-                                "pdsh error: Nothing get from pdsh! Check" \
-                                "the network connectivity between $1 and" \
-                                "${HOST_NAMES[i]} or the two hosts' rcmd module!"
-                       return 1
-               fi
-
-               REAL_NAME=`echo ${RET_STR} | awk '{print $3}'`
-               if [ "${HOST_NAMES[i]}" != "${REAL_NAME}" ]; then
-                       echo >&2 "`basename $0`: network_check() error:" \
-                                "${RET_STR}"
-                       return 1
-               fi
-       done
-
-       return 0
-}
-
-# Verify forward and reverse network connectivity of the Lustre cluster,
-# and that hostnames match the names in the /etc/hosts tables.
-network_verify() {
-       declare -i i
-
-       # Initialize the HOST_IPADDRS array
-       for ((i = 0; i < ${#HOST_IPADDRS[@]}; i++)); do
-               HOST_IPADDRS[i]=$""
-       done
-
-       # Get all the host names from the csv file
-       if ! get_hostnames; then
-               return 1
-       fi
-
-       # Check whether all the host names match the names in 
-       # all the /etc/hosts tables of the Lustre cluster
-       for ((i = 0; i < ${#HOST_NAMES[@]}; i++)); do
-               verbose_output "Verifying IP address of host" \
-                              "${HOST_NAMES[i]} in the local /etc/hosts..."
-               if ! local_check ${HOST_NAMES[i]} $i; then
-                       return 1
-               fi
-               verbose_output "OK"
-       done
-
-       for ((i = 0; i < ${#HOST_NAMES[@]}; i++)); do
-               verbose_output "Verifying IP address of host" \
-                              "${HOST_NAMES[i]} in the remote /etc/hosts..."
-               if ! remote_check ${HOST_NAMES[i]} $i; then
-                       return 1
-               fi
-               verbose_output "OK"
-       done
-
-       # Verify network connectivity of the Lustre cluster
-       for ((i = 0; i < ${#HOST_NAMES[@]}; i++)); do
-               verbose_output "Verifying network connectivity of host" \
-                              "${HOST_NAMES[i]} to other hosts..."
-               if ! network_check ${HOST_NAMES[i]}; then
-                       return 1
-               fi
-               verbose_output "OK"
-       done
-
-       return 0
-}
-
-# Main flow
-if ! check_file; then
-       exit 1  
-fi
-
-if ! network_verify; then
-       exit 1  
-fi
-
-exit 0
diff --git a/lustre/utils/cluster_scripts/verify_serviceIP.sh b/lustre/utils/cluster_scripts/verify_serviceIP.sh
deleted file mode 100755 (executable)
index cdc749d..0000000
+++ /dev/null
@@ -1,228 +0,0 @@
-#!/bin/bash
-#
-# verify_serviceIP.sh - script for verifying the service IP and the real
-#                      interface IP in a remote host are in the same subnet
-#
-###############################################################################
-
-# Usage
-usage() {
-       cat >&2 <<EOF
-
-Usage:  `basename $0` <service IPaddr> <hostname>
-       
-       service IPaddr          the IP address to failover
-       hostname                the hostname of the remote node
-
-EOF
-       exit 1
-}
-
-# Check arguments
-if [ $# -lt 2 ]; then
-        usage
-fi
-
-#
-# inSameIPsubnet serviceIPaddr interfaceIPaddr mask
-#
-# Given two IP addresses and a subnet mask determine if these IP
-# addresses are in the same subnet. If they are, return 0, else return 1.
-#
-inSameIPsubnet() {
-       declare -i n
-       declare -ia mask 
-       declare -ia ip1 ip2             # IP addresses given
-       declare -i quad1 quad2          # calculated quad words
-
-       #
-       # Remove '.' characters from dotted decimal notation and save
-       # in arrays. i.e.
-       #
-       #       192.168.1.163 -> array[0] = 192
-       #                        array[1] = 168
-       #                        array[2] = 1
-       #                        array[3] = 163
-       #
-       let n=0
-       for quad in $(echo $1 | awk -F. '{print $1 " " $2 " " $3 " " $4}')
-       do
-               ip1[n]=$quad
-               let n=n+1
-       done
-
-       let n=0
-       for quad in $(echo $2 | awk -F. '{print $1 " " $2 " " $3 " " $4}')
-       do
-               ip2[n]=$quad
-               let n=n+1
-       done
-
-       let n=0
-       for quad in $(echo $3 | awk -F. '{print $1 " " $2 " " $3 " " $4}')
-       do
-               mask[n]=$quad
-               let n=n+1
-       done
-
-       #
-       # For each quad word, logically AND the IP address with the subnet
-       # mask to get the network/subnet quad word.  If the resulting
-       # quad words for both IP addresses are the same they are in the 
-       # same IP subnet.
-       #
-       for n in 0 1 2 3
-       do
-               let $((quad1=${ip1[n]} & ${mask[n]}))
-               let $((quad2=${ip2[n]} & ${mask[n]}))
-
-               if [ $quad1 != $quad2 ]; then
-                       echo >&2 $"`basename $0`: Service IP address $1 and"\
-                                 "real interface IP address $2 are in"\
-                                 "different subnets!"
-                       return 1        # in different subnets
-               fi
-       done
-
-       return 0        # in the same subnet, all quad words matched
-}
-
-#
-# findInterface IPaddr hostname
-#
-# Given a target IP address and a hostname, find the interface in which 
-# this address is configured.  If found return 0, if not return 1.  The
-# interface name is returned to stdout.
-#
-findInterface() {
-       declare host 
-       declare line
-       declare intf
-       declare addr
-       declare state
-
-       declare target=$1
-       declare hostname=$2
-
-       {
-       while read host intf line
-       do
-               while read host line
-               do
-                       if [ "$line" = "" ]; then       # go to next interface
-                               continue 2
-                       fi
-
-                       set - $line
-                       addr=
-                       while [ $# -gt 0 ]; do
-                               case $1 in
-                               addr:*)
-                                       addr=${1##addr:}
-                                       if [ -n "$addr" -a "$addr" = "$target" ]
-                                       then
-                                               echo $intf
-                                               return 0
-                                       fi
-                                       ;;
-                               esac
-                               shift
-                       done
-               done
-       done
-       } < <(${PDSH} -w $hostname /sbin/ifconfig)
-
-       echo >&2 "`basename $0`: Cannot find the interface in which" \
-                 "$target is configured in the host $hostname!"
-       return 1
-}
-
-#
-# findNetmask interface hostname
-#
-# Given an interface find the netmask addresses associated with it.
-# Return 0 when found, else return 1. The netmask is returned to stdout.
-#
-findNetmask() {
-       declare line
-       declare addr
-       declare target=$1
-       declare hostname=$2
-
-       while read line
-       do
-               set - $line
-
-               while [ $# -gt 0 ]; do
-                       case $1 in
-                       Mask:*)
-                               echo ${1##*:}   # return netmask addr
-                               return 0 
-                               ;;
-                       esac
-                       shift
-               done
-       done < <(${PDSH} -w $hostname /sbin/ifconfig $target)
-
-       echo >&2 "`basename $0`: Cannot find the netmask associated with" \
-                 "the interface $target in the host $hostname!"
-       return 1 
-}
-
-#
-# check_srvIPaddr serviceIPaddr hostname
-#
-# Given a service IP address and hostname, check whether the service IP address
-# and the real interface IP address of hostname are in the same subnet. 
-# If they are, return 0, else return 1.
-#
-check_srvIPaddr() {
-       declare real_IPaddr
-       declare real_intf
-       declare netmask
-       declare srv_IPaddr=$1
-       declare hostname=$2
-
-       # Get the IP address from /etc/hosts table according to the hostname
-       real_IPaddr=`egrep "[[:space:]]$hostname([[:space:]]|$)" /etc/hosts \
-                     | awk '{print $1}'`
-        if [ -z "$real_IPaddr" ]; then
-                echo >&2 "`basename $0`: $hostname does not exist in" \
-                         "the local /etc/hosts table!"
-                return 1
-        fi
-
-        if [ ${#real_IPaddr} -gt 15 ]; then
-                echo >&2 "`basename $0`: More than one IP address line" \
-                         "according to $hostname in the local /etc/hosts table!"
-                return 1
-        fi
-
-       # Get the interface in which the real IP address is configured
-       real_intf=$(findInterface $real_IPaddr $hostname)
-       if [ $? -ne 0 ]; then
-               return 1
-       fi
-       real_intf=${real_intf%%:*}
-
-       # Get the netmask address associated with the real interface
-       netmask=$(findNetmask $real_intf $hostname)
-       if [ $? -ne 0 ]; then
-               return 1
-       fi
-
-       # Determine if the service IP address and the real IP address
-       # are in the same subnet
-       inSameIPsubnet $srv_IPaddr $real_IPaddr $netmask
-       if [ $? -ne 0 ]; then
-               return 1
-       fi
-
-       return 0
-}
-
-# Check service IP address
-if ! check_srvIPaddr $1 $2; then
-       exit 1
-fi
-exit 0
diff --git a/lustre/utils/lactive b/lustre/utils/lactive
deleted file mode 100644 (file)
index 04841eb..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-#!/usr/bin/env python
-#
-#  Copyright (C) 2002 Cluster File Systems, Inc.
-#   Author: Robert Read <rread@clusterfs.com>
-#   This file is part of Lustre, http://www.lustre.org.
-#
-#   Lustre is free software; you can redistribute it and/or
-#   modify it under the terms of version 2 of the GNU General Public
-#   License as published by the Free Software Foundation.
-#
-#   Lustre is distributed in the hope that it will be useful,
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#   GNU General Public License for more details.
-#
-#   You should have received a copy of the GNU General Public License
-#   along with Lustre; if not, write to the Free Software
-#   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-
-# For all the OST/MDSs that are primary on the --primary node, set
-# them to be active on --active if that OST is available on --active.
-#
-# Make the active node the active node for all devices it shares with the
-# old. The bulk of this code is for figuring out which devices to
-# change, and what to change them to.
-
-# XXX add error checking
-# XXX make this code less ugly
-
-import sys, getopt, types
-import string, os
-import ldap
-from stat import S_IROTH, S_IRGRP
-PYMOD_DIR = "/usr/lib/lustre/python"
-
-def development_mode():
-    base = os.path.dirname(sys.argv[0])
-    if os.access(base+"/Makefile.am", os.R_OK):
-        return 1
-    return 0
-
-if not development_mode():
-    sys.path.append(PYMOD_DIR)
-
-import Lustre
-PARAM = Lustre.Options.PARAM
-
-lactive_options = [
-    ('ldapurl',"LDAP server URL", PARAM, "ldap://localhost"),
-    ('config', "Cluster config name used for LDAP query", PARAM),
-    ('group', "The group of devices to update", PARAM),
-    ('active', "The active node name", PARAM),
-    ('pwfile', "File containing password", PARAM),
-    ]
-
-def fatal(*args):
-    msg = string.join(map(str,args))
-    print "! " + msg
-    sys.exit(1)
-
-cl = Lustre.Options("lactive","", lactive_options)
-config, args = cl.parse(sys.argv[1:])
-
-if not (config.group or config.active):
-    fatal("Must specify both  group and active node.")
-
-if not config.config:
-    fatal("Missing config")
-
-if config.pwfile:
-    try:
-        pwperm = os.stat(config.pwfile)[0]
-        pwreadable = pwperm & (S_IRGRP | S_IROTH)
-        if pwreadable:
-            if pwreadable == (S_IRGRP | S_IROTH):
-                readable_by = "group and others"
-            elif pwreadable == S_IRGRP:
-                readable_by = "group"
-            else:
-                readable_by = "others"
-            print "WARNING: Password file %s is readable by %s" % (
-                config.pwfile, readable_by)
-                 
-        pwfile = open(config.pwfile, "r")
-        pw = string.strip(pwfile.readline())
-        pwfile.close()
-    except Exception, e:
-        fatal("Can't read secret from pwfile %s: %s" % (config.pwfile, e))
-else:
-    print "no pwfile specified, binding anonymously"
-    pw = ""
-
-base = "config=%s,fs=lustre" % (config.config,)
-db = Lustre.LustreDB_LDAP('', {}, base=base, pw = pw, url = config.ldapurl)
-
-active_node = db.lookup_name(config.active)
-if not active_node:
-    fatal(config.active, "node not found in database.")
-
-devices =  db.get_group(config.group)
-if len(devices) < 0:
-    fatal("no devices found for group", config.group)
-
-# for all devices in group
-  # lookup device in active node
-  # update the active device 
-for tgtuuid in devices:
-    active_uuid = db.get_active_dev(tgtuuid)
-    new_active_uuid = active_node.get_tgt_dev(tgtuuid)
-    if active_uuid != new_active_uuid:
-        print ("%s: changing active %s to %s:%s"
-               % (tgtuuid, active_uuid,
-                  config.active, new_active_uuid))
-        db.update_active(tgtuuid, new_active_uuid)
-
-
-
-
-
index fa92ab1..9cce534 100755 (executable)
@@ -72,7 +72,7 @@ PORTALS_DIR = '../lnet'
 # Needed to call lconf --record
 CONFIG_FILE = ""
 
-# Please keep these in sync with the values in portals/kp30.h
+# Please keep these in sync with the values in lnet/include/libcfs/libcfs.h
 ptldebug_names = {
     "trace" :     (1 << 0),
     "inode" :     (1 << 1),
@@ -88,7 +88,8 @@ ptldebug_names = {
     "buffs" :     (1 << 11),
     "other" :     (1 << 12),
     "dentry" :    (1 << 13),
-    "portals" :   (1 << 14),
+    "portals" :   (1 << 14), # deprecated
+    "lnet" :      (1 << 14),
     "page" :      (1 << 15),
     "dlmtrace" :  (1 << 16),
     "error" :     (1 << 17),
@@ -114,22 +115,29 @@ subsystem_names = {
     "log" :          (1 << 6),
     "llite" :        (1 << 7),
     "rpc" :          (1 << 8),
-    "portals" :      (1 << 10),
-    "nal" :          (1 << 11),
+    "lnet" :         (1 << 10),
+    "portals" :      (1 << 10), # deprecated
+    "lnd" :          (1 << 11),
+    "nal" :          (1 << 11), # deprecated
     "pinger" :       (1 << 12),
     "filter" :       (1 << 13),
-    "ptlbd" :        (1 << 14),
+    "ptlbd" :        (1 << 14), # deprecated
     "echo" :         (1 << 15),
     "ldlm" :         (1 << 16),
     "lov" :          (1 << 17),
-    "ptlrouter" :    (1 << 18),
+    "ptlrouter" :    (1 << 18), # deprecated
     "cobd" :         (1 << 19),
     "sm" :           (1 << 20),
     "asobd" :        (1 << 21),
-    "confobd" :      (1 << 22),
+    "confobd" :      (1 << 22), # deprecated
     "lmv" :          (1 << 23),
     "cmobd" :        (1 << 24),
     "sec" :          (1 << 25),
+    "sec" :          (1 << 26),
+    "gss" :          (1 << 27),
+    "gks" :          (1 << 28),
+    "mgc" :          (1 << 29),
+    "mgs" :          (1 << 30),
     }
 
 
@@ -1024,6 +1032,10 @@ class kmod:
                     run('/sbin/rmmod kiiblnd')
                 if mod_loaded("kviblnd"):
                     run('/sbin/rmmod kviblnd')
+                if mod_loaded("kciblnd"):
+                    run('/sbin/rmmod kciblnd')
+                if mod_loaded("ko2iblnd"):
+                    run('/sbin/rmmod ko2iblnd')
                 if mod_loaded("kralnd"):
                     run('/sbin/rmmod kralnd')
                 if mod_loaded("kptllnd"):
@@ -1264,7 +1276,7 @@ class MDSDEV(Module):
         self.filesystem_uuids = mds.get_refs('filesystem')
         # FIXME: if fstype not set, then determine based on kernel version
         self.format = self.db.get_val('autoformat', "no")
-        if mds.get_val('failover', 0):
+        if mds.get_val('failover', '1') != '0':
             self.failover_mds = 'f'
         else:
             self.failover_mds = 'n'
@@ -1419,7 +1431,7 @@ class MDSDEV(Module):
                         if not fs_uuid in self.filesystem_uuids:
                             continue;
 
-                        debug("recording", client_name)
+                        log("Recording log", client_name, "on", self.name)
                         old_noexec = config.noexec
                         config.noexec = 0
                         noexec_opt = ('', '-n')
@@ -1538,7 +1550,7 @@ class OSD(Module):
         ost = self.db.lookup(target_uuid)
         self.name = ost.getName()
         self.format = self.db.get_val('autoformat', 'yes')
-        if ost.get_val('failover', 1):
+        if ost.get_val('failover', '1') != '0':
             self.failover_ost = 'f'
         else:
             self.failover_ost = 'n'
diff --git a/lustre/utils/lfind b/lustre/utils/lfind
deleted file mode 100755 (executable)
index 552394e..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-PATH=`dirname $0`:$PATH
-
-if [ $# -eq 0 ] || [ "$1" == "-h" -o "$1" == "--help" ]; then
-       lfs help find 2>&1 | sed "s/find/lfind/g"
-       exit 0
-fi
-
-lfs find "$@"
index 349c703..c45581e 100644 (file)
@@ -36,6 +36,7 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <dirent.h>
+#include <time.h>
 
 #include <lnet/api-support.h>
 #include <lnet/lnetctl.h>
@@ -80,13 +81,20 @@ command_t cmdlist[] = {
          "\tstripe size:  Number of bytes on each OST (0 filesystem default)\n"
          "\tstripe start: OST index of first stripe (-1 filesystem default)\n"
          "\tstripe count: Number of OSTs to stripe over (0 default, -1 all)"},
-        {"find", lfs_find, 0,
-         "To list the extended attributes for a given filename or files in a\n"
-         "directory or recursively for all files in a directory tree.\n"
-         "usage: find [--obd <uuid>] [--quiet | --verbose] [--recursive] <dir|file> ..."},
         {"getstripe", lfs_getstripe, 0,
-         "To list the striping pattern for given filename.\n"
-         "usage:getstripe <filename>"},
+         "To list the striping info for a given filename or files in a\n"
+         "directory or recursively for all files in a directory tree.\n"
+         "usage: getstripe [--obd|-O <uuid>] [--quiet | -q] [--verbose | -v]\n"
+         "                 [--recursive | -r] <dir|file> ..."},
+        {"find", lfs_find, 0,
+         "To find files that match given parameters recursively in a directory tree.\n"
+         "usage: find [--atime|-A N] [--mtime|-M N] [--ctime|-C N] [--maxdepth|-D N]\n"
+         "            [--print0|-P] [--print|-p] [--obd|-O <uuid>] <dir/file> ...\n"
+         "If one of the options below is provided, find works the same as 'getstripe':\n"
+         "To list the striping info for a given filename or files in a directory or\n"
+         "recursively.\n"
+         "OBSOLETE usage: find [--quiet | -q] [--verbose | -v]\n"
+         "                     [--recursive | -r] <dir|file> ..."},
         {"check", lfs_check, 0,
          "Display the status of MDS or OSTs (as specified in the command)\n"
          "or all the servers (MDS and OSTs).\n"
@@ -185,25 +193,99 @@ static int lfs_setstripe(int argc, char **argv)
         return result;
 }
 
+static int set_time(time_t *time, time_t *set, char *str)
+{
+        time_t t;
+        int res = 0;
+        
+        if (str[0] == '+')
+                res = 1;
+        else if (str[0] == '-')
+                res = -1;
+
+        if (res)
+                str++;
+
+        t = strtol(str, NULL, 0);
+        if (*time < t * 24 * 60 * 60) {
+                if (res)
+                        str--;
+                fprintf(stderr, "Wrong time '%s' is specified.\n", str);
+                return INT_MAX;
+        }
+
+        *set = *time - t * 24 * 60 * 60;
+        return res;
+}
+
 static int lfs_find(int argc, char **argv)
 {
+        int new_fashion = 1;
+        int c, ret;
+        int zeroend;
+        time_t t;
+        unsigned int depth;
+        time_t atime, ctime, mtime;
+        int asign, msign, csign;
+        int quiet, verbose, recursive;
+        struct find_param param;
+        struct obd_uuid *obduuid = NULL;
         struct option long_opts[] = {
-                {"obd", 1, 0, 'o'},
-                {"quiet", 0, 0, 'q'},
-                {"recursive", 0, 0, 'r'},
-                {"verbose", 0, 0, 'v'},
+                /* New find options. */
+                {"atime",     required_argument, 0, 'A'},
+                {"ctime",     required_argument, 0, 'C'},
+                {"mtime",     required_argument, 0, 'M'},
+                {"maxdepth",  required_argument, 0, 'D'},
+                /* --obd is considered as a new option. */
+                {"obd",       required_argument, 0, 'O'},
+                {"print",     no_argument,       0, 'P'},
+                {"print0",    no_argument,       0, 'p'},
+                /* Old find options. */
+                {"quiet",     no_argument,       0, 'q'},
+                {"recursive", no_argument,       0, 'r'},
+                {"verbose",   no_argument,       0, 'v'},
                 {0, 0, 0, 0}
         };
-        char short_opts[] = "ho:qrv";
-        int quiet, verbose, recursive, c, rc;
-        struct obd_uuid *obduuid = NULL;
 
-        optind = 0;
+        time(&t);
+        zeroend = 0;
+        depth = -1;
+        atime = ctime = mtime = 0;
+        asign = csign = msign = 0;
         quiet = verbose = recursive = 0;
-        while ((c = getopt_long(argc, argv, short_opts,
-                                        long_opts, NULL)) != -1) {
+        
+        while ((c = getopt_long_only(argc, argv, "A:C:D:M:PpOqrv", 
+                                     long_opts, NULL)) >= 0)
+        {
                 switch (c) {
-                case 'o':
+                case 0:
+                        /* Long options. */
+                        break;
+                case 'A':
+                        ret = set_time(&t, &atime, optarg);
+                        if (ret == INT_MAX)
+                                return -1;
+                        if (ret)
+                                asign = ret;
+                        break;
+                case 'C':
+                        ret = set_time(&t, &ctime, optarg);
+                        if (ret == INT_MAX)
+                                return -1;
+                        if (ret)
+                                csign = ret;
+                        break;
+                case 'D':
+                        depth = strtol(optarg, 0, 0);
+                        break;
+                case 'M':
+                        ret = set_time(&t, &mtime, optarg);
+                        if (ret == INT_MAX)
+                                return -1;
+                        if (ret)
+                                msign = ret;
+                        break;
+                case 'O':
                         if (obduuid) {
                                 fprintf(stderr,
                                         "error: %s: only one obduuid allowed",
@@ -212,57 +294,89 @@ static int lfs_find(int argc, char **argv)
                         }
                         obduuid = (struct obd_uuid *)optarg;
                         break;
+                case 'p':
+                        zeroend = 1;
+                        break;
+                case 'P':
+                        break;
                 case 'q':
+                        new_fashion = 0;
                         quiet++;
                         verbose = 0;
                         break;
                 case 'r':
+                        new_fashion = 0;
                         recursive = 1;
                         break;
                 case 'v':
+                        new_fashion = 0;
                         verbose++;
                         quiet = 0;
                         break;
                 case '?':
                         return CMD_HELP;
-                        break;
                 default:
                         fprintf(stderr, "error: %s: option '%s' unrecognized\n",
                                 argv[0], argv[optind - 1]);
                         return CMD_HELP;
-                        break;
-                }
+                };
         }
-
+        
         if (optind >= argc)
                 return CMD_HELP;
 
+        memset(&param, 0, sizeof(param));
+        param.obduuid = obduuid;
+        if (new_fashion) {
+                param.maxdepth = depth;
+                param.atime = atime;
+                param.ctime = ctime;
+                param.mtime = mtime;
+                param.asign = asign;
+                param.csign = csign;
+                param.msign = msign;
+                param.zeroend = zeroend;
+                param.quiet = 1;
+        } else {
+                param.recursive = recursive;
+                param.verbose = verbose;
+                param.quiet = quiet;
+                param.maxdepth = recursive ? -1 : 1;
+        }
+        
         do {
-                rc = llapi_find(argv[optind], obduuid, recursive,verbose,quiet);
-        } while (++optind < argc && !rc);
+                if (new_fashion)
+                        ret = llapi_find(argv[optind], &param);
+                else
+                        ret = llapi_getstripe(argv[optind], &param);
+        } while (++optind < argc && !ret);
 
-        if (rc)
-                fprintf(stderr, "error: %s: find failed\n", argv[0]);
-        return rc;
+        if (ret)
+                fprintf(stderr, "error: %s failed for %s.\n", 
+                        argv[0], argv[optind - 1]);
+        return ret;
 }
 
 static int lfs_getstripe(int argc, char **argv)
 {
         struct option long_opts[] = {
+                {"obd", 1, 0, 'O'},
                 {"quiet", 0, 0, 'q'},
+                {"recursive", 0, 0, 'r'},
                 {"verbose", 0, 0, 'v'},
                 {0, 0, 0, 0}
         };
-        char short_opts[] = "qv";
+        char short_opts[] = "hO:qrv";
         int quiet, verbose, recursive, c, rc;
         struct obd_uuid *obduuid = NULL;
+        struct find_param param;
 
         optind = 0;
         quiet = verbose = recursive = 0;
         while ((c = getopt_long(argc, argv, short_opts,
-                                        long_opts, NULL)) != -1) {
+                                long_opts, NULL)) != -1) {
                 switch (c) {
-                case 'o':
+                case 'O':
                         if (obduuid) {
                                 fprintf(stderr,
                                         "error: %s: only one obduuid allowed",
@@ -275,32 +389,39 @@ static int lfs_getstripe(int argc, char **argv)
                         quiet++;
                         verbose = 0;
                         break;
+                case 'r':
+                        recursive = 1;
+                        break;
                 case 'v':
                         verbose++;
                         quiet = 0;
                         break;
                 case '?':
                         return CMD_HELP;
-                        break;
                 default:
                         fprintf(stderr, "error: %s: option '%s' unrecognized\n",
                                 argv[0], argv[optind - 1]);
                         return CMD_HELP;
-                        break;
                 }
         }
 
         if (optind >= argc)
                 return CMD_HELP;
 
+        memset(&param, 0, sizeof(param));
+        param.recursive = recursive;
+        param.verbose = verbose;
+        param.quiet = quiet;
+        param.obduuid = obduuid;
+        param.maxdepth = recursive ? -1 : 1;
+
         do {
-                rc = llapi_find(argv[optind], obduuid, recursive,verbose,quiet);
+                rc = llapi_getstripe(argv[optind], &param);
         } while (++optind < argc && !rc);
 
         if (rc)
-                fprintf(stderr, "error: %s: getstripe failed for %s\n",
-                        argv[0], argv[1]);
-
+                fprintf(stderr, "error: %s failed for %s.\n", 
+                        argv[0], argv[optind - 1]);
         return rc;
 }
 
@@ -309,6 +430,7 @@ static int lfs_osts(int argc, char **argv)
         FILE *fp;
         struct mntent *mnt = NULL;
         struct obd_uuid *obduuid = NULL;
+        struct find_param param;
         int rc=0;
 
         if (argc != 1)
@@ -321,9 +443,11 @@ static int lfs_osts(int argc, char **argv)
                         strerror (errno));
         } else {
                 mnt = getmntent(fp);
+                memset(&param, 0, sizeof(param));
+                param.obduuid = obduuid;
                 while (feof(fp) == 0 && ferror(fp) ==0) {
                         if (llapi_is_lustre_mnttype(mnt)) {
-                                rc = llapi_find(mnt->mnt_dir, obduuid, 0, 0, 0);
+                                rc = llapi_getstripe(mnt->mnt_dir, &param);
                                 if (rc)
                                         fprintf(stderr,
                                                "error: %s: failed on %s\n",
@@ -393,7 +517,7 @@ static int showdf(char *mntdir, struct obd_statfs *stat,
                   char *uuid, int ishow, int cooked,
                   char *type, int index, int rc)
 {
-        __u64 avail, used, total;
+        long long avail, used, total;
         double ratio = 0;
         char *suffix = "KMGTPEZY";
         char tbuf[10], ubuf[10], abuf[10], rbuf[10];
@@ -715,7 +839,7 @@ int lfs_join(int argc, char **argv)
         size = lseek(fd, 0, SEEK_END);
         if (size % JOIN_FILE_ALIGN) {
                 fprintf(stderr,"head file %s size %llu must be mutiple of %d\n",
-                        name_head, size, JOIN_FILE_ALIGN);
+                        name_head, (long long)size, JOIN_FILE_ALIGN);
                 rc = -EINVAL;
                 goto out;
         }
@@ -1180,9 +1304,9 @@ static void print_quota(char *mnt, struct if_quotactl *qctl, int ost_only)
                         if (bover)
                                 diff2str(dqb->dqb_btime, timebuf, now);
 
-                        sprintf(numbuf[0], "%llu", toqb(dqb->dqb_curspace));
-                        sprintf(numbuf[1], "%llu", dqb->dqb_bsoftlimit);
-                        sprintf(numbuf[2], "%llu", dqb->dqb_bhardlimit);
+                        sprintf(numbuf[0], LPU64, toqb(dqb->dqb_curspace));
+                        sprintf(numbuf[1], LPU64, dqb->dqb_bsoftlimit);
+                        sprintf(numbuf[2], LPU64, dqb->dqb_bhardlimit);
                         printf(" %7s%c %6s %7s %7s",
                                numbuf[0], bover ? '*' : ' ', numbuf[1],
                                numbuf[2], bover > 1 ? timebuf : "");
@@ -1190,9 +1314,9 @@ static void print_quota(char *mnt, struct if_quotactl *qctl, int ost_only)
                         if (iover)
                                 diff2str(dqb->dqb_itime, timebuf, now);
 
-                        sprintf(numbuf[0], "%llu", dqb->dqb_curinodes);
-                        sprintf(numbuf[1], "%llu", dqb->dqb_isoftlimit);
-                        sprintf(numbuf[2], "%llu", dqb->dqb_ihardlimit);
+                        sprintf(numbuf[0], LPU64, dqb->dqb_curinodes);
+                        sprintf(numbuf[1], LPU64, dqb->dqb_isoftlimit);
+                        sprintf(numbuf[2], LPU64, dqb->dqb_ihardlimit);
                         if (!ost_only)
                                 printf(" %7s%c %6s %7s %7s",
                                        numbuf[0], iover ? '*' : ' ', numbuf[1],
index c320aed..ad988a7 100644 (file)
@@ -69,7 +69,7 @@ static void err_msg(char *fmt, ...)
         fprintf(stderr, ": %s (%d)\n", strerror(tmp_errno), tmp_errno);
 }
 
-int llapi_file_create(char *name, long stripe_size, int stripe_offset,
+int llapi_file_create(const char *name, long stripe_size, int stripe_offset,
                       int stripe_count, int stripe_pattern)
 {
         struct lov_user_md lum = { 0 };
@@ -145,50 +145,27 @@ out:
         return rc;
 }
 
-/* short term backwards compat only */
-int op_create_file(char *name, long stripe_size, int stripe_offset,
-                   int stripe_count)
-{
-        return llapi_file_create(name, stripe_size, stripe_offset,
-                                 stripe_count, 0);
-}
-
-struct find_param {
-        int     recursive;
-        int     verbose;
-        int     quiet;
-        struct  obd_uuid        *obduuid;
-        int     lumlen;
-        struct  lov_user_mds_data *lmd;
-/*        struct  lov_user_md     *lum;*/
-        int     got_uuids;
-        int     obdindex;
-        int     (* process_file)(DIR *dir, char *dname, char *fname,
-                        struct find_param *param);
-};
+typedef int (semantic_func_t)(char *path, DIR *parent, DIR *d, void *data);
 
 #define MAX_LOV_UUID_COUNT      max(LOV_MAX_STRIPE_COUNT, 1000)
 #define OBD_NOT_FOUND           (-1)
 
-static int prepare_find(struct find_param *param)
+static int common_param_init(struct find_param *param)
 {
         param->lumlen = lov_mds_md_size(MAX_LOV_UUID_COUNT);
         if ((param->lmd = malloc(sizeof(lstat_t) + param->lumlen)) == NULL) {
                 err_msg("error: allocation of %d bytes for ioctl",
                         sizeof(lstat_t) + param->lumlen);
-                return ENOMEM;
+                return -ENOMEM;
         }
 
         param->got_uuids = 0;
         param->obdindex = OBD_NOT_FOUND;
-
         return 0;
 }
 
-static void cleanup_find(struct find_param *param)
+static void find_param_fini(struct find_param *param)
 {
-        if (param->obduuid)
-                free(param->obduuid);
         if (param->lmd)
                 free(param->lmd);
 }
@@ -257,20 +234,20 @@ static int setup_obd_uuids(DIR *dir, char *dname, struct find_param *param)
         FILE *fp;
         int rc = 0, index;
 
-        param->got_uuids = 1;
-
         /* Get the lov name */
         rc = ioctl(dirfd(dir), OBD_IOC_GETNAME, (void *)uuid);
         if (rc) {
-                rc = errno;
-                if (rc == -ENOTTY)
-                        fprintf(stderr, "error: %s does not appear to be in "
-                                "a Lustre filesystem\n", dname);
-                else
-                        err_msg("error: can't get lov name: %s");
+                if (errno != ENOTTY) {
+                        err_msg("error: can't get lov name: %s", dname);
+                        rc = errno;
+                } else {
+                        rc = 0;
+                }
                 return rc;
         }
 
+        param->got_uuids = 1;
+
         /* Now get the ost uuids from /proc */
         snprintf(buf, sizeof(buf), "/proc/fs/lustre/lov/%s/target_obd",
                  uuid);
@@ -280,7 +257,7 @@ static int setup_obd_uuids(DIR *dir, char *dname, struct find_param *param)
                 return rc;
         }
 
-        if (!param->obduuid && !param->quiet)
+        if (!param->obduuid && !param->quiet && !param->obds_printed)
                 printf("OBDS:\n");
 
         while (fgets(buf, sizeof(buf), fp) != NULL) {
@@ -293,43 +270,45 @@ static int setup_obd_uuids(DIR *dir, char *dname, struct find_param *param)
                                 param->obdindex = index;
                                 break;
                         }
-                } else if (!param->quiet) {
+                } else if (!param->quiet && !param->obds_printed) {
                         /* Print everything */
                         printf("%s", buf);
                 }
         }
+        param->obds_printed = 1;
 
         fclose(fp);
 
-        if (param->obduuid && (param->obdindex == OBD_NOT_FOUND)) {
+        if (!param->quiet && param->obduuid &&
+            (param->obdindex == OBD_NOT_FOUND)) {
                 fprintf(stderr, "error: %s: unknown obduuid: %s\n",
                         __FUNCTION__, param->obduuid->uuid);
-                rc = EINVAL;
+                //rc = EINVAL;
         }
 
         return (rc);
 }
 
-void lov_dump_user_lmm_v1(struct lov_user_md_v1 *lum, char *dname, char *fname,
+void lov_dump_user_lmm_v1(struct lov_user_md_v1 *lum, char *path, int is_dir,
                           int obdindex, int quiet, int header, int body)
 {
         int i, obdstripe = 0;
 
         if (obdindex != OBD_NOT_FOUND) {
-                for (i = 0; fname[0] && i < lum->lmm_stripe_count; i++) {
+                for (i = 0; !is_dir && i < lum->lmm_stripe_count; i++) {
                         if (obdindex == lum->lmm_objects[i].l_ost_idx) {
-                                printf("%s/%s\n", dname, fname);
+                                printf("%s\n", path);
                                 obdstripe = 1;
                                 break;
                         }
                 }
         } else if (!quiet) {
-                printf("%s/%s\n", dname, fname);
+                printf("%s\n", path);
                 obdstripe = 1;
         }
 
         /* if it's a directory */
-        if (*fname == '\0') {
+        if (is_dir) {
                 if (obdstripe == 1) {
                         printf("default stripe_count: %d stripe_size: %u "
                                "stripe_offset: %d\n",
@@ -368,8 +347,8 @@ void lov_dump_user_lmm_v1(struct lov_user_md_v1 *lum, char *dname, char *fname,
         }
 }
 
-void lov_dump_user_lmm_join(struct lov_user_md_v1 *lum, char *dname,
-                            char *fname, int obdindex, int quiet,
+void lov_dump_user_lmm_join(struct lov_user_md_v1 *lum, char *path,
+                            int is_dir, int obdindex, int quiet,
                             int header, int body)
 {
         struct lov_user_md_join *lumj = (struct lov_user_md_join *)lum;
@@ -378,13 +357,13 @@ void lov_dump_user_lmm_join(struct lov_user_md_v1 *lum, char *dname,
         if (obdindex != OBD_NOT_FOUND) {
                 for (i = 0; i < lumj->lmm_stripe_count; i++) {
                         if (obdindex == lumj->lmm_objects[i].l_ost_idx) {
-                                printf("%s/%s\n", dname, fname);
+                                printf("%s\n", path);
                                 obdstripe = 1;
                                 break;
                         }
                 }
         } else if (!quiet) {
-                printf("%s/%s\n", dname, fname);
+                printf("%s\n", path);
                 obdstripe = 1;
         }
 
@@ -428,17 +407,18 @@ void lov_dump_user_lmm_join(struct lov_user_md_v1 *lum, char *dname,
         }
 }
 
-void llapi_lov_dump_user_lmm(struct find_param *param, char *dname, char *fname)
+void llapi_lov_dump_user_lmm(struct find_param *param,
+                             char *path, int is_dir)
 {
         switch(*(__u32 *)&param->lmd->lmd_lmm) { /* lum->lmm_magic */
         case LOV_USER_MAGIC_V1:
-                lov_dump_user_lmm_v1(&param->lmd->lmd_lmm, dname, fname,
+                lov_dump_user_lmm_v1(&param->lmd->lmd_lmm, path, is_dir,
                                       param->obdindex, param->quiet,
                                       param->verbose,
                                       (param->verbose || !param->obduuid));
                 break;
         case LOV_USER_MAGIC_JOIN:
-                lov_dump_user_lmm_join(&param->lmd->lmd_lmm, dname, fname,
+                lov_dump_user_lmm_join(&param->lmd->lmd_lmm, path, is_dir,
                                        param->obdindex, param->quiet,
                                        param->verbose,
                                        (param->verbose || !param->obduuid));
@@ -450,7 +430,7 @@ void llapi_lov_dump_user_lmm(struct find_param *param, char *dname, char *fname)
         }
 }
 
-int llapi_file_get_stripe(char *path, struct lov_user_md *lum)
+int llapi_file_get_stripe(const char *path, struct lov_user_md *lum)
 {
         char *dname, *fname;
         int fd, rc = 0;
@@ -463,7 +443,7 @@ int llapi_file_get_stripe(char *path, struct lov_user_md *lum)
                 if (dname == NULL)
                         return ENOMEM;
                 strcpy(dname, ".");
-                fname = path;
+                fname = (char *)path;
         } else {
                 dname = (char *)malloc(fname - path + 1);
                 if (dname == NULL)
@@ -479,7 +459,7 @@ int llapi_file_get_stripe(char *path, struct lov_user_md *lum)
         }
 
         strcpy((char *)lum, fname);
-        if (ioctl(fd, IOC_MDC_GETSTRIPE, (void *)lum) == -1) {
+        if (ioctl(fd, IOC_MDC_GETFILESTRIPE, (void *)lum) == -1) {
                 close(fd);
                 free(dname);
                 return errno;
@@ -493,57 +473,37 @@ int llapi_file_get_stripe(char *path, struct lov_user_md *lum)
         return rc;
 }
 
-/* short term backwards compat only */
-int op_get_file_stripe(char *path, struct lov_user_md *lum)
-{
-        return llapi_file_get_stripe(path, lum);
-}
-
-static int find_process_file(DIR *dir, char *dname, char *fname,
-                        struct find_param *param)
+int llapi_file_lookup(int dirfd, const char *name)
 {
+        struct obd_ioctl_data data = { 0 };
+        char rawbuf[8192];
+        char *buf = rawbuf;
         int rc;
 
-        strncpy((char *)&param->lmd->lmd_lmm, fname, param->lumlen);
+        if (dirfd < 0 || name == NULL)
+                return -EINVAL;
 
-        rc = ioctl(dirfd(dir), IOC_MDC_GETSTRIPE, (void *)&param->lmd->lmd_lmm);
+        data.ioc_version = OBD_IOCTL_VERSION;
+        data.ioc_len = sizeof(data);
+        data.ioc_inlbuf1 = (char *)name;
+        data.ioc_inllen1 = strlen(name) + 1;
+
+        rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
         if (rc) {
-                if (errno == ENODATA) {
-                        if (!param->obduuid && !param->quiet)
-                                fprintf(stderr, "%s/%s has no stripe info\n",
-                                        dname, fname);
-                        rc = 0;
-                } else if (errno == ENOTTY) {
-                        fprintf(stderr, "error: %s/%s is not a Lustre fs?\n",
-                                dname, fname);
-                } else if (errno == EISDIR) {
-                        err_msg("error: %s: directory %s/%s",
-                                __FUNCTION__, dname, fname);
-                        /* add fname to directory list; */
-                        rc = errno;
-                } else {
-                        err_msg("error: IOC_MDC_GETSTRIPE failed for '%s/%s'",
-                                dname, fname);
-                        rc = errno;
-                }
+                fprintf(stderr,
+                        "error: IOC_MDC_LOOKUP pack failed for '%s': rc %d\n",
+                        name, rc);
                 return rc;
         }
 
-        llapi_lov_dump_user_lmm(param, dname, fname);
-
-        return 0;
+        return ioctl(dirfd, IOC_MDC_LOOKUP, buf);
 }
 
 /* some 64bit libcs implement readdir64() by calling sys_getdents().  the
  * kernel's sys_getdents() doesn't return d_type.  */
-unsigned char handle_dt_unknown(char *parent, char *entry)
+unsigned char handle_dt_unknown(char *path)
 {
-        char path[PATH_MAX + 1];
-        int fd, ret;
-
-        ret = snprintf(path, PATH_MAX, "%s/%s", parent, entry);
-        if (ret >= PATH_MAX)
-                return DT_UNKNOWN;
+        int fd;
 
         fd = open(path, O_DIRECTORY|O_RDONLY);
         if (fd < 0) {
@@ -555,162 +515,427 @@ unsigned char handle_dt_unknown(char *parent, char *entry)
         return DT_DIR;
 }
 
-static int process_dir(DIR *dir, char *dname, struct find_param *param)
+static DIR *opendir_parent(char *path)
 {
-        struct dirent64 *dirp;
-        DIR *subdir;
-        char path[1024];
-        int rc;
+        DIR *parent;
+        char *fname;
+        char c;
 
-        if (!param->got_uuids) {
-                rc = setup_obd_uuids(dir, dname, param);
-                if (rc)
-                        return rc;
-        }
+        fname = strrchr(path, '/');
+        if (fname == NULL)
+                return opendir(".");
+
+        c = fname[1];
+        fname[1] = '\0';
+        parent = opendir(path);
+        fname[1] = c;
+        return parent;
+}
 
-        /* retrieve dir's stripe info */
-        strncpy((char *)&param->lmd->lmd_lmm, dname, param->lumlen);
-        rc = ioctl(dirfd(dir), LL_IOC_LOV_GETSTRIPE, (void *)&param->lmd->lmd_lmm);
-        if (rc) {
-                if (errno == ENODATA) {
-                        if (!param->obduuid && param->verbose)
-                                printf("%s has no stripe info\n", dname);
-                        rc = 0;
-                } else if (errno == ENOTTY) {
-                        fprintf(stderr, "error: %s: %s not on a Lustre fs?\n",
-                                __FUNCTION__, dname);
-                } else {
-                        err_msg("error: %s: LL_IOC_LOV_GETSTRIPE failed for %s",
-                                __FUNCTION__, dname);
-                }
-        } else {
-               llapi_lov_dump_user_lmm(param, dname, "");
+static int llapi_semantic_traverse(char *path, DIR *parent,
+                                   semantic_func_t sem_init,
+                                   semantic_func_t sem_fini, void *data)
+{
+        struct dirent64 *dent;
+        int len, ret;
+        DIR *d, *p = NULL;
+
+        ret = 0;
+        len = strlen(path);
+
+        d = opendir(path);
+        if (!d && errno != ENOTDIR) {
+                fprintf(stderr, "%s: Failed to open '%s': %s.",
+                        __FUNCTION__, path, strerror(errno));
+                return -EINVAL;
+        } else if (!d && !parent) {
+                /* ENOTDIR. Open the parent dir. */
+                p = opendir_parent(path);
+                if (!p)
+                        GOTO(out, ret = -EINVAL);
         }
 
-        /* Handle the contents of the directory */
-        while ((dirp = readdir64(dir)) != NULL) {
-                if (!strcmp(dirp->d_name, ".") || !strcmp(dirp->d_name, ".."))
+        if (sem_init && (ret = sem_init(path, parent ?: p, d, data)))
+                goto err;
+
+        if (!d)
+                GOTO(out, ret = 0);
+
+        while ((dent = readdir64(d)) != NULL) {
+                if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
                         continue;
 
-                if (dirp->d_type == DT_UNKNOWN)
-                        dirp->d_type = handle_dt_unknown(dname, dirp->d_name);
+                path[len] = 0;
+                strcat(path, "/");
+                strcat(path, dent->d_name);
+
+                if (dent->d_type == DT_UNKNOWN)
+                        dent->d_type = handle_dt_unknown(path);
 
-                switch (dirp->d_type) {
+                switch (dent->d_type) {
                 case DT_UNKNOWN:
                         fprintf(stderr, "error: %s: '%s' is UNKNOWN type %d",
-                                __FUNCTION__, dirp->d_name, dirp->d_type);
+                                __FUNCTION__, dent->d_name, dent->d_type);
                         /* If we cared we could stat the file to determine
                          * type and continue on here, but we don't since we
                          * know d_type should be valid for lustre and this
                          * tool only makes sense for lustre filesystems. */
                         break;
                 case DT_DIR:
-                        if (!param->recursive)
-                                break;
-                        strcpy(path, dname);
-                        strcat(path, "/");
-                        strcat(path, dirp->d_name);
-                        subdir = opendir(path);
-                        if (subdir == NULL) {
-                                err_msg("error: %s: opendir '%.40s'",
-                                        __FUNCTION__, path);
-                                return errno;
-                        }
-                        rc = process_dir(subdir, path, param);
-                        closedir(subdir);
-                        break;
-                case DT_REG:
-                        rc = param->process_file(dir,dname,dirp->d_name,param);
+                        ret = llapi_semantic_traverse(path, d, sem_init,
+                                                      sem_fini, data);
+                        if (ret < 0)
+                                goto out;
                         break;
                 default:
-                        break;
+                        ret = 0;
+                        if (sem_init) {
+                                ret = sem_init(path, d, NULL, data);
+                                if (ret < 0)
+                                        goto out;
+                        }
+                        if (sem_fini && ret == 0)
+                                sem_fini(path, d, NULL, data);
                 }
         }
 
-        return 0;
+out:
+        path[len] = 0;
+
+        if (sem_fini)
+                sem_fini(path, parent, d, data);
+err:
+        if (d)
+                closedir(d);
+        if (p)
+                closedir(p);
+        return ret;
+}
+
+/* Check if the file time matches 1 of the given criteria (e.g. --atime +/-N).
+ * @mds indicates if this is MDS timestamps and there are attributes on OSTs.
+ *
+ * The result is -1 if it does not match, 0 if not yet clear, 1 if matches.
+ * The table bolow gives the answers for the specified parameters (time and
+ * sign), 1st column is the answer for the MDS time, the 2nd is for the OST:
+ * --------------------------------------
+ * 1 | file > limit; sign > 0 | -1 / -1 |
+ * 2 | file = limit; sign > 0 |  ? /  1 |
+ * 3 | file < limit; sign > 0 |  ? /  1 |
+ * 4 | file > limit; sign = 0 | -1 / -1 |
+ * 5 | file = limit; sign = 0 |  ? /  1 |  <- (see the Note below)
+ * 6 | file < limit; sign = 0 |  ? / -1 |
+ * 7 | file > limit; sign < 0 |  1 /  1 |
+ * 8 | file = limit; sign < 0 |  ? / -1 |
+ * 9 | file < limit; sign < 0 |  ? / -1 |
+ * --------------------------------------
+ * Note: 5th actually means that the file time stamp is within the interval
+ * (limit - 24hours, limit]. */
+static int find_time_cmp(time_t file, time_t limit, int sign, int mds) {
+        if (sign > 0) {
+                if (file <= limit)
+                        return mds ? 0 : 1;
+        }
+
+        if (sign == 0) {
+                if (file <= limit && file + 24 * 60 * 60 > limit)
+                        return mds ? 0 : 1;
+                if (file + 24 * 60 * 60 <= limit)
+                        return mds ? 0 : -1;
+        }
+
+        if (sign < 0) {
+                if (file > limit)
+                        return 1;
+                if (mds)
+                        return 0;
+        }
+
+        return -1;
 }
 
-static int process_path(char *path, struct find_param *param)
+/* Check if the file time matches all the given criteria (e.g. --atime +/-N).
+ * Return -1 or 1 if file timestamp does not or does match the given criteria
+ * correspondingly. Return 0 if the MDS time is being checked and there are
+ * attributes on OSTs and it is not yet clear if the timespamp matches.
+ *
+ * If 0 is returned, we need to do another RPC to the OSTs to obtain the
+ * updated timestamps. */
+static int find_time_check(lstat_t *st, struct find_param *param, int mds)
 {
-        char *fname, *dname;
-        DIR *dir;
+        int ret;
         int rc = 0;
 
-        fname = strrchr(path, '/');
-        if (fname != NULL && fname[1] == '\0') {
-                /* Trailing '/', it must be a dir */
-                if (strlen(path) > 1)
-                        *fname = '\0';
-
-                dir = opendir(path);
-                if (dir == NULL) {
-                        err_msg("error: %s: '%.40s' opendir",__FUNCTION__,path);
-                        rc = errno;
+        /* Check if file is accepted. */
+        if (param->atime) {
+                ret = find_time_cmp(st->st_atime, param->atime,
+                                    param->asign, mds);
+                if (ret < 0)
+                        return ret;
+                rc = ret;
+        }
+
+        if (param->mtime) {
+                ret = find_time_cmp(st->st_mtime, param->mtime,
+                                    param->msign, mds);
+                if (ret < 0)
+                        return ret;
+
+                /* If the previous check matches, but this one is not yet clear,
+                 * we should return 0 to do an RPC on OSTs. */
+                if (rc == 1)
+                        rc = ret;
+        }
+
+        if (param->ctime) {
+                ret = find_time_cmp(st->st_ctime, param->ctime,
+                                    param->csign, mds);
+                if (ret < 0)
+                        return ret;
+
+                /* If the previous check matches, but this one is not yet clear,
+                 * we should return 0 to do an RPC on OSTs. */
+                if (rc == 1)
+                        rc = ret;
+        }
+
+        return rc;
+}
+
+static int cb_find_init(char *path, DIR *parent, DIR *dir, void *data)
+{
+        struct find_param *param = (struct find_param *)data;
+        int decision = 1; /* 1 is accepted; -1 is rejected. */
+        lstat_t *st = &param->lmd->lmd_st;
+        int lustre_fs = 1;
+        int ret = 0;
+
+        LASSERT(parent != NULL || dir != NULL);
+
+        param->lmd->lmd_lmm.lmm_stripe_count = 0;
+
+        /* If a time or OST should be checked, the decision is not taken yet. */
+        if (param->atime || param->ctime || param->mtime || param->obduuid)
+                decision = 0;
+
+        /* Request MDS for the stat info. */
+        if (!decision && dir) {
+                /* retrieve needed file info */
+                ret = ioctl(dirfd(dir), LL_IOC_MDC_GETINFO,
+                            (void *)param->lmd);
+        } else if (!decision && parent) {
+                char *fname = strrchr(path, '/') + 1;
+
+                /* retrieve needed file info */
+                strncpy((char *)param->lmd, fname, param->lumlen);
+                ret = ioctl(dirfd(parent), IOC_MDC_GETFILEINFO,
+                           (void *)param->lmd);
+        }
+
+        if (ret) {
+                if (errno == ENOTTY) {
+                        /* ioctl is not supported, it is not a lustre fs.
+                         * Do the regular lstat(2) instead. */
+                        lustre_fs = 0;
+                        ret = lstat_f(path, st);
+                        if (ret) {
+                                err_msg("error: %s: lstat failed for %s",
+                                        __FUNCTION__, path);
+                                return ret;
+                        }
                 } else {
-                        rc = process_dir(dir, path, param);
-                        closedir(dir);
+                        err_msg("error: %s: %s failed for %s", __FUNCTION__,
+                                dir ? "LL_IOC_MDC_GETINFO" :
+                                "IOC_MDC_GETFILEINFO", path);
+                        return ret;
                 }
-        } else if ((dir = opendir(path)) != NULL) {
-                /* No trailing '/', but it is still a dir */
-                rc = process_dir(dir, path, param);
-                closedir(dir);
-        } else {
-                /* It must be a file (or other non-directory) */
-                if (fname == NULL) {
-                        dname = ".";
-                        fname = path;
-                } else {
-                        *fname = '\0';
-                        fname++;
-                        dname = path;
-                        if (dname[0] == '\0')
-                                dname = "/";
+        }
+
+        /* Prepare odb. */
+        if (param->obduuid) {
+                if (lustre_fs && param->got_uuids &&
+                    param->st_dev != st->st_dev) {
+                        /* A lustre/lustre mount point is crossed. */
+                        param->got_uuids = 0;
+                        param->obds_printed = 0;
+                        param->obdindex = OBD_NOT_FOUND;
                 }
-                dir = opendir(dname);
-                if (dir == NULL) {
-                        err_msg("error: %s: '%.40s' open failed",
-                                __FUNCTION__, dname);
-                        rc = errno;
+
+                if (lustre_fs && !param->got_uuids) {
+                        ret = setup_obd_uuids(dir ? dir : parent, path, param);
+                        if (ret)
+                                return ret;
+                        param->st_dev = st->st_dev;
+                } else if (!lustre_fs && param->got_uuids) {
+                        /* A lustre/non-lustre mount point is crossed. */
+                        param->got_uuids = 0;
+                        param->obdindex = OBD_NOT_FOUND;
+                }
+        }
+
+        /* If an OBD UUID is specified but no one matches, skip this file. */
+        if (param->obduuid && param->obdindex == OBD_NOT_FOUND)
+                decision = -1;
+
+        /* If a OST UUID is given, and some OST matches, check it here. */
+        if (decision != -1 && param->obdindex != OBD_NOT_FOUND) {
+                /* Only those files should be accepted, which have a strip on
+                 * the specified OST. */
+                if (!param->lmd->lmd_lmm.lmm_stripe_count) {
+                        decision = -1;
                 } else {
-                        if (!param->got_uuids)
-                                rc = setup_obd_uuids(dir, dname, param);
-                        if (rc == 0)
-                                rc = param->process_file(dir, dname, fname, param);
-                        closedir(dir);
+                        int i;
+                        for (i = 0;
+                             i < param->lmd->lmd_lmm.lmm_stripe_count; i++) {
+                               if (param->obdindex ==
+                                   param->lmd->lmd_lmm.lmm_objects[i].l_ost_idx)
+                                        break;
+                        }
+
+                        if (i == param->lmd->lmd_lmm.lmm_stripe_count)
+                                decision = -1;
                 }
         }
 
-        return rc;
+        /* Check the time on mds. */
+        if (!decision) {
+                int for_mds;
+
+                for_mds = lustre_fs ? param->lmd->lmd_lmm.lmm_stripe_count : 0;
+                decision = find_time_check(st, param, for_mds);
+        }
+
+        /* If file still fits the request, ask osd for updated info.
+           The regulat stat is almost of the same speed as some new
+           'glimpse-size-ioctl'. */
+        if (!decision && param->lmd->lmd_lmm.lmm_stripe_count) {
+                if (dir) {
+                        ret = ioctl(dirfd(dir), IOC_LOV_GETINFO,
+                                    (void *)param->lmd);
+                } else if (parent) {
+                        ret = ioctl(dirfd(parent), IOC_LOV_GETINFO,
+                                    (void *)param->lmd);
+                }
+
+                if (ret) {
+                        fprintf(stderr, "%s: IOC_LOV_GETINFO on %s failed: "
+                                "%s.\n", __FUNCTION__, path, strerror(errno));
+                        return -EINVAL;
+                }
+
+                /* Check the time on osc. */
+                if (!decision)
+                        decision = find_time_check(st, param, 0);
+        }
+
+        if (decision != -1) {
+                printf("%s", path);
+                if (param->zeroend)
+                        printf("%c", '\0');
+                else
+                        printf("\n");
+        }
+
+        /* Do not get down anymore? */
+        if (param->depth == param->maxdepth)
+                return 1;
+
+        param->depth++;
+        return 0;
 }
 
-int llapi_find(char *path, struct obd_uuid *obduuid, int recursive,
-               int verbose, int quiet)
+static int cb_common_fini(char *path, DIR *parent, DIR *d, void *data)
 {
-        struct find_param param;
+        struct find_param *param = (struct find_param *)data;
+        param->depth--;
+        return 0;
+}
+
+int llapi_find(char *path, struct find_param *param)
+{
+        char buf[PATH_MAX + 1];
+        int ret;
+
+        ret = common_param_init(param);
+        if (ret)
+                return ret;
+
+        param->depth = 0;
+        strncpy(buf, path, strlen(path));
+        buf[strlen(path)] = '\0';
+
+        ret = llapi_semantic_traverse(buf, NULL, cb_find_init,
+                                      cb_common_fini, param);
+
+        find_param_fini(param);
+        return ret < 0 ? ret : 0;
+}
+
+static int cb_getstripe(char *path, DIR *parent, DIR *d, void *data)
+{
+        struct find_param *param = (struct find_param *)data;
         int ret = 0;
 
-        memset(&param, 0, sizeof(param));
-        param.recursive = recursive;
-        param.verbose = verbose;
-        param.quiet = quiet;
-        param.process_file = find_process_file;
-        if (obduuid) {
-                param.obduuid = malloc(sizeof(*obduuid));
-                if (param.obduuid == NULL) {
-                        ret = ENOMEM;
+        LASSERT(parent != NULL || d != NULL);
+
+        /* Prepare odb. */
+        if (!param->got_uuids) {
+                ret = setup_obd_uuids(d ? d : parent, path, param);
+                if (ret)
+                        return ret;
+        }
+
+        if (d) {
+                ret = ioctl(dirfd(d), LL_IOC_LOV_GETSTRIPE,
+                            (void *)&param->lmd->lmd_lmm);
+        } else if (parent) {
+                char *fname = strrchr(path, '/') + 1;
+
+                strncpy((char *)&param->lmd->lmd_lmm, fname, param->lumlen);
+                ret = ioctl(dirfd(parent), IOC_MDC_GETFILESTRIPE,
+                            (void *)&param->lmd->lmd_lmm);
+        }
+
+        if (ret) {
+                if (errno == ENODATA) {
+                        if (!param->obduuid && !param->quiet)
+                                printf("%s has no stripe info\n", path);
                         goto out;
+                } else if (errno == ENOTTY) {
+                        fprintf(stderr, "%s: '%s' not on a Lustre fs?\n",
+                                __FUNCTION__, path);
+                } else {
+                        err_msg("error: %s: %s failed for %s", __FUNCTION__,
+                                d ? "LL_IOC_LOV_GETSTRIPE" :
+                                "IOC_MDC_GETFILESTRIPE", path);
                 }
-                memcpy(param.obduuid, obduuid, sizeof(*obduuid));
+
+                return ret;
         }
 
-        ret = prepare_find(&param);
+        llapi_lov_dump_user_lmm(param, path, d ? 1 : 0);
+out:
+        /* Do not get down anymore? */
+        if (param->depth == param->maxdepth)
+                return 1;
+
+        param->depth++;
+        return 0;
+}
+
+int llapi_getstripe(char *path, struct find_param *param)
+{
+        int ret = 0;
+
+        ret = common_param_init(param);
         if (ret)
-                goto out;
+                return ret;
 
-        process_path(path, &param);
-out:
-        cleanup_find(&param);
-        return ret;
+        param->depth = 0;
+        ret = llapi_semantic_traverse(path, NULL, cb_getstripe,
+                                      cb_common_fini, param);
+        find_param_fini(param);
+        return ret < 0 ? ret : 0;
 }
 
 int llapi_obd_statfs(char *path, __u32 type, __u32 index,
@@ -746,7 +971,7 @@ int llapi_obd_statfs(char *path, __u32 type, __u32 index,
                 err_msg("error: %s: opening '%s'", __FUNCTION__, path);
                 return rc;
         }
-        rc = ioctl(fd, LL_IOC_OBD_STATFS, (void *)rawbuf);
+        rc = ioctl(fd, IOC_OBD_STATFS, (void *)rawbuf);
         if (rc)
                 rc = -errno;
 
@@ -956,40 +1181,51 @@ int llapi_quotactl(char *mnt, struct if_quotactl *qctl)
         return rc;
 }
 
-static int quotachown_process_file(DIR *dir, char *dname, char *fname,
-                        struct find_param *param)
+static int cb_quotachown(char *path, DIR *parent, DIR *d, void *data)
 {
+        struct find_param *param = (struct find_param *)data;
         lstat_t *st;
-        char pathname[PATH_MAX + 1] = "";
         int rc;
 
-        strncpy((char *)param->lmd, fname, param->lumlen);
+        LASSERT(parent != NULL || d != NULL);
+
+        if (d) {
+                rc = ioctl(dirfd(d), LL_IOC_MDC_GETINFO,
+                           (void *)param->lmd);
+        } else if (parent) {
+                char *fname = strrchr(path, '/') + 1;
+
+                strncpy((char *)param->lmd, fname, param->lumlen);
+                rc = ioctl(dirfd(parent), IOC_MDC_GETFILEINFO,
+                           (void *)param->lmd);
+        } else {
+                return 0;
+        }
 
-        rc = ioctl(dirfd(dir), IOC_MDC_GETFILEINFO, (void *)param->lmd);
         if (rc) {
                 if (errno == ENODATA) {
                         if (!param->obduuid && !param->quiet)
-                                fprintf(stderr,
-                                        "%s/%s has no stripe info\n",
-                                        dname, fname);
+                                fprintf(stderr, "%s has no stripe info\n",
+                                        path);
                         rc = 0;
                 } else if (errno != EISDIR) {
-                        err_msg("IOC_MDC_GETFILEINFO ioctl failed");
+                        err_msg("%s ioctl failed for %s.",
+                                d ? "LL_IOC_MDC_GETINFO" :
+                                "IOC_MDC_GETFILEINFO", path);
                         rc = errno;
                 }
                 return rc;
         }
 
         st = &param->lmd->lmd_st;
-        snprintf(pathname, sizeof(pathname), "%s/%s", dname, fname);
 
         /* libc chown() will do extra check, and if the real owner is
          * the same as the ones to set, it won't fall into kernel, so
          * invoke syscall directly. */
-        rc = syscall(SYS_chown, pathname, st->st_uid, st->st_gid);
+        rc = syscall(SYS_chown, path, st->st_uid, st->st_gid);
         if (rc)
                 err_msg("error: chown %s (%u,%u)",
-                        pathname, st->st_uid, st->st_gid);
+                        path, st->st_uid, st->st_gid);
         return rc;
 }
 
@@ -1002,14 +1238,14 @@ int llapi_quotachown(char *path, int flag)
         param.recursive = 1;
         param.verbose = 0;
         param.quiet = 1;
-        param.process_file = quotachown_process_file;
 
-        ret = prepare_find(&param);
+        ret = common_param_init(&param);
         if (ret)
                 goto out;
 
-        process_path(path, &param);
+        ret = llapi_semantic_traverse(path, NULL, cb_quotachown,
+                                      NULL, &param);
 out:
-        cleanup_find(&param);
+        find_param_fini(&param);
         return ret;
 }
diff --git a/lustre/utils/llmount.c b/lustre/utils/llmount.c
deleted file mode 100644 (file)
index 1c10faa..0000000
+++ /dev/null
@@ -1,472 +0,0 @@
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- *  Copyright (C) 2002 Cluster File Systems, Inc.
- *   Author: Robert Read <rread@clusterfs.com>
- *
- *   This file is part of Lustre, http://www.lustre.org.
- *
- *   Lustre is free software; you can redistribute it and/or
- *   modify it under the terms of version 2 of the GNU General Public
- *   License as published by the Free Software Foundation.
- *
- *   Lustre is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with Lustre; if not, write to the Free Software
- *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-
-#define _GNU_SOURCE
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/mount.h>
-#include <mntent.h>
-#include <getopt.h>
-#include <sys/utsname.h>
-
-#include "obdctl.h"
-#include <lnet/lnetctl.h>
-
-int          verbose;
-int          nomtab;
-int          fake;
-int          force;
-int          retry;
-static char *progname = NULL;
-#define MAX_RETRIES 99
-
-void usage(FILE *out)
-{
-        fprintf(out, "%s v1.%d\n", progname, LMD_MAGIC & 0xFF);
-        fprintf(out, "usage: %s <mdsnode>[,<altmdsnode>]:/<mdsname>/<cfgname>"
-                " <mountpt> [-fhnv] [-o mntopt]\n", progname);
-        fprintf(out, "\t<mdsnode>: nid of MDS (config) node\n"
-                "\t<mdsname>: name of MDS service (e.g. mds1)\n"
-                "\t<cfgname>: name of client config (e.g. client)\n"
-                "\t<mountpt>: filesystem mountpoint (e.g. /mnt/lustre)\n"
-                "\t-f|--fake: fake mount (updates /etc/mtab)\n"
-                "\t--force: force mount even if already in /etc/mtab\n"
-                "\t-h|--help: print this usage message\n"
-                "\t-n|--nomtab: do not update /etc/mtab after mount\n"
-                "\t-v|--verbose: print verbose config settings\n"
-                "\t-o: filesystem mount options:\n"
-                "\t\tflock/noflock: enable/disable flock support\n"
-                "\t\troute=<gw>[-<gw>]:<low>[-<high>]: portal route to MDS\n"
-                "\t\tuser_xattr/nouser_xattr: enable/disable user extended "
-                "attributes\n"
-                );
-        exit(out != stdout);
-}
-
-static int check_mtab_entry(char *spec, char *mtpt, char *type)
-{
-        FILE *fp;
-        struct mntent *mnt;
-
-        if (!force) {
-                fp = setmntent(MOUNTED, "r");
-                if (fp == NULL)
-                        return(0);
-
-                while ((mnt = getmntent(fp)) != NULL) {
-                        if (strcmp(mnt->mnt_fsname, spec) == 0 &&
-                            strcmp(mnt->mnt_dir, mtpt) == 0 &&
-                            strcmp(mnt->mnt_type, type) == 0) {
-                                fprintf(stderr, "%s: according to %s %s is "
-                                        "already mounted on %s\n",
-                                        progname, MOUNTED, spec, mtpt);
-                                return(1); /* or should we return an error? */
-                        }
-                }
-                endmntent(fp);
-        }
-        return(0);
-}
-
-static int
-update_mtab_entry(char *spec, char *mtpt, char *type, char *opts,
-                  int flags, int freq, int pass)
-{
-        FILE *fp;
-        struct mntent mnt;
-        int rc = 0;
-
-        mnt.mnt_fsname = spec;
-        mnt.mnt_dir = mtpt;
-        mnt.mnt_type = type;
-        mnt.mnt_opts = opts ? opts : "";
-        mnt.mnt_freq = freq;
-        mnt.mnt_passno = pass;
-
-        fp = setmntent(MOUNTED, "a+");
-        if (fp == NULL) {
-                fprintf(stderr, "%s: setmntent(%s): %s:",
-                        progname, MOUNTED, strerror (errno));
-                rc = 16;
-        } else {
-                if ((addmntent(fp, &mnt)) == 1) {
-                        fprintf(stderr, "%s: addmntent: %s:",
-                                progname, strerror (errno));
-                        rc = 16;
-                } else if (verbose > 1) {
-                        fprintf(stderr, "%s: added %s on %s to %s\n",
-                                progname, spec, mtpt, MOUNTED);
-                }
-                endmntent(fp);
-        }
-
-        return rc;
-}
-
-int
-init_options(struct lustre_mount_data *lmd)
-{
-        memset(lmd, 0, sizeof(*lmd));
-        lmd->lmd_magic = LMD_MAGIC;
-        return 0;
-}
-
-int
-print_options(FILE *out, struct lustre_mount_data *lmd, const char *options)
-{
-        int i;
-        for (i = 0; i < lmd->lmd_nid_count; i++) {
-                fprintf(out, "mds nid %d:       %s\n", i,
-                        libcfs_nid2str(lmd->lmd_nid[i]));
-        }
-        fprintf(out, "mds name:        %s\n", lmd->lmd_mds);
-        fprintf(out, "profile:         %s\n", lmd->lmd_profile);
-        fprintf(out, "options:         %s\n", options);
-        fprintf(out, "retry:           %d\n", retry);
-
-        return 0;
-}
-
-static int parse_nids(struct lustre_mount_data *lmd, char *nids)
-{
-        int i = 0;
-        char *tmp = 0;
-        lnet_nid_t nid;
-
-        while ((tmp = strsep(&nids, ",:"))) {
-                nid = libcfs_str2nid(tmp);
-                if (nid == LNET_NID_ANY) {
-                        fprintf(stderr, "%s: Can't parse NID '%s'\n",
-                                progname, tmp);
-                        continue;
-                }
-                lmd->lmd_nid[lmd->lmd_nid_count++] = nid;
-                if (lmd->lmd_nid_count >= MAX_FAILOVER_NIDS) {
-                        fprintf(stderr, "%s: Too many target NIDs: "
-                                "ignoring nids after %s\n",
-                                progname, tmp);
-                        break;
-                }
-        }
-        return (lmd->lmd_nid_count);
-}
-
-
-/*****************************************************************************
- *
- * This part was cribbed from util-linux/mount/mount.c.  There was no clear
- * license information, but many other files in the package are identified as
- * GNU GPL, so it's a pretty safe bet that was their intent.
- *
- ****************************************************************************/
-struct opt_map {
-        const char *opt;        /* option name */
-        int skip;               /* skip in mtab option string */
-        int inv;                /* true if flag value should be inverted */
-        int ms_mask;            /* MS flag mask value */
-        int lmd_mask;           /* LMD flag mask value */
-};
-
-static const struct opt_map opt_map[] = {
-  { "defaults", 0, 0, 0, 0         },      /* default options */
-  { "rw",       1, 1, MS_RDONLY, 0 },      /* read-write */
-  { "ro",       0, 0, MS_RDONLY, 0 },      /* read-only */
-  { "exec",     0, 1, MS_NOEXEC, 0 },      /* permit execution of binaries */
-  { "noexec",   0, 0, MS_NOEXEC, 0 },      /* don't execute binaries */
-  { "suid",     0, 1, MS_NOSUID, 0 },      /* honor suid executables */
-  { "nosuid",   0, 0, MS_NOSUID, 0 },      /* don't honor suid executables */
-  { "dev",      0, 1, MS_NODEV,  0 },      /* interpret device files  */
-  { "nodev",    0, 0, MS_NODEV,  0 },      /* don't interpret devices */
-  { "async",    0, 1, MS_SYNCHRONOUS, 0},  /* asynchronous I/O */
-  { "auto",     0, 0, 0, 0         },      /* Can be mounted using -a */
-  { "noauto",   0, 0, 0, 0         },      /* Can only be mounted explicitly */
-  { "nousers",  0, 1, 0, 0         },      /* Forbid ordinary user to mount */
-  { "nouser",   0, 1, 0, 0         },      /* Forbid ordinary user to mount */
-  { "noowner",  0, 1, 0, 0         },      /* Device owner has no special privs */
-  { "_netdev",  0, 0, 0, 0         },      /* Device accessible only via network */
-  { "flock",    0, 0, 0, LMD_FLG_FLOCK},   /* Enable flock support */
-  { "noflock",  1, 1, 0, LMD_FLG_FLOCK},   /* Disable flock support */
-  { "user_xattr", 0, 0, 0, LMD_FLG_USER_XATTR}, /* Enable get/set user xattr */
-  { "nouser_xattr", 1, 1, 0, LMD_FLG_USER_XATTR}, /* Disable user xattr */
-  { "acl",      0, 0, 0, LMD_FLG_ACL},     /* Enable ACL support */
-  { "noacl",    1, 1, 0, LMD_FLG_ACL},     /* Disable ACL support */
-  /* please add new mount options to usage message */
-  { NULL,       0, 0, 0, 0         }
-};
-/****************************************************************************/
-
-static int parse_one_option(const char *check, int *ms_flags, int *lmd_flags)
-{
-        const struct opt_map *opt;
-
-        for (opt = &opt_map[0]; opt->opt != NULL; opt++) {
-                if (strcmp(check, opt->opt) == 0) {
-                        if (opt->inv) {
-                                *ms_flags &= ~(opt->ms_mask);
-                                *lmd_flags &= ~(opt->lmd_mask);
-                        } else {
-                                *ms_flags |= opt->ms_mask;
-                                *lmd_flags |= opt->lmd_mask;
-                        }
-                        return 1;
-                }
-        }
-        return 0;
-}
-
-int parse_options(char *options, struct lustre_mount_data *lmd, int *flagp)
-{
-        int val;
-        char *opt, *opteq;
-
-        *flagp = 0;
-        /* parsing ideas here taken from util-linux/mount/nfsmount.c */
-        for (opt = strtok(options, ","); opt; opt = strtok(NULL, ",")) {
-                if ((opteq = strchr(opt, '='))) {
-                        val = atoi(opteq + 1);
-                        *opteq = '\0';
-                        if (!strcmp(opt, "retry")) {
-                                if (val >= 0 || val < MAX_RETRIES)
-                                        retry = val;
-                                else
-                                        retry = 0;
-                        } else {
-                                fprintf(stderr, "%s: unknown option '%s'. "
-                                        "Ignoring.\n", progname, opt);
-                                /* Ignore old nettype= for now 
-                                usage(stderr);
-                                */
-                        }
-                } else {
-                        if (parse_one_option(opt, flagp, &lmd->lmd_flags))
-                                continue;
-
-                        fprintf(stderr, "%s: unknown option '%s'\n",
-                                progname, opt);
-                        usage(stderr);
-                }
-        }
-        return 0;
-}
-
-int
-build_data(char *source, char *options, struct lustre_mount_data *lmd,
-           int *flagp)
-{
-        char  buf[1024];
-        char *nid = NULL;
-        char *mds = NULL;
-        char *profile = NULL;
-        char *s;
-        int   rc;
-
-        if (lmd_bad_magic(lmd))
-                return 4;
-
-        if (strlen(source) >= sizeof(buf)) {
-                fprintf(stderr, "%s: nid:/mds/profile argument too long\n",
-                        progname);
-                return 1;
-        }
-        strcpy(buf, source);
-        if ((s = strchr(buf, ':'))) {
-                nid = buf;
-                *s = '\0';
-
-                while (*++s == '/')
-                        ;
-                mds = s;
-                if ((s = strchr(mds, '/'))) {
-                        *s = '\0';
-                        profile = s + 1;
-                } else {
-                        fprintf(stderr, "%s: directory to mount not in "
-                                "nid:/mds/profile format\n",
-                                progname);
-                        return(1);
-                }
-        } else {
-                fprintf(stderr, "%s: "
-                        "directory to mount not in nid:/mds/profile format\n",
-                        progname);
-                return(1);
-        }
-
-        rc = parse_options(options, lmd, flagp);
-        if (rc)
-                return rc;
-
-        if (parse_nids(lmd, nid) == 0) {
-                fprintf(stderr, "%s: Can't parse any mds nids\n", progname);
-                return(1);
-        }
-
-        if (strlen(mds) + 1 > sizeof(lmd->lmd_mds)) {
-                fprintf(stderr, "%s: mds name too long\n", progname);
-                return(1);
-        }
-        strcpy(lmd->lmd_mds, mds);
-
-        if (strlen(profile) + 1 > sizeof(lmd->lmd_profile)) {
-                fprintf(stderr, "%s: profile name too long\n", progname);
-                return(1);
-        }
-        strcpy(lmd->lmd_profile, profile);
-
-        return 0;
-}
-
-int main(int argc, char *const argv[])
-{
-        char *source, *target, *options = "", optbuf[65536] = { '\0' };
-        int i, nargs = 3, opt, rc, flags, buflen = sizeof(optbuf) - 1;
-        struct lustre_mount_data lmd;
-        static struct option long_opt[] = {
-                {"fake", 0, 0, 'f'},
-                {"force", 0, 0, 1},
-                {"help", 0, 0, 'h'},
-                {"nomtab", 0, 0, 'n'},
-                {"options", 1, 0, 'o'},
-                {"verbose", 0, 0, 'v'},
-                {0, 0, 0, 0}
-        };
-
-        progname = strrchr(argv[0], '/');
-        progname = progname ? progname + 1 : argv[0];
-
-        while ((opt = getopt_long(argc, argv, "fhno:v", long_opt,NULL)) != EOF){
-                switch (opt) {
-                case 1:
-                        ++force;
-                        if (verbose)
-                                printf("force: %d\n", force);
-                        nargs++;
-                        break;
-                case 'f':
-                        ++fake;
-                        if (verbose)
-                                printf("fake: %d\n", fake);
-                        nargs++;
-                        break;
-                case 'h':
-                        usage(stdout);
-                        break;
-                case 'n':
-                        ++nomtab;
-                        if (verbose)
-                                printf("nomtab: %d\n", nomtab);
-                        nargs++;
-                        break;
-                case 'o':
-                        options = optarg;
-                        nargs++;
-                        break;
-                case 'v':
-                        ++verbose;
-                        printf("verbose: %d\n", verbose);
-                        nargs++;
-                        break;
-                default:
-                        fprintf(stderr, "%s: unknown option '%c'\n",
-                                progname, opt);
-                        usage(stderr);
-                        break;
-                }
-        }
-
-        if (optind + 2 > argc) {
-                fprintf(stderr, "%s: too few arguments\n", progname);
-                usage(stderr);
-        }
-
-        source = argv[optind];
-        target = argv[optind + 1];
-
-        if (verbose) {
-                for (i = 0; i < argc; i++)
-                        printf("arg[%d] = %s\n", i, argv[i]);
-                printf("source = %s, target = %s\n", source, target);
-        }
-
-        if (!force && check_mtab_entry(source, target, "lustre"))
-                exit(32);
-
-        init_options(&lmd);
-
-        /* need to copy options, as parse_options->strtok() clobbers it
-         * and we can't use it later to put in /etc/mtab. */
-        if (strlen(options) > buflen)
-                fprintf(stderr, "%s: options too long (%d > %d), ignore last\n",
-                        progname, strlen(options), buflen);
-        strncpy(optbuf, options, buflen);
-
-        rc = build_data(source, optbuf, &lmd, &flags);
-        if (rc) {
-                exit(1);
-        }
-
-        if (verbose)
-                print_options(stdout, &lmd, options);
-
-        rc = access(target, F_OK);
-        if (rc) {
-                rc = errno;
-                fprintf(stderr, "%s: %s inaccessible: %s\n", progname, target,
-                        strerror(errno));
-                return 1;
-        }
-
-        if (!fake) {
-                FILE *modpipe = popen("/sbin/modprobe -q llite", "r");
-                if (modpipe != NULL)
-                        pclose(modpipe);
-                /* use <= to include the initial mount before we retry */
-                for (i = 0, rc = -EAGAIN; i <= retry && rc != 0; i++)
-                        rc = mount(source, target, "lustre", flags, &lmd);
-        }
-        if (rc) {
-                fprintf(stderr, "%s: mount(%s, %s) failed: %s\n", progname,
-                        source, target, strerror(errno));
-                print_options(stderr, &lmd, options);
-                if (errno == ENODEV) {
-                        struct utsname unamebuf;
-                        char *modfile = "/etc/modutils.conf";
-
-                        if (uname(&unamebuf) == 0 &&
-                            strncmp(unamebuf.release, "2.4", 3) == 0)
-                                modfile = "/etc/modules.conf";
-
-                        fprintf(stderr, "Are the lustre modules loaded?\n"
-                                "Check %s and /proc/filesystems\n");
-                }
-                rc = 32;
-        } else if (!nomtab) {
-                rc = update_mtab_entry(source, target, "lustre", options,0,0,0);
-        }
-        return rc;
-}
index b42c8a3..be8fba7 100755 (executable)
@@ -73,7 +73,7 @@ sub get_cpumhz()
 get_cpumhz();
 print "Processor counters run at $mhz MHz\n";
 
-sub readall()
+sub readstat()
 {
        my $prevcount;
        my @iodata;
@@ -101,6 +101,7 @@ sub readall()
                }
        }
 }
+
 sub process_stats()
 {
        my $delta;
@@ -149,7 +150,7 @@ sub process_stats()
 
 open(STATS, $statspath) || die "Cannot open $statspath: $!\n";
 do {
-       readall();
+       readstat();
        process_stats();
        if ($interval) { 
                sleep($interval);
@@ -157,4 +158,3 @@ do {
        }
 } while ($interval);
 close STATS;
-
index 9bcf577..15b84ff 100644 (file)
@@ -1,7 +1,7 @@
 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
  * vim:expandtab:shiftwidth=8:tabstop=8:
  *
- *  Copyright (C) 2002 Cluster File Systems, Inc.
+ *  Copyright (C) 2006 Cluster File Systems, Inc.
  *
  *   This file is part of Lustre, http://www.lustre.org.
  *
@@ -19,6 +19,7 @@
  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  */
+ /* Interpret configuration llogs */
 
 
 #include <stdio.h>
 #include <liblustre.h>
 #include <lustre/lustre_idl.h>
 
-int llog_pack_buffer(int fd, struct llog_log_hdr** llog_buf, struct llog_rec_hdr*** recs, int* recs_number);
+int llog_pack_buffer(int fd, struct llog_log_hdr **llog_buf,
+                     struct llog_rec_hdr ***recs, int *recs_number);
 
-void print_llog_header(struct llog_log_hdr* llog_buf);
-void print_records(struct llog_rec_hdr** recs_buf,int rec_number);
-void llog_unpack_buffer(int fd,struct llog_log_hdr* llog_buf,struct llog_rec_hdr** recs_buf);
+void print_llog_header(struct llog_log_hdr *llog_buf);
+void print_records(struct llog_rec_hdr **recs_buf,int rec_number);
+void llog_unpack_buffer(int fd, struct llog_log_hdr *llog_buf,
+                        struct llog_rec_hdr **recs_buf);
 
 #define PTL_CMD_BASE 100
 char* portals_command[17]=
@@ -57,37 +60,36 @@ char* portals_command[17]=
         "GET_INTERFACE",
         ""
 };
-                
+
 int main(int argc, char **argv)
 {
-        int rc=0;
-        int fd,rec_number;
-        
-        struct llog_log_hdr* llog_buf=NULL;
-        struct llog_rec_hdr** recs_buf=NULL;
-                
+        int rc = 0;
+        int fd, rec_number;
+        struct llog_log_hdr *llog_buf = NULL;
+        struct llog_rec_hdr **recs_buf = NULL;
 
         setlinebuf(stdout);
-        
+
         if(argc != 2 ){
-                printf("Usage: llog_reader filename \n");
+                printf("Usage: llog_reader filename\n");
                 return -1;
         }
-        
+
         fd = open(argv[1],O_RDONLY);
         if (fd < 0){
-                printf("Could not open the file %s \n",argv[1]);
+                printf("Could not open the file %s\n", argv[1]);
                 goto out;
         }
         rc = llog_pack_buffer(fd, &llog_buf, &recs_buf, &rec_number);
-                
-        if(llog_buf == NULL )
-                printf("error");
+        if (rc < 0) {
+                printf("Could not pack buffer; rc=%d\n", rc);
+                goto out_fd;
+        }
+
         print_llog_header(llog_buf);
-        
         print_records(recs_buf,rec_number);
-
         llog_unpack_buffer(fd,llog_buf,recs_buf);
+out_fd:
         close(fd);
 out:
         return rc;
@@ -95,31 +97,31 @@ out:
 
 
 
-int llog_pack_buffer(int fd, struct llog_log_hdr** llog, 
-                     struct llog_rec_hdr*** recs, 
-                     intrecs_number)
+int llog_pack_buffer(int fd, struct llog_log_hdr **llog,
+                     struct llog_rec_hdr ***recs,
+                     int *recs_number)
 {
-        int rc=0,recs_num,rd;
+        int rc = 0, recs_num,rd;
         off_t file_size;
         struct stat st;
-        char  *file_buf=NULL, *recs_buf=NULL;
-        struct llog_rec_hdr** recs_pr=NULL;
-        charptr=NULL;
+        char *file_buf=NULL, *recs_buf=NULL;
+        struct llog_rec_hdr **recs_pr=NULL;
+        char *ptr=NULL;
         int cur_idx,i;
-        
+
         rc = fstat(fd,&st);
         if (rc < 0){
                 printf("Get file stat error.\n");
                 goto out;
-        }       
+        }
         file_size = st.st_size;
-        
+
         file_buf = malloc(file_size);
         if (file_buf == NULL){
                 printf("Memory Alloc for file_buf error.\n");
                 rc = -ENOMEM;
                 goto out;
-        }       
+        }
         *llog = (struct llog_log_hdr*)file_buf;
 
         rd = read(fd,file_buf,file_size);
@@ -127,40 +129,37 @@ int llog_pack_buffer(int fd, struct llog_log_hdr** llog,
                 printf("Read file error.\n");
                 rc = -EIO; /*FIXME*/
                 goto clear_file_buf;
-        }       
+        }
 
         /* the llog header not countable here.*/
         recs_num = le32_to_cpu((*llog)->llh_count)-1;
-        
-        recs_buf = malloc(recs_num*sizeof(struct llog_rec_hdr*));
+
+        recs_buf = malloc(recs_num * sizeof(struct llog_rec_hdr *));
         if (recs_buf == NULL){
                 printf("Memory Alloc for recs_buf error.\n");
                 rc = -ENOMEM;
                 goto clear_file_buf;
-        }       
+        }
         recs_pr = (struct llog_rec_hdr **)recs_buf;
-        
+
         ptr = file_buf + le32_to_cpu((*llog)->llh_hdr.lrh_len);
         cur_idx = 1;
         i = 0;
-        while (i < recs_num){   
-                struct llog_rec_hdr* cur_rec=(struct llog_rec_hdr*)ptr;
 
-                while(!ext2_test_bit(cur_idx,(*llog)->llh_bitmap)){
-                        cur_idx++;
+        while (i < recs_num){
+                struct llog_rec_hdr *cur_rec = (struct llog_rec_hdr*)ptr;
+
+                if (ext2_test_bit(cur_idx++, (*llog)->llh_bitmap)) {
+                        recs_pr[i++] = cur_rec;
                         ptr += cur_rec->lrh_len;
-                        if ((ptr-file_buf) > file_size){
-                                printf("The log is corrupted. \n");
+                        if ((ptr - file_buf) > file_size) {
+                                printf("The log is corrupted.\n");
                                 rc = -EINVAL;
                                 goto clear_recs_buf;
-                        }       
+                        }
                 }
-                recs_pr[i] = cur_rec;
-                ptr+=cur_rec->lrh_len;
-                i++;
-                cur_idx++;
         }
-        
+
         *recs = recs_pr;
         *recs_number=recs_num;
 
@@ -175,36 +174,33 @@ clear_file_buf:
 
         *llog=NULL;
         goto out;
-
 }
 
-
-void llog_unpack_buffer(int fd,struct llog_log_hdr* llog_buf,struct llog_rec_hdr **recs_buf)
+void llog_unpack_buffer(int fd, struct llog_log_hdr *llog_buf,
+                        struct llog_rec_hdr **recs_buf)
 {
         free(llog_buf);
         free(recs_buf);
         return;
 }
 
-
-void print_llog_header(struct llog_log_hdr* llog_buf)
+void print_llog_header(struct llog_log_hdr *llog_buf)
 {
         time_t t;
 
-        printf("Header size : %d \n",
-        //              le32_to_cpu(llog_buf->llh_hdr.lrh_len));
+        printf("Header size : %u\n",
                 llog_buf->llh_hdr.lrh_len);
 
         t = le64_to_cpu(llog_buf->llh_timestamp);
         printf("Time : %s", ctime(&t));
 
-        printf("Number of records: %d\n",
+        printf("Number of records: %u\n",
                le32_to_cpu(llog_buf->llh_count)-1);
 
         printf("Target uuid : %s \n",
                (char *)(&llog_buf->llh_tgtuuid));
 
-        /* Add the other infor you want to view here*/
+        /* Add the other info you want to view here */
 
         printf("-----------------------\n");
         return;
@@ -213,13 +209,14 @@ void print_llog_header(struct llog_log_hdr* llog_buf)
 static void print_1_cfg(struct lustre_cfg *lcfg)
 {
         int i;
+
         if (lcfg->lcfg_nid)
                 printf("nid=%s("LPX64")  ", libcfs_nid2str(lcfg->lcfg_nid),
                        lcfg->lcfg_nid);
         if (lcfg->lcfg_nal)
                 printf("nal=%d ", lcfg->lcfg_nal);
         for (i = 0; i <  lcfg->lcfg_bufcount; i++)
-                printf("%d:%.*s  ", i, lcfg->lcfg_buflens[i], 
+                printf("%d:%.*s  ", i, lcfg->lcfg_buflens[i],
                        (char*)lustre_cfg_buf(lcfg, i));
         return;
 }
@@ -227,27 +224,19 @@ static void print_1_cfg(struct lustre_cfg *lcfg)
 
 static void print_setup_cfg(struct lustre_cfg *lcfg)
 {
-        char *name = lustre_cfg_string(lcfg, 0);
-        char *type = name + strlen(name) - 3;
-        if (!strcmp(type,"lov")){
-                struct lov_desc *lovdesc;
+        struct lov_desc *desc;
+
+        if ((lcfg->lcfg_bufcount == 2) &&
+            (lcfg->lcfg_buflens[1] == sizeof(*desc))) {
                 printf("lov_setup ");
-                printf("0:%s  ", name);
+                printf("0:%s  ", lustre_cfg_string(lcfg, 0));
                 printf("1:(struct lov_desc)\n");
-                lovdesc = (struct lov_desc*)(lustre_cfg_string(lcfg, 1));
-                printf("\t\tuuid=%s  ", (char*)lovdesc->ld_uuid.uuid);
-                printf("stripe:cnt=%d ", lovdesc->ld_default_stripe_count);
-                printf("size=%lld ", lovdesc->ld_default_stripe_size);
-                printf("offset=%lld ", lovdesc->ld_default_stripe_offset);
-                printf("pattern=%d", lovdesc->ld_pattern);
-        } else if (!strcmp(type,"lmv")){
-                struct lmv_desc *lmvdesc;
-                printf("lmv_setup ");
-                printf("0:%s  ", name);
-                printf("1:(struct lmv_desc)\n");
-                lmvdesc = (struct lmv_desc*)(lustre_cfg_string(lcfg, 1));
-                printf("count=%d ", lmvdesc->ld_tgt_count);
-                printf("atcive_count=%d", lmvdesc->ld_active_tgt_count);
+                desc = (struct lov_desc*)(lustre_cfg_string(lcfg, 1));
+                printf("\t\tuuid=%s  ", (char*)desc->ld_uuid.uuid);
+                printf("stripe:cnt=%u ", desc->ld_default_stripe_count);
+                printf("size="LPU64" ", desc->ld_default_stripe_size);
+                printf("offset="LPU64" ", desc->ld_default_stripe_offset);
+                printf("pattern=%#x", desc->ld_pattern);
         } else {
                 printf("setup ");
                 print_1_cfg(lcfg);
@@ -259,7 +248,7 @@ static void print_setup_cfg(struct lustre_cfg *lcfg)
 void print_lustre_cfg(struct lustre_cfg *lcfg, int *skip)
 {
         enum lcfg_command_type cmd = le32_to_cpu(lcfg->lcfg_command);
-        
+
         if (*skip > 0)
                 printf("SKIP ");
 
@@ -357,8 +346,13 @@ void print_lustre_cfg(struct lustre_cfg *lcfg, int *skip)
                         if (marker->cm_flags & CM_END)
                                 (*skip)--;
                 }
-                printf("marker %d (flags=%#x) %.16s '%s' %s:%s", marker->cm_step,
-                       marker->cm_flags, marker->cm_svname, 
+                printf("marker %d (flags=%#x, v%d.%d.%d.%d) %.16s '%s' %s:%s",
+                       marker->cm_step, marker->cm_flags,
+                       OBD_OCD_VERSION_MAJOR(marker->cm_vers),
+                       OBD_OCD_VERSION_MINOR(marker->cm_vers),
+                       OBD_OCD_VERSION_PATCH(marker->cm_vers),
+                       OBD_OCD_VERSION_FIX(marker->cm_vers),
+                       marker->cm_svname, 
                        marker->cm_comment, ctime(&marker->cm_createtime),
                        marker->cm_canceltime ? 
                        ctime(&marker->cm_canceltime) : "");
@@ -371,27 +365,25 @@ void print_lustre_cfg(struct lustre_cfg *lcfg, int *skip)
         return;
 }
 
-void print_records(struct llog_rec_hdr** recs,int rec_number)
+void print_records(struct llog_rec_hdr **recs, int rec_number)
 {
         __u32 lopt;
         int i, skip = 0;
         
-        for(i = 0; i < rec_number; i++){
-        
+        for(i = 0; i < rec_number; i++) {
                 printf("#%.2d ", le32_to_cpu(recs[i]->lrh_index));
 
                 lopt = le32_to_cpu(recs[i]->lrh_type);
 
                 if (lopt == OBD_CFG_REC){
                         struct lustre_cfg *lcfg;
-                        printf("L "); 
-                        lcfg = (struct lustre_cfg *)
-                                ((char*)(recs[i]) + sizeof(struct llog_rec_hdr));
+                        printf("L ");
+                        lcfg = (struct lustre_cfg *)((char*)(recs[i]) +
+                                                     sizeof(struct llog_rec_hdr));
                         print_lustre_cfg(lcfg, &skip);
                 }
 
-                if (lopt == PTL_CFG_REC){
-                        printf("Portals - unknown type\n"); 
-                }
+                if (lopt == PTL_CFG_REC)
+                        printf("Portals - unknown type\n");
         }
 }
index 7c3855a..0305f3d 100755 (executable)
@@ -2,6 +2,9 @@
 
 my $pname = $0;
 
+my $defaultpath = "/proc/fs/lustre";
+my $obdstats = "stats";
+
 sub usage()
 {
     print STDERR "Usage: $pname <stats_file> [<interval>]\n";
@@ -9,19 +12,41 @@ sub usage()
 }
 
 
-my $statspath;
+my $statspath = "None";
 my $interval = 0;
 
 if (($#ARGV < 0) || ($#ARGV > 1)) {
     usage();
 } else {
-    $statspath = $ARGV[0];
+    if ( $ARGV[0] =~ /help$/ ) {
+       usage();
+    }
+    if ( -f $ARGV[0] ) {
+       $statspath = $ARGV[0];
+    } elsif ( -f "$ARGV[0]/$obdstats" ) {
+       $statspath = "$ARGV[0]/$obdstats";
+    } else {
+       my $st = `ls $defaultpath/*/$ARGV[0]/$obdstats 2> /dev/null`;
+       chop $st;
+       if ( -f "$st" ) {
+           $statspath = $st;
+       } else {
+           $st = `ls $defaultpath/*/*/$ARGV[0]/$obdstats 2> /dev/null`;
+           chop $st;
+           if ( -f "$st" ) {
+               $statspath = $st;
+           }
+       }
+    }
+    if ( $statspath =~ /^None$/ ) {
+       die "Cannot locate stat file for: $ARGV[0]\n";
+    }
     if ($#ARGV == 1) {
        $interval = $ARGV[1];
     } 
 }
 
-
+print "$pname on $statspath\n";
 
 my %cumulhash;
 my %sumhash;
@@ -43,6 +68,7 @@ sub get_cpumhz()
     if (defined($itc_freq)) { $mhz = $itc_freq; }
     elsif (defined($cpu_freq)) { $mhz = $cpu_freq; }
     else { $mhz = 1; }
+    close CPUINFO;
 }
 
 get_cpumhz();
@@ -50,7 +76,7 @@ print "Processor counters run at $mhz MHz\n";
 
 sub readstat()
 {
-    open(STATS, $statspath) || die "Cannot open $statspath: $!\n";
+    seek STATS, 0, 0;
     while (<STATS>) {
        chop;
        ($name, $cumulcount, $samples, $unit, $min, $max, $sum, $sumsquare) 
@@ -125,9 +151,11 @@ sub readstat()
     }
 }
 
+open(STATS, $statspath) || die "Cannot open $statspath: $!\n";
 do {
     readstat();
     if ($interval) { 
        sleep($interval);
     }
 } while ($interval);
+close STATS;
diff --git a/lustre/utils/llverdev.c b/lustre/utils/llverdev.c
new file mode 100644 (file)
index 0000000..b3af06f
--- /dev/null
@@ -0,0 +1,552 @@
+/*
+ * Large Block Device Verification Tool.
+ * This program is used to test whether the block device is correctly
+ * handling IO beyond 2TB boundary.
+ * This tool have two working modes
+ * 1. full mode
+ * 2. fast mode
+ *     The full mode is basic mode in which program writes the test pattern
+ * on entire disk. The test pattern (device offset and timestamp) is written
+ * at the beginning of each 4kB block. When the whole device is full then
+ * read operation is performed to verify that the test pattern is correct.
+ *     In the fast mode the program writes data at the critical locations
+ * of the device such as start of the device, before and after multiple of 1GB
+ * offset and at the end.
+ *     A chunk buffer with default size of 1MB is used to write and read test
+ * pattern in bulk.
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#ifndef LUSTRE_UTILS
+#define LUSTRE_UTILS
+#endif
+#ifndef _LARGEFILE64_SOURCE
+#define _LARGEFILE64_SOURCE
+#endif
+#ifndef _FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 64
+#endif
+
+#include <features.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mount.h>
+#include <sys/time.h>
+#include <gnu/stubs.h>
+
+#ifdef HAVE_EXT2FS_EXT2FS_H
+#  include <ext2fs/ext2fs.h>
+#endif
+
+#define ONE_MB (1024 * 1024)
+#define ONE_GB (1024 * 1024 * 1024)
+#define HALF_MB (ONE_MB / 2)
+#define ONE_KB 1024
+#define HALF_KB (ONE_KB / 2)
+#define BLOCKSIZE 4096
+
+/* Structure for writting test pattern */
+struct block_data {
+       long long  bd_offset;
+       time_t  bd_time;
+};
+static char *progname;         /* name by which this program was run. */
+static unsigned verbose = 1;   /* prints offset in kB, operation rate */
+static int readoption;         /* run test in read-only (verify) mode */
+static int writeoption;                /* run test in write_only mode */
+const char *devname;           /* name of device to be tested. */
+static unsigned full = 1;      /* flag to full check */
+static int fd;
+static int isatty_flag;
+
+static struct option const longopts[] =
+{
+       { "chunksize", required_argument, 0, 'c' },
+       { "force", no_argument, 0, 'f' },
+       { "help", no_argument, 0, 'h' },
+       { "offset", required_argument, 0, 'o' },
+       { "partial", required_argument, 0, 'p' },
+       { "quiet", required_argument, 0, 'q' },
+       { "read", no_argument, 0, 'r' },
+       { "timestamp", required_argument, 0, 't' },
+       { "verbose", no_argument, 0, 'v' },
+       { "write", no_argument, 0, 'w' },
+       { "long", no_argument, 0, 'l' },
+       { 0, 0, 0, 0}
+};
+
+/*
+ * Usage: displays help information, whenever user supply --help option in
+ * command or enters incorrect command line.
+ */
+void usage(int status)
+{
+       if (status != 0) {
+             printf("\nUsage: %s [OPTION]... <device-name> ...\n",
+                    progname);
+             printf("Block device verification tool.\n"
+                    "\t-t {seconds}, --timestamp, "
+                    "set test time  (default=current time())\n"
+                    "\t-o {offset}, --offset, "
+                    "offset in kB of start of test, default=0\n"
+                    "\t-r, --read run test in verify mode\n"
+                    "\t-w, --write run test in test-pattern mode, default=rw\n"
+                    "\t-v, --verbose\n"
+                    "\t-q, --quiet\n"
+                    "\t-l, --long, full check of device\n"
+                    "\t-p, --partial, for partial check (1GB steps)\n"
+                    "\t-c, --chunksize, IO chunk size, default=1048576\n"
+                    "\t-f, --force, force test to run without confirmation\n"
+                    "\t-h, --help display this help and exit\n");
+       }
+       exit(status);
+}
+
+/*
+ * Open_dev: Opens device in specified mode and returns fd.
+ */
+static int open_dev(const char *devname, int mode)
+{
+#ifdef HAVE_EXT2FS_EXT2FS_H
+       int     mount_flags;
+       char    mountpt[80] = "";
+
+       if (ext2fs_check_mount_point(devname, &mount_flags, mountpt,
+                                    sizeof(mountpt))) {
+               fprintf(stderr, "%s: ext2fs_check_mount_point failed:%s",
+                       progname, strerror(errno));
+               exit(1);
+       }
+       if (mount_flags & EXT2_MF_MOUNTED){
+               fprintf(stderr, "%s: %s is already mounted\n", progname,
+                       devname);
+               exit(1);
+       }
+#endif
+       fd = open(devname, mode | O_EXCL | O_LARGEFILE);
+       if (fd < 0) {
+               fprintf(stderr, "%s: Open failed: %s",progname,strerror(errno));
+               exit(3);
+       }
+       return (fd);
+}
+
+#ifdef HAVE_BLKID_BLKID_H
+#include <blkid/blkid.h>
+#endif
+/*
+ * sizeof_dev: Returns size of device in bytes
+ */
+static loff_t sizeof_dev(int fd)
+{
+       loff_t numbytes;
+
+#ifdef HAVE_BLKID_BLKID_H
+       numbytes = blkid_get_dev_size(fd);
+       if (numbytes <= 0) {
+               fprintf(stderr, "%s: blkid_get_dev_size(%s) failed",
+                       progname, devname);
+               return 1;
+       }
+       goto out;
+#else
+# if defined BLKGETSIZE64      /* in sys/mount.h */
+       if (ioctl(fd, BLKGETSIZE64, &numbytes) >= 0)
+               goto out;
+# endif
+# if defined BLKGETSIZE                /* in sys/mount.h */
+       {
+               unsigned long sectors;
+
+               if (ioctl(fd, BLKGETSIZE, &sectors) >= 0) {
+                       numbytes = (loff_t)sectors << 9;
+                       goto out;
+               }
+       }
+# endif
+       {
+               struct stat statbuf;
+
+               if (fstat(fd, &statbuf) == 0 && S_ISREG(statbuf.st_mode)) {
+                       numbytes = statbuf.st_size;
+                       goto out;
+               }
+       }
+       fprintf(stderr, "%s: unable to determine size of %s\n",
+                       progname, devname);
+       return 0;
+#endif
+
+out:
+       if (verbose)
+               printf("%s: %s is %llu bytes (%g GB) in size\n",
+                      progname, devname,
+                      (unsigned long long)numbytes, (double)numbytes / ONE_GB);
+
+       return numbytes;
+}
+
+/*
+ * Verify_chunk: Verifies test pattern in each 4kB (BLOCKSIZE) is correct.
+ * Returns 0 if test offset and timestamp is correct otherwise 1.
+ */
+int verify_chunk(char *chunk_buf, size_t chunksize,
+                unsigned long long chunk_off, time_t time_st)
+{
+       struct block_data *bd;
+       char *chunk_end;
+
+       for (chunk_end = chunk_buf + chunksize - sizeof(*bd);
+            (char *)chunk_buf < chunk_end;
+            chunk_buf += BLOCKSIZE, chunk_off += BLOCKSIZE) {
+               bd = (struct block_data *)chunk_buf;
+               if ((bd->bd_offset == chunk_off) && (bd->bd_time == time_st))
+                       continue;
+
+               fprintf(stderr, "\n%s: verify failed at offset/timestamp "
+                       "%llu/%lu: found %llu/%lu instead\n", progname,
+                       chunk_off, time_st, bd->bd_offset, bd->bd_time);
+               return 1;
+       }
+       return 0;
+}
+
+/*
+ * fill_chunk: Fills the chunk with current or user specified timestamp
+ * and  offset. The test patters is filled at the beginning of
+ * each 4kB(BLOCKSIZE) blocks in chunk_buf.
+ */
+void fill_chunk(char *chunk_buf, size_t chunksize, loff_t chunk_off,
+               time_t time_st)
+{
+       struct block_data *bd;
+       char *chunk_end;
+
+       for (chunk_end = chunk_buf + chunksize - sizeof(*bd);
+            (char *)chunk_buf < chunk_end;
+            chunk_buf += BLOCKSIZE, chunk_off += BLOCKSIZE) {
+               bd = (struct block_data *)chunk_buf;
+               bd->bd_offset = chunk_off;
+               bd->bd_time = time_st;
+       }
+}
+
+void show_rate(char *op, unsigned long long offset, unsigned long long *count)
+{
+       static time_t last;
+       time_t now;
+       double diff;
+
+       now = time(NULL);
+       diff = now - last;
+
+       if (diff > 4) {
+               if (last != 0) {
+                       if (isatty_flag)
+                               printf("\r");
+                       printf("%s offset: %14llukB %5g MB/s            ", op,
+                              offset / ONE_KB, (double)(*count) /ONE_MB /diff);
+                       if (isatty_flag)
+                               fflush(stdout);
+                       else
+                               printf("\n");
+
+                       *count = 0;
+               }
+               last = now;
+       }
+}
+
+/*
+ * write_chunk: write the chunk_buf on the device. The number of write
+ * operations are based on the parameters write_end, offset, and chunksize.
+ */
+int write_chunks(unsigned long long offset, unsigned long long write_end,
+                char *chunk_buf, size_t chunksize, time_t time_st)
+{
+       unsigned long long stride, count = 0;
+
+       stride = full ? chunksize : (ONE_GB - chunksize);
+
+       for (offset = offset & ~(chunksize - 1); offset < write_end;
+            offset += stride) {
+               if (lseek64(fd, offset, SEEK_SET) == -1) {
+                       fprintf(stderr, "\n%s: lseek64(%llu) failed: %s\n",
+                               progname, offset, strerror(errno));
+                       return 1;
+               }
+               if (offset + chunksize > write_end)
+                       chunksize = write_end - offset;
+
+               if (!full && offset > chunksize) {
+                       fill_chunk(chunk_buf, chunksize, offset, time_st);
+                       if (write(fd, chunk_buf, chunksize) < 0) {
+                               fprintf(stderr, "\n%s: write %llu failed: %s\n",
+                                       progname, offset, strerror(errno));
+                               return 1;
+                       }
+                       offset += chunksize;
+                       if (offset + chunksize > write_end)
+                               chunksize = write_end - offset;
+               }
+
+               fill_chunk(chunk_buf, chunksize, offset, time_st);
+               if (write(fd, chunk_buf, chunksize) < 0) {
+                       fprintf(stderr, "\n%s: write %llu failed: %s\n",
+                               progname, offset, strerror(errno));
+                       return 1;
+               }
+
+               count += chunksize;
+               if (verbose > 1)
+                       show_rate("write", offset, &count);
+       }
+       if (verbose > 1) {
+               show_rate("write", offset, &count);
+               printf("\nwrite complete\n");
+       }
+       if (fsync(fd) == -1) {
+               fprintf(stderr, "%s: fsync faild: %s\n", progname,
+                       strerror(errno));
+                       return 1;
+       }
+       return 0;
+}
+
+/*
+ * read_chunk: reads the chunk_buf from the device. The number of read
+ * operations are based on the parameters read_end, offset, and chunksize.
+ */
+int read_chunks(unsigned long long offset, unsigned long long read_end,
+               char *chunk_buf, size_t chunksize, time_t time_st)
+{
+       unsigned long long stride, count = 0;
+
+       stride = full ? chunksize : (ONE_GB - chunksize);
+
+       if (ioctl(fd, BLKFLSBUF, 0) < 0 && verbose)
+               fprintf(stderr, "%s: ioctl BLKFLSBUF failed: %s (ignoring)\n",
+                       progname, strerror(errno));
+
+       for (offset = offset & ~(chunksize - 1); offset < read_end;
+            offset += stride) {
+               if (lseek64(fd, offset, SEEK_SET) == -1) {
+                       fprintf(stderr, "\n%s: lseek64(%llu) failed: %s\n",
+                               progname, offset, strerror(errno));
+                       return 1;
+               }
+               if (offset + chunksize > read_end)
+                       chunksize = read_end - offset;
+
+               if (!full && offset > chunksize) {
+                       if (read (fd, chunk_buf, chunksize) < 0) {
+                               fprintf(stderr, "\n%s: read %llu failed: %s\n",
+                                       progname, offset, strerror(errno));
+                               return 1;
+                       }
+                       if (verify_chunk(chunk_buf, chunksize, offset,
+                                        time_st) != 0)
+                               return 1;
+                       offset += chunksize;
+                       if (offset + chunksize >= read_end)
+                               chunksize = read_end - offset;
+               }
+
+               if (read(fd, chunk_buf, chunksize) < 0) {
+                       fprintf(stderr, "\n%s: read failed: %s\n", progname,
+                               strerror(errno));
+                       return 1;
+               }
+
+               if (verify_chunk(chunk_buf, chunksize, offset, time_st) != 0)
+                       return 1;
+
+               count += chunksize;
+               if (verbose > 1)
+                       show_rate("read", offset, &count);
+       }
+       if (verbose > 1) {
+               show_rate("read", offset, &count);
+               printf("\nread complete\n");
+       }
+       return 0;
+}
+
+int main(int argc, char **argv)
+{
+       time_t time_st = 0;             /* Default timestamp */
+       long long offset = 0, offset_orig; /* offset in kB */
+       size_t chunksize = ONE_MB;      /* IO chunk size */
+       char *chunk_buf = NULL;
+       unsigned int force = 0;         /* run test run without confirmation*/
+       unsigned long long dev_size = 0;
+       char yesno[4];
+       int mode = O_RDWR;              /* mode which device should be opened */
+       int error = 0, c;
+
+       progname = strrchr(argv[0], '/') == NULL ?
+               argv[0] : strrchr(argv[0], '/') + 1;
+       while ((c = getopt_long(argc, argv, "c:fhlo:pqrt:vw", longopts,
+                               NULL)) != -1) {
+               switch (c) {
+               case 'c':
+                       chunksize = (strtoul(optarg, NULL, 0) * ONE_MB);
+                       if (!chunksize) {
+                               fprintf(stderr, "%s: chunk size value should be"
+                                       "nonzero and multiple of 1MB\n",
+                                       progname);
+                               return -1;
+                       }
+                       break;
+               case 'f':
+                       force = 1;
+                       break;
+               case 'l':
+                       full = 1;
+                       break;
+               case 'o':
+                       offset = strtoull(optarg, NULL, 0) * ONE_KB;
+                       break;
+               case 'p':
+                       full = 0;
+                       break;
+               case 'q':
+                       verbose = 0;
+                       break;
+               case 'r':
+                       readoption = 1;
+                       mode = O_RDONLY;
+                       break;
+               case 't':
+                       time_st = (time_t)strtoul(optarg, NULL, 0);
+                       break;
+               case 'v':
+                       verbose++;
+                       break;
+               case 'w':
+                       writeoption = 1;
+                       mode = O_WRONLY;
+                       break;
+               case 'h':
+               default:
+                       usage (1);
+                       return 0;
+               }
+       }
+       offset_orig = offset;
+       devname = argv[optind];
+       if (!devname) {
+               fprintf(stderr, "%s: device name not given\n", progname);
+               usage (1);
+               return -1;
+       }
+
+       if (readoption && writeoption)
+               mode = O_RDWR;
+       if (!readoption && !writeoption) {
+               readoption = 1;
+               writeoption = 1;
+       }
+
+       if (!force && writeoption) {
+               printf("%s: permanently overwrite all data on %s (yes/no)? ",
+                      progname, devname);
+               scanf("%3s", yesno);
+               if (!(strcasecmp("yes", yesno) || strcasecmp("y", yesno))) {
+                       printf("Not continuing due to '%s' response", yesno);
+                       return 0;
+               }
+       }
+
+       if (!writeoption && time_st == 0) {
+               fprintf(stderr, "%s: must give timestamp for read-only test\n",
+                       progname);
+               usage(1);
+       }
+
+       fd = open_dev(devname, mode);
+       dev_size = sizeof_dev(fd);
+       if (!dev_size) {
+               fprintf(stderr, "%s: cannot test on device size < 1MB\n",
+                       progname);
+               error = 7;
+               goto close_dev;
+       }
+
+       if (dev_size < (offset * 2)) {
+               fprintf(stderr, "%s: device size %llu < offset %llu\n",
+                       progname, dev_size, offset);
+               error = 6;
+               goto close_dev;
+       }
+       if (!time_st)
+               (void)time(&time_st);
+
+       isatty_flag = isatty(STDOUT_FILENO);
+
+       if (verbose)
+               printf("Timestamp: %lu\n", time_st);
+
+       chunk_buf = (char *)calloc(chunksize, 1);
+       if (chunk_buf == NULL) {
+               fprintf(stderr, "%s: memory allocation failed for chunk_buf\n",
+                       progname);
+               error = 4;
+               goto close_dev;
+       }
+       if (writeoption) {
+               if (write_chunks(offset, dev_size, chunk_buf, chunksize,
+                                time_st)) {
+                       error = 3;
+                       goto chunk_buf;
+               }
+               if (!full) {  /* end of device aligned to a block */
+                       offset = ((dev_size - chunksize + BLOCKSIZE - 1) &
+                                 ~(BLOCKSIZE - 1));
+                       if (write_chunks(offset, dev_size, chunk_buf, chunksize,
+                                        time_st)) {
+                               error = 3;
+                               goto chunk_buf;
+                       }
+               }
+               offset = offset_orig;
+       }
+       if (readoption) {
+               if (read_chunks(offset, dev_size, chunk_buf, chunksize,
+                               time_st)) {
+                       error = 2;
+                       goto chunk_buf;
+               }
+               if (!full) { /* end of device aligned to a block */
+                       offset = ((dev_size - chunksize + BLOCKSIZE - 1) &
+                                 ~(BLOCKSIZE - 1));
+                       if (read_chunks(offset, dev_size, chunk_buf, chunksize,
+                                       time_st)) {
+                               error = 2;
+                               goto chunk_buf;
+                       }
+               }
+               if (verbose)
+                       printf("\n%s: data verified successfully\n", progname);
+       }
+       error = 0;
+chunk_buf:
+       free(chunk_buf);
+close_dev:
+       close(fd);
+       return error;
+}
diff --git a/lustre/utils/llverfs.c b/lustre/utils/llverfs.c
new file mode 100644 (file)
index 0000000..b98093c
--- /dev/null
@@ -0,0 +1,650 @@
+/*
+ * ext3 Filesystem Verification Tool.
+ * This program tests the correct operation of ext3 filesystem.
+ * This tool have two working modes
+ * 1. full mode
+ * 2. fast mode
+ *     The full mode is basic mode in which program creates a subdirectory
+ * in the test fileysytem, writes n(files_in_dir, default=16) large(4GB) files
+ * to the directory with the test pattern at the start of each 4kb block.
+ * The test pattern contains timestamp, relative file offset and per file
+ * unique idenfifier(inode number). this continues until whole filesystem is
+ * full and then this tooll verifies that the data in all of the test files
+ * is correct.
+ *     In the fast mode the tool creates a test directories with
+ * EXT3_TOPDIR_FL flag set. the number of directories equals to the number
+ * of block groups in the filesystem(e.g. 65536 directories for 8TB filesystem)
+ * and then writes a single 1MB file in each directory. The tool then verifies
+ * that the data in each file is correct.
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#ifndef LUSTRE_UTILS
+#define LUSTRE_UTILS
+#endif
+#ifndef _LARGEFILE64_SOURCE
+#define _LARGEFILE64_SOURCE
+#endif
+#ifndef _FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 64
+#endif
+
+#include <features.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <time.h>
+#include <dirent.h>
+#include <mntent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/vfs.h>
+#include <gnu/stubs.h>
+#include <gnu/stubs.h>
+
+#ifdef HAVE_EXT2FS_EXT2FS_H
+#  include <e2p/e2p.h>
+#  include <ext2fs/ext2fs.h>
+#endif
+
+#define ONE_MB (1024 * 1024)
+#define ONE_GB ((unsigned long long)(1024 * 1024 * 1024))
+#define BLOCKSIZE 4096
+
+/* Structure for writing test pattern */
+struct block_data {
+       unsigned long long bd_offset;
+       unsigned long long bd_time;
+       unsigned long long bd_inode;
+};
+static char *progname;             /* name by which this program was run. */
+static unsigned verbose = 1;       /* prints offset in kB, operation rate */
+static int readoption;             /* run test in read-only (verify) mode */
+static int writeoption;                    /* run test in write_only mode */
+char *testdir;                     /* name of device to be tested. */
+static unsigned full = 1;          /* flag to full check */
+static int errno_local;                    /* local copy of errno */
+static unsigned long num_files;     /* Total number of files for read/write */
+static loff_t file_size = 4*ONE_GB; /* Size of each file */
+static unsigned files_in_dir = 32;  /* number of files in each directioy */
+static unsigned num_dirs = 30000;   /* total number of directories */
+const int dirmode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
+static int fd = -1;
+static int isatty_flag;
+static int perms =  S_IRWXU | S_IRGRP | S_IROTH;
+
+static struct option const longopts[] =
+{
+       { "chunksize", required_argument, 0, 'c' },
+       { "help", no_argument, 0, 'h' },
+       { "offset", required_argument, 0, 'o' },
+       { "long", no_argument, 0, 'l' },
+       { "partial", required_argument, 0, 'p' },
+       { "quiet", required_argument, 0, 'q' },
+       { "read", no_argument, 0, 'r' },
+       { "timestamp", required_argument, 0, 't' },
+       { "verbose", no_argument, 0, 'v' },
+       { "write", no_argument, 0, 'w' },
+       { 0, 0, 0, 0}
+};
+
+/*
+ * Usages: displays help information, whenever user supply --help option in
+ * command or enters incorrect command line.
+ */
+void usage(int status)
+{
+       if (status != 0)
+       {
+             printf("\nUsage: %s [OPTION]... <filesystem path> ...\n",
+                       progname);
+             printf("ext3 filesystem verification tool.\n"
+                 "\t-t {seconds} for --timestamp,  set test time"
+                 "(default=current time())\n"
+                 "\t-o {offset}  for --offset, directory starting offset"
+                 " from which tests should start\n"
+                 "\t-r run test in read (verify) mode\n"
+                 "\t-w run test in write (test-pattern) mode (default=r&w)\n"
+                 "\t-v for verbose\n"
+                 "\t-p for --partial, for partial check (1MB files)\n"
+                 "\t-l for --long, full check (4GB file with 4k blocks)\n"
+                 "\t-c for --chunksize, IO chunk size (default=1048576)\n"
+                 "\t-h display this help and exit\n"
+                 "\t--help display this help and exit\n");
+       }
+       exit(status);
+}
+
+/*
+ * open_file: Opens file in specified mode and returns fd.
+ */
+static int open_file(const char *file, int flag)
+{
+       fd = open(file, flag, perms);
+       if (fd < 0) {
+               fprintf(stderr, "\n%s: Open '%s' failed:%s\n",
+                       progname, file, strerror(errno));
+               exit(3);
+       }
+       return (fd);
+}
+
+/*
+ * Verify_chunk: Verifies test pattern in each 4kB (BLOCKSIZE) is correct.
+ * Returns 0 if test offset and timestamp is correct otherwise 1.
+ */
+int verify_chunk(char *chunk_buf, size_t chunksize,unsigned long long chunk_off,
+                unsigned long long time_st, unsigned long long inode_st,
+                char *file)
+{
+       struct block_data *bd;
+       char *chunk_end;
+
+       for (chunk_end = chunk_buf + chunksize - sizeof(*bd);
+            (char *)chunk_buf < chunk_end;
+            chunk_buf += BLOCKSIZE, chunk_off += BLOCKSIZE) {
+               bd = (struct block_data *)chunk_buf;
+               if ((bd->bd_offset == chunk_off) && (bd->bd_time == time_st) &&
+                   (bd->bd_inode == inode_st))
+                       continue;
+               fprintf(stderr,"\n%s: verify %s failed offset/timestamp/inode "
+                       "%llu/%llu/%llu: found %llu/%llu/%llu instead\n",
+                       progname, file, chunk_off, time_st, inode_st,
+                       bd->bd_offset, bd->bd_time, bd->bd_inode);
+               return 1;
+       }
+       return 0;
+}
+
+/*
+ * fill_chunk: Fills the chunk with current or user specified timestamp
+ * and  offset. The test patters is filled at the beginning of
+ * each 4kB(BLOCKSIZE) blocks in chunk_buf.
+ */
+void fill_chunk(char *chunk_buf, size_t chunksize, loff_t chunk_off,
+               time_t time_st, ino_t inode_st)
+{
+       struct block_data *bd;
+       char *chunk_end;
+
+       for (chunk_end = chunk_buf + chunksize - sizeof(*bd);
+            (char *)chunk_buf < chunk_end;
+            chunk_buf += BLOCKSIZE, chunk_off += BLOCKSIZE) {
+               bd = (struct block_data *)chunk_buf;
+               bd->bd_offset = chunk_off;
+               bd->bd_time = time_st;
+               bd->bd_inode = inode_st;
+       }
+}
+
+/*
+ * write_chunk: write the chunk_buf on the device. The number of write
+ * operations are based on the parameters write_end, offset, and chunksize.
+ */
+int write_chunks(int fd, unsigned long long offset,unsigned long long write_end,
+                char *chunk_buf, size_t chunksize, time_t time_st,
+                ino_t inode_st, const char *file)
+{
+       unsigned long long stride;
+
+       stride = full ? chunksize : (ONE_GB - chunksize);
+       for (offset = offset & ~(chunksize - 1); offset < write_end;
+            offset += stride) {
+               if (lseek64(fd, offset, SEEK_SET) == -1) {
+                       fprintf(stderr, "\n%s: lseek64(%s+%llu) failed: %s\n",
+                               progname, file, offset, strerror(errno));
+                       return 1;
+               }
+               if (offset + chunksize > write_end)
+                       chunksize = write_end - offset;
+               if (!full && offset > chunksize) {
+                       fill_chunk(chunk_buf, chunksize, offset, time_st,
+                                   inode_st);
+                       if (write(fd, chunk_buf, chunksize) < 0) {
+                               if (errno == ENOSPC) {
+                                       errno_local = errno;
+                                       return 0;
+                               }
+                               fprintf(stderr,
+                                       "\n%s: write %s+%llu failed: %s\n",
+                                       progname, file, offset,strerror(errno));
+                               return errno;
+                       }
+                       offset += chunksize;
+                       if (offset + chunksize > write_end)
+                               chunksize = write_end - offset;
+               }
+               fill_chunk(chunk_buf, chunksize, offset, time_st, inode_st);
+               if (write(fd, (char *) chunk_buf, chunksize) < 0) {
+                       if (errno == ENOSPC) {
+                               errno_local = errno;
+                               return 0;
+                       }
+                       fprintf(stderr, "\n%s: write %s+%llu failed: %s\n",
+                               progname, file, offset, strerror(errno));
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+/*
+ * read_chunk: reads the chunk_buf from the device. The number of read
+ * operations are based on the parameters read_end, offset, and chunksize.
+ */
+int read_chunks(int fd, unsigned long long offset, unsigned long long read_end,
+               char *chunk_buf, size_t chunksize, time_t time_st,
+               ino_t inode_st, char *file)
+{
+       unsigned long long stride;
+
+       stride = full ? chunksize : (ONE_GB - chunksize);
+       for (offset = offset & ~(chunksize - 1); offset < read_end;
+            offset += stride) {
+               if (lseek64(fd, offset, SEEK_SET) == -1) {
+                       fprintf(stderr, "\n%s: lseek64(%s+%llu) failed: %s\n",
+                               progname, file, offset, strerror(errno));
+                       return 1;
+               }
+               if (offset + chunksize > read_end)
+                       chunksize = read_end - offset;
+               if (!full && offset > chunksize) {
+                       if (read(fd, chunk_buf, chunksize) < 0) {
+                               fprintf(stderr,
+                                       "\n%s: read %s+%llu failed: %s\n",
+                                       progname, file, offset,strerror(errno));
+                               return 1;
+                       }
+                       if (verify_chunk(chunk_buf, chunksize, offset,
+                                        time_st, inode_st, file) != 0)
+                               return 1;
+                       offset += chunksize;
+                       if (offset + chunksize >= read_end)
+                               chunksize = read_end - offset;
+               }
+               if (read(fd, chunk_buf, chunksize) < 0) {
+                       fprintf(stderr, "\n%s: read %s+%llu failed: %s\n",
+                               progname, file, offset, strerror(errno));
+                       return 1;
+               }
+               if (verify_chunk(chunk_buf, chunksize, offset, time_st,
+                                inode_st, file) != 0)
+                       return 1;
+       }
+       return 0;
+}
+
+/*
+ * new_file: prepares new filename using file counter and current dir.
+ */
+char *new_file(char *tempfile, char *cur_dir, int file_num)
+{
+       sprintf(tempfile, "%s/file%03d", cur_dir, file_num);
+       return tempfile;
+}
+
+/*
+ * new_dir: prepares new dir name using dir counters.
+ */
+char *new_dir(char *tempdir, int dir_num)
+{
+       sprintf(tempdir, "%s/dir%05d", testdir, dir_num);
+       return tempdir;
+}
+
+/*
+ * show_filename: Displays name of current file read/write
+ */
+void show_filename(char *op, char *filename)
+{
+       static time_t last;
+       time_t now;
+       double diff;
+
+       now = time(NULL);
+       diff = now - last;
+       if (diff > 4 || verbose > 2) {
+               if (isatty_flag)
+                       printf("\r");
+               printf("%s File name: %s          ", op, filename);
+               if (isatty_flag)
+                       fflush(stdout);
+               else
+                       printf("\n");
+               last = now;
+       }
+}
+
+/*
+ * dir_write: This function writes directories and files on device.
+ * it works for both full and fast modes.
+ */
+static int dir_write(char *chunk_buf, size_t chunksize,
+                    time_t time_st, unsigned long dir_num)
+{
+       char tempfile[PATH_MAX];
+       char tempdir[PATH_MAX];
+       struct stat64 file;
+       int file_num = 999999999;
+       ino_t inode_st = 0;
+
+#ifdef HAVE_EXT2FS_EXT2FS_H
+       if (!full && fsetflags(testdir, EXT2_TOPDIR_FL))
+               fprintf(stderr,
+                       "\n%s: can't set TOPDIR_FL on %s: %s (ignoring)",
+                       progname, testdir, strerror(errno));
+#endif
+       for (; dir_num < num_dirs; num_files++, file_num++) {
+               if (file_num >= files_in_dir) {
+                       if (dir_num == num_dirs - 1)
+                               break;
+
+                       file_num = 0;
+                       if (mkdir(new_dir(tempdir, dir_num), dirmode) < 0) {
+                               if (errno == ENOSPC)
+                                       break;
+                               if (errno != EEXIST) {
+                                       fprintf(stderr, "\n%s: mkdir %s : %s\n",
+                                               progname, tempdir,
+                                               strerror(errno));
+                                       return 1;
+                               }
+                       }
+                       dir_num++;
+               }
+               fd = open_file(new_file(tempfile, tempdir, file_num),
+                              O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE);
+
+               if (fd >= 0 && fstat64(fd, &file) == 0) {
+                       inode_st = file.st_ino;
+               } else {
+                       fprintf(stderr, "\n%s: write stat64 to file %s: %s",
+                               progname, tempfile, strerror(errno));
+                       exit(1);
+               }
+
+               if (verbose > 1)
+                       show_filename("write", tempfile);
+
+               if (write_chunks(fd, 0, file_size, chunk_buf, chunksize,
+                                time_st, inode_st, tempfile)) {
+                       close(fd);
+                       return 1;
+               }
+               close(fd);
+
+               if (errno_local == ENOSPC)
+                       break;
+       }
+
+       if (verbose) {
+               verbose++;
+               show_filename("write", tempfile);
+               printf("\nwrite complete\n");
+               verbose--;
+       }
+
+       return 0;
+}
+
+/*
+ * dir_read: This function reads directories and files on device.
+ * it works for both full and fast modes.
+ */
+static int dir_read(char *chunk_buf, size_t chunksize,
+                   time_t time_st, unsigned long dir_num)
+{
+       char tempfile[PATH_MAX];
+       char tempdir[PATH_MAX];
+       unsigned long count = 0;
+       struct stat64 file;
+       int file_num = 0;
+       ino_t inode_st = 0;
+
+       for (count = 0; count < num_files && dir_num < num_dirs; count++) {
+               if (file_num == 0) {
+                       if (dir_num == num_dirs - 1)
+                               break;
+
+                       new_dir(tempdir, dir_num);
+                       dir_num++;
+               }
+
+               fd = open_file(new_file(tempfile, tempdir, file_num),
+                              O_RDONLY | O_LARGEFILE);
+               if (fd >= 0 && fstat64(fd, &file) == 0) {
+                       inode_st = file.st_ino;
+               } else {
+                       fprintf(stderr, "\n%s: read stat64 file '%s': %s\n",
+                               progname, tempfile, strerror(errno));
+                       return 1;
+               }
+
+               if (verbose > 1)
+                       show_filename("read", tempfile);
+
+               if (count == num_files)
+                       file_size = file.st_size;
+               if (read_chunks(fd, 0, file_size, chunk_buf, chunksize,
+                               time_st, inode_st, tempfile)) {
+                       close(fd);
+                       return 1;
+               }
+               close(fd);
+
+               if (++file_num >= files_in_dir)
+                       file_num = 0;
+       }
+       if (verbose > 1){
+               verbose++;
+               show_filename("read", tempfile);
+               printf("\nread complete\n");
+               verbose--;
+       }
+       return 0;
+}
+
+int main(int argc, char **argv)
+{
+       time_t time_st = 0;             /* Default timestamp */
+       size_t chunksize = ONE_MB;      /* IO chunk size(defailt=1MB) */
+       char *chunk_buf;                /* chunk buffer */
+       int error = 0;
+       FILE *countfile = NULL;
+       char filecount[PATH_MAX];
+       unsigned long dir_num = 0, dir_num_orig = 0;/* starting directory */
+       char c;
+
+       progname = strrchr(argv[0], '/') ? strrchr(argv[0], '/') + 1 : argv[0];
+       while ((c = (char)getopt_long(argc, argv, "t:rwvplo:h",
+                                     longopts, NULL)) != -1) {
+               switch (c) {
+               case 'c':
+                       chunksize = (strtoul(optarg, NULL, 0) * ONE_MB);
+                       if (!chunksize) {
+                               fprintf(stderr, "%s: Chunk size value should be"
+                                       "a multiple of 1MB\n", progname);
+                               return -1;
+                       }
+                       break;
+               case 'l':
+                       full = 1;
+                       break;
+               case 'o': /* offset */
+                       dir_num = strtoul(optarg, NULL, 0);
+                       break;
+               case 'p':
+                       full = 0;
+                       break;
+               case 'q':
+                       verbose = 0;
+                       break;
+               case 'r':
+                       readoption = 1;
+                       break;
+               case 't':
+                       time_st = (time_t)strtoul(optarg, NULL, 0);
+                       break;
+               case 'w':
+                       writeoption = 1;
+                       break;
+               case 'v':
+                       verbose++;
+                       break;
+
+               case 'h':
+               default:
+                       usage(1);
+                       return 0;
+               }
+       }
+       testdir = argv[optind];
+
+       if (!testdir) {
+               fprintf(stderr, "%s: pathname not given\n", progname);
+               usage(1);
+               return -1;
+       }
+       if (!readoption && !writeoption) {
+               readoption = 1;
+               writeoption = 1;
+       }
+       if (!time_st)
+               (void) time(&time_st);
+       printf("Timestamp: %lu\n", (unsigned long )time_st);
+       isatty_flag = isatty(STDOUT_FILENO);
+
+       if (!full) {
+#ifdef HAVE_EXT2FS_EXT2FS_H
+               struct mntent *tempmnt;
+               FILE *fp = NULL;
+               ext2_filsys fs;
+
+               if ((fp = setmntent("/etc/mtab", "r")) == NULL){
+                       fprintf(stderr, "%s: fail to open /etc/mtab in read"
+                               "mode :%s\n", progname, strerror(errno));
+                       goto guess;
+               }
+
+               /* find device name using filesystem */
+               while ((tempmnt = getmntent(fp)) != NULL) {
+                       if (strcmp(tempmnt->mnt_dir, testdir) == 0)
+                               break;
+               }
+
+               if (tempmnt == NULL) {
+                       fprintf(stderr, "%s: no device found for '%s'\n",
+                               progname, testdir);
+                       endmntent(fp);
+                       goto guess;
+               }
+
+               if (ext2fs_open(tempmnt->mnt_fsname, 0, 0, 0,
+                               unix_io_manager, &fs)) {
+                       fprintf(stderr, "%s: unable to open ext3 fs on '%s'\n",
+                               progname, testdir);
+                       endmntent(fp);
+                       goto guess;
+               }
+               endmntent(fp);
+
+               num_dirs = (fs->super->s_blocks_count +
+                           fs->super->s_blocks_per_group - 1) /
+                       fs->super->s_blocks_per_group;
+               if (verbose)
+                       printf("ext3 block groups: %u, fs blocks: %u "
+                              "blocks per group: %u\n",
+                              num_dirs, fs->super->s_blocks_count,
+                              fs->super->s_blocks_per_group);
+               ext2fs_close(fs);
+#else
+                goto guess;
+#endif
+               if (0) { /* ugh */
+                       struct statfs64 statbuf;
+               guess:
+                       if (statfs64(testdir, &statbuf) == 0) {
+                               num_dirs = (long long)statbuf.f_blocks *
+                                       statbuf.f_bsize / (128ULL << 20);
+                               if (verbose)
+                                       printf("dirs: %u, fs blocks: %llu\n",
+                                              num_dirs,
+                                              (long long)statbuf.f_blocks);
+                       } else {
+                               fprintf(stderr, "%s: unable to stat '%s': %s\n",
+                                       progname, testdir, strerror(errno));
+                               if (verbose)
+                                       printf("dirs: %u\n", num_dirs);
+                       }
+               }
+
+               file_size = ONE_MB;
+               chunksize = ONE_MB;
+               files_in_dir = 1;
+       }
+       chunk_buf = (char *)calloc(chunksize, 1);
+       if (chunk_buf == NULL) {
+               fprintf(stderr, "Memory allocation failed for chunk_buf\n");
+               return 4;
+       }
+       sprintf(filecount, "%s/%s.filecount", testdir, progname);
+       if (writeoption) {
+               (void)mkdir(testdir, dirmode);
+
+               unlink(filecount);
+               if (dir_num != 0) {
+                       num_files = dir_num * files_in_dir;
+                       if (verbose)
+                               printf("\n%s: %lu files already written\n",
+                                      progname, num_files);
+               }
+               if (dir_write(chunk_buf, chunksize, time_st, dir_num)) {
+                       error = 3;
+                       goto out;
+               }
+               countfile = fopen(filecount, "w");
+               if (countfile != NULL) {
+                       if (fprintf(countfile, "%lu", num_files) < 1 ||
+                           fflush(countfile) != 0) {
+                               fprintf(stderr, "\n%s: writing %s failed :%s\n",
+                                       progname, filecount, strerror(errno));
+                       }
+                       fclose(countfile);
+               }
+               dir_num = dir_num_orig;
+       }
+       if (readoption) {
+               if (!writeoption) {
+                       countfile = fopen(filecount, "r");
+                       if (countfile == NULL ||
+                           fscanf(countfile, "%lu", &num_files) != 1) {
+                               fprintf(stderr, "\n%s: reading %s failed :%s\n",
+                                       progname, filecount, strerror(errno));
+                               num_files = num_dirs * files_in_dir;
+                       } else {
+                               num_files -= (dir_num * files_in_dir);
+                       }
+                       if (countfile)
+                               fclose(countfile);
+               }
+               if (dir_read(chunk_buf, chunksize, time_st, dir_num)) {
+                       fprintf(stderr, "\n%s: Data verification failed\n",
+                               progname) ;
+                       error = 2;
+                       goto out;
+               }
+       }
+       error = 0;
+out:
+       free(chunk_buf);
+       return error;
+}
index fb80016..c05883c 100755 (executable)
@@ -699,9 +699,10 @@ def add_net(gen, lustre, options):
         if options.verbose:
             print "Testing network on", node_name
         target = string.split(nid,'@')[0]
-        out = runcmd("ping -c 1 -w 5 %s" %target)
-        if out != 0:
-            print "Could not connect to", node_name,", Please check network."
+       if target != '*' and target != '\\*':
+               out = runcmd("ping -c 1 -w 5 %s" %target)
+               if out != 0:
+                   print "Could not connect to %s, please check network." % node_name
             
     ret = findByName(lustre, node_name, "node")
     if not ret:
diff --git a/lustre/utils/lr_reader.c b/lustre/utils/lr_reader.c
new file mode 100644 (file)
index 0000000..32a66e1
--- /dev/null
@@ -0,0 +1,209 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ *   Copyright (C) 2006 Cluster File Systems, Inc.
+ *   Author: Nathan Rutman <nathan@clusterfs.com>
+ *
+ *   This file is part of Lustre, http://www.lustre.org.
+ *
+ *   Lustre is free software; you can redistribute it and/or
+ *   modify it under the terms of version 2 of the GNU General Public
+ *   License as published by the Free Software Foundation.
+ *
+ *   Lustre is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Lustre; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+ /* Safely read the last_rcvd file from a device */
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <mntent.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+
+#include <string.h>
+#include <getopt.h>
+
+#include <lustre_disk.h>
+#include <lustre_ver.h>
+
+int run_command(char *cmd)
+{
+        char log[] = "/tmp/mkfs_logXXXXXX";
+        int fd, rc;
+        
+        
+        if ((fd = mkstemp(log)) >= 0) {
+                close(fd);
+                strcat(cmd, " >");
+                strcat(cmd, log);
+        }
+        strcat(cmd, " 2>&1");
+
+        /* Can't use popen because we need the rv of the command */
+        rc = system(cmd);
+        if (rc && fd >= 0) {
+                char buf[128];
+                FILE *fp;
+                fp = fopen(log, "r");
+                if (fp) {
+                        while (fgets(buf, sizeof(buf), fp) != NULL) {
+                                if (rc) 
+                                        printf("   %s", buf);
+                        }
+                        fclose(fp);
+                }
+        }
+        if (fd >= 0) 
+                remove(log);
+        return rc;
+}                                                       
+
+
+
+int main(int argc, char *const argv[])
+{
+        char tmpdir[] = "/tmp/dirXXXXXX";
+        char cmd[128];
+        char filepnm[128];
+        char *progname, *dev;
+        struct lr_server_data lsd;
+        FILE *filep;
+        int ret;
+
+        if ((argc < 2) || (argv[argc - 1][0] == '-')) {
+                printf("Usage: %s devicename\n", argv[0]);
+                printf("Read and print the last_rcvd file from a device\n");
+                printf("(safe for mounted devices)\n");
+                return EINVAL;
+        }
+
+        progname = argv[0];
+        dev = argv[argc - 1];
+
+        /* Make a temporary directory to hold Lustre data files. */
+        if (!mkdtemp(tmpdir)) {
+                fprintf(stderr, "%s: Can't create temporary directory %s: %s\n",
+                        progname, tmpdir, strerror(errno));
+                return errno;
+        }
+
+        memset(cmd, 0, sizeof(cmd));
+        sprintf(cmd,
+                "debugfs -c -R 'dump /%s %s/%s' %s",
+                LAST_RCVD, tmpdir, LAST_RCVD, dev);
+
+        ret = run_command(cmd);
+        if (ret) {
+                fprintf(stderr, "%s: Unable to dump %s file\n",
+                        progname, LAST_RCVD);
+                goto out_rmdir;
+        }
+
+        sprintf(filepnm, "%s/%s", tmpdir, LAST_RCVD);
+        filep = fopen(filepnm, "r");
+        if (!filep) {
+                fprintf(stderr, "%s: Unable to read old data\n",
+                        progname);
+                ret = -errno;
+                goto out_rmdir;
+        }
+        
+        printf("Reading %s\n", LAST_RCVD);
+        ret = fread(&lsd, 1, sizeof(lsd), filep);
+        if (ret < sizeof(lsd)) {
+                fprintf(stderr, "%s: Short read (%d of %d)\n",
+                        progname, ret, sizeof(lsd));
+                ret = -ferror(filep);
+                if (ret) 
+                        goto out_close;
+        }
+        
+        #if 0
+        __u8  lsd_uuid[40];        /* server UUID */
+        __u64 lsd_last_transno;    /* last completed transaction ID */
+        __u64 lsd_compat14;        /* reserved - compat with old last_rcvd */
+        __u64 lsd_mount_count;     /* incarnation number */
+        __u32 lsd_feature_compat;  /* compatible feature flags */
+        __u32 lsd_feature_rocompat;/* read-only compatible feature flags */
+        __u32 lsd_feature_incompat;/* incompatible feature flags */
+        __u32 lsd_server_size;     /* size of server data area */
+        __u32 lsd_client_start;    /* start of per-client data area */
+        __u16 lsd_client_size;     /* size of per-client data area */
+        __u16 lsd_subdir_count;    /* number of subdirectories for objects */
+        __u64 lsd_catalog_oid;     /* recovery catalog object id */
+        __u32 lsd_catalog_ogen;    /* recovery catalog inode generation */
+        __u8  lsd_peeruuid[40];    /* UUID of MDS associated with this OST */
+        __u32 lsd_ost_index;       /* index number of OST in LOV */
+        __u32 lsd_mdt_index;       /* index number of MDT in LMV */
+        __u8  lsd_padding[LR_SERVER_SIZE - 148];
+        #endif
+
+        printf("UUID %s\n", lsd.lsd_uuid);
+        printf("Feature compat=%#x\n", lsd.lsd_feature_compat);
+        printf("Feature incompat=%#x\n", lsd.lsd_feature_incompat);
+        printf("Feature rocompat=%#x\n", lsd.lsd_feature_rocompat);
+        printf("Last transaction %llu\n", lsd.lsd_last_transno);
+        printf("ost index %u\n", lsd.lsd_ost_index);
+        printf("mdt index %u\n", lsd.lsd_mdt_index);
+
+        if ((lsd.lsd_feature_compat & OBD_COMPAT_OST) ||
+            (lsd.lsd_feature_incompat & OBD_INCOMPAT_OST)) {
+                printf("OST, index %d\n", lsd.lsd_ost_index);
+        } else if ((lsd.lsd_feature_compat & OBD_COMPAT_MDT) ||
+                   (lsd.lsd_feature_incompat & OBD_INCOMPAT_MDT)) {
+                /* We must co-locate so mgs can see old logs.
+                   If user doesn't want this, they can copy the old
+                   logs manually and re-tunefs. */
+                printf("MDS, index %d\n", lsd.lsd_mdt_index);
+        } else  {
+                /* If neither is set, we're pre-1.4.6, make a guess. */
+                /* Construct debugfs command line. */
+                memset(cmd, 0, sizeof(cmd));
+                sprintf(cmd,
+                        "debugfs -c -R 'rdump /%s %s' %s",
+                        MDT_LOGS_DIR, tmpdir, dev);
+
+                run_command(cmd);
+
+                sprintf(filepnm, "%s/%s", tmpdir, MDT_LOGS_DIR);
+                if (lsd.lsd_ost_index > 0) {
+                        printf("non-flagged OST, index %d\n", 
+                               lsd.lsd_ost_index);
+                } else {
+                        /* If there's a LOGS dir, it's an MDT */
+                        if ((ret = access(filepnm, F_OK)) == 0) {
+                                /* Old MDT's are always index 0 
+                                   (pre CMD) */
+                                printf("non-flagged MDS, index 0\n");
+                        } else {
+                                printf("non-flagged OST, index unknown\n");
+                        }
+                }
+        }
+        
+out_close:        
+        fclose(filep);
+
+out_rmdir:
+        memset(cmd, 0, sizeof(cmd));
+        sprintf(cmd, "rm -rf %s", tmpdir);
+        run_command(cmd);
+        return ret;
+}
+
+
+
diff --git a/lustre/utils/lstripe b/lustre/utils/lstripe
deleted file mode 100755 (executable)
index 03b2014..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-PATH=`dirname $0`:$PATH
-
-if [ $# -eq 0 ] || [ "$1" == "-h" -o "$1" == "--help" ]; then
-       lfs help setstripe 2>&1 | sed "s/setstripe/lstripe/g"
-       exit 0
-fi
-
-lfs setstripe "$@"
index 342a4da..dd98b78 100644 (file)
@@ -389,7 +389,6 @@ int jt_lcfg_lov_setup(int argc, char **argv)
                         jt_cmdname(argv[0]), argv[5]);
                 return CMD_HELP;
         }
-        desc.ld_qos_threshold = QOS_DEFAULT_THRESHOLD;
         desc.ld_qos_maxage = QOS_DEFAULT_MAXAGE;
 
         if (argc == 7) {
@@ -705,13 +704,6 @@ int jt_lcfg_mgsparam(int argc, char **argv)
                 index_offset = 1;
         }
 
-        if (lcfg_devname == NULL) {
-                fprintf(stderr, "%s: please use 'cfg_device name' to set the "
-                        "device name for config commands.\n", 
-                        jt_cmdname(argv[0])); 
-                return -EINVAL;
-        }
-
         lustre_cfg_bufs_reset(&bufs, lcfg_devname);
 
         for (i = 1; i < (argc - index_offset); i++) {
index 41a19b6..1d271b0 100644 (file)
@@ -1,8 +1,7 @@
 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
  * vim:expandtab:shiftwidth=8:tabstop=8:
  *
- *   Copyright (C) 2002 Cluster File Systems, Inc.
- *   Author: Lin Song Tao <lincent@clusterfs.com>
+ *   Copyright (C) 2006 Cluster File Systems, Inc.
  *   Author: Nathan Rutman <nathan@clusterfs.com>
  *
  *   This file is part of Lustre, http://www.lustre.org.
@@ -21,6 +20,7 @@
  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  */
+ /* This source file is compiled into both mkfs.lustre and tunefs.lustre */
 
 #define _GNU_SOURCE
 #include <stdlib.h>
@@ -37,9 +37,9 @@
 #include <string.h>
 #include <getopt.h>
 
-#include <linux/types.h>
-//#define HAVE_SYS_VFS_H 1
-#include <linux/fs.h> // for BLKGETSIZE64
+#ifdef __linux__
+# include <linux/fs.h> /* for BLKGETSIZE64 */
+#endif
 #include <lustre_disk.h>
 #include <lustre_param.h>
 #include <lnet/lnetctl.h>
 #define MAX_LOOP_DEVICES 16
 #define L_BLOCK_SIZE 4096
 #define INDEX_UNASSIGNED 0xFFFF
+#define MO_IS_LOOP     0x01
+#define MO_FORCEFORMAT 0x02
+
+/* used to describe the options to format the lustre disk, not persistent */
+struct mkfs_opts {
+        struct lustre_disk_data mo_ldd; /* to be written in MOUNT_DATA_FILE */
+        char  mo_mount_type_string[20]; /* "ext3", "ldiskfs", ... */
+        char  mo_device[128];           /* disk device name */
+        char  mo_mkfsopts[128];         /* options to the backing-store mkfs */
+        char  mo_loopdev[128];          /* in case a loop dev is needed */
+        __u64 mo_device_sz;             /* in KB */
+        int   mo_stripe_count;
+        int   mo_flags; 
+        int   mo_mgs_failnodes;
+};
 
 static char *progname;
 static int verbose = 0;
@@ -62,7 +77,7 @@ void usage(FILE *out)
         fprintf(out,
                 "\t<device>:block device or file (e.g /dev/sda or /tmp/ost1)\n"
                 "\ttarget types:\n"
-                "\t\t--ost: object storage, mutually exclusive with mdt\n"
+                "\t\t--ost: object storage, mutually exclusive with mdt,mgs\n"
                 "\t\t--mdt: metadata storage, mutually exclusive with ost\n"
                 "\t\t--mgs: configuration management service - one per site\n"
                 "\toptions (in order of popularity):\n"
@@ -71,15 +86,17 @@ void usage(FILE *out)
                 "\t\t--fsname=<filesystem_name> : default is 'lustre'\n"
                 "\t\t--failnode=<nid>[,<...>] : NID(s) of a failover partner\n"
                 "\t\t--param <key>=<value> : set a permanent parameter\n"
-                "\t\t--index=#N : target index\n"
+                "\t\t\te.g. --param sys.timeout=40\n"
+                "\t\t\t     --param lov.stripe.size=4194304\n"
+                "\t\t--index=#N : target index (i.e. ost index within the lov)\n"
                 /* FIXME implement 1.6.x
                 "\t\t--configdev=<altdevice|file>: store configuration info\n"
                 "\t\t\tfor this device on an alternate device\n"
                 */
                 "\t\t--mountfsoptions=<opts> : permanent mount options\n"
+#ifndef TUNEFS
                 "\t\t--backfstype=<fstype> : backing fs type (ext3, ldiskfs)\n"
                 "\t\t--device-size=#N(KB) : device size for loop devices\n"
-#ifndef TUNEFS
                 "\t\t--mkfsoptions=<opts> : format options\n"
                 "\t\t--reformat: overwrite an existing disk\n"
                 "\t\t--stripe-count-hint=#N : used for optimizing MDT inode size\n"
@@ -88,14 +105,15 @@ void usage(FILE *out)
                 "\t\t--nomgs: turn off MGS service on this MDT\n"
                 "\t\t--writeconf: erase all config logs for this fs.\n"
 #endif
-                "\t\t--print: just report what we would do; don't write to "
-                "disk\n"
+                "\t\t--noformat: just report what we would do; "
+                "don't write to disk\n"
                 "\t\t--verbose\n"
                 "\t\t--quiet\n");
         return;
 }
 
-#define vprint(i, fmt, arg...) if(verbose > i) printf(fmt, ## arg)
+#define vprint if (verbose > 0) printf
+#define verrprint if (verbose >= 0) printf
 
 static void fatal(void)
 {
@@ -146,7 +164,7 @@ int run_command(char *cmd)
         char log[] = "/tmp/mkfs_logXXXXXX";
         int fd, rc;
 
-        vprint(1, "cmd: %s\n", cmd);
+        vprint("cmd: %s\n", cmd);
         if ((fd = mkstemp(log)) >= 0) {
                 close(fd);
                 strcat(cmd, " >");
@@ -156,13 +174,13 @@ int run_command(char *cmd)
 
         /* Can't use popen because we need the rv of the command */
         rc = system(cmd);
-        if (rc && fd >= 0) {
+        if ((rc || (verbose > 2)) && (fd >= 0)) {
                 char buf[128];
                 FILE *fp;
                 fp = fopen(log, "r");
                 if (fp) {
                         while (fgets(buf, sizeof(buf), fp) != NULL) {
-                                vprint(2, "   %s", buf);
+                                printf("   %s", buf);
                         }
                         fclose(fp);
                 }
@@ -172,7 +190,7 @@ int run_command(char *cmd)
         return rc;
 }
 
-static int check_mtab_entry(char *spec, char *type)
+static int check_mtab_entry(char *spec)
 {
         FILE *fp;
         struct mntent *mnt;
@@ -182,8 +200,7 @@ static int check_mtab_entry(char *spec, char *type)
                 return(0);
 
         while ((mnt = getmntent(fp)) != NULL) {
-                if ((strcmp(mnt->mnt_fsname, spec) == 0) &&
-                        (strcmp(mnt->mnt_type, type) == 0)) {
+                if (strcmp(mnt->mnt_fsname, spec) == 0) {
                         endmntent(fp);
                         fprintf(stderr, "%s: according to %s %s is "
                                 "already mounted on %s\n",
@@ -213,7 +230,7 @@ int loop_setup(struct mkfs_opts *mop)
                 strcpy(loop_base, "/dev/loop/\0");
         } else {
                 fprintf(stderr, "%s: can't access loop devices\n", progname);
-                return 1;
+                return EACCES;
         }
 
         /* Find unused loop device */
@@ -224,6 +241,7 @@ int loop_setup(struct mkfs_opts *mop)
                         break;
                 sprintf(cmd, "losetup %s > /dev/null 2>&1", l_device);
                 ret = system(cmd);
+                
                 /* losetup gets 1 (ret=256) for non-set-up device */
                 if (ret) {
                         /* Set up a loopback device to our file */
@@ -283,8 +301,17 @@ __u64 get_device_size(char* device)
                 return 0;
         }
 
+#ifdef BLKGETSIZE64
         /* size in bytes. bz5831 */
         ret = ioctl(fd, BLKGETSIZE64, (void*)&size);
+#else
+        {
+                __u32 lsize = 0;
+                /* size in blocks */
+                ret = ioctl(fd, BLKGETSIZE, (void*)&lsize);
+                size = (__u64)lsize * 512; 
+        }
+#endif
         close(fd);
         if (ret < 0) {
                 fprintf(stderr, "%s: size ioctl failed: %s\n",
@@ -292,7 +319,7 @@ __u64 get_device_size(char* device)
                 return 0;
         }
 
-        vprint(0, "device size = "LPU64"MB\n", size >> 20);
+        vprint("device size = "LPU64"MB\n", size >> 20);
         /* return value in KB */
         return size >> 10;
 }
@@ -353,12 +380,16 @@ static int file_in_dev(char *file_name, char *dev_name)
         }
         i = fread(debugfs_cmd, 1, sizeof(debugfs_cmd), fp);
         if (i) {
-                /* Filesystem has unsupported feature */
-                vprint(0, "%.*s", i, debugfs_cmd);
-                /* in all likelihood, the "unsupported feature" is
-                  'extents', which older debugfs does not understand.
-                  Use e2fsprogs-1.38-cfs1 or later, available from
-                  ftp://ftp.lustre.org/pub/lustre/other/e2fsprogs/ */
+                debugfs_cmd[i] = 0;
+                fprintf(stderr, "%s", debugfs_cmd);
+                if (strstr(debugfs_cmd, "unsupported feature")) {
+                        fprintf(stderr, "In all likelihood, the "
+                                "'unsupported feature' is 'extents', which "
+                                "older debugfs does not understand.\n"  
+                                "Use e2fsprogs-1.38-cfs1 or later, available "
+                                "from ftp://ftp.lustre.org/pub/lustre/other/"
+                                "e2fsprogs/\n");
+                }
                 return -1;
         }
         pclose(fp);
@@ -370,10 +401,10 @@ static int is_lustre_target(struct mkfs_opts *mop)
 {
         int rc;
 
-        vprint(0, "checking for existing Lustre data\n");
+        vprint("checking for existing Lustre data\n");
         if ((rc = file_in_dev(MOUNT_DATA_FILE, mop->mo_device))
             || (rc = file_in_dev(LAST_RCVD, mop->mo_device))) {
-                vprint(0, "found Lustre data\n");
+                vprint("found Lustre data\n");
                 /* in the -1 case, 'extents' means this really IS a lustre
                    target */
                 return rc;
@@ -509,11 +540,11 @@ int make_lustre_backfs(struct mkfs_opts *mop)
         if (mop->mo_flags & MO_IS_LOOP)
                 dev = mop->mo_loopdev;
 
-        vprint(0, "formatting backing filesystem %s on %s\n",
+        vprint("formatting backing filesystem %s on %s\n",
                MT_STR(&mop->mo_ldd), dev);
-        vprint(0, "\ttarget name  %s\n", mop->mo_ldd.ldd_svname);
-        vprint(0, "\t4k blocks     %d\n", block_count);
-        vprint(0, "\toptions       %s\n", mop->mo_mkfsopts);
+        vprint("\ttarget name  %s\n", mop->mo_ldd.ldd_svname);
+        vprint("\t4k blocks     %d\n", block_count);
+        vprint("\toptions       %s\n", mop->mo_mkfsopts);
 
         /* mkfs_cmd's trailing space is important! */
         strcat(mkfs_cmd, mop->mo_mkfsopts);
@@ -524,7 +555,7 @@ int make_lustre_backfs(struct mkfs_opts *mop)
                 strcat(mkfs_cmd, buf);
         }
 
-        vprint(0, "mkfs_cmd = %s\n", mkfs_cmd);
+        vprint("mkfs_cmd = %s\n", mkfs_cmd);
         ret = run_command(mkfs_cmd);
         if (ret) {
                 fatal();
@@ -618,7 +649,7 @@ int write_local_files(struct mkfs_opts *mop)
 
         /* Save the persistent mount data into a file. Lustre must pre-read
            this file to get the real mount options. */
-        vprint(0, "Writing %s\n", MOUNT_DATA_FILE);
+        vprint("Writing %s\n", MOUNT_DATA_FILE);
         sprintf(filepnm, "%s/%s", mntpt, MOUNT_DATA_FILE);
         filep = fopen(filepnm, "w");
         if (!filep) {
@@ -636,22 +667,18 @@ int write_local_files(struct mkfs_opts *mop)
             == (LDD_F_UPGRADE14 | LDD_F_SV_TYPE_MGS)) {
                 char cmd[128];
                 char *term;
-                vprint(0, "Copying old logs\n");
-#if 0
- /* Generate new client log as servers upgrade.  Starting a new client 
-    may end up with short lov's, so will be degraded until all servers
-    upgrade */
+                vprint("Copying old logs\n");
+                
                 /* Copy the old client log to fsname-client */
                 sprintf(filepnm, "%s/%s/%s-client", 
                         mntpt, MOUNT_CONFIGS_DIR, mop->mo_ldd.ldd_fsname);
                 sprintf(cmd, "cp %s/%s/client %s", mntpt, MDT_LOGS_DIR,
                         filepnm);
-                vprint(1, "cmd: %s\n", cmd);
                 ret = run_command(cmd);
                 if (ret) {
                         fprintf(stderr, "%s: Can't copy 1.4 config %s/client "
                                 "(%d)\n", progname, MDT_LOGS_DIR, ret);
-                        fprintf(stderr, "mount -t ext3 %s somewhere, "
+                        fprintf(stderr, "mount -t ldiskfs %s somewhere, "
                                 "find the client log for fs %s and "
                                 "copy it manually into %s/%s-client, "
                                 "then umount.\n",
@@ -660,7 +687,7 @@ int write_local_files(struct mkfs_opts *mop)
                                 mop->mo_ldd.ldd_fsname);
                         goto out_umnt;
                 }
- #endif
+
                 /* We need to use the old mdt log because otherwise mdt won't
                    have complete lov if old clients connect before all 
                    servers upgrade. */
@@ -675,7 +702,6 @@ int write_local_files(struct mkfs_opts *mop)
                                 mntpt, MDT_LOGS_DIR, filepnm, 
                                 mntpt, MOUNT_CONFIGS_DIR,
                                 mop->mo_ldd.ldd_svname);
-                        vprint(1, "cmd: %s\n", cmd);
                         ret = run_command(cmd);
                 }
                 if (ret) {
@@ -704,50 +730,70 @@ out_rmdir:
 
 int read_local_files(struct mkfs_opts *mop)
 {
-        char mntpt[] = "/tmp/mntXXXXXX";
+        char tmpdir[] = "/tmp/dirXXXXXX";
+        char cmd[128];
         char filepnm[128];
         char *dev;
         FILE *filep;
         int ret = 0;
 
-        /* Mount this device temporarily in order to read these files */
-        if (!mkdtemp(mntpt)) {
-                fprintf(stderr, "%s: Can't create temp mount point %s: %s\n",
-                        progname, mntpt, strerror(errno));
+        /* Make a temporary directory to hold Lustre data files. */
+        if (!mkdtemp(tmpdir)) {
+                fprintf(stderr, "%s: Can't create temporary directory %s: %s\n",
+                        progname, tmpdir, strerror(errno));
                 return errno;
         }
 
         dev = mop->mo_device;
-        if (mop->mo_flags & MO_IS_LOOP) 
-                dev = mop->mo_loopdev;
-        
-        ret = mount(dev, mntpt, MT_STR(&mop->mo_ldd), 0, NULL);
-        if (ret) {
-                fprintf(stderr, "%s: Unable to mount %s: %s\n", 
-                        progname, dev, strerror(errno));
-                goto out_rmdir;
-        }
 
-        sprintf(filepnm, "%s/%s", mntpt, MOUNT_DATA_FILE);
+        /* Construct debugfs command line. */
+        memset(cmd, 0, sizeof(cmd));
+        sprintf(cmd, "debugfs -c -R 'rdump /%s %s' %s",
+                MOUNT_CONFIGS_DIR, tmpdir, dev);
+
+        ret = run_command(cmd);
+        if (ret)
+                verrprint("%s: Unable to dump %s dir (%d)\n",
+                          progname, MOUNT_CONFIGS_DIR, ret);
+
+        sprintf(filepnm, "%s/%s", tmpdir, MOUNT_DATA_FILE);
         filep = fopen(filepnm, "r");
         if (filep) {
-                vprint(0, "Reading %s\n", MOUNT_DATA_FILE);
+                vprint("Reading %s\n", MOUNT_DATA_FILE);
                 fread(&mop->mo_ldd, sizeof(mop->mo_ldd), 1, filep);
         } else {
                 /* COMPAT_146 */
                 /* Try to read pre-1.6 config from last_rcvd */
                 struct lr_server_data lsd;
-                vprint(0, "%s: Unable to read %s, trying last_rcvd\n",
-                       progname, MOUNT_DATA_FILE);
-                sprintf(filepnm, "%s/%s", mntpt, LAST_RCVD);
+                verrprint("%s: Unable to read %s (%s).\n",
+                          progname, MOUNT_DATA_FILE, strerror(errno));
+                verrprint("Contents of %s:\n", MOUNT_CONFIGS_DIR);
+                sprintf(cmd, "ls -l %s", tmpdir);
+                run_command(cmd);
+                verrprint("Trying last_rcvd\n");
+
+                /* Construct debugfs command line. */
+                memset(cmd, 0, sizeof(cmd));
+                sprintf(cmd,
+                        "debugfs -c -R 'dump /%s %s/%s' %s",
+                        LAST_RCVD, tmpdir, LAST_RCVD, dev);
+
+                ret = run_command(cmd);
+                if (ret) {
+                        fprintf(stderr, "%s: Unable to dump %s file\n",
+                                progname, LAST_RCVD);
+                        goto out_rmdir;
+                }
+
+                sprintf(filepnm, "%s/%s", tmpdir, LAST_RCVD);
                 filep = fopen(filepnm, "r");
                 if (!filep) {
                         fprintf(stderr, "%s: Unable to read old data\n",
                                 progname);
                         ret = -errno;
-                        goto out_umnt;
+                        goto out_rmdir;
                 }
-                vprint(0, "Reading %s\n", LAST_RCVD);
+                vprint("Reading %s\n", LAST_RCVD);
                 ret = fread(&lsd, 1, sizeof(lsd), filep);
                 if (ret < sizeof(lsd)) {
                         fprintf(stderr, "%s: Short read (%d of %d)\n",
@@ -756,11 +802,15 @@ int read_local_files(struct mkfs_opts *mop)
                         if (ret) 
                                 goto out_close;
                 }
-                ret = 0;
-                if (lsd.lsd_feature_compat & OBD_COMPAT_OST) {
+                vprint("Feature compat=%x, incompat=%x\n",
+                       lsd.lsd_feature_compat, lsd.lsd_feature_incompat);
+
+                if ((lsd.lsd_feature_compat & OBD_COMPAT_OST) ||
+                    (lsd.lsd_feature_incompat & OBD_INCOMPAT_OST)) {
                         mop->mo_ldd.ldd_flags = LDD_F_SV_TYPE_OST;
                         mop->mo_ldd.ldd_svindex = lsd.lsd_ost_index;
-                } else if (lsd.lsd_feature_compat & OBD_COMPAT_MDT) {
+                } else if ((lsd.lsd_feature_compat & OBD_COMPAT_MDT) ||
+                           (lsd.lsd_feature_incompat & OBD_INCOMPAT_MDT)) {
                         /* We must co-locate so mgs can see old logs.
                            If user doesn't want this, they can copy the old
                            logs manually and re-tunefs. */
@@ -769,7 +819,15 @@ int read_local_files(struct mkfs_opts *mop)
                         mop->mo_ldd.ldd_svindex = lsd.lsd_mdt_index;
                 } else  {
                         /* If neither is set, we're pre-1.4.6, make a guess. */
-                        sprintf(filepnm, "%s/%s", mntpt, MDT_LOGS_DIR);
+                        /* Construct debugfs command line. */
+                        memset(cmd, 0, sizeof(cmd));
+                        sprintf(cmd,
+                                "debugfs -c -R 'rdump /%s %s' %s",
+                                MDT_LOGS_DIR, tmpdir, dev);
+
+                        run_command(cmd);
+
+                        sprintf(filepnm, "%s/%s", tmpdir, MDT_LOGS_DIR);
                         if (lsd.lsd_ost_index > 0) {
                                 mop->mo_ldd.ldd_flags = LDD_F_SV_TYPE_OST;
                                 mop->mo_ldd.ldd_svindex = lsd.lsd_ost_index;
@@ -783,13 +841,15 @@ int read_local_files(struct mkfs_opts *mop)
                                            (pre CMD) */
                                         mop->mo_ldd.ldd_svindex = 0;
                                 } else {
-                                        /* The index won't be correct */
+                                        /* The index may not be correct */
                                         mop->mo_ldd.ldd_flags =
                                         LDD_F_SV_TYPE_OST | LDD_F_NEED_INDEX;
+                                        verrprint("OST with unknown index\n");
                                 }
                         }
                 }
-
+                
+                ret = 0;
                 memcpy(mop->mo_ldd.ldd_uuid, lsd.lsd_uuid, 
                        sizeof(mop->mo_ldd.ldd_uuid));
                 mop->mo_ldd.ldd_flags |= LDD_F_UPGRADE14;
@@ -797,11 +857,11 @@ int read_local_files(struct mkfs_opts *mop)
         /* end COMPAT_146 */
 out_close:        
         fclose(filep);
-        
-out_umnt:
-        umount(mntpt);    
+
 out_rmdir:
-        rmdir(mntpt);
+        memset(cmd, 0, sizeof(cmd));
+        sprintf(cmd, "rm -rf %s", tmpdir);
+        run_command(cmd);
         return ret;
 }
 
@@ -873,16 +933,18 @@ static char *convert_hostnames(char *s1)
                         free(converted);
                         return NULL;
                 }
-                if (LNET_NETTYP(LNET_NIDNET(nid)) == SOCKLND) {
-                        __u32 addr = LNET_NIDADDR(nid);
-                        c += snprintf(c, left, "%u.%u.%u.%u@%s%u,",
-                                      (addr >> 24) & 0xff, (addr >> 16) & 0xff,
-                                      (addr >> 8) & 0xff, addr & 0xff,
-                                      libcfs_lnd2str(SOCKLND)
-                                      LNET_NETNUM(LNET_NIDNET(nid)));
-                } else {
-                        c += snprintf(c, left, "%s,", s2);
+
+                if (strncmp(libcfs_nid2str(nid), "127.0.0.1", 
+                            strlen("127.0.0.1")) == 0) {
+                        fprintf(stderr, "%s: The NID '%s' resolves to the "
+                                "loopback address '%s'.  Lustre requires a "
+                                "non-loopback address.\n"
+                                progname, s2, libcfs_nid2str(nid));
+                        free(converted);
+                        return NULL;
                 }
+
+                c += snprintf(c, left, "%s,", libcfs_nid2str(nid));
                 left = converted + MAXNIDSTR - c;
         }
         *(c - 1) = '\0';
@@ -907,19 +969,20 @@ int parse_opts(int argc, char *const argv[], struct mkfs_opts *mop,
                 {"mgsnode", 1, 0, 'm'},
                 {"mgsnid", 1, 0, 'm'},
                 {"mdt", 0, 0, 'M'},
-                {"fsname",1, 0, 'n'},
+                {"fsname",1, 0, 'L'},
+                {"noformat", 0, 0, 'n'},
                 {"nomgs", 0, 0, 'N'},
                 {"mountfsoptions", 1, 0, 'o'},
                 {"ost", 0, 0, 'O'},
                 {"param", 1, 0, 'p'},
-                {"print", 0, 0, 'P'},
+                {"print", 0, 0, 'n'},
                 {"quiet", 0, 0, 'q'},
                 {"reformat", 0, 0, 'r'},
                 {"verbose", 0, 0, 'v'},
                 {"writeconf", 0, 0, 'w'},
                 {0, 0, 0, 0}
         };
-        char *optstring = "b:c:C:d:ef:Ghi:k:m:Mn:No:Op:Pqrvw";
+        char *optstring = "b:c:C:d:ef:Ghi:k:L:m:MnNo:Op:Pqrvw";
         char opt;
         int rc, longidx;
 
@@ -960,6 +1023,8 @@ int parse_opts(int argc, char *const argv[], struct mkfs_opts *mop,
                         break;
                 case 'e':
                         mop->mo_ldd.ldd_params[0] = '\0';
+                        /* Must update the mgs logs */
+                        mop->mo_ldd.ldd_flags |= LDD_F_UPDATE;
                         break;
                 case 'f': {
                         char *nids = convert_hostnames(optarg);
@@ -970,6 +1035,8 @@ int parse_opts(int argc, char *const argv[], struct mkfs_opts *mop,
                         free(nids);
                         if (rc) 
                                 return rc;
+                        /* Must update the mgs logs */
+                        mop->mo_ldd.ldd_flags |= LDD_F_UPDATE;
                         break;
                 }
                 case 'G':
@@ -979,6 +1046,13 @@ int parse_opts(int argc, char *const argv[], struct mkfs_opts *mop,
                         usage(stdout);
                         return 1;
                 case 'i':
+                        if (!(mop->mo_ldd.ldd_flags & 
+                              (LDD_F_UPGRADE14 | LDD_F_VIRGIN |
+                               LDD_F_WRITECONF))) {
+                                fprintf(stderr, "%s: cannot change the index of"
+                                        " a registered target\n", progname);
+                                return 1;
+                        }
                         if (IS_MDT(&mop->mo_ldd) || IS_OST(&mop->mo_ldd)) {
                                 mop->mo_ldd.ldd_svindex = atol(optarg);
                                 mop->mo_ldd.ldd_flags &= ~LDD_F_NEED_INDEX;
@@ -991,6 +1065,23 @@ int parse_opts(int argc, char *const argv[], struct mkfs_opts *mop,
                         strncpy(mop->mo_mkfsopts, optarg, 
                                 sizeof(mop->mo_mkfsopts) - 1);
                         break;
+                case 'L':
+                        if (!(mop->mo_ldd.ldd_flags & 
+                              (LDD_F_UPGRADE14 | LDD_F_VIRGIN |
+                               LDD_F_WRITECONF))) {
+                                fprintf(stderr, "%s: cannot change the name of"
+                                        " a registered target\n", progname);
+                                return 1;
+                        }
+                        if (strlen(optarg) > 8) {
+                                fprintf(stderr, "%s: filesystem name must be "
+                                        "<= 8 chars\n", progname);
+                                return 1;
+                        }
+                        if (optarg[0] != 0) 
+                                strncpy(mop->mo_ldd.ldd_fsname, optarg, 
+                                        sizeof(mop->mo_ldd.ldd_fsname) - 1);
+                        break;
                 case 'm': {
                         char *nids = convert_hostnames(optarg);
                         if (!nids) 
@@ -1007,18 +1098,7 @@ int parse_opts(int argc, char *const argv[], struct mkfs_opts *mop,
                         mop->mo_ldd.ldd_flags |= LDD_F_SV_TYPE_MDT;
                         break;
                 case 'n':
-                        if (!(IS_MDT(&mop->mo_ldd) || IS_OST(&mop->mo_ldd))) {
-                                badopt(long_opt[longidx].name, "MDT,OST");
-                                return 1;
-                        }
-                        if (strlen(optarg) > 8) {
-                                fprintf(stderr, "%s: filesystem name must be "
-                                        "<= 8 chars\n", progname);
-                                return 1;
-                        }
-                        if (optarg[0] != 0) 
-                                strncpy(mop->mo_ldd.ldd_fsname, optarg, 
-                                        sizeof(mop->mo_ldd.ldd_fsname) - 1);
+                        print_only++;
                         break;
                 case 'N':
                         mop->mo_ldd.ldd_flags &= ~LDD_F_SV_TYPE_MGS;
@@ -1033,9 +1113,8 @@ int parse_opts(int argc, char *const argv[], struct mkfs_opts *mop,
                         rc = add_param(mop->mo_ldd.ldd_params, NULL, optarg);
                         if (rc) 
                                 return rc;
-                        break;
-                case 'P':
-                        print_only++;
+                        /* Must update the mgs logs */
+                        mop->mo_ldd.ldd_flags |= LDD_F_UPDATE;
                         break;
                 case 'q':
                         verbose--;
@@ -1283,9 +1362,9 @@ int main(int argc, char *argv[])
         else
                 progname = argv[0];
 
-        if (argc < 2) {
+        if ((argc < 2) || (argv[argc - 1][0] == '-')) {
                 usage(stderr);
-                ret = 1;
+                ret = EINVAL;
                 goto out;
         }
 
@@ -1295,9 +1374,6 @@ int main(int argc, char *argv[])
         /* device is last arg */
         strcpy(mop.mo_device, argv[argc - 1]);
 
-        if (check_mtab_entry(mop.mo_device, "lustre"))
-                return(EEXIST);
-
         /* Are we using a loop device? */
         ret = is_block(mop.mo_device);
         if (ret < 0) 
@@ -1308,18 +1384,6 @@ int main(int argc, char *argv[])
 #ifdef TUNEFS
         /* For tunefs, we must read in the old values before parsing any
            new ones. */
-        /* Create the loopback file */
-        if (mop.mo_flags & MO_IS_LOOP) {
-                ret = access(mop.mo_device, F_OK);
-                if (ret == 0)  
-                        ret = loop_setup(&mop);
-                if (ret) {
-                        fatal();
-                        fprintf(stderr, "Loop device setup for %s failed: %s\n", 
-                                mop.mo_device, strerror(ret));
-                        goto out;
-                }
-        }
         
         /* Check whether the disk has already been formatted by mkfs.lustre */
         ret = is_lustre_target(&mop);
@@ -1327,6 +1391,7 @@ int main(int argc, char *argv[])
                 fatal();
                 fprintf(stderr, "Device %s has not been formatted with "
                         "mkfs.lustre\n", mop.mo_device);
+                ret = ENODEV;
                 goto out;
         }
 
@@ -1337,6 +1402,8 @@ int main(int argc, char *argv[])
                         mop.mo_device);
                 goto out;
         }
+        if (strstr(mop.mo_ldd.ldd_params, PARAM_MGSNODE))
+            mop.mo_mgs_failnodes++;
 
         if (verbose > 0) 
                 print_ldd("Read previous values", &(mop.mo_ldd));
@@ -1347,61 +1414,76 @@ int main(int argc, char *argv[])
                 goto out;
 
         ldd = &mop.mo_ldd;
+        
         if (!(IS_MDT(ldd) || IS_OST(ldd) || IS_MGS(ldd))) {
                 fatal();
-                fprintf(stderr, "must set target type :{mdt,ost,mgs}\n");
-                usage(stderr);
-                ret = 1;
+                fprintf(stderr, "must set target type: MDT,OST,MGS\n");
+                ret = EINVAL;
+                goto out;
+        }
+
+        if (((IS_MDT(ldd) || IS_MGS(ldd))) && IS_OST(ldd)) {
+                fatal();
+                fprintf(stderr, "OST type is exclusive with MDT,MGS\n");
+                ret = EINVAL;
+                goto out;
+        }
+
+        if ((mop.mo_ldd.ldd_flags & (LDD_F_NEED_INDEX | LDD_F_UPGRADE14)) ==
+            (LDD_F_NEED_INDEX | LDD_F_UPGRADE14)) {
+                fatal();
+                fprintf(stderr, "Can't find the target index, "
+                        "specify with --index\n");
+                ret = EINVAL;
                 goto out;
         }
 
         if (IS_MDT(ldd) && !IS_MGS(ldd) && (mop.mo_mgs_failnodes == 0)) {
-                vprint(0, "No management node specified, adding MGS to this "
-                       "MDT\n");
+                verrprint("No management node specified, adding MGS to this "
+                          "MDT\n");
                 ldd->ldd_flags |= LDD_F_SV_TYPE_MGS;
         }
 
         if (!IS_MGS(ldd) && (mop.mo_mgs_failnodes == 0)) {
                 fatal();
                 fprintf(stderr, "Must specify either --mgs or --mgsnode\n");
-                usage(stderr);
+                ret = EINVAL;
                 goto out;
         }
 
         /* These are the permanent mount options (always included) */ 
         switch (ldd->ldd_mount_type) {
-                case LDD_MT_EXT3:
-                case LDD_MT_LDISKFS: {
-                        sprintf(always_mountopts, "errors=remount-ro");
-                        if (IS_MDT(ldd) || IS_MGS(ldd))
-                                strcat(always_mountopts,
-                                       ",iopen_nopriv,user_xattr");
-                        if ((get_os_version() == 24) && IS_OST(ldd))
-                                strcat(always_mountopts, ",asyncdel");
-#if 0
-                        /* Files created while extents are enabled cannot be
-                           read if mounted with a kernel that doesn't include
-                           the CFS patches.*/
-                        if (IS_OST(ldd) && 
-                            ldd->ldd_mount_type == LDD_MT_LDISKFS) {
-                                strcat(default_mountopts, ",extents,mballoc");
-                        }
-#endif 
-                        break;
-                }
-                case LDD_MT_SMFS: {
-                        mop.mo_flags |= MO_IS_LOOP;
-                        sprintf(always_mountopts, "type=ext3,dev=%s",
-                                mop.mo_device);
-                        break;
-                }
-                default: {
-                        fatal();
-                        fprintf(stderr, "unknown fs type %d '%s'\n",
-                                ldd->ldd_mount_type, MT_STR(ldd));
-                        ret = EINVAL;
-                        goto out;
+        case LDD_MT_EXT3:
+        case LDD_MT_LDISKFS: {
+                sprintf(always_mountopts, "errors=remount-ro");
+                if (IS_MDT(ldd) || IS_MGS(ldd))
+                        strcat(always_mountopts,
+                               ",iopen_nopriv,user_xattr");
+                if ((get_os_version() == 24) && IS_OST(ldd))
+                        strcat(always_mountopts, ",asyncdel");
+                /* NB: Files created while extents are enabled cannot be read
+                   if mounted with a kernel that doesn't include the CFS 
+                   patches! */
+                if (IS_OST(ldd) && 
+                    ldd->ldd_mount_type == LDD_MT_LDISKFS) {
+                        strcat(default_mountopts, ",extents,mballoc");
                 }
+                break;
+        }
+        case LDD_MT_SMFS: {
+                mop.mo_flags |= MO_IS_LOOP;
+                sprintf(always_mountopts, "type=ext3,dev=%s",
+                        mop.mo_device);
+                break;
+        }
+        default: {
+                fatal();
+                fprintf(stderr, "unknown fs type %d '%s'\n",
+                        ldd->ldd_mount_type,
+                        MT_STR(ldd));
+                ret = EINVAL;
+                goto out;
+        }
         }               
 
         if (mountopts) {
@@ -1415,19 +1497,15 @@ int main(int argc, char *argv[])
                         /* use the defaults unless old opts exist */
 #endif
                 {
-                        if (default_mountopts[0]) 
-                                sprintf(ldd->ldd_mount_opts, "%s,%s", 
-                                        always_mountopts, default_mountopts);
-                        else
-                                strcpy(ldd->ldd_mount_opts,
-                                       always_mountopts);
+                        sprintf(ldd->ldd_mount_opts, "%s%s", 
+                                always_mountopts, default_mountopts);
                 }
         }
 
         server_make_name(ldd->ldd_flags, ldd->ldd_svindex,
                          ldd->ldd_fsname, ldd->ldd_svname);
 
-        if (verbose > 0)
+        if (verbose >= 0)
                 print_ldd("Permanent disk data", ldd);
 
         if (print_only) {
@@ -1435,23 +1513,30 @@ int main(int argc, char *argv[])
                 goto out;
         }
 
-#ifndef TUNEFS /* mkfs.lustre */
-        /* Create the loopback file of the correct size */
+        if (check_mtab_entry(mop.mo_device))
+                return(EEXIST);
+
+        /* Create the loopback file */
         if (mop.mo_flags & MO_IS_LOOP) {
                 ret = access(mop.mo_device, F_OK);
-                /* Don't destroy the loopback file if no FORCEFORMAT */
+                if (ret) 
+                        ret = errno;
+#ifndef TUNEFS /* mkfs.lustre */
+                /* Reformat the loopback file */
                 if (ret || (mop.mo_flags & MO_FORCEFORMAT))
                         ret = loop_format(&mop);
+#endif
                 if (ret == 0)  
                         ret = loop_setup(&mop);
                 if (ret) {
                         fatal();
-                        fprintf(stderr, "Loop device setup failed: %s\n", 
-                                strerror(ret));
+                        fprintf(stderr, "Loop device setup for %s failed: %s\n",
+                                mop.mo_device, strerror(ret));
                         goto out;
                 }
         }
 
+#ifndef TUNEFS /* mkfs.lustre */
         /* Check whether the disk has already been formatted by mkfs.lustre */
         if (!(mop.mo_flags & MO_FORCEFORMAT)) {
                 ret = is_lustre_target(&mop);
@@ -1474,6 +1559,7 @@ int main(int argc, char *argv[])
         }
 #endif
 
+        /* Write our config files */
         ret = write_local_files(&mop);
         if (ret != 0) {
                 fatal();
diff --git a/lustre/utils/module_cleanup.sh b/lustre/utils/module_cleanup.sh
new file mode 100755 (executable)
index 0000000..92f0cce
--- /dev/null
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+MDIR=/lib/modules/`uname -r`/lustre
+mkdir -p $MDIR
+
+KVER=24
+EXT=o
+FSFLT=fsfilt_ext3
+MODFILE="/etc/modules.conf"
+if [ `uname -r | cut -c 3` -eq 6 ]; then
+    KVER=26
+    EXT=ko
+    FSFLT=fsfilt_ldiskfs
+    MODFILE="/etc/modprobe.conf"
+fi
+
+echo "Removing Lustre modules from "$MDIR
+
+rm -f $MDIR/*
+depmod -a
+rm -f /sbin/mount.lustre
+
index aabfa7b..5cddcf3 100755 (executable)
@@ -17,46 +17,35 @@ fi
 
 echo "Copying modules from local build dir to "$MDIR
 
-cp -u ../../lustre/mds/mds.ko $MDIR
-cp -u ../../lustre/osd/osd.ko $MDIR
-cp -u ../../lustre/obdfilter/obdfilter.ko $MDIR
-cp -u ../../lustre/ost/ost.ko $MDIR
-cp -u ../../lustre/mgs/mgs.ko $MDIR
-cp -u ../../lustre/lov/lov.ko $MDIR
-cp -u ../../lustre/ptlrpc/ptlrpc.ko $MDIR
-cp -u ../../lustre/obdecho/obdecho.ko $MDIR
-cp -u ../../lustre/llite/llite.ko $MDIR
-cp -u ../../lustre/mgc/mgc.ko $MDIR
-cp -u ../../lustre/ldiskfs/ldiskfs.ko $MDIR
-cp -u ../../lustre/ldiskfs/quotafmt_test.ko $MDIR
-cp -u ../../lustre/osc/osc.ko $MDIR
-cp -u ../../lustre/mdt/mdt.ko $MDIR
-cp -u ../../lustre/quota/lquota.ko $MDIR
-cp -u ../../lustre/quota/quotactl_test.ko $MDIR
-cp -u ../../lustre/quota/quotacheck_test.ko $MDIR
-cp -u ../../lustre/cmm/cmm.ko $MDIR
-cp -u ../../lustre/mdc/mdc.ko $MDIR
-cp -u ../../lustre/lvfs/fsfilt_ldiskfs.ko $MDIR
-cp -u ../../lustre/lvfs/lvfs.ko $MDIR
-cp -u ../../lustre/obdclass/llog_test.ko $MDIR
-cp -u ../../lustre/obdclass/obdclass.ko $MDIR
-cp -u ../../lustre/mdd/mdd.ko $MDIR
-cp -u ../../lustre/fld/fld.ko $MDIR
-cp -u ../../lustre/fid/fid.ko $MDIR
-cp -u ../../lustre/lmv/lmv.ko $MDIR
-cp -u ../../lnet/libcfs/libcfs.ko $MDIR
-cp -u ../../lnet/tests/pingcli.ko $MDIR
-cp -u ../../lnet/tests/spingsrv.ko $MDIR
-cp -u ../../lnet/tests/pingsrv.ko $MDIR
-cp -u ../../lnet/tests/spingcli.ko $MDIR
-cp -u ../../lnet/lnet/lnet.ko $MDIR
-cp -u ../../lnet/klnds/socklnd/ksocklnd.ko $MDIR
-
+cp -u ../../lnet/libcfs/libcfs.$EXT $MDIR
+cp -u ../../lnet/lnet/lnet.$EXT $MDIR
+cp -u ../../lnet/klnds/socklnd/ksocklnd.$EXT $MDIR
+cp -u ../lvfs/lvfs.$EXT $MDIR
+cp -u ../obdclass/obdclass.$EXT $MDIR
+cp -u ../ptlrpc/ptlrpc.$EXT $MDIR
+cp -u ../mdc/mdc.$EXT $MDIR
+cp -u ../osc/osc.$EXT $MDIR
+cp -u ../mdt/mdt.$EXT $MDIR
+cp -u ../cmm/cmm.$EXT $MDIR
+cp -u ../mdd/mdd.$EXT $MDIR
+cp -u ../osd/osd.$EXT $MDIR
+cp -u ../fld/fld.$EXT $MDIR
+cp -u ../fid/fid.$EXT $MDIR
+cp -u ../lmv/lmv.$EXT $MDIR
+cp -u ../lov/lov.$EXT $MDIR
+cp -u ../mds/mds.$EXT $MDIR
+cp -u ../lvfs/$FSFLT.$EXT $MDIR
+[ $KVER == "26" ] && cp -u ../ldiskfs/ldiskfs.$EXT $MDIR
+cp -u ../ost/ost.$EXT $MDIR
+cp -u ../obdfilter/obdfilter.$EXT $MDIR
+cp -u ../llite/lustre.$EXT $MDIR
+cp -u ../mgc/mgc.$EXT $MDIR
+cp -u ../mgs/mgs.$EXT $MDIR
 
 # prevent warnings on my uml
 rm -f /lib/modules/`uname -r`/modules.*
 echo "Depmod"
-depmod -a -e
+depmod -A -e
 
 echo "Copying mount from local build dir to "$MDIR
 cp -u ../utils/mount.lustre /sbin/.
@@ -70,7 +59,6 @@ if [ `egrep -c "lustre|lnet" $MODFILE` -eq 0 ]; then
     echo "# Lustre modules added by $0" >> $MODFILE
     echo "# Networking options, see /sys/module/lnet/parameters" >> $MODFILE
     echo "options lnet networks=tcp" >> $MODFILE
-    echo "alias lustre llite" >> $MODFILE
     echo "# end Lustre modules" >> $MODFILE
 fi
 
index be8ebdf..17c5471 100644 (file)
@@ -46,6 +46,8 @@ static char *progname = NULL;
 void usage(FILE *out)
 {
         fprintf(out, "%s v"LUSTRE_VERSION_STRING"\n", progname);
+        fprintf(out, "\nThis mount helper should only be invoked via the "
+                "mount (8) command,\ne.g. mount -t lustre dev dir\n\n");
         fprintf(out, "usage: %s [-fhnv] [-o <mntopt>] <device> <mountpt>\n", 
                 progname);
         fprintf(out, 
@@ -72,9 +74,6 @@ static int check_mtab_entry(char *spec, char *mtpt, char *type)
         FILE *fp;
         struct mntent *mnt;
 
-        if (force)
-                return (0);
-
         fp = setmntent(MOUNTED, "r");
         if (fp == NULL)
                 return(0);
@@ -84,9 +83,6 @@ static int check_mtab_entry(char *spec, char *mtpt, char *type)
                         strcmp(mnt->mnt_dir, mtpt) == 0 &&
                         strcmp(mnt->mnt_type, type) == 0) {
                         endmntent(fp);
-                        fprintf(stderr, "%s: according to %s %s is "
-                                "already mounted on %s\n",
-                                progname, MOUNTED, spec, mtpt);
                         return(EEXIST); 
                 }
         }
@@ -147,16 +143,7 @@ static char *convert_hostnames(char *s1)
                 nid = libcfs_str2nid(s1);
                 if (nid == LNET_NID_ANY)
                         goto out_free;
-                if (LNET_NETTYP(LNET_NIDNET(nid)) == SOCKLND) {
-                        __u32 addr = LNET_NIDADDR(nid);
-                        c += snprintf(c, left, "%u.%u.%u.%u@%s%u%c",
-                                      (addr >> 24) & 0xff, (addr >> 16) & 0xff,
-                                      (addr >> 8) & 0xff, addr & 0xff,
-                                      libcfs_lnd2str(SOCKLND), 
-                                      LNET_NETNUM(LNET_NIDNET(nid)), sep);
-                } else {
-                        c += snprintf(c, left, "%s%c", s1, sep);
-                }
+                c += snprintf(c, left, "%s%c", libcfs_nid2str(nid), sep);
                 left = converted + MAXNIDSTR - c;
                 s1 = s2 + 1;
         }
@@ -177,65 +164,58 @@ out_free:
  ****************************************************************************/
 struct opt_map {
         const char *opt;        /* option name */
-        int skip;               /* skip in mtab option string */
         int inv;                /* true if flag value should be inverted */
         int mask;               /* flag mask value */
 };
 
 static const struct opt_map opt_map[] = {
+  /*"optname", inv,ms_mask */
   /* These flags are parsed by mount, not lustre */
-  { "defaults", 0, 0, 0         },      /* default options */
-  { "rw",       1, 1, MS_RDONLY },      /* read-write */
-  { "ro",       0, 0, MS_RDONLY },      /* read-only */
-  { "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 */
-  { "async",    0, 1, MS_SYNCHRONOUS},  /* asynchronous I/O */
-  { "auto",     0, 0, 0         },      /* Can be mounted using -a */
-  { "noauto",   0, 0, 0         },      /* Can only be mounted explicitly */
-  { "nousers",  0, 1, 0         },      /* Forbid ordinary user to mount */
-  { "nouser",   0, 1, 0         },      /* Forbid ordinary user to mount */
-  { "noowner",  0, 1, 0         },      /* Device owner has no special privs */
-  { "_netdev",  0, 0, 0         },      /* Device accessible only via network */
-  /* These strings are passed through and parsed in lustre ll_options */
-  { "flock",    0, 0, 0         },      /* Enable flock support */
-  { "noflock",  1, 1, 0         },      /* Disable flock support */
-  { "user_xattr",   0, 0, 0     },      /* Enable get/set user xattr */
-  { "nouser_xattr", 1, 1, 0     },      /* Disable user xattr */
-  { "acl",      0, 0, 0         },      /* Enable ACL support */
-  { "noacl",    1, 1, 0         },      /* Disable ACL support */
-  { "nosvc",    0, 0, 0         },      /* Only start MGS/MGC, nothing else */
-  { "exclude",  0, 0, 0         },      /* OST exclusion list */
-  { NULL,       0, 0, 0         }
+  { "defaults", 0, 0         },      /* default options */
+  { "remount",  0, MS_REMOUNT},      /* remount with different options */
+  { "rw",       1, MS_RDONLY },      /* read-write */
+  { "ro",       0, MS_RDONLY },      /* read-only */
+  { "exec",     1, MS_NOEXEC },      /* permit execution of binaries */
+  { "noexec",   0, MS_NOEXEC },      /* don't execute binaries */
+  { "suid",     1, MS_NOSUID },      /* honor suid executables */
+  { "nosuid",   0, MS_NOSUID },      /* don't honor suid executables */
+  { "dev",      1, MS_NODEV  },      /* interpret device files  */
+  { "nodev",    0, MS_NODEV  },      /* don't interpret devices */
+  { "async",    1, MS_SYNCHRONOUS},  /* asynchronous I/O */
+  { "auto",     0, 0         },      /* Can be mounted using -a */
+  { "noauto",   0, 0         },      /* Can only be mounted explicitly */
+  { "nousers",  1, 0         },      /* Forbid ordinary user to mount */
+  { "nouser",   1, 0         },      /* Forbid ordinary user to mount */
+  { "noowner",  1, 0         },      /* Device owner has no special privs */
+  { "_netdev",  0, 0         },      /* Device accessible only via network */
+  { NULL,       0, 0         }
 };
 /****************************************************************************/
 
-/* 1  = found, flag set
-   0  = found, no flag set
-   -1 = not found in above list */
+/* 1  = don't pass on to lustre
+   0  = pass on to lustre */
 static int parse_one_option(const char *check, int *flagp)
 {
         const struct opt_map *opt;
 
         for (opt = &opt_map[0]; opt->opt != NULL; opt++) {
                 if (strncmp(check, opt->opt, strlen(opt->opt)) == 0) {
-                        if (!opt->mask) 
-                                return 0;
-                        if (opt->inv)
-                                *flagp &= ~(opt->mask);
-                        else
-                                *flagp |= opt->mask;
+                        if (opt->mask) {
+                                if (opt->inv)
+                                        *flagp &= ~(opt->mask);
+                                else
+                                        *flagp |= opt->mask;
+                        }
                         return 1;
                 }
         }
-        fprintf(stderr, "%s: ignoring unknown option '%s'\n", progname,
-                check);
-        return -1;
+        /* Assume any unknown options are valid and pass them on.  The mount
+           will fail if lmd_parse, ll_options or ldiskfs doesn't recognize it.*/
+        return 0;
 }
 
+/* Replace options with subset of Lustre-specific options, and
+   fill in mount flags */
 int parse_options(char *orig_options, int *flagp)
 {
         char *options, *opt, *nextopt;
@@ -248,13 +228,12 @@ int parse_options(char *orig_options, int *flagp)
                         /* empty option */
                         continue;
                 if (parse_one_option(opt, flagp) == 0) {
-                        /* no mount flags set, so pass this on as an option */
+                        /* pass this on as an option */
                         if (*options)
                                 strcat(options, ",");
                         strcat(options, opt);
                 }
         }
-        /* options will always be <= orig_options */
         strcpy(orig_options, options);
         free(options);
         return 0;
@@ -264,7 +243,8 @@ int parse_options(char *orig_options, int *flagp)
 int main(int argc, char *const argv[])
 {
         char default_options[] = "";
-        char *source, *target, *options = default_options, *optcopy;
+        char *source, *target, *ptr;
+        char *options, *optcopy, *orig_options = default_options;
         int i, nargs = 3, opt, rc, flags, optlen;
         static struct option long_opt[] = {
                 {"fake", 0, 0, 'f'},
@@ -301,12 +281,11 @@ int main(int argc, char *const argv[])
                         nargs++;
                         break;
                 case 'o':
-                        options = optarg;
+                        orig_options = optarg;
                         nargs++;
                         break;
                 case 'v':
                         ++verbose;
-                        printf("verbose: %d\n", verbose);
                         nargs++;
                         break;
                 default:
@@ -324,20 +303,25 @@ int main(int argc, char *const argv[])
 
         source = convert_hostnames(argv[optind]);
         target = argv[optind + 1];
+        ptr = target + strlen(target) - 1;
+        while ((ptr > target) && (*ptr == '/')) {
+                *ptr = 0;
+                ptr--;
+        }
 
         if (!source) {
                 usage(stderr);
         }
 
-        if (verbose > 1) {
+        if (verbose) {
                 for (i = 0; i < argc; i++)
                         printf("arg[%d] = %s\n", i, argv[i]);
                 printf("source = %s, target = %s\n", source, target);
+                printf("options = %s\n", orig_options);
         }
 
-        if (!force && check_mtab_entry(source, target, "lustre"))
-                return(EEXIST);
-
+        options = malloc(strlen(orig_options) + 1);
+        strcpy(options, orig_options);
         rc = parse_options(options, &flags); 
         if (rc) {
                 fprintf(stderr, "%s: can't parse options: %s\n",
@@ -345,6 +329,24 @@ int main(int argc, char *const argv[])
                 return(EINVAL);
         }
 
+        if (!force) {
+                rc = check_mtab_entry(source, target, "lustre");
+                if (rc && !(flags & MS_REMOUNT)) {
+                        fprintf(stderr, "%s: according to %s %s is "
+                                "already mounted on %s\n",
+                                progname, MOUNTED, source, target);
+                        return(EEXIST);
+                }
+                if (!rc && (flags & MS_REMOUNT)) {
+                        fprintf(stderr, "%s: according to %s %s is "
+                                "not already mounted on %s\n",
+                                progname, MOUNTED, source, target);
+                        return(ENOENT);
+                }
+        }
+        if (flags & MS_REMOUNT) 
+                nomtab++;
+
         rc = access(target, F_OK);
         if (rc) {
                 rc = errno;
@@ -374,30 +376,65 @@ int main(int argc, char *const argv[])
                 rc = mount(source, target, "lustre", flags, (void *)optcopy);
 
         if (rc) {
-                fprintf(stderr, "%s: mount(%s, %s) failed: %s\n", progname, 
+                char *cli;
+
+                rc = errno;
+
+                cli = strrchr(source, ':');
+                if (cli && (strlen(cli) > 2)) 
+                        cli += 2;
+                else
+                        cli = NULL;
+
+                fprintf(stderr, "%s: mount %s at %s failed: %s\n", progname, 
                         source, target, strerror(errno));
                 if (errno == ENODEV)
                         fprintf(stderr, "Are the lustre modules loaded?\n"
-                             "Check /etc/modules.conf and /proc/filesystems\n");
+                                "Check /etc/modprobe.conf and /proc/filesystems"
+                                "\nNote 'alias lustre llite' should be removed"
+                                " from modprobe.conf\n");
                 if (errno == ENOTBLK)
-                        fprintf(stderr,"Does this filesystem have any OSTs?\n");
-                if (errno == ENOENT)
-                        fprintf(stderr,"Is the MGS specification correct? "
-                                "(%s)\n", source);
+                        fprintf(stderr, "Do you need -o loop?\n");
+                if (errno == ENOMEDIUM)
+                        fprintf(stderr, 
+                                "This filesystem needs at least 1 OST\n");
+                if (errno == ENOENT) {
+                        fprintf(stderr, "Is the MGS specification correct?\n");
+                        fprintf(stderr, "Is the filesystem name correct?\n");
+                        fprintf(stderr, "If upgrading, is the copied client log"
+                                " valid? (see upgrade docs)\n");
+                }
                 if (errno == EALREADY)
-                        fprintf(stderr,"The target service is already running. "
-                                "(%s)\n", source);
+                        fprintf(stderr, "The target service is already running."
+                                " (%s)\n", source);
                 if (errno == ENXIO)
-                        fprintf(stderr,"The target service failed to start "
-                                "(bad config log?) (%s)\n", source);
+                        fprintf(stderr, "The target service failed to start "
+                                "(bad config log?) (%s).  "
+                                "See /var/log/messages.\n", source);
                 if (errno == EIO)
-                        fprintf(stderr,"Is the MGS running? (%s)\n", source);
+                        fprintf(stderr, "Is the MGS running?\n");
                 if (errno == EADDRINUSE)
-                        fprintf(stderr,"The target service's index is already "
+                        fprintf(stderr, "The target service's index is already "
                                 "in use. (%s)\n", source);
-                rc = errno;
+                if (errno == EINVAL) {
+                        fprintf(stderr, "This may have multiple causes.\n");
+                        if (cli) 
+                                fprintf(stderr, "Is '%s' the correct filesystem"
+                                        " name?\n", cli);
+                        fprintf(stderr, "Are the mount options correct?\n");
+                        fprintf(stderr, "Check the syslog for more info.\n");
+                }
+
+                /* May as well try to clean up loop devs */
+                if (strncmp(source, "/dev/loop", 9) == 0) {
+                        char cmd[256];
+                        sprintf(cmd, "/sbin/losetup -d %s", source);
+                        system(cmd);
+                }
+
         } else if (!nomtab) {
-                rc = update_mtab_entry(source, target, "lustre", options,0,0,0);
+                rc = update_mtab_entry(source, target, "lustre", orig_options,
+                                       0,0,0);
         }
 
         free(optcopy);
index 85ee351..6d8be40 100644 (file)
@@ -93,7 +93,7 @@ static char rawbuf[8192];
 static char *buf = rawbuf;
 static int max = sizeof(rawbuf);
 
-static int cur_device = MAX_OBD_DEVICES;
+static int cur_device = -1;
 
 union lsm_buffer {
         char                 space [4096];
@@ -153,6 +153,8 @@ int lcfg_ioctl(char * func, int dev_id, struct lustre_cfg *lcfg)
         return rc;
 }
 
+static int do_device(char *func, char *devname);
+
 int lcfg_mgs_ioctl(char *func, int dev_id, struct lustre_cfg *lcfg)
 {
         struct obd_ioctl_data data;
@@ -161,7 +163,6 @@ int lcfg_mgs_ioctl(char *func, int dev_id, struct lustre_cfg *lcfg)
 
         /* Always operates on MGS dev */
         if (mgs_device == -1) {
-                static int do_device(char *func, char *devname);
                 do_disconnect(NULL, 1);
                 rc = do_device("mgsioc", "MGS");
                 if (rc) {
@@ -397,8 +398,7 @@ static int be_verbose(int verbose, struct timeval *next_time,
                 gettimeofday(&now, NULL);
 
         /* A positive verbosity means to print every X iterations */
-        if (verbose > 0 &&
-            (next_num == NULL || num >= *next_num || num >= num_total)) {
+        if (verbose > 0 && (num >= *next_num || num >= num_total)) {
                 *next_num += verbose;
                 if (next_time) {
                         next_time->tv_sec = now.tv_sec - verbose;
@@ -412,8 +412,7 @@ static int be_verbose(int verbose, struct timeval *next_time,
             difftime(&now, next_time) >= 0.0){
                 next_time->tv_sec = now.tv_sec - verbose;
                 next_time->tv_usec = now.tv_usec;
-                if (next_num)
-                        *next_num = num;
+                *next_num = num;
                 return 1;
         }
 
@@ -450,7 +449,7 @@ static int get_verbose(char *func, const char *arg)
 
 int do_disconnect(char *func, int verbose)
 {
-        cur_device = MAX_OBD_DEVICES;
+        cur_device = -1;
         return 0;
 }
 
@@ -896,17 +895,18 @@ int jt_obd_list(int argc, char **argv)
         int rc;
 #if HAVE_PROC_FS
         char buf[MAX_STRING_SIZE];
-        FILE *fp = fopen(DEVICES_LIST, "r");
+        FILE *fp = NULL;
+
+        if (argc != 1)
+                return CMD_HELP;
 
+        fp = fopen(DEVICES_LIST,"r");
         if (fp == NULL) {
                 fprintf(stderr, "error: %s: %s opening "DEVICES_LIST"\n",
                         jt_cmdname(argv[0]), strerror(rc =  errno));
                 return rc;
         }
 
-        if (argc != 1)
-                return CMD_HELP;
-
         while (fgets(buf, sizeof(buf), fp) != NULL)
                 printf("%s", buf);
 
index f10dff3..0152064 100644 (file)
@@ -43,8 +43,8 @@ obdio_test_fixed_extent (struct obdio_conn *conn,
         int                  j;
         int                  rc = 0;
 
-        buffer = obdio_alloc_aligned_buffer (&space, size);
-        if (buffer == NULL) {
+        space = obdio_alloc_aligned_buffer (&buffer, size);
+        if (space == NULL) {
                 fprintf (stderr, "Can't allocate buffer size %d\n", size);
                 return (-1);
         }
index b948c45..c402104 100644 (file)
@@ -51,9 +51,9 @@ obdio_ioctl (struct obdio_conn *conn, int cmd)
 
         rc = obd_ioctl_pack (&conn->oc_data, &buf, sizeof (conn->oc_buffer));
         if (rc != 0) {
-                fprintf (stderr, "obdio_ioctl: obd_ioctl_pack: %d (%s)\n",
-                         rc, strerror (errno));
-                abort ();
+                fprintf(stderr, "%s: obd_ioctl_pack: %d (%s)\n",
+                        __FUNCTION__, rc, strerror(errno));
+                abort();
         }
 
         rc = ioctl (conn->oc_fd, cmd, buf);
@@ -62,8 +62,8 @@ obdio_ioctl (struct obdio_conn *conn, int cmd)
 
         rc2 = obd_ioctl_unpack (&conn->oc_data, buf, sizeof (conn->oc_buffer));
         if (rc2 != 0) {
-                fprintf (stderr, "obdio_ioctl: obd_ioctl_unpack: %d (%s)\n",
-                         rc2, strerror (errno));
+                fprintf(stderr, "%s: obd_ioctl_unpack: %d (%s)\n",
+                        __FUNCTION__, rc2, strerror(errno));
                 abort ();
         }
 
@@ -77,15 +77,15 @@ obdio_connect (int device)
 
         conn = malloc (sizeof (*conn));
         if (conn == NULL) {
-                fprintf (stderr, "obdio_connect: no memory\n");
+                fprintf (stderr, "%s: no memory\n", __FUNCTION__);
                 return (NULL);
         }
         memset (conn, 0, sizeof (*conn));
 
         conn->oc_fd = open ("/dev/obd", O_RDWR);
         if (conn->oc_fd < 0) {
-                fprintf (stderr, "obdio_connect: Can't open /dev/obd: %s\n",
-                         strerror (errno));
+                fprintf(stderr, "%s: Can't open /dev/obd: %s\n",
+                        __FUNCTION__, strerror(errno));
                 goto failed;
         }
 
@@ -107,13 +107,14 @@ obdio_disconnect (struct obdio_conn *conn, int flags)
 
 int
 obdio_pread (struct obdio_conn *conn, uint64_t oid,
-             char *buffer, uint32_t count, uint64_t offset)
+             void *buffer, uint32_t count, uint64_t offset)
 {
         obdio_iocinit (conn);
 
         conn->oc_data.ioc_obdo1.o_id = oid;
         conn->oc_data.ioc_obdo1.o_mode = S_IFREG;
-        conn->oc_data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
+        conn->oc_data.ioc_obdo1.o_valid =
+                OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
 
         conn->oc_data.ioc_pbuf2 = buffer;
         conn->oc_data.ioc_plen2 = count;
@@ -125,13 +126,14 @@ obdio_pread (struct obdio_conn *conn, uint64_t oid,
 
 int
 obdio_pwrite (struct obdio_conn *conn, uint64_t oid,
-              char *buffer, uint32_t count, uint64_t offset)
+              void *buffer, uint32_t count, uint64_t offset)
 {
         obdio_iocinit (conn);
 
         conn->oc_data.ioc_obdo1.o_id = oid;
         conn->oc_data.ioc_obdo1.o_mode = S_IFREG;
-        conn->oc_data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
+        conn->oc_data.ioc_obdo1.o_valid =
+                OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
 
         conn->oc_data.ioc_pbuf2 = buffer;
         conn->oc_data.ioc_plen2 = count;
@@ -180,14 +182,14 @@ obdio_cancel (struct obdio_conn *conn, struct lustre_handle *lh)
 void *
 obdio_alloc_aligned_buffer (void **spacep, int size)
 {
-        int   pagesize = getpagesize();
-        void *space = malloc (size + pagesize - 1);
+        int   pagemask = getpagesize() - 1;
+        void *space = malloc(size + pagemask);
 
-        *spacep = space;
         if (space == NULL)
                 return (NULL);
 
-        return ((void *)(((unsigned long)space + pagesize - 1) & ~(pagesize - 1)));
+        *spacep = (void *)(((unsigned long)space + pagemask) & ~pagemask);
+        return space;
 }
 
 struct obdio_barrier *
@@ -195,10 +197,11 @@ obdio_new_barrier (uint64_t oid, uint64_t id, int npeers)
 {
         struct obdio_barrier *b;
 
-        b = (struct obdio_barrier *)malloc (sizeof (*b));
+        b = malloc(sizeof(*b));
         if (b == NULL) {
-                fprintf (stderr, "obdio_new_barrier "LPX64": Can't allocate\n", oid);
-                return (NULL);
+                fprintf(stderr, "%s "LPX64": Can't allocate\n",
+                        __FUNCTION__, oid);
+                return(NULL);
         }
 
         b->ob_id = id;
@@ -215,41 +218,42 @@ obdio_setup_barrier (struct obdio_conn *conn, struct obdio_barrier *b)
         struct lustre_handle    lh;
         int                     rc;
         int                     rc2;
-        void                   *space;
+        void                   *space, *fileptr;
         struct obdio_barrier   *fileb;
 
         if (b->ob_ordinal != 0 ||
             b->ob_count != 0) {
-                fprintf (stderr, "obdio_setup_barrier: invalid parameter\n");
+                fprintf(stderr, "%s: invalid parameter\n", __FUNCTION__);
                 abort ();
         }
 
-        fileb = (struct obdio_barrier *) obdio_alloc_aligned_buffer (&space, getpagesize ());
-        if (fileb == NULL) {
-                fprintf (stderr, "obdio_setup_barrier "LPX64": Can't allocate page buffer\n",
-                         b->ob_oid);
+        space = obdio_alloc_aligned_buffer(&fileptr, getpagesize());
+        if (space == NULL) {
+                fprintf(stderr, "%s "LPX64": Can't allocate page buffer\n",
+                        __FUNCTION__, b->ob_oid);
                 return (-1);
         }
 
-        memset (fileb, 0, getpagesize ());
+        fileb = fileptr;
+        memset(fileb, 0, getpagesize());
         *fileb = *b;
 
-        rc = obdio_enqueue (conn, b->ob_oid, LCK_PW, 0, getpagesize (), &lh);
+        rc = obdio_enqueue(conn, b->ob_oid, LCK_PW, 0, getpagesize(), &lh);
         if (rc != 0) {
-                fprintf (stderr, "obdio_setup_barrier "LPX64": Error on enqueue: %s\n",
-                         b->ob_oid, strerror (errno));
+                fprintf(stderr, "%s "LPX64": Error on enqueue: %s\n",
+                        __FUNCTION__, b->ob_oid, strerror(errno));
                 goto out;
         }
 
-        rc = obdio_pwrite (conn, b->ob_oid, (void *)fileb, getpagesize (), 0);
+        rc = obdio_pwrite(conn, b->ob_oid, fileb, getpagesize(), 0);
         if (rc != 0)
-                fprintf (stderr, "obdio_setup_barrier "LPX64": Error on write: %s\n",
-                         b->ob_oid, strerror (errno));
+                fprintf(stderr, "%s "LPX64": Error on write: %s\n",
+                        __FUNCTION__, b->ob_oid, strerror(errno));
 
         rc2 = obdio_cancel (conn, &lh);
         if (rc == 0 && rc2 != 0) {
-                fprintf (stderr, "obdio_setup_barrier "LPX64": Error on cancel: %s\n",
-                         b->ob_oid, strerror (errno));
+                fprintf(stderr, "%s "LPX64": Error on cancel: %s\n",
+                        __FUNCTION__, b->ob_oid, strerror(errno));
                 rc = rc2;
         }
  out:
@@ -263,29 +267,30 @@ obdio_barrier (struct obdio_conn *conn, struct obdio_barrier *b)
         struct lustre_handle   lh;
         int                    rc;
         int                    rc2;
-        void                  *space;
+        void                  *space, *fileptr;
         struct obdio_barrier  *fileb;
         char                  *mode;
 
-        fileb = (struct obdio_barrier *) obdio_alloc_aligned_buffer (&space, getpagesize ());
-        if (fileb == NULL) {
-                fprintf (stderr, "obdio_barrier "LPX64": Can't allocate page buffer\n",
-                         b->ob_oid);
+        space = obdio_alloc_aligned_buffer(&fileptr, getpagesize());
+        if (space == NULL) {
+                fprintf(stderr, "%s "LPX64": Can't allocate page buffer\n",
+                        __FUNCTION__, b->ob_oid);
                 return (-1);
         }
 
-        rc = obdio_enqueue (conn, b->ob_oid, LCK_PW, 0, getpagesize (), &lh);
+        rc = obdio_enqueue(conn, b->ob_oid, LCK_PW, 0, getpagesize(), &lh);
         if (rc != 0) {
-                fprintf (stderr, "obdio_barrier "LPX64": Error on PW enqueue: %s\n",
-                         b->ob_oid, strerror (errno));
+                fprintf(stderr, "%s "LPX64": Error on PW enqueue: %s\n",
+                        __FUNCTION__, b->ob_oid, strerror(errno));
                 goto out_1;
         }
 
-        memset (fileb, 0xeb, getpagesize ());
-        rc = obdio_pread (conn, b->ob_oid, (void *)fileb, getpagesize (), 0);
+        fileb = fileptr;
+        memset(fileb, 0xeb, getpagesize());
+        rc = obdio_pread(conn, b->ob_oid, fileb, getpagesize(), 0);
         if (rc != 0) {
-                fprintf (stderr, "obdio_barrier "LPX64": Error on initial read: %s\n",
-                         b->ob_oid, strerror (errno));
+                fprintf(stderr, "%s "LPX64": Error on initial read: %s\n",
+                        __FUNCTION__, b->ob_oid, strerror(errno));
                 goto out_2;
         }
 
@@ -294,13 +299,16 @@ obdio_barrier (struct obdio_conn *conn, struct obdio_barrier *b)
             fileb->ob_npeers != b->ob_npeers ||
             fileb->ob_count >= b->ob_npeers ||
             fileb->ob_ordinal != b->ob_ordinal) {
-                fprintf (stderr, "obdio_barrier "LPX64": corrupt on initial read\n", b->ob_id);
-                fprintf (stderr, "  got ["LPX64","LPX64","LPX64","LPX64","LPX64"]\n",
-                         fileb->ob_id, fileb->ob_oid, fileb->ob_npeers,
-                         fileb->ob_ordinal, fileb->ob_count);
-                fprintf (stderr, "  expected ["LPX64","LPX64","LPX64","LPX64","LPX64"]\n",
-                         b->ob_id, b->ob_oid, b->ob_npeers,
-                         b->ob_ordinal, b->ob_count);
+                fprintf(stderr, "%s "LPX64": corrupt on initial read\n",
+                        __FUNCTION__, b->ob_id);
+                fprintf(stderr,
+                        "  got ["LPX64","LPX64","LPX64","LPX64","LPX64"]\n",
+                        fileb->ob_id, fileb->ob_oid, fileb->ob_npeers,
+                        fileb->ob_ordinal, fileb->ob_count);
+                fprintf(stderr,
+                       "  expected ["LPX64","LPX64","LPX64","LPX64","LPX64"]\n",
+                        b->ob_id, b->ob_oid, b->ob_npeers,
+                        b->ob_ordinal, b->ob_count);
                 rc = -1;
                 goto out_2;
         }
@@ -311,37 +319,36 @@ obdio_barrier (struct obdio_conn *conn, struct obdio_barrier *b)
                 fileb->ob_ordinal++;                 /* signal all joined */
         }
 
-        rc = obdio_pwrite (conn, b->ob_oid, (void *)fileb, getpagesize (), 0);
+        rc = obdio_pwrite(conn, b->ob_oid, fileb, getpagesize(), 0);
         if (rc != 0) {
-                fprintf (stderr, "obdio_barrier "LPX64": Error on initial write: %s\n",
-                         b->ob_oid, strerror (errno));
+                fprintf (stderr, "%s "LPX64": Error on initial write: %s\n",
+                         __FUNCTION__, b->ob_oid, strerror(errno));
                 goto out_2;
         }
 
         mode = "PW";
         b->ob_ordinal++;           /* now I wait... */
         while (fileb->ob_ordinal != b->ob_ordinal) {
-
                 rc = obdio_cancel (conn, &lh);
                 if (rc != 0) {
-                        fprintf (stderr, "obdio_barrier "LPX64": Error on %s cancel: %s\n",
-                                 b->ob_oid, mode, strerror (errno));
+                        fprintf(stderr, "%s "LPX64": Error on %s cancel: %s\n",
+                                __FUNCTION__, b->ob_oid, mode, strerror(errno));
                         goto out_1;
                 }
 
                 mode = "PR";
-                rc = obdio_enqueue (conn, b->ob_oid, LCK_PR, 0, getpagesize (), &lh);
+                rc = obdio_enqueue(conn, b->ob_oid, LCK_PR,0,getpagesize(),&lh);
                 if (rc != 0) {
-                        fprintf (stderr, "obdio_barrier "LPX64": Error on PR enqueue: %s\n",
-                                 b->ob_oid, strerror (errno));
+                        fprintf(stderr, "%s "LPX64": Error on PR enqueue: %s\n",
+                                __FUNCTION__, b->ob_oid, strerror(errno));
                         goto out_1;
                 }
 
-                memset (fileb, 0xeb, getpagesize ());
-                rc = obdio_pread (conn, b->ob_oid, (void *)fileb, getpagesize (), 0);
+                memset (fileb, 0xeb, getpagesize());
+                rc = obdio_pread(conn, b->ob_oid, fileb, getpagesize(), 0);
                 if (rc != 0) {
-                        fprintf (stderr, "obdio_barrier "LPX64": Error on read: %s\n",
-                                 b->ob_oid, strerror (errno));
+                        fprintf(stderr, "%s "LPX64": Error on read: %s\n",
+                                __FUNCTION__, b->ob_oid, strerror(errno));
                         goto out_2;
                 }
 
@@ -351,13 +358,16 @@ obdio_barrier (struct obdio_conn *conn, struct obdio_barrier *b)
                     fileb->ob_count >= b->ob_npeers ||
                     (fileb->ob_ordinal != b->ob_ordinal - 1 &&
                      fileb->ob_ordinal != b->ob_ordinal)) {
-                        fprintf (stderr, "obdio_barrier "LPX64": corrupt\n", b->ob_id);
-                        fprintf (stderr, "  got ["LPX64","LPX64","LPX64","LPX64","LPX64"]\n",
-                                 fileb->ob_id, fileb->ob_oid, fileb->ob_npeers,
-                                 fileb->ob_ordinal, fileb->ob_count);
-                        fprintf (stderr, "  expected ["LPX64","LPX64","LPX64","LPX64","LPX64"]\n",
-                                 b->ob_id, b->ob_oid, b->ob_npeers,
-                                 b->ob_ordinal, b->ob_count);
+                        fprintf(stderr, "%s "LPX64": corrupt\n",
+                                __FUNCTION__, b->ob_id);
+                        fprintf(stderr, "  got ["LPX64","LPX64","LPX64","
+                                LPX64","LPX64"]\n",
+                                fileb->ob_id, fileb->ob_oid, fileb->ob_npeers,
+                                fileb->ob_ordinal, fileb->ob_count);
+                        fprintf(stderr, "  expected ["LPX64","LPX64","LPX64
+                                ","LPX64","LPX64"]\n",
+                                b->ob_id, b->ob_oid, b->ob_npeers,
+                                b->ob_ordinal, b->ob_count);
                         rc = -1;
                         goto out_2;
                 }
@@ -366,13 +376,11 @@ obdio_barrier (struct obdio_conn *conn, struct obdio_barrier *b)
  out_2:
         rc2 = obdio_cancel (conn, &lh);
         if (rc == 0 && rc2 != 0) {
-                fprintf (stderr, "obdio_barrier "LPX64": Error on cancel: %s\n",
-                         b->ob_oid, strerror (errno));
+                fprintf(stderr, "%s "LPX64": Error on cancel: %s\n",
+                        __FUNCTION__, b->ob_oid, strerror(errno));
                 rc = rc2;
         }
  out_1:
         free (space);
         return (rc);
 }
-
-
index 8813de4..97be436 100644 (file)
@@ -30,16 +30,16 @@ struct obdio_barrier {
         uint64_t               ob_count;
 };
 
-extern struct obdio_conn * obdio_connect (int device);
+extern struct obdio_conn *obdio_connect(int device);
 extern void obdio_disconnect(struct obdio_conn *conn, int flags);
 extern int obdio_open(struct obdio_conn *conn, uint64_t oid,
                       struct lustre_handle *fh);
 extern int obdio_close(struct obdio_conn *conn, uint64_t oid,
                        struct lustre_handle *fh);
 extern int obdio_pread(struct obdio_conn *conn, uint64_t oid,
-                       char *buffer, uint32_t count, uint64_t offset);
+                       void *buffer, uint32_t count, uint64_t offset);
 extern int obdio_pwrite(struct obdio_conn *conn, uint64_t oid,
-                        char *buffer, uint32_t count, uint64_t offset);
+                        void *buffer, uint32_t count, uint64_t offset);
 extern int obdio_enqueue(struct obdio_conn *conn, uint64_t oid,
                          int mode, uint64_t offset, uint32_t count,
                          struct lustre_handle *lh);
@@ -47,8 +47,7 @@ extern int obdio_cancel(struct obdio_conn *conn, struct lustre_handle *lh);
 extern void *obdio_alloc_aligned_buffer(void **spacep, int size);
 extern struct obdio_barrier *obdio_new_barrier(uint64_t oid, uint64_t id,
                                                int npeers);
-extern int obdio_setup_barrier(struct obdio_conn *conn,
-                               struct obdio_barrier *b);
+extern int obdio_setup_barrier(struct obdio_conn *conn,struct obdio_barrier *b);
 extern int obdio_barrier(struct obdio_conn *conn, struct obdio_barrier *b);
 
 #endif
index 72ce2df..8c64eb9 100644 (file)
 #define lustre_swab_lu_range NULL
 #define lustre_swab_md_fld NULL
 #define lustre_swab_mdt_body NULL
+#define lustre_swab_ptlrpc_body NULL
 #define lustre_swab_obd_statfs NULL
 #define lustre_swab_connect NULL
 #define lustre_swab_ldlm_request NULL
 #define lustre_swab_ldlm_reply NULL
 #define lustre_swab_ldlm_intent NULL
 #define lustre_swab_lov_mds_md NULL
-#define lustre_swab_mds_rec_unlink NULL
+#define lustre_swab_mdt_rec_unlink NULL
 #define lustre_swab_mdt_rec_link NULL
 #define lustre_swab_mdt_rec_rename NULL
 #define lustre_swab_mdt_rec_create NULL
@@ -91,7 +92,7 @@ void print_layout(const struct req_format *rf)
 
                         fld = rf->rf_fields[j].d[k];
 
-                        printf("        F%s %0i [%03.3i%s %-20.20s (",
+                        printf("        F%s %i [%03.3i%s %-20.20s (",
                                prefix[j], k, offset,
                                variable ? " + ...]" : "]      ",
                                fld->rmf_name);
index 5a1f55a..c103a45 100644 (file)
@@ -7,6 +7,7 @@
 #include <liblustre.h>
 #include <lustre_lib.h>
 #include <lustre/lustre_idl.h>
+#include <lustre_disk.h>
 
 #define BLANK_LINE()                                            \
 do {                                                            \
@@ -61,7 +62,7 @@ do {                                                            \
 #define CHECK_MEMBER(s,m)                                       \
 do {                                                            \
         CHECK_MEMBER_OFFSET(s, m);                              \
-                CHECK_MEMBER_SIZEOF(s, m);                      \
+        CHECK_MEMBER_SIZEOF(s, m);                              \
 } while(0)
 
 #define CHECK_STRUCT(s)                                         \
@@ -79,23 +80,91 @@ check_lustre_handle(void)
         CHECK_MEMBER(lustre_handle, cookie);
 }
 
-static void
-check_lustre_msg(void)
+void
+check_lustre_msg_v1(void)
+{
+        BLANK_LINE();
+        CHECK_STRUCT(lustre_msg_v1);
+        CHECK_MEMBER(lustre_msg_v1, lm_handle);
+        CHECK_MEMBER(lustre_msg_v1, lm_magic);
+        CHECK_MEMBER(lustre_msg_v1, lm_type);
+        CHECK_MEMBER(lustre_msg_v1, lm_version);
+        CHECK_MEMBER(lustre_msg_v1, lm_opc);
+        CHECK_MEMBER(lustre_msg_v1, lm_last_xid);
+        CHECK_MEMBER(lustre_msg_v1, lm_last_committed);
+        CHECK_MEMBER(lustre_msg_v1, lm_transno);
+        CHECK_MEMBER(lustre_msg_v1, lm_status);
+        CHECK_MEMBER(lustre_msg_v1, lm_flags);
+        CHECK_MEMBER(lustre_msg_v1, lm_conn_cnt);
+        CHECK_MEMBER(lustre_msg_v1, lm_bufcount);
+        CHECK_MEMBER(lustre_msg_v1, lm_buflens[7]);
+}
+
+void
+check_lustre_msg_v2(void)
+{
+        BLANK_LINE();
+        CHECK_STRUCT(lustre_msg_v2);
+        CHECK_MEMBER(lustre_msg_v2, lm_bufcount);
+        CHECK_MEMBER(lustre_msg_v2, lm_secflvr);
+        CHECK_MEMBER(lustre_msg_v2, lm_magic);
+        CHECK_MEMBER(lustre_msg_v2, lm_buflens[7]);
+}
+
+void
+check_ptlrpc_body(void)
 {
         BLANK_LINE();
-        CHECK_STRUCT(lustre_msg);
-        CHECK_MEMBER(lustre_msg, handle);
-        CHECK_MEMBER(lustre_msg, magic);
-        CHECK_MEMBER(lustre_msg, type);
-        CHECK_MEMBER(lustre_msg, version);
-        CHECK_MEMBER(lustre_msg, opc);
-        CHECK_MEMBER(lustre_msg, last_xid);
-        CHECK_MEMBER(lustre_msg, last_committed);
-        CHECK_MEMBER(lustre_msg, transno);
-        CHECK_MEMBER(lustre_msg, status);
-        CHECK_MEMBER(lustre_msg, flags);
-        CHECK_MEMBER(lustre_msg, bufcount);
-        CHECK_MEMBER(lustre_msg, buflens[7]);
+        CHECK_STRUCT(ptlrpc_body);
+        CHECK_MEMBER(ptlrpc_body, pb_handle);
+        CHECK_MEMBER(ptlrpc_body, pb_type);
+        CHECK_MEMBER(ptlrpc_body, pb_version);
+        CHECK_MEMBER(ptlrpc_body, pb_opc);
+        CHECK_MEMBER(ptlrpc_body, pb_status);
+        CHECK_MEMBER(ptlrpc_body, pb_last_xid);
+        CHECK_MEMBER(ptlrpc_body, pb_last_committed);
+        CHECK_MEMBER(ptlrpc_body, pb_transno);
+        CHECK_MEMBER(ptlrpc_body, pb_flags);
+        CHECK_MEMBER(ptlrpc_body, pb_op_flags);
+        CHECK_MEMBER(ptlrpc_body, pb_conn_cnt);
+        CHECK_MEMBER(ptlrpc_body, pb_paddings[3]);
+}
+
+static void check_obd_connect_data(void)
+{
+        BLANK_LINE();
+        CHECK_STRUCT(obd_connect_data);
+        CHECK_MEMBER(obd_connect_data, ocd_connect_flags);
+        CHECK_MEMBER(obd_connect_data, ocd_version);
+        CHECK_MEMBER(obd_connect_data, ocd_grant);
+        CHECK_MEMBER(obd_connect_data, ocd_index);
+        CHECK_MEMBER(obd_connect_data, ocd_brw_size);
+        CHECK_MEMBER(obd_connect_data, ocd_ibits_known);
+        CHECK_MEMBER(obd_connect_data, ocd_nllu);
+        CHECK_MEMBER(obd_connect_data, ocd_nllg);
+        CHECK_MEMBER(obd_connect_data, padding1);
+        CHECK_MEMBER(obd_connect_data, padding2);
+        CHECK_MEMBER(obd_connect_data, padding3);
+        CHECK_MEMBER(obd_connect_data, padding4);
+
+        CHECK_CDEFINE(OBD_CONNECT_RDONLY);
+        CHECK_CDEFINE(OBD_CONNECT_INDEX);
+        CHECK_CDEFINE(OBD_CONNECT_GRANT);
+        CHECK_CDEFINE(OBD_CONNECT_SRVLOCK);
+        CHECK_CDEFINE(OBD_CONNECT_VERSION);
+        CHECK_CDEFINE(OBD_CONNECT_REQPORTAL);
+        CHECK_CDEFINE(OBD_CONNECT_ACL);
+        CHECK_CDEFINE(OBD_CONNECT_XATTR);
+        CHECK_CDEFINE(OBD_CONNECT_CROW);
+        CHECK_CDEFINE(OBD_CONNECT_TRUNCLOCK);
+        CHECK_CDEFINE(OBD_CONNECT_TRANSNO);
+        CHECK_CDEFINE(OBD_CONNECT_IBITS);
+        CHECK_CDEFINE(OBD_CONNECT_JOIN);
+        CHECK_CDEFINE(OBD_CONNECT_ATTRFID);
+        CHECK_CDEFINE(OBD_CONNECT_NODEVOH);
+        CHECK_CDEFINE(OBD_CONNECT_LCL_CLIENT);
+        CHECK_CDEFINE(OBD_CONNECT_RMT_CLIENT);
+        CHECK_CDEFINE(OBD_CONNECT_BRW_SIZE);
 }
 
 static void
@@ -381,6 +450,15 @@ check_mds_body(void)
         CHECK_CDEFINE(MDS_OPEN_HAS_EA);
         CHECK_CDEFINE(MDS_OPEN_HAS_OBJS);
 
+        /* these should be identical to their EXT3_*_FL counterparts, and
+         * are redefined only to avoid dragging in ext3_fs.h */
+        CHECK_CDEFINE(MDS_SYNC_FL);
+        CHECK_CDEFINE(MDS_IMMUTABLE_FL);
+        CHECK_CDEFINE(MDS_APPEND_FL);
+        CHECK_CDEFINE(MDS_NOATIME_FL);
+        CHECK_CDEFINE(MDS_DIRSYNC_FL);
+        CHECK_CDEFINE(MDS_BFLAG_EXT_FLAGS);
+
         CHECK_CDEFINE(MDS_INODELOCK_LOOKUP);
         CHECK_CDEFINE(MDS_INODELOCK_UPDATE);
         CHECK_CDEFINE(MDS_INODELOCK_OPEN);
@@ -494,7 +572,6 @@ check_lov_desc(void)
         CHECK_MEMBER(lov_desc, ld_pattern);
         CHECK_MEMBER(lov_desc, ld_default_stripe_size);
         CHECK_MEMBER(lov_desc, ld_default_stripe_offset);
-        CHECK_MEMBER(lov_desc, ld_qos_threshold);
         CHECK_MEMBER(lov_desc, ld_qos_maxage);
         CHECK_MEMBER(lov_desc, ld_padding_1);
         CHECK_MEMBER(lov_desc, ld_padding_2);
@@ -848,6 +925,43 @@ check_qunit_data(void)
 }
 
 static void
+check_mgs_target_info(void)
+{
+        BLANK_LINE();
+        CHECK_STRUCT(mgs_target_info);
+        CHECK_MEMBER(mgs_target_info, mti_lustre_ver);
+        CHECK_MEMBER(mgs_target_info, mti_stripe_index);
+        CHECK_MEMBER(mgs_target_info, mti_config_ver);
+        CHECK_MEMBER(mgs_target_info, mti_flags);
+        CHECK_MEMBER(mgs_target_info, mti_nid_count);
+        CHECK_MEMBER(mgs_target_info, mti_fsname);
+        CHECK_MEMBER(mgs_target_info, mti_svname);
+        CHECK_MEMBER(mgs_target_info, mti_uuid);
+        CHECK_MEMBER(mgs_target_info, mti_nids);
+        CHECK_MEMBER(mgs_target_info, mti_params);
+}
+
+static void
+check_lustre_disk_data(void)
+{
+        BLANK_LINE();
+        CHECK_STRUCT(lustre_disk_data);
+        CHECK_MEMBER(lustre_disk_data, ldd_magic);
+        CHECK_MEMBER(lustre_disk_data, ldd_feature_compat);
+        CHECK_MEMBER(lustre_disk_data, ldd_feature_rocompat);
+        CHECK_MEMBER(lustre_disk_data, ldd_feature_incompat);
+        CHECK_MEMBER(lustre_disk_data, ldd_config_ver);
+        CHECK_MEMBER(lustre_disk_data, ldd_flags);
+        CHECK_MEMBER(lustre_disk_data, ldd_svindex);
+        CHECK_MEMBER(lustre_disk_data, ldd_mount_type);
+        CHECK_MEMBER(lustre_disk_data, ldd_fsname);
+        CHECK_MEMBER(lustre_disk_data, ldd_svname);
+        CHECK_MEMBER(lustre_disk_data, ldd_uuid);
+        CHECK_MEMBER(lustre_disk_data, ldd_mount_opts);
+        CHECK_MEMBER(lustre_disk_data, ldd_params);
+}
+
+static void
 system_string (char *cmdline, char *str, int len)
 {
         int   fds[2];
@@ -910,6 +1024,7 @@ main(int argc, char **argv)
         printf ("void lustre_assert_wire_constants(void)\n"
                 "{\n"
                 "        /* Wire protocol assertions generated by 'wirecheck'\n"
+                "         * (make -C lustre/utils newwirecheck)\n"
                 "         * running on %s\n"
                 "         * with %s */\n"
                 "\n", unameinfo, gccinfo);
@@ -917,7 +1032,8 @@ main(int argc, char **argv)
         BLANK_LINE ();
 
         COMMENT("Constants...");
-        CHECK_DEFINE(PTLRPC_MSG_MAGIC);
+        CHECK_DEFINE(LUSTRE_MSG_MAGIC_V1);
+        CHECK_DEFINE(LUSTRE_MSG_MAGIC_V2);
         CHECK_DEFINE(PTLRPC_MSG_VERSION);
 
         CHECK_VALUE(PTL_RPC_MSG_REQUEST);
@@ -1027,24 +1143,22 @@ main(int argc, char **argv)
         CHECK_VALUE(QUOTA_DQACQ);
         CHECK_VALUE(QUOTA_DQREL);
 
-        CHECK_CDEFINE(OBD_CONNECT_RDONLY);
-        CHECK_CDEFINE(OBD_CONNECT_INDEX);
-        CHECK_CDEFINE(OBD_CONNECT_GRANT);
-        CHECK_CDEFINE(OBD_CONNECT_SRVLOCK);
-        CHECK_CDEFINE(OBD_CONNECT_VERSION);
-        CHECK_CDEFINE(OBD_CONNECT_REQPORTAL);
-        CHECK_CDEFINE(OBD_CONNECT_ACL);
-        CHECK_CDEFINE(OBD_CONNECT_XATTR);
-        CHECK_CDEFINE(OBD_CONNECT_CROW);
-        CHECK_CDEFINE(OBD_CONNECT_TRUNCLOCK);
-        CHECK_CDEFINE(OBD_CONNECT_TRANSNO);
-        CHECK_CDEFINE(OBD_CONNECT_IBITS);
-        CHECK_CDEFINE(OBD_CONNECT_JOIN);
+        CHECK_VALUE(MGS_CONNECT);
+        CHECK_VALUE(MGS_DISCONNECT);
+        CHECK_VALUE(MGS_EXCEPTION);   
+        CHECK_VALUE(MGS_TARGET_REG);
+        CHECK_VALUE(MGS_TARGET_DEL);
 
         COMMENT("Sizes and Offsets");
         BLANK_LINE();
+        CHECK_STRUCT(obd_uuid);
         check_lustre_handle();
-        check_lustre_msg();
+        check_lustre_msg_v1();
+        check_lustre_msg_v2();
+        printf("        LASSERT(offsetof(struct lustre_msg_v1, lm_magic) == "
+               "offsetof(struct lustre_msg_v2, lm_magic));\n");
+        check_ptlrpc_body();
+        check_obd_connect_data();
         check_obdo();
         check_lov_mds_md_v1();
         check_lov_mds_md_join();
@@ -1092,6 +1206,9 @@ main(int argc, char **argv)
         check_llog_array_rec();
         check_mds_extent_desc();
         check_qunit_data();
+        check_mgs_target_info();
+        check_lustre_disk_data();
+
 
         printf("}\n\n");
 
index 95de9db..a0592d1 100644 (file)
@@ -2,6 +2,7 @@
 #include <liblustre.h>
 #include <lustre_lib.h>
 #include <lustre/lustre_idl.h>
+#include <lustre_disk.h>
 
 #undef LASSERT
 #undef LASSERTF
@@ -15,11 +16,11 @@ void lustre_assert_wire_constants(void);
 
 int main()
 {
-       lustre_assert_wire_constants();
+        lustre_assert_wire_constants();
 
-       if (ret == 0)
-               printf("wire constants OK\n");
+        if (ret == 0)
+                printf("wire constants OK\n");
 
-       return ret;
+        return ret;
 }
 
index 66eb6f2..abcffad 100644 (file)
@@ -2,6 +2,7 @@
 #include <liblustre.h>
 #include <lustre_lib.h>
 #include <lustre/lustre_idl.h>
+#include <lustre_disk.h>
 
 #undef LASSERT
 #undef LASSERTF
@@ -26,1789 +27,6 @@ int main()
 
 void lustre_assert_wire_constants(void)
 {
-        /* Wire protocol assertions generated by 'wirecheck'
-         * running on Linux tau 2.6.15-dirty #13 SMP Sat Feb 11 18:30:54 MSK 2006 i686 i686 i386 GNU/
-         * with gcc version 3.3.3 (SuSE Linux) */
-
-        /* Constants... */
-        LASSERTF(PTLRPC_MSG_MAGIC == 0x0BD00BD0," found %lld\n",
-                 (long long)PTLRPC_MSG_MAGIC);
-        LASSERTF(PTLRPC_MSG_VERSION == 0x00000003," found %lld\n",
-                 (long long)PTLRPC_MSG_VERSION);
-        LASSERTF(PTL_RPC_MSG_REQUEST == 4711, " found %lld\n",
-                 (long long)PTL_RPC_MSG_REQUEST);
-        LASSERTF(PTL_RPC_MSG_ERR == 4712, " found %lld\n",
-                 (long long)PTL_RPC_MSG_ERR);
-        LASSERTF(PTL_RPC_MSG_REPLY == 4713, " found %lld\n",
-                 (long long)PTL_RPC_MSG_REPLY);
-        LASSERTF(MSG_LAST_REPLAY == 1, " found %lld\n",
-                 (long long)MSG_LAST_REPLAY);
-        LASSERTF(MSG_RESENT == 2, " found %lld\n",
-                 (long long)MSG_RESENT);
-        LASSERTF(MSG_REPLAY == 4, " found %lld\n",
-                 (long long)MSG_REPLAY);
-        LASSERTF(MSG_CONNECT_RECOVERING == 1, " found %lld\n",
-                 (long long)MSG_CONNECT_RECOVERING);
-        LASSERTF(MSG_CONNECT_RECONNECT == 2, " found %lld\n",
-                 (long long)MSG_CONNECT_RECONNECT);
-        LASSERTF(MSG_CONNECT_REPLAYABLE == 4, " found %lld\n",
-                 (long long)MSG_CONNECT_REPLAYABLE);
-        LASSERTF(OST_REPLY == 0, " found %lld\n",
-                 (long long)OST_REPLY);
-        LASSERTF(OST_GETATTR == 1, " found %lld\n",
-                 (long long)OST_GETATTR);
-        LASSERTF(OST_SETATTR == 2, " found %lld\n",
-                 (long long)OST_SETATTR);
-        LASSERTF(OST_READ == 3, " found %lld\n",
-                 (long long)OST_READ);
-        LASSERTF(OST_WRITE == 4, " found %lld\n",
-                 (long long)OST_WRITE);
-        LASSERTF(OST_CREATE == 5, " found %lld\n",
-                 (long long)OST_CREATE);
-        LASSERTF(OST_DESTROY == 6, " found %lld\n",
-                 (long long)OST_DESTROY);
-        LASSERTF(OST_GET_INFO == 7, " found %lld\n",
-                 (long long)OST_GET_INFO);
-        LASSERTF(OST_CONNECT == 8, " found %lld\n",
-                 (long long)OST_CONNECT);
-        LASSERTF(OST_DISCONNECT == 9, " found %lld\n",
-                 (long long)OST_DISCONNECT);
-        LASSERTF(OST_PUNCH == 10, " found %lld\n",
-                 (long long)OST_PUNCH);
-        LASSERTF(OST_OPEN == 11, " found %lld\n",
-                 (long long)OST_OPEN);
-        LASSERTF(OST_CLOSE == 12, " found %lld\n",
-                 (long long)OST_CLOSE);
-        LASSERTF(OST_STATFS == 13, " found %lld\n",
-                 (long long)OST_STATFS);
-        LASSERTF(OST_SAN_READ == 14, " found %lld\n",
-                 (long long)OST_SAN_READ);
-        LASSERTF(OST_SAN_WRITE == 15, " found %lld\n",
-                 (long long)OST_SAN_WRITE);
-        LASSERTF(OST_SYNC == 16, " found %lld\n",
-                 (long long)OST_SYNC);
-        LASSERTF(OST_QUOTACHECK == 18, " found %lld\n",
-                 (long long)OST_QUOTACHECK);
-        LASSERTF(OST_QUOTACTL == 19, " found %lld\n",
-                 (long long)OST_QUOTACTL);
-        LASSERTF(OST_LAST_OPC == 20, " found %lld\n",
-                 (long long)OST_LAST_OPC);
-        LASSERTF(OBD_OBJECT_EOF == 0xffffffffffffffffULL," found %lld\n",
-                 (long long)OBD_OBJECT_EOF);
-        LASSERTF(MDS_GETATTR == 33, " found %lld\n",
-                 (long long)MDS_GETATTR);
-        LASSERTF(MDS_GETATTR_NAME == 34, " found %lld\n",
-                 (long long)MDS_GETATTR_NAME);
-        LASSERTF(MDS_CLOSE == 35, " found %lld\n",
-                 (long long)MDS_CLOSE);
-        LASSERTF(MDS_REINT == 36, " found %lld\n",
-                 (long long)MDS_REINT);
-        LASSERTF(MDS_READPAGE == 37, " found %lld\n",
-                 (long long)MDS_READPAGE);
-        LASSERTF(MDS_CONNECT == 38, " found %lld\n",
-                 (long long)MDS_CONNECT);
-        LASSERTF(MDS_DISCONNECT == 39, " found %lld\n",
-                 (long long)MDS_DISCONNECT);
-        LASSERTF(MDS_GETSTATUS == 40, " found %lld\n",
-                 (long long)MDS_GETSTATUS);
-        LASSERTF(MDS_STATFS == 41, " found %lld\n",
-                 (long long)MDS_STATFS);
-        LASSERTF(MDS_PIN == 42, " found %lld\n",
-                 (long long)MDS_PIN);
-        LASSERTF(MDS_UNPIN == 43, " found %lld\n",
-                 (long long)MDS_UNPIN);
-        LASSERTF(MDS_SYNC == 44, " found %lld\n",
-                 (long long)MDS_SYNC);
-        LASSERTF(MDS_DONE_WRITING == 45, " found %lld\n",
-                 (long long)MDS_DONE_WRITING);
-        LASSERTF(MDS_SET_INFO == 46, " found %lld\n",
-                 (long long)MDS_SET_INFO);
-        LASSERTF(MDS_QUOTACHECK == 47, " found %lld\n",
-                 (long long)MDS_QUOTACHECK);
-        LASSERTF(MDS_QUOTACTL == 48, " found %lld\n",
-                 (long long)MDS_QUOTACTL);
-        LASSERTF(MDS_LAST_OPC == 51, " found %lld\n",
-                 (long long)MDS_LAST_OPC);
-        LASSERTF(REINT_SETATTR == 1, " found %lld\n",
-                 (long long)REINT_SETATTR);
-        LASSERTF(REINT_CREATE == 2, " found %lld\n",
-                 (long long)REINT_CREATE);
-        LASSERTF(REINT_LINK == 3, " found %lld\n",
-                 (long long)REINT_LINK);
-        LASSERTF(REINT_UNLINK == 4, " found %lld\n",
-                 (long long)REINT_UNLINK);
-        LASSERTF(REINT_RENAME == 5, " found %lld\n",
-                 (long long)REINT_RENAME);
-        LASSERTF(REINT_OPEN == 6, " found %lld\n",
-                 (long long)REINT_OPEN);
-        LASSERTF(REINT_MAX == 7, " found %lld\n",
-                 (long long)REINT_MAX);
-        LASSERTF(MGS_CONNECT == 250, " found %lld\n",
-                 (long long)MGS_CONNECT);
-        LASSERTF(MGS_DISCONNECT == 251, " found %lld\n",
-                 (long long)MGS_DISCONNECT);
-        LASSERTF(MGS_EXCEPTION == 252, " found %lld\n",
-                 (long long)MGS_EXCEPTION);
-        LASSERTF(MGS_TARGET_REG == 253, " found %lld\n",
-                 (long long)MGS_TARGET_REG);
-        LASSERTF(MGS_TARGET_DEL == 254, " found %lld\n",
-                 (long long)MGS_TARGET_DEL);
-        LASSERTF(DISP_IT_EXECD == 1, " found %lld\n",
-                 (long long)DISP_IT_EXECD);
-        LASSERTF(DISP_LOOKUP_EXECD == 2, " found %lld\n",
-                 (long long)DISP_LOOKUP_EXECD);
-        LASSERTF(DISP_LOOKUP_NEG == 4, " found %lld\n",
-                 (long long)DISP_LOOKUP_NEG);
-        LASSERTF(DISP_LOOKUP_POS == 8, " found %lld\n",
-                 (long long)DISP_LOOKUP_POS);
-        LASSERTF(DISP_OPEN_CREATE == 16, " found %lld\n",
-                 (long long)DISP_OPEN_CREATE);
-        LASSERTF(DISP_OPEN_OPEN == 32, " found %lld\n",
-                 (long long)DISP_OPEN_OPEN);
-        LASSERTF(MDS_STATUS_CONN == 1, " found %lld\n",
-                 (long long)MDS_STATUS_CONN);
-        LASSERTF(MDS_STATUS_LOV == 2, " found %lld\n",
-                 (long long)MDS_STATUS_LOV);
-        LASSERTF(LDLM_ENQUEUE == 101, " found %lld\n",
-                 (long long)LDLM_ENQUEUE);
-        LASSERTF(LDLM_CONVERT == 102, " found %lld\n",
-                 (long long)LDLM_CONVERT);
-        LASSERTF(LDLM_CANCEL == 103, " found %lld\n",
-                 (long long)LDLM_CANCEL);
-        LASSERTF(LDLM_BL_CALLBACK == 104, " found %lld\n",
-                 (long long)LDLM_BL_CALLBACK);
-        LASSERTF(LDLM_CP_CALLBACK == 105, " found %lld\n",
-                 (long long)LDLM_CP_CALLBACK);
-        LASSERTF(LDLM_GL_CALLBACK == 106, " found %lld\n",
-                 (long long)LDLM_GL_CALLBACK);
-        LASSERTF(LDLM_LAST_OPC == 107, " found %lld\n",
-                 (long long)LDLM_LAST_OPC);
-        LASSERTF(LCK_EX == 1, " found %lld\n",
-                 (long long)LCK_EX);
-        LASSERTF(LCK_PW == 2, " found %lld\n",
-                 (long long)LCK_PW);
-        LASSERTF(LCK_PR == 4, " found %lld\n",
-                 (long long)LCK_PR);
-        LASSERTF(LCK_CW == 8, " found %lld\n",
-                 (long long)LCK_CW);
-        LASSERTF(LCK_CR == 16, " found %lld\n",
-                 (long long)LCK_CR);
-        LASSERTF(LCK_NL == 32, " found %lld\n",
-                 (long long)LCK_NL);
-        LASSERTF(LCK_GROUP == 64, " found %lld\n",
-                 (long long)LCK_GROUP);
-        LASSERTF(LCK_MAXMODE == 65, " found %lld\n",
-                 (long long)LCK_MAXMODE);
-        CLASSERT(LDLM_PLAIN == 10);
-        CLASSERT(LDLM_EXTENT == 11);
-        CLASSERT(LDLM_FLOCK == 12);
-        CLASSERT(LDLM_IBITS == 13);
-        LASSERTF(OBD_PING == 400, " found %lld\n",
-                 (long long)OBD_PING);
-        LASSERTF(OBD_LOG_CANCEL == 401, " found %lld\n",
-                 (long long)OBD_LOG_CANCEL);
-        LASSERTF(OBD_QC_CALLBACK == 402, " found %lld\n",
-                 (long long)OBD_QC_CALLBACK);
-        LASSERTF(OBD_LAST_OPC == 403, " found %lld\n",
-                 (long long)OBD_LAST_OPC);
-        LASSERTF(QUOTA_DQACQ == 601, " found %lld\n",
-                 (long long)QUOTA_DQACQ);
-        LASSERTF(QUOTA_DQREL == 602, " found %lld\n",
-                 (long long)QUOTA_DQREL);
-        CLASSERT(OBD_CONNECT_RDONLY == 0x1ULL);
-        CLASSERT(OBD_CONNECT_INDEX == 0x2ULL);
-        CLASSERT(OBD_CONNECT_GRANT == 0x8ULL);
-        CLASSERT(OBD_CONNECT_SRVLOCK == 0x10ULL);
-        CLASSERT(OBD_CONNECT_VERSION == 0x20ULL);
-        CLASSERT(OBD_CONNECT_REQPORTAL == 0x40ULL);
-        CLASSERT(OBD_CONNECT_ACL == 0x80ULL);
-        CLASSERT(OBD_CONNECT_XATTR == 0x100ULL);
-        CLASSERT(OBD_CONNECT_CROW == 0x200ULL);
-        CLASSERT(OBD_CONNECT_TRUNCLOCK == 0x400ULL);
-        CLASSERT(OBD_CONNECT_TRANSNO == 0x800ULL);
-        CLASSERT(OBD_CONNECT_IBITS == 0x1000ULL);
-        CLASSERT(OBD_CONNECT_JOIN == 0x2000ULL);
-        /* Sizes and Offsets */
-
-
-        /* Checks for struct lustre_handle */
-        LASSERTF((int)sizeof(struct lustre_handle) == 8, " found %lld\n",
-                 (long long)(int)sizeof(struct lustre_handle));
-        LASSERTF((int)offsetof(struct lustre_handle, cookie) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct lustre_handle, cookie));
-        LASSERTF((int)sizeof(((struct lustre_handle *)0)->cookie) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct lustre_handle *)0)->cookie));
-
-        /* Checks for struct lustre_msg */
-        LASSERTF((int)sizeof(struct lustre_msg) == 64, " found %lld\n",
-                 (long long)(int)sizeof(struct lustre_msg));
-        LASSERTF((int)offsetof(struct lustre_msg, handle) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct lustre_msg, handle));
-        LASSERTF((int)sizeof(((struct lustre_msg *)0)->handle) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct lustre_msg *)0)->handle));
-        LASSERTF((int)offsetof(struct lustre_msg, magic) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct lustre_msg, magic));
-        LASSERTF((int)sizeof(((struct lustre_msg *)0)->magic) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lustre_msg *)0)->magic));
-        LASSERTF((int)offsetof(struct lustre_msg, type) == 12, " found %lld\n",
-                 (long long)(int)offsetof(struct lustre_msg, type));
-        LASSERTF((int)sizeof(((struct lustre_msg *)0)->type) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lustre_msg *)0)->type));
-        LASSERTF((int)offsetof(struct lustre_msg, version) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct lustre_msg, version));
-        LASSERTF((int)sizeof(((struct lustre_msg *)0)->version) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lustre_msg *)0)->version));
-        LASSERTF((int)offsetof(struct lustre_msg, opc) == 20, " found %lld\n",
-                 (long long)(int)offsetof(struct lustre_msg, opc));
-        LASSERTF((int)sizeof(((struct lustre_msg *)0)->opc) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lustre_msg *)0)->opc));
-        LASSERTF((int)offsetof(struct lustre_msg, last_xid) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct lustre_msg, last_xid));
-        LASSERTF((int)sizeof(((struct lustre_msg *)0)->last_xid) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct lustre_msg *)0)->last_xid));
-        LASSERTF((int)offsetof(struct lustre_msg, last_committed) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct lustre_msg, last_committed));
-        LASSERTF((int)sizeof(((struct lustre_msg *)0)->last_committed) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct lustre_msg *)0)->last_committed));
-        LASSERTF((int)offsetof(struct lustre_msg, transno) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct lustre_msg, transno));
-        LASSERTF((int)sizeof(((struct lustre_msg *)0)->transno) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct lustre_msg *)0)->transno));
-        LASSERTF((int)offsetof(struct lustre_msg, status) == 48, " found %lld\n",
-                 (long long)(int)offsetof(struct lustre_msg, status));
-        LASSERTF((int)sizeof(((struct lustre_msg *)0)->status) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lustre_msg *)0)->status));
-        LASSERTF((int)offsetof(struct lustre_msg, flags) == 52, " found %lld\n",
-                 (long long)(int)offsetof(struct lustre_msg, flags));
-        LASSERTF((int)sizeof(((struct lustre_msg *)0)->flags) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lustre_msg *)0)->flags));
-        LASSERTF((int)offsetof(struct lustre_msg, bufcount) == 60, " found %lld\n",
-                 (long long)(int)offsetof(struct lustre_msg, bufcount));
-        LASSERTF((int)sizeof(((struct lustre_msg *)0)->bufcount) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lustre_msg *)0)->bufcount));
-        LASSERTF((int)offsetof(struct lustre_msg, buflens[7]) == 92, " found %lld\n",
-                 (long long)(int)offsetof(struct lustre_msg, buflens[7]));
-        LASSERTF((int)sizeof(((struct lustre_msg *)0)->buflens[7]) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lustre_msg *)0)->buflens[7]));
-
-        /* Checks for struct obdo */
-        LASSERTF((int)sizeof(struct obdo) == 208, " found %lld\n",
-                 (long long)(int)sizeof(struct obdo));
-        LASSERTF((int)offsetof(struct obdo, o_valid) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_valid));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_valid) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_valid));
-        LASSERTF((int)offsetof(struct obdo, o_id) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_id));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_id) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_id));
-        LASSERTF((int)offsetof(struct obdo, o_gr) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_gr));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_gr) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_gr));
-        LASSERTF((int)offsetof(struct obdo, o_fid) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_fid));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_fid) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_fid));
-        LASSERTF((int)offsetof(struct obdo, o_size) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_size));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_size) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_size));
-        LASSERTF((int)offsetof(struct obdo, o_mtime) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_mtime));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_mtime) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_mtime));
-        LASSERTF((int)offsetof(struct obdo, o_atime) == 48, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_atime));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_atime) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_atime));
-        LASSERTF((int)offsetof(struct obdo, o_ctime) == 56, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_ctime));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_ctime) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_ctime));
-        LASSERTF((int)offsetof(struct obdo, o_blocks) == 64, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_blocks));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_blocks) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_blocks));
-        LASSERTF((int)offsetof(struct obdo, o_grant) == 72, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_grant));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_grant) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_grant));
-        LASSERTF((int)offsetof(struct obdo, o_blksize) == 80, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_blksize));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_blksize) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_blksize));
-        LASSERTF((int)offsetof(struct obdo, o_mode) == 84, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_mode));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_mode) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_mode));
-        LASSERTF((int)offsetof(struct obdo, o_uid) == 88, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_uid));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_uid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_uid));
-        LASSERTF((int)offsetof(struct obdo, o_gid) == 92, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_gid));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_gid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_gid));
-        LASSERTF((int)offsetof(struct obdo, o_flags) == 96, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_flags));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_flags) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_flags));
-        LASSERTF((int)offsetof(struct obdo, o_nlink) == 100, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_nlink));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_nlink) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_nlink));
-        LASSERTF((int)offsetof(struct obdo, o_generation) == 104, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_generation));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_generation) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_generation));
-        LASSERTF((int)offsetof(struct obdo, o_misc) == 108, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_misc));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_misc) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_misc));
-        LASSERTF((int)offsetof(struct obdo, o_easize) == 112, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_easize));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_easize) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_easize));
-        LASSERTF((int)offsetof(struct obdo, o_mds) == 116, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_mds));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_mds) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_mds));
-        LASSERTF((int)offsetof(struct obdo, o_stripe_idx) == 120, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_stripe_idx));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_stripe_idx) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_stripe_idx));
-        LASSERTF((int)offsetof(struct obdo, o_padding_1) == 124, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_padding_1));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_padding_1) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_padding_1));
-        LASSERTF((int)offsetof(struct obdo, o_inline) == 128, " found %lld\n",
-                 (long long)(int)offsetof(struct obdo, o_inline));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_inline) == 80, " found %lld\n",
-                 (long long)(int)sizeof(((struct obdo *)0)->o_inline));
-        LASSERTF(OBD_INLINESZ == 80, " found %lld\n",
-                 (long long)OBD_INLINESZ);
-        CLASSERT(OBD_MD_FLID == (0x00000001ULL));
-        CLASSERT(OBD_MD_FLATIME == (0x00000002ULL));
-        CLASSERT(OBD_MD_FLMTIME == (0x00000004ULL));
-        CLASSERT(OBD_MD_FLCTIME == (0x00000008ULL));
-        CLASSERT(OBD_MD_FLSIZE == (0x00000010ULL));
-        CLASSERT(OBD_MD_FLBLOCKS == (0x00000020ULL));
-        CLASSERT(OBD_MD_FLBLKSZ == (0x00000040ULL));
-        CLASSERT(OBD_MD_FLMODE == (0x00000080ULL));
-        CLASSERT(OBD_MD_FLTYPE == (0x00000100ULL));
-        CLASSERT(OBD_MD_FLUID == (0x00000200ULL));
-        CLASSERT(OBD_MD_FLGID == (0x00000400ULL));
-        CLASSERT(OBD_MD_FLFLAGS == (0x00000800ULL));
-        CLASSERT(OBD_MD_FLNLINK == (0x00002000ULL));
-        CLASSERT(OBD_MD_FLGENER == (0x00004000ULL));
-        CLASSERT(OBD_MD_FLINLINE == (0x00008000ULL));
-        CLASSERT(OBD_MD_FLRDEV == (0x00010000ULL));
-        CLASSERT(OBD_MD_FLEASIZE == (0x00020000ULL));
-        CLASSERT(OBD_MD_LINKNAME == (0x00040000ULL));
-        CLASSERT(OBD_MD_FLHANDLE == (0x00080000ULL));
-        CLASSERT(OBD_MD_FLCKSUM == (0x00100000ULL));
-        CLASSERT(OBD_MD_FLQOS == (0x00200000ULL));
-        CLASSERT(OBD_MD_FLCOOKIE == (0x00800000ULL));
-        CLASSERT(OBD_MD_FLGROUP == (0x01000000ULL));
-        CLASSERT(OBD_MD_FLFID == (0x02000000ULL));
-        CLASSERT(OBD_MD_FLEPOCH == (0x04000000ULL));
-        CLASSERT(OBD_MD_FLGRANT == (0x08000000ULL));
-        CLASSERT(OBD_MD_FLDIREA == (0x10000000ULL));
-        CLASSERT(OBD_MD_FLUSRQUOTA == (0x20000000ULL));
-        CLASSERT(OBD_MD_FLGRPQUOTA == (0x40000000ULL));
-        CLASSERT(OBD_MD_FLMODEASIZE == (0x80000000ULL));
-        CLASSERT(OBD_MD_MDS == (0x0000000100000000ULL));
-        CLASSERT(OBD_MD_REINT == (0x0000000200000000ULL));
-        CLASSERT(OBD_MD_FLXATTR == (0x0000001000000000ULL));
-        CLASSERT(OBD_MD_FLXATTRLS == (0x0000002000000000ULL));
-        CLASSERT(OBD_MD_FLXATTRRM == (0x0000004000000000ULL));
-        CLASSERT(OBD_MD_FLACL == (0x0000008000000000ULL));
-        CLASSERT(OBD_FL_INLINEDATA == (0x00000001));
-        CLASSERT(OBD_FL_OBDMDEXISTS == (0x00000002));
-        CLASSERT(OBD_FL_DELORPHAN == (0x00000004));
-        CLASSERT(OBD_FL_NORPC == (0x00000008));
-        CLASSERT(OBD_FL_IDONLY == (0x00000010));
-        CLASSERT(OBD_FL_RECREATE_OBJS == (0x00000020));
-        CLASSERT(OBD_FL_DEBUG_CHECK == (0x00000040));
-        CLASSERT(OBD_FL_NO_USRQUOTA == (0x00000100));
-        CLASSERT(OBD_FL_NO_GRPQUOTA == (0x00000200));
-        CLASSERT(OBD_FL_CREATE_CROW == (0x00000400));
-
-        /* Checks for struct lov_mds_md_v1 */
-        LASSERTF((int)sizeof(struct lov_mds_md_v1) == 32, " found %lld\n",
-                 (long long)(int)sizeof(struct lov_mds_md_v1));
-        LASSERTF((int)offsetof(struct lov_mds_md_v1, lmm_magic) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_mds_md_v1, lmm_magic));
-        LASSERTF((int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_magic) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_magic));
-        LASSERTF((int)offsetof(struct lov_mds_md_v1, lmm_pattern) == 4, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_mds_md_v1, lmm_pattern));
-        LASSERTF((int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_pattern) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_pattern));
-        LASSERTF((int)offsetof(struct lov_mds_md_v1, lmm_object_id) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_mds_md_v1, lmm_object_id));
-        LASSERTF((int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_object_id) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_object_id));
-        LASSERTF((int)offsetof(struct lov_mds_md_v1, lmm_object_gr) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_mds_md_v1, lmm_object_gr));
-        LASSERTF((int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_object_gr) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_object_gr));
-        LASSERTF((int)offsetof(struct lov_mds_md_v1, lmm_stripe_size) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_mds_md_v1, lmm_stripe_size));
-        LASSERTF((int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_stripe_size) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_stripe_size));
-        LASSERTF((int)offsetof(struct lov_mds_md_v1, lmm_stripe_count) == 28, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_mds_md_v1, lmm_stripe_count));
-        LASSERTF((int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_stripe_count) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_stripe_count));
-        LASSERTF((int)offsetof(struct lov_mds_md_v1, lmm_objects) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_mds_md_v1, lmm_objects));
-        LASSERTF((int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_objects) == 0, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_objects));
-
-        /* Checks for struct lov_ost_data_v1 */
-        LASSERTF((int)sizeof(struct lov_ost_data_v1) == 24, " found %lld\n",
-                 (long long)(int)sizeof(struct lov_ost_data_v1));
-        LASSERTF((int)offsetof(struct lov_ost_data_v1, l_object_id) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_ost_data_v1, l_object_id));
-        LASSERTF((int)sizeof(((struct lov_ost_data_v1 *)0)->l_object_id) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_ost_data_v1 *)0)->l_object_id));
-        LASSERTF((int)offsetof(struct lov_ost_data_v1, l_object_gr) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_ost_data_v1, l_object_gr));
-        LASSERTF((int)sizeof(((struct lov_ost_data_v1 *)0)->l_object_gr) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_ost_data_v1 *)0)->l_object_gr));
-        LASSERTF((int)offsetof(struct lov_ost_data_v1, l_ost_gen) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_ost_data_v1, l_ost_gen));
-        LASSERTF((int)sizeof(((struct lov_ost_data_v1 *)0)->l_ost_gen) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_ost_data_v1 *)0)->l_ost_gen));
-        LASSERTF((int)offsetof(struct lov_ost_data_v1, l_ost_idx) == 20, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_ost_data_v1, l_ost_idx));
-        LASSERTF((int)sizeof(((struct lov_ost_data_v1 *)0)->l_ost_idx) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_ost_data_v1 *)0)->l_ost_idx));
-        CLASSERT(LOV_MAGIC_V1 == 0x0BD10BD0);
-        CLASSERT(LOV_MAGIC_JOIN == 0x0BD20BD0);
-        LASSERTF(LOV_PATTERN_RAID0 == 1, " found %lld\n",
-                 (long long)LOV_PATTERN_RAID0);
-        LASSERTF(LOV_PATTERN_RAID1 == 2, " found %lld\n",
-                 (long long)LOV_PATTERN_RAID1);
-
-        /* Checks for struct lov_mds_md_join */
-        LASSERTF((int)sizeof(struct lov_mds_md_join) == 56, " found %lld\n",
-                 (long long)(int)sizeof(struct lov_mds_md_join));
-        LASSERTF((int)offsetof(struct lov_mds_md_join, lmmj_md) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_mds_md_join, lmmj_md));
-        LASSERTF((int)sizeof(((struct lov_mds_md_join *)0)->lmmj_md) == 32, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_mds_md_join *)0)->lmmj_md));
-        LASSERTF((int)offsetof(struct lov_mds_md_join, lmmj_array_id) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_mds_md_join, lmmj_array_id));
-        LASSERTF((int)sizeof(((struct lov_mds_md_join *)0)->lmmj_array_id) == 20, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_mds_md_join *)0)->lmmj_array_id));
-        LASSERTF((int)offsetof(struct lov_mds_md_join, lmmj_extent_count) == 52, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_mds_md_join, lmmj_extent_count));
-        LASSERTF((int)sizeof(((struct lov_mds_md_join *)0)->lmmj_extent_count) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_mds_md_join *)0)->lmmj_extent_count));
-
-        /* Checks for struct obd_statfs */
-        LASSERTF((int)sizeof(struct obd_statfs) == 144, " found %lld\n",
-                 (long long)(int)sizeof(struct obd_statfs));
-        LASSERTF((int)offsetof(struct obd_statfs, os_type) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_type));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_type) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_type));
-        LASSERTF((int)offsetof(struct obd_statfs, os_blocks) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_blocks));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_blocks) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_blocks));
-        LASSERTF((int)offsetof(struct obd_statfs, os_bfree) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_bfree));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_bfree) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_bfree));
-        LASSERTF((int)offsetof(struct obd_statfs, os_bavail) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_bavail));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_bavail) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_bavail));
-        LASSERTF((int)offsetof(struct obd_statfs, os_ffree) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_ffree));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_ffree) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_ffree));
-        LASSERTF((int)offsetof(struct obd_statfs, os_fsid) == 48, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_fsid));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_fsid) == 40, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_fsid));
-        LASSERTF((int)offsetof(struct obd_statfs, os_bsize) == 88, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_bsize));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_bsize) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_bsize));
-        LASSERTF((int)offsetof(struct obd_statfs, os_namelen) == 92, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_namelen));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_namelen) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_namelen));
-        LASSERTF((int)offsetof(struct obd_statfs, os_state) == 104, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_state));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_state) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_state));
-        LASSERTF((int)offsetof(struct obd_statfs, os_spare1) == 108, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_spare1));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_spare1) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_spare1));
-        LASSERTF((int)offsetof(struct obd_statfs, os_spare2) == 112, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_spare2));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_spare2) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_spare2));
-        LASSERTF((int)offsetof(struct obd_statfs, os_spare3) == 116, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_spare3));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_spare3) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_spare3));
-        LASSERTF((int)offsetof(struct obd_statfs, os_spare4) == 120, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_spare4));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_spare4) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_spare4));
-        LASSERTF((int)offsetof(struct obd_statfs, os_spare5) == 124, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_spare5));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_spare5) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_spare5));
-        LASSERTF((int)offsetof(struct obd_statfs, os_spare6) == 128, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_spare6));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_spare6) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_spare6));
-        LASSERTF((int)offsetof(struct obd_statfs, os_spare7) == 132, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_spare7));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_spare7) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_spare7));
-        LASSERTF((int)offsetof(struct obd_statfs, os_spare8) == 136, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_spare8));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_spare8) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_spare8));
-        LASSERTF((int)offsetof(struct obd_statfs, os_spare9) == 140, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_statfs, os_spare9));
-        LASSERTF((int)sizeof(((struct obd_statfs *)0)->os_spare9) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_statfs *)0)->os_spare9));
-
-        /* Checks for struct obd_ioobj */
-        LASSERTF((int)sizeof(struct obd_ioobj) == 24, " found %lld\n",
-                 (long long)(int)sizeof(struct obd_ioobj));
-        LASSERTF((int)offsetof(struct obd_ioobj, ioo_id) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_ioobj, ioo_id));
-        LASSERTF((int)sizeof(((struct obd_ioobj *)0)->ioo_id) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_ioobj *)0)->ioo_id));
-        LASSERTF((int)offsetof(struct obd_ioobj, ioo_gr) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_ioobj, ioo_gr));
-        LASSERTF((int)sizeof(((struct obd_ioobj *)0)->ioo_gr) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_ioobj *)0)->ioo_gr));
-        LASSERTF((int)offsetof(struct obd_ioobj, ioo_type) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_ioobj, ioo_type));
-        LASSERTF((int)sizeof(((struct obd_ioobj *)0)->ioo_type) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_ioobj *)0)->ioo_type));
-        LASSERTF((int)offsetof(struct obd_ioobj, ioo_bufcnt) == 20, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_ioobj, ioo_bufcnt));
-        LASSERTF((int)sizeof(((struct obd_ioobj *)0)->ioo_bufcnt) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_ioobj *)0)->ioo_bufcnt));
-
-        /* Checks for struct obd_quotactl */
-        LASSERTF((int)sizeof(struct obd_quotactl) == 112, " found %lld\n",
-                 (long long)(int)sizeof(struct obd_quotactl));
-        LASSERTF((int)offsetof(struct obd_quotactl, qc_cmd) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_quotactl, qc_cmd));
-        LASSERTF((int)sizeof(((struct obd_quotactl *)0)->qc_cmd) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_quotactl *)0)->qc_cmd));
-        LASSERTF((int)offsetof(struct obd_quotactl, qc_type) == 4, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_quotactl, qc_type));
-        LASSERTF((int)sizeof(((struct obd_quotactl *)0)->qc_type) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_quotactl *)0)->qc_type));
-        LASSERTF((int)offsetof(struct obd_quotactl, qc_id) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_quotactl, qc_id));
-        LASSERTF((int)sizeof(((struct obd_quotactl *)0)->qc_id) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_quotactl *)0)->qc_id));
-        LASSERTF((int)offsetof(struct obd_quotactl, qc_stat) == 12, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_quotactl, qc_stat));
-        LASSERTF((int)sizeof(((struct obd_quotactl *)0)->qc_stat) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_quotactl *)0)->qc_stat));
-        LASSERTF((int)offsetof(struct obd_quotactl, qc_dqinfo) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_quotactl, qc_dqinfo));
-        LASSERTF((int)sizeof(((struct obd_quotactl *)0)->qc_dqinfo) == 24, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_quotactl *)0)->qc_dqinfo));
-        LASSERTF((int)offsetof(struct obd_quotactl, qc_dqblk) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_quotactl, qc_dqblk));
-        LASSERTF((int)sizeof(((struct obd_quotactl *)0)->qc_dqblk) == 72, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_quotactl *)0)->qc_dqblk));
-
-        /* Checks for struct obd_dqinfo */
-        LASSERTF((int)sizeof(struct obd_dqinfo) == 24, " found %lld\n",
-                 (long long)(int)sizeof(struct obd_dqinfo));
-        LASSERTF((int)offsetof(struct obd_dqinfo, dqi_bgrace) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_dqinfo, dqi_bgrace));
-        LASSERTF((int)sizeof(((struct obd_dqinfo *)0)->dqi_bgrace) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_dqinfo *)0)->dqi_bgrace));
-        LASSERTF((int)offsetof(struct obd_dqinfo, dqi_igrace) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_dqinfo, dqi_igrace));
-        LASSERTF((int)sizeof(((struct obd_dqinfo *)0)->dqi_igrace) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_dqinfo *)0)->dqi_igrace));
-        LASSERTF((int)offsetof(struct obd_dqinfo, dqi_flags) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_dqinfo, dqi_flags));
-        LASSERTF((int)sizeof(((struct obd_dqinfo *)0)->dqi_flags) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_dqinfo *)0)->dqi_flags));
-        LASSERTF((int)offsetof(struct obd_dqinfo, dqi_valid) == 20, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_dqinfo, dqi_valid));
-        LASSERTF((int)sizeof(((struct obd_dqinfo *)0)->dqi_valid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_dqinfo *)0)->dqi_valid));
-
-        /* Checks for struct obd_dqblk */
-        LASSERTF((int)sizeof(struct obd_dqblk) == 72, " found %lld\n",
-                 (long long)(int)sizeof(struct obd_dqblk));
-        LASSERTF((int)offsetof(struct obd_dqblk, dqb_bhardlimit) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_dqblk, dqb_bhardlimit));
-        LASSERTF((int)sizeof(((struct obd_dqblk *)0)->dqb_bhardlimit) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_dqblk *)0)->dqb_bhardlimit));
-        LASSERTF((int)offsetof(struct obd_dqblk, dqb_bsoftlimit) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_dqblk, dqb_bsoftlimit));
-        LASSERTF((int)sizeof(((struct obd_dqblk *)0)->dqb_bsoftlimit) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_dqblk *)0)->dqb_bsoftlimit));
-        LASSERTF((int)offsetof(struct obd_dqblk, dqb_curspace) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_dqblk, dqb_curspace));
-        LASSERTF((int)sizeof(((struct obd_dqblk *)0)->dqb_curspace) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_dqblk *)0)->dqb_curspace));
-        LASSERTF((int)offsetof(struct obd_dqblk, dqb_ihardlimit) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_dqblk, dqb_ihardlimit));
-        LASSERTF((int)sizeof(((struct obd_dqblk *)0)->dqb_ihardlimit) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_dqblk *)0)->dqb_ihardlimit));
-        LASSERTF((int)offsetof(struct obd_dqblk, dqb_isoftlimit) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_dqblk, dqb_isoftlimit));
-        LASSERTF((int)sizeof(((struct obd_dqblk *)0)->dqb_isoftlimit) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_dqblk *)0)->dqb_isoftlimit));
-        LASSERTF((int)offsetof(struct obd_dqblk, dqb_curinodes) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_dqblk, dqb_curinodes));
-        LASSERTF((int)sizeof(((struct obd_dqblk *)0)->dqb_curinodes) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_dqblk *)0)->dqb_curinodes));
-        LASSERTF((int)offsetof(struct obd_dqblk, dqb_btime) == 48, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_dqblk, dqb_btime));
-        LASSERTF((int)sizeof(((struct obd_dqblk *)0)->dqb_btime) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_dqblk *)0)->dqb_btime));
-        LASSERTF((int)offsetof(struct obd_dqblk, dqb_itime) == 56, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_dqblk, dqb_itime));
-        LASSERTF((int)sizeof(((struct obd_dqblk *)0)->dqb_itime) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_dqblk *)0)->dqb_itime));
-        LASSERTF((int)offsetof(struct obd_dqblk, dqb_valid) == 64, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_dqblk, dqb_valid));
-        LASSERTF((int)sizeof(((struct obd_dqblk *)0)->dqb_valid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_dqblk *)0)->dqb_valid));
-        LASSERTF((int)offsetof(struct obd_dqblk, padding) == 68, " found %lld\n",
-                 (long long)(int)offsetof(struct obd_dqblk, padding));
-        LASSERTF((int)sizeof(((struct obd_dqblk *)0)->padding) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct obd_dqblk *)0)->padding));
-        LASSERTF(Q_QUOTACHECK == 0x800100," found %lld\n",
-                 (long long)Q_QUOTACHECK);
-        LASSERTF(Q_INITQUOTA == 0x800101," found %lld\n",
-                 (long long)Q_INITQUOTA);
-        LASSERTF(Q_GETOINFO == 0x800102," found %lld\n",
-                 (long long)Q_GETOINFO);
-        LASSERTF(Q_GETOQUOTA == 0x800103," found %lld\n",
-                 (long long)Q_GETOQUOTA);
-
-        /* Checks for struct niobuf_remote */
-        LASSERTF((int)sizeof(struct niobuf_remote) == 16, " found %lld\n",
-                 (long long)(int)sizeof(struct niobuf_remote));
-        LASSERTF((int)offsetof(struct niobuf_remote, offset) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct niobuf_remote, offset));
-        LASSERTF((int)sizeof(((struct niobuf_remote *)0)->offset) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct niobuf_remote *)0)->offset));
-        LASSERTF((int)offsetof(struct niobuf_remote, len) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct niobuf_remote, len));
-        LASSERTF((int)sizeof(((struct niobuf_remote *)0)->len) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct niobuf_remote *)0)->len));
-        LASSERTF((int)offsetof(struct niobuf_remote, flags) == 12, " found %lld\n",
-                 (long long)(int)offsetof(struct niobuf_remote, flags));
-        LASSERTF((int)sizeof(((struct niobuf_remote *)0)->flags) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct niobuf_remote *)0)->flags));
-        LASSERTF(OBD_BRW_READ == 1, " found %lld\n",
-                 (long long)OBD_BRW_READ);
-        LASSERTF(OBD_BRW_WRITE == 2, " found %lld\n",
-                 (long long)OBD_BRW_WRITE);
-        LASSERTF(OBD_BRW_SYNC == 8, " found %lld\n",
-                 (long long)OBD_BRW_SYNC);
-        LASSERTF(OBD_BRW_FROM_GRANT == 32, " found %lld\n",
-                 (long long)OBD_BRW_FROM_GRANT);
-        LASSERTF(OBD_BRW_NOQUOTA == 256, " found %lld\n",
-                 (long long)OBD_BRW_NOQUOTA);
-
-        /* Checks for struct ost_body */
-        LASSERTF((int)sizeof(struct ost_body) == 208, " found %lld\n",
-                 (long long)(int)sizeof(struct ost_body));
-        LASSERTF((int)offsetof(struct ost_body, oa) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct ost_body, oa));
-        LASSERTF((int)sizeof(((struct ost_body *)0)->oa) == 208, " found %lld\n",
-                 (long long)(int)sizeof(((struct ost_body *)0)->oa));
-
-        /* Checks for struct ll_fid */
-        LASSERTF((int)sizeof(struct ll_fid) == 16, " found %lld\n",
-                 (long long)(int)sizeof(struct ll_fid));
-        LASSERTF((int)offsetof(struct ll_fid, id) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct ll_fid, id));
-        LASSERTF((int)sizeof(((struct ll_fid *)0)->id) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ll_fid *)0)->id));
-        LASSERTF((int)offsetof(struct ll_fid, generation) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct ll_fid, generation));
-        LASSERTF((int)sizeof(((struct ll_fid *)0)->generation) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct ll_fid *)0)->generation));
-        LASSERTF((int)offsetof(struct ll_fid, f_type) == 12, " found %lld\n",
-                 (long long)(int)offsetof(struct ll_fid, f_type));
-        LASSERTF((int)sizeof(((struct ll_fid *)0)->f_type) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct ll_fid *)0)->f_type));
-
-        /* Checks for struct mds_status_req */
-        LASSERTF((int)sizeof(struct mds_status_req) == 8, " found %lld\n",
-                 (long long)(int)sizeof(struct mds_status_req));
-        LASSERTF((int)offsetof(struct mds_status_req, flags) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_status_req, flags));
-        LASSERTF((int)sizeof(((struct mds_status_req *)0)->flags) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_status_req *)0)->flags));
-        LASSERTF((int)offsetof(struct mds_status_req, repbuf) == 4, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_status_req, repbuf));
-        LASSERTF((int)sizeof(((struct mds_status_req *)0)->repbuf) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_status_req *)0)->repbuf));
-
-        /* Checks for struct mds_body */
-        LASSERTF((int)sizeof(struct mds_body) == 168, " found %lld\n",
-                 (long long)(int)sizeof(struct mds_body));
-        LASSERTF((int)offsetof(struct mds_body, fid1) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, fid1));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->fid1) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->fid1));
-        LASSERTF((int)offsetof(struct mds_body, fid2) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, fid2));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->fid2) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->fid2));
-        LASSERTF((int)offsetof(struct mds_body, handle) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, handle));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->handle) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->handle));
-        LASSERTF((int)offsetof(struct mds_body, size) == 48, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, size));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->size) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->size));
-        LASSERTF((int)offsetof(struct mds_body, blocks) == 80, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, blocks));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->blocks) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->blocks));
-        LASSERTF((int)offsetof(struct mds_body, io_epoch) == 88, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, io_epoch));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->io_epoch) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->io_epoch));
-        LASSERTF((int)offsetof(struct mds_body, ino) == 96, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, ino));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->ino) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->ino));
-        LASSERTF((int)offsetof(struct mds_body, valid) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, valid));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->valid) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->valid));
-        LASSERTF((int)offsetof(struct mds_body, fsuid) == 104, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, fsuid));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->fsuid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->fsuid));
-        LASSERTF((int)offsetof(struct mds_body, fsgid) == 108, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, fsgid));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->fsgid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->fsgid));
-        LASSERTF((int)offsetof(struct mds_body, capability) == 112, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, capability));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->capability) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->capability));
-        LASSERTF((int)offsetof(struct mds_body, mode) == 116, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, mode));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->mode) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->mode));
-        LASSERTF((int)offsetof(struct mds_body, uid) == 120, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, uid));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->uid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->uid));
-        LASSERTF((int)offsetof(struct mds_body, gid) == 124, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, gid));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->gid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->gid));
-        LASSERTF((int)offsetof(struct mds_body, mtime) == 56, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, mtime));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->mtime) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->mtime));
-        LASSERTF((int)offsetof(struct mds_body, ctime) == 72, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, ctime));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->ctime) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->ctime));
-        LASSERTF((int)offsetof(struct mds_body, atime) == 64, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, atime));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->atime) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->atime));
-        LASSERTF((int)offsetof(struct mds_body, flags) == 128, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, flags));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->flags) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->flags));
-        LASSERTF((int)offsetof(struct mds_body, rdev) == 132, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, rdev));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->rdev) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->rdev));
-        LASSERTF((int)offsetof(struct mds_body, nlink) == 136, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, nlink));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->nlink) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->nlink));
-        LASSERTF((int)offsetof(struct mds_body, generation) == 140, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, generation));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->generation) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->generation));
-        LASSERTF((int)offsetof(struct mds_body, suppgid) == 144, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, suppgid));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->suppgid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->suppgid));
-        LASSERTF((int)offsetof(struct mds_body, eadatasize) == 148, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, eadatasize));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->eadatasize) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->eadatasize));
-        LASSERTF((int)offsetof(struct mds_body, aclsize) == 152, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, aclsize));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->aclsize) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->aclsize));
-        LASSERTF((int)offsetof(struct mds_body, max_mdsize) == 156, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, max_mdsize));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->max_mdsize) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->max_mdsize));
-        LASSERTF((int)offsetof(struct mds_body, max_cookiesize) == 160, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, max_cookiesize));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->max_cookiesize) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->max_cookiesize));
-        LASSERTF((int)offsetof(struct mds_body, padding_4) == 164, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_body, padding_4));
-        LASSERTF((int)sizeof(((struct mds_body *)0)->padding_4) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_body *)0)->padding_4));
-        LASSERTF(FMODE_READ == 1, " found %lld\n",
-                 (long long)FMODE_READ);
-        LASSERTF(FMODE_WRITE == 2, " found %lld\n",
-                 (long long)FMODE_WRITE);
-        LASSERTF(MDS_FMODE_EXEC == 4, " found %lld\n",
-                 (long long)MDS_FMODE_EXEC);
-        CLASSERT(MDS_OPEN_CREAT == 00000100);
-        CLASSERT(MDS_OPEN_EXCL == 00000200);
-        CLASSERT(MDS_OPEN_TRUNC == 00001000);
-        CLASSERT(MDS_OPEN_APPEND == 00002000);
-        CLASSERT(MDS_OPEN_SYNC == 00010000);
-        CLASSERT(MDS_OPEN_DIRECTORY == 00200000);
-        CLASSERT(MDS_OPEN_DELAY_CREATE == 0100000000);
-        CLASSERT(MDS_OPEN_OWNEROVERRIDE == 0200000000);
-        CLASSERT(MDS_OPEN_JOIN_FILE == 0400000000);
-        CLASSERT(MDS_OPEN_HAS_EA == 010000000000);
-        CLASSERT(MDS_OPEN_HAS_OBJS == 020000000000);
-        CLASSERT(MDS_INODELOCK_LOOKUP == 0x000001);
-        CLASSERT(MDS_INODELOCK_UPDATE == 0x000002);
-        CLASSERT(MDS_INODELOCK_OPEN == 0x000004);
-
-        /* Checks for struct mds_rec_setattr */
-        LASSERTF((int)sizeof(struct mds_rec_setattr) == 96, " found %lld\n",
-                 (long long)(int)sizeof(struct mds_rec_setattr));
-        LASSERTF((int)offsetof(struct mds_rec_setattr, sa_opcode) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_setattr, sa_opcode));
-        LASSERTF((int)sizeof(((struct mds_rec_setattr *)0)->sa_opcode) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_setattr *)0)->sa_opcode));
-        LASSERTF((int)offsetof(struct mds_rec_setattr, sa_fsuid) == 4, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_setattr, sa_fsuid));
-        LASSERTF((int)sizeof(((struct mds_rec_setattr *)0)->sa_fsuid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_setattr *)0)->sa_fsuid));
-        LASSERTF((int)offsetof(struct mds_rec_setattr, sa_fsgid) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_setattr, sa_fsgid));
-        LASSERTF((int)sizeof(((struct mds_rec_setattr *)0)->sa_fsgid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_setattr *)0)->sa_fsgid));
-        LASSERTF((int)offsetof(struct mds_rec_setattr, sa_cap) == 12, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_setattr, sa_cap));
-        LASSERTF((int)sizeof(((struct mds_rec_setattr *)0)->sa_cap) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_setattr *)0)->sa_cap));
-        LASSERTF((int)offsetof(struct mds_rec_setattr, sa_suppgid) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_setattr, sa_suppgid));
-        LASSERTF((int)sizeof(((struct mds_rec_setattr *)0)->sa_suppgid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_setattr *)0)->sa_suppgid));
-        LASSERTF((int)offsetof(struct mds_rec_setattr, sa_mode) == 20, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_setattr, sa_mode));
-        LASSERTF((int)sizeof(((struct mds_rec_setattr *)0)->sa_mode) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_setattr *)0)->sa_mode));
-        LASSERTF((int)offsetof(struct mds_rec_setattr, sa_fid) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_setattr, sa_fid));
-        LASSERTF((int)sizeof(((struct mds_rec_setattr *)0)->sa_fid) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_setattr *)0)->sa_fid));
-        LASSERTF((int)offsetof(struct mds_rec_setattr, sa_valid) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_setattr, sa_valid));
-        LASSERTF((int)sizeof(((struct mds_rec_setattr *)0)->sa_valid) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_setattr *)0)->sa_valid));
-        LASSERTF((int)offsetof(struct mds_rec_setattr, sa_size) == 48, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_setattr, sa_size));
-        LASSERTF((int)sizeof(((struct mds_rec_setattr *)0)->sa_size) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_setattr *)0)->sa_size));
-        LASSERTF((int)offsetof(struct mds_rec_setattr, sa_mtime) == 56, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_setattr, sa_mtime));
-        LASSERTF((int)sizeof(((struct mds_rec_setattr *)0)->sa_mtime) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_setattr *)0)->sa_mtime));
-        LASSERTF((int)offsetof(struct mds_rec_setattr, sa_atime) == 64, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_setattr, sa_atime));
-        LASSERTF((int)sizeof(((struct mds_rec_setattr *)0)->sa_atime) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_setattr *)0)->sa_atime));
-        LASSERTF((int)offsetof(struct mds_rec_setattr, sa_ctime) == 72, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_setattr, sa_ctime));
-        LASSERTF((int)sizeof(((struct mds_rec_setattr *)0)->sa_ctime) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_setattr *)0)->sa_ctime));
-        LASSERTF((int)offsetof(struct mds_rec_setattr, sa_uid) == 80, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_setattr, sa_uid));
-        LASSERTF((int)sizeof(((struct mds_rec_setattr *)0)->sa_uid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_setattr *)0)->sa_uid));
-        LASSERTF((int)offsetof(struct mds_rec_setattr, sa_gid) == 84, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_setattr, sa_gid));
-        LASSERTF((int)sizeof(((struct mds_rec_setattr *)0)->sa_gid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_setattr *)0)->sa_gid));
-        LASSERTF((int)offsetof(struct mds_rec_setattr, sa_attr_flags) == 88, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_setattr, sa_attr_flags));
-        LASSERTF((int)sizeof(((struct mds_rec_setattr *)0)->sa_attr_flags) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_setattr *)0)->sa_attr_flags));
-
-        /* Checks for struct mds_rec_create */
-        LASSERTF((int)sizeof(struct mds_rec_create) == 96, " found %lld\n",
-                 (long long)(int)sizeof(struct mds_rec_create));
-        LASSERTF((int)offsetof(struct mds_rec_create, cr_opcode) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_create, cr_opcode));
-        LASSERTF((int)sizeof(((struct mds_rec_create *)0)->cr_opcode) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_create *)0)->cr_opcode));
-        LASSERTF((int)offsetof(struct mds_rec_create, cr_fsuid) == 4, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_create, cr_fsuid));
-        LASSERTF((int)sizeof(((struct mds_rec_create *)0)->cr_fsuid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_create *)0)->cr_fsuid));
-        LASSERTF((int)offsetof(struct mds_rec_create, cr_fsgid) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_create, cr_fsgid));
-        LASSERTF((int)sizeof(((struct mds_rec_create *)0)->cr_fsgid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_create *)0)->cr_fsgid));
-        LASSERTF((int)offsetof(struct mds_rec_create, cr_cap) == 12, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_create, cr_cap));
-        LASSERTF((int)sizeof(((struct mds_rec_create *)0)->cr_cap) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_create *)0)->cr_cap));
-        LASSERTF((int)offsetof(struct mds_rec_create, cr_flags) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_create, cr_flags));
-        LASSERTF((int)sizeof(((struct mds_rec_create *)0)->cr_flags) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_create *)0)->cr_flags));
-        LASSERTF((int)offsetof(struct mds_rec_create, cr_mode) == 20, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_create, cr_mode));
-        LASSERTF((int)sizeof(((struct mds_rec_create *)0)->cr_mode) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_create *)0)->cr_mode));
-        LASSERTF((int)offsetof(struct mds_rec_create, cr_fid) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_create, cr_fid));
-        LASSERTF((int)sizeof(((struct mds_rec_create *)0)->cr_fid) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_create *)0)->cr_fid));
-        LASSERTF((int)offsetof(struct mds_rec_create, cr_replayfid) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_create, cr_replayfid));
-        LASSERTF((int)sizeof(((struct mds_rec_create *)0)->cr_replayfid) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_create *)0)->cr_replayfid));
-        LASSERTF((int)offsetof(struct mds_rec_create, cr_time) == 56, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_create, cr_time));
-        LASSERTF((int)sizeof(((struct mds_rec_create *)0)->cr_time) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_create *)0)->cr_time));
-        LASSERTF((int)offsetof(struct mds_rec_create, cr_rdev) == 64, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_create, cr_rdev));
-        LASSERTF((int)sizeof(((struct mds_rec_create *)0)->cr_rdev) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_create *)0)->cr_rdev));
-        LASSERTF((int)offsetof(struct mds_rec_create, cr_suppgid) == 72, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_create, cr_suppgid));
-        LASSERTF((int)sizeof(((struct mds_rec_create *)0)->cr_suppgid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_create *)0)->cr_suppgid));
-
-        /* Checks for struct mds_rec_link */
-        LASSERTF((int)sizeof(struct mds_rec_link) == 80, " found %lld\n",
-                 (long long)(int)sizeof(struct mds_rec_link));
-        LASSERTF((int)offsetof(struct mds_rec_link, lk_opcode) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_link, lk_opcode));
-        LASSERTF((int)sizeof(((struct mds_rec_link *)0)->lk_opcode) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_link *)0)->lk_opcode));
-        LASSERTF((int)offsetof(struct mds_rec_link, lk_fsuid) == 4, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_link, lk_fsuid));
-        LASSERTF((int)sizeof(((struct mds_rec_link *)0)->lk_fsuid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_link *)0)->lk_fsuid));
-        LASSERTF((int)offsetof(struct mds_rec_link, lk_fsgid) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_link, lk_fsgid));
-        LASSERTF((int)sizeof(((struct mds_rec_link *)0)->lk_fsgid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_link *)0)->lk_fsgid));
-        LASSERTF((int)offsetof(struct mds_rec_link, lk_cap) == 12, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_link, lk_cap));
-        LASSERTF((int)sizeof(((struct mds_rec_link *)0)->lk_cap) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_link *)0)->lk_cap));
-        LASSERTF((int)offsetof(struct mds_rec_link, lk_suppgid1) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_link, lk_suppgid1));
-        LASSERTF((int)sizeof(((struct mds_rec_link *)0)->lk_suppgid1) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_link *)0)->lk_suppgid1));
-        LASSERTF((int)offsetof(struct mds_rec_link, lk_suppgid2) == 20, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_link, lk_suppgid2));
-        LASSERTF((int)sizeof(((struct mds_rec_link *)0)->lk_suppgid2) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_link *)0)->lk_suppgid2));
-        LASSERTF((int)offsetof(struct mds_rec_link, lk_fid1) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_link, lk_fid1));
-        LASSERTF((int)sizeof(((struct mds_rec_link *)0)->lk_fid1) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_link *)0)->lk_fid1));
-        LASSERTF((int)offsetof(struct mds_rec_link, lk_fid2) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_link, lk_fid2));
-        LASSERTF((int)sizeof(((struct mds_rec_link *)0)->lk_fid2) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_link *)0)->lk_fid2));
-        LASSERTF((int)offsetof(struct mds_rec_link, lk_time) == 56, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_link, lk_time));
-        LASSERTF((int)sizeof(((struct mds_rec_link *)0)->lk_time) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_link *)0)->lk_time));
-
-        /* Checks for struct mds_rec_unlink */
-        LASSERTF((int)sizeof(struct mds_rec_unlink) == 80, " found %lld\n",
-                 (long long)(int)sizeof(struct mds_rec_unlink));
-        LASSERTF((int)offsetof(struct mds_rec_unlink, ul_opcode) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_unlink, ul_opcode));
-        LASSERTF((int)sizeof(((struct mds_rec_unlink *)0)->ul_opcode) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_unlink *)0)->ul_opcode));
-        LASSERTF((int)offsetof(struct mds_rec_unlink, ul_fsuid) == 4, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_unlink, ul_fsuid));
-        LASSERTF((int)sizeof(((struct mds_rec_unlink *)0)->ul_fsuid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_unlink *)0)->ul_fsuid));
-        LASSERTF((int)offsetof(struct mds_rec_unlink, ul_fsgid) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_unlink, ul_fsgid));
-        LASSERTF((int)sizeof(((struct mds_rec_unlink *)0)->ul_fsgid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_unlink *)0)->ul_fsgid));
-        LASSERTF((int)offsetof(struct mds_rec_unlink, ul_cap) == 12, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_unlink, ul_cap));
-        LASSERTF((int)sizeof(((struct mds_rec_unlink *)0)->ul_cap) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_unlink *)0)->ul_cap));
-        LASSERTF((int)offsetof(struct mds_rec_unlink, ul_suppgid) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_unlink, ul_suppgid));
-        LASSERTF((int)sizeof(((struct mds_rec_unlink *)0)->ul_suppgid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_unlink *)0)->ul_suppgid));
-        LASSERTF((int)offsetof(struct mds_rec_unlink, ul_mode) == 20, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_unlink, ul_mode));
-        LASSERTF((int)sizeof(((struct mds_rec_unlink *)0)->ul_mode) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_unlink *)0)->ul_mode));
-        LASSERTF((int)offsetof(struct mds_rec_unlink, ul_fid1) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_unlink, ul_fid1));
-        LASSERTF((int)sizeof(((struct mds_rec_unlink *)0)->ul_fid1) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_unlink *)0)->ul_fid1));
-        LASSERTF((int)offsetof(struct mds_rec_unlink, ul_fid2) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_unlink, ul_fid2));
-        LASSERTF((int)sizeof(((struct mds_rec_unlink *)0)->ul_fid2) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_unlink *)0)->ul_fid2));
-        LASSERTF((int)offsetof(struct mds_rec_unlink, ul_time) == 56, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_unlink, ul_time));
-        LASSERTF((int)sizeof(((struct mds_rec_unlink *)0)->ul_time) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_unlink *)0)->ul_time));
-
-        /* Checks for struct mds_rec_rename */
-        LASSERTF((int)sizeof(struct mds_rec_rename) == 80, " found %lld\n",
-                 (long long)(int)sizeof(struct mds_rec_rename));
-        LASSERTF((int)offsetof(struct mds_rec_rename, rn_opcode) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_rename, rn_opcode));
-        LASSERTF((int)sizeof(((struct mds_rec_rename *)0)->rn_opcode) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_rename *)0)->rn_opcode));
-        LASSERTF((int)offsetof(struct mds_rec_rename, rn_fsuid) == 4, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_rename, rn_fsuid));
-        LASSERTF((int)sizeof(((struct mds_rec_rename *)0)->rn_fsuid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_rename *)0)->rn_fsuid));
-        LASSERTF((int)offsetof(struct mds_rec_rename, rn_fsgid) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_rename, rn_fsgid));
-        LASSERTF((int)sizeof(((struct mds_rec_rename *)0)->rn_fsgid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_rename *)0)->rn_fsgid));
-        LASSERTF((int)offsetof(struct mds_rec_rename, rn_cap) == 12, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_rename, rn_cap));
-        LASSERTF((int)sizeof(((struct mds_rec_rename *)0)->rn_cap) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_rename *)0)->rn_cap));
-        LASSERTF((int)offsetof(struct mds_rec_rename, rn_suppgid1) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_rename, rn_suppgid1));
-        LASSERTF((int)sizeof(((struct mds_rec_rename *)0)->rn_suppgid1) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_rename *)0)->rn_suppgid1));
-        LASSERTF((int)offsetof(struct mds_rec_rename, rn_suppgid2) == 20, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_rename, rn_suppgid2));
-        LASSERTF((int)sizeof(((struct mds_rec_rename *)0)->rn_suppgid2) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_rename *)0)->rn_suppgid2));
-        LASSERTF((int)offsetof(struct mds_rec_rename, rn_fid1) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_rename, rn_fid1));
-        LASSERTF((int)sizeof(((struct mds_rec_rename *)0)->rn_fid1) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_rename *)0)->rn_fid1));
-        LASSERTF((int)offsetof(struct mds_rec_rename, rn_fid2) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_rename, rn_fid2));
-        LASSERTF((int)sizeof(((struct mds_rec_rename *)0)->rn_fid2) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_rename *)0)->rn_fid2));
-        LASSERTF((int)offsetof(struct mds_rec_rename, rn_time) == 56, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_rename, rn_time));
-        LASSERTF((int)sizeof(((struct mds_rec_rename *)0)->rn_time) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_rename *)0)->rn_time));
-
-        /* Checks for struct mds_rec_join */
-        LASSERTF((int)sizeof(struct mds_rec_join) == 24, " found %lld\n",
-                 (long long)(int)sizeof(struct mds_rec_join));
-        LASSERTF((int)offsetof(struct mds_rec_join, jr_fid) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_join, jr_fid));
-        LASSERTF((int)sizeof(((struct mds_rec_join *)0)->jr_fid) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_join *)0)->jr_fid));
-        LASSERTF((int)offsetof(struct mds_rec_join, jr_headsize) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_rec_join, jr_headsize));
-        LASSERTF((int)sizeof(((struct mds_rec_join *)0)->jr_headsize) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_rec_join *)0)->jr_headsize));
-
-        /* Checks for struct lov_desc */
-        LASSERTF((int)sizeof(struct lov_desc) == 88, " found %lld\n",
-                 (long long)(int)sizeof(struct lov_desc));
-        LASSERTF((int)offsetof(struct lov_desc, ld_tgt_count) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_desc, ld_tgt_count));
-        LASSERTF((int)sizeof(((struct lov_desc *)0)->ld_tgt_count) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_desc *)0)->ld_tgt_count));
-        LASSERTF((int)offsetof(struct lov_desc, ld_active_tgt_count) == 4, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_desc, ld_active_tgt_count));
-        LASSERTF((int)sizeof(((struct lov_desc *)0)->ld_active_tgt_count) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_desc *)0)->ld_active_tgt_count));
-        LASSERTF((int)offsetof(struct lov_desc, ld_default_stripe_count) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_desc, ld_default_stripe_count));
-        LASSERTF((int)sizeof(((struct lov_desc *)0)->ld_default_stripe_count) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_desc *)0)->ld_default_stripe_count));
-        LASSERTF((int)offsetof(struct lov_desc, ld_pattern) == 12, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_desc, ld_pattern));
-        LASSERTF((int)sizeof(((struct lov_desc *)0)->ld_pattern) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_desc *)0)->ld_pattern));
-        LASSERTF((int)offsetof(struct lov_desc, ld_default_stripe_size) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_desc, ld_default_stripe_size));
-        LASSERTF((int)sizeof(((struct lov_desc *)0)->ld_default_stripe_size) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_desc *)0)->ld_default_stripe_size));
-        LASSERTF((int)offsetof(struct lov_desc, ld_default_stripe_offset) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_desc, ld_default_stripe_offset));
-        LASSERTF((int)sizeof(((struct lov_desc *)0)->ld_default_stripe_offset) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_desc *)0)->ld_default_stripe_offset));
-        LASSERTF((int)offsetof(struct lov_desc, ld_qos_threshold) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_desc, ld_qos_threshold));
-        LASSERTF((int)sizeof(((struct lov_desc *)0)->ld_qos_threshold) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_desc *)0)->ld_qos_threshold));
-        LASSERTF((int)offsetof(struct lov_desc, ld_qos_maxage) == 36, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_desc, ld_qos_maxage));
-        LASSERTF((int)sizeof(((struct lov_desc *)0)->ld_qos_maxage) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_desc *)0)->ld_qos_maxage));
-        LASSERTF((int)offsetof(struct lov_desc, ld_padding_1) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_desc, ld_padding_1));
-        LASSERTF((int)sizeof(((struct lov_desc *)0)->ld_padding_1) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_desc *)0)->ld_padding_1));
-        LASSERTF((int)offsetof(struct lov_desc, ld_padding_2) == 44, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_desc, ld_padding_2));
-        LASSERTF((int)sizeof(((struct lov_desc *)0)->ld_padding_2) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_desc *)0)->ld_padding_2));
-        LASSERTF((int)offsetof(struct lov_desc, ld_uuid) == 48, " found %lld\n",
-                 (long long)(int)offsetof(struct lov_desc, ld_uuid));
-        LASSERTF((int)sizeof(((struct lov_desc *)0)->ld_uuid) == 40, " found %lld\n",
-                 (long long)(int)sizeof(((struct lov_desc *)0)->ld_uuid));
-
-        /* Checks for struct ldlm_res_id */
-        LASSERTF((int)sizeof(struct ldlm_res_id) == 32, " found %lld\n",
-                 (long long)(int)sizeof(struct ldlm_res_id));
-        LASSERTF((int)offsetof(struct ldlm_res_id, name[4]) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_res_id, name[4]));
-        LASSERTF((int)sizeof(((struct ldlm_res_id *)0)->name[4]) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_res_id *)0)->name[4]));
-
-        /* Checks for struct ldlm_extent */
-        LASSERTF((int)sizeof(struct ldlm_extent) == 24, " found %lld\n",
-                 (long long)(int)sizeof(struct ldlm_extent));
-        LASSERTF((int)offsetof(struct ldlm_extent, start) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_extent, start));
-        LASSERTF((int)sizeof(((struct ldlm_extent *)0)->start) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_extent *)0)->start));
-        LASSERTF((int)offsetof(struct ldlm_extent, end) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_extent, end));
-        LASSERTF((int)sizeof(((struct ldlm_extent *)0)->end) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_extent *)0)->end));
-        LASSERTF((int)offsetof(struct ldlm_extent, gid) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_extent, gid));
-        LASSERTF((int)sizeof(((struct ldlm_extent *)0)->gid) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_extent *)0)->gid));
-
-        /* Checks for struct ldlm_flock */
-        LASSERTF((int)sizeof(struct ldlm_flock) == 32, " found %lld\n",
-                 (long long)(int)sizeof(struct ldlm_flock));
-        LASSERTF((int)offsetof(struct ldlm_flock, start) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_flock, start));
-        LASSERTF((int)sizeof(((struct ldlm_flock *)0)->start) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_flock *)0)->start));
-        LASSERTF((int)offsetof(struct ldlm_flock, end) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_flock, end));
-        LASSERTF((int)sizeof(((struct ldlm_flock *)0)->end) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_flock *)0)->end));
-        LASSERTF((int)offsetof(struct ldlm_flock, blocking_pid) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_flock, blocking_pid));
-        LASSERTF((int)sizeof(((struct ldlm_flock *)0)->blocking_pid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_flock *)0)->blocking_pid));
-        LASSERTF((int)offsetof(struct ldlm_flock, pid) == 28, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_flock, pid));
-        LASSERTF((int)sizeof(((struct ldlm_flock *)0)->pid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_flock *)0)->pid));
-
-        /* Checks for struct ldlm_inodebits */
-        LASSERTF((int)sizeof(struct ldlm_inodebits) == 8, " found %lld\n",
-                 (long long)(int)sizeof(struct ldlm_inodebits));
-        LASSERTF((int)offsetof(struct ldlm_inodebits, bits) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_inodebits, bits));
-        LASSERTF((int)sizeof(((struct ldlm_inodebits *)0)->bits) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_inodebits *)0)->bits));
-
-        /* Checks for struct ldlm_intent */
-        LASSERTF((int)sizeof(struct ldlm_intent) == 8, " found %lld\n",
-                 (long long)(int)sizeof(struct ldlm_intent));
-        LASSERTF((int)offsetof(struct ldlm_intent, opc) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_intent, opc));
-        LASSERTF((int)sizeof(((struct ldlm_intent *)0)->opc) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_intent *)0)->opc));
-
-        /* Checks for struct ldlm_resource_desc */
-        LASSERTF((int)sizeof(struct ldlm_resource_desc) == 40, " found %lld\n",
-                 (long long)(int)sizeof(struct ldlm_resource_desc));
-        LASSERTF((int)offsetof(struct ldlm_resource_desc, lr_type) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_resource_desc, lr_type));
-        LASSERTF((int)sizeof(((struct ldlm_resource_desc *)0)->lr_type) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_resource_desc *)0)->lr_type));
-        LASSERTF((int)offsetof(struct ldlm_resource_desc, lr_padding) == 4, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_resource_desc, lr_padding));
-        LASSERTF((int)sizeof(((struct ldlm_resource_desc *)0)->lr_padding) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_resource_desc *)0)->lr_padding));
-        LASSERTF((int)offsetof(struct ldlm_resource_desc, lr_name) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_resource_desc, lr_name));
-        LASSERTF((int)sizeof(((struct ldlm_resource_desc *)0)->lr_name) == 32, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_resource_desc *)0)->lr_name));
-
-        /* Checks for struct ldlm_lock_desc */
-        LASSERTF((int)sizeof(struct ldlm_lock_desc) == 80, " found %lld\n",
-                 (long long)(int)sizeof(struct ldlm_lock_desc));
-        LASSERTF((int)offsetof(struct ldlm_lock_desc, l_resource) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_lock_desc, l_resource));
-        LASSERTF((int)sizeof(((struct ldlm_lock_desc *)0)->l_resource) == 40, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_lock_desc *)0)->l_resource));
-        LASSERTF((int)offsetof(struct ldlm_lock_desc, l_req_mode) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_lock_desc, l_req_mode));
-        LASSERTF((int)sizeof(((struct ldlm_lock_desc *)0)->l_req_mode) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_lock_desc *)0)->l_req_mode));
-        LASSERTF((int)offsetof(struct ldlm_lock_desc, l_granted_mode) == 44, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_lock_desc, l_granted_mode));
-        LASSERTF((int)sizeof(((struct ldlm_lock_desc *)0)->l_granted_mode) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_lock_desc *)0)->l_granted_mode));
-        LASSERTF((int)offsetof(struct ldlm_lock_desc, l_policy_data) == 48, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_lock_desc, l_policy_data));
-        LASSERTF((int)sizeof(((struct ldlm_lock_desc *)0)->l_policy_data) == 32, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_lock_desc *)0)->l_policy_data));
-
-        /* Checks for struct ldlm_request */
-        LASSERTF((int)sizeof(struct ldlm_request) == 104, " found %lld\n",
-                 (long long)(int)sizeof(struct ldlm_request));
-        LASSERTF((int)offsetof(struct ldlm_request, lock_flags) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_request, lock_flags));
-        LASSERTF((int)sizeof(((struct ldlm_request *)0)->lock_flags) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_request *)0)->lock_flags));
-        LASSERTF((int)offsetof(struct ldlm_request, lock_padding) == 4, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_request, lock_padding));
-        LASSERTF((int)sizeof(((struct ldlm_request *)0)->lock_padding) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_request *)0)->lock_padding));
-        LASSERTF((int)offsetof(struct ldlm_request, lock_desc) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_request, lock_desc));
-        LASSERTF((int)sizeof(((struct ldlm_request *)0)->lock_desc) == 80, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_request *)0)->lock_desc));
-        LASSERTF((int)offsetof(struct ldlm_request, lock_handle1) == 88, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_request, lock_handle1));
-        LASSERTF((int)sizeof(((struct ldlm_request *)0)->lock_handle1) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_request *)0)->lock_handle1));
-        LASSERTF((int)offsetof(struct ldlm_request, lock_handle2) == 96, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_request, lock_handle2));
-        LASSERTF((int)sizeof(((struct ldlm_request *)0)->lock_handle2) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_request *)0)->lock_handle2));
-
-        /* Checks for struct ldlm_reply */
-        LASSERTF((int)sizeof(struct ldlm_reply) == 112, " found %lld\n",
-                 (long long)(int)sizeof(struct ldlm_reply));
-        LASSERTF((int)offsetof(struct ldlm_reply, lock_flags) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_reply, lock_flags));
-        LASSERTF((int)sizeof(((struct ldlm_reply *)0)->lock_flags) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_reply *)0)->lock_flags));
-        LASSERTF((int)offsetof(struct ldlm_request, lock_padding) == 4, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_request, lock_padding));
-        LASSERTF((int)sizeof(((struct ldlm_request *)0)->lock_padding) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_request *)0)->lock_padding));
-        LASSERTF((int)offsetof(struct ldlm_request, lock_desc) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_request, lock_desc));
-        LASSERTF((int)sizeof(((struct ldlm_request *)0)->lock_desc) == 80, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_request *)0)->lock_desc));
-        LASSERTF((int)offsetof(struct ldlm_reply, lock_handle) == 88, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_reply, lock_handle));
-        LASSERTF((int)sizeof(((struct ldlm_reply *)0)->lock_handle) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_reply *)0)->lock_handle));
-        LASSERTF((int)offsetof(struct ldlm_reply, lock_policy_res1) == 96, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_reply, lock_policy_res1));
-        LASSERTF((int)sizeof(((struct ldlm_reply *)0)->lock_policy_res1) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_reply *)0)->lock_policy_res1));
-        LASSERTF((int)offsetof(struct ldlm_reply, lock_policy_res2) == 104, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_reply, lock_policy_res2));
-        LASSERTF((int)sizeof(((struct ldlm_reply *)0)->lock_policy_res2) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_reply *)0)->lock_policy_res2));
-
-        /* Checks for struct ost_lvb */
-        LASSERTF((int)sizeof(struct ost_lvb) == 40, " found %lld\n",
-                 (long long)(int)sizeof(struct ost_lvb));
-        LASSERTF((int)offsetof(struct ost_lvb, lvb_size) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct ost_lvb, lvb_size));
-        LASSERTF((int)sizeof(((struct ost_lvb *)0)->lvb_size) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ost_lvb *)0)->lvb_size));
-        LASSERTF((int)offsetof(struct ost_lvb, lvb_mtime) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct ost_lvb, lvb_mtime));
-        LASSERTF((int)sizeof(((struct ost_lvb *)0)->lvb_mtime) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ost_lvb *)0)->lvb_mtime));
-        LASSERTF((int)offsetof(struct ost_lvb, lvb_atime) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct ost_lvb, lvb_atime));
-        LASSERTF((int)sizeof(((struct ost_lvb *)0)->lvb_atime) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ost_lvb *)0)->lvb_atime));
-        LASSERTF((int)offsetof(struct ost_lvb, lvb_ctime) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct ost_lvb, lvb_ctime));
-        LASSERTF((int)sizeof(((struct ost_lvb *)0)->lvb_ctime) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ost_lvb *)0)->lvb_ctime));
-        LASSERTF((int)offsetof(struct ost_lvb, lvb_blocks) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct ost_lvb, lvb_blocks));
-        LASSERTF((int)sizeof(((struct ost_lvb *)0)->lvb_blocks) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ost_lvb *)0)->lvb_blocks));
-
-        /* Checks for struct llog_logid */
-        LASSERTF((int)sizeof(struct llog_logid) == 20, " found %lld\n",
-                 (long long)(int)sizeof(struct llog_logid));
-        LASSERTF((int)offsetof(struct llog_logid, lgl_oid) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_logid, lgl_oid));
-        LASSERTF((int)sizeof(((struct llog_logid *)0)->lgl_oid) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_logid *)0)->lgl_oid));
-        LASSERTF((int)offsetof(struct llog_logid, lgl_ogr) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_logid, lgl_ogr));
-        LASSERTF((int)sizeof(((struct llog_logid *)0)->lgl_ogr) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_logid *)0)->lgl_ogr));
-        LASSERTF((int)offsetof(struct llog_logid, lgl_ogen) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_logid, lgl_ogen));
-        LASSERTF((int)sizeof(((struct llog_logid *)0)->lgl_ogen) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_logid *)0)->lgl_ogen));
-        CLASSERT(OST_SZ_REC == 274730752);
-        CLASSERT(OST_RAID1_REC == 274731008);
-        CLASSERT(MDS_UNLINK_REC == 274801668);
-        CLASSERT(MDS_SETATTR_REC == 274801665);
-        CLASSERT(OBD_CFG_REC == 274857984);
-        CLASSERT(PTL_CFG_REC == 274923520);
-        CLASSERT(LLOG_GEN_REC == 274989056);
-        CLASSERT(LLOG_JOIN_REC == 275054592);
-        CLASSERT(LLOG_HDR_MAGIC == 275010873);
-        CLASSERT(LLOG_LOGID_MAGIC == 275010875);
-
-        /* Checks for struct llog_catid */
-        LASSERTF((int)sizeof(struct llog_catid) == 32, " found %lld\n",
-                 (long long)(int)sizeof(struct llog_catid));
-        LASSERTF((int)offsetof(struct llog_catid, lci_logid) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_catid, lci_logid));
-        LASSERTF((int)sizeof(((struct llog_catid *)0)->lci_logid) == 20, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_catid *)0)->lci_logid));
-        LASSERTF((int)offsetof(struct llog_catid, lci_padding1) == 20, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_catid, lci_padding1));
-        LASSERTF((int)sizeof(((struct llog_catid *)0)->lci_padding1) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_catid *)0)->lci_padding1));
-        LASSERTF((int)offsetof(struct llog_catid, lci_padding2) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_catid, lci_padding2));
-        LASSERTF((int)sizeof(((struct llog_catid *)0)->lci_padding2) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_catid *)0)->lci_padding2));
-        LASSERTF((int)offsetof(struct llog_catid, lci_padding3) == 28, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_catid, lci_padding3));
-        LASSERTF((int)sizeof(((struct llog_catid *)0)->lci_padding3) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_catid *)0)->lci_padding3));
-
-        /* Checks for struct llog_rec_hdr */
-        LASSERTF((int)sizeof(struct llog_rec_hdr) == 16, " found %lld\n",
-                 (long long)(int)sizeof(struct llog_rec_hdr));
-        LASSERTF((int)offsetof(struct llog_rec_hdr, lrh_len) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_rec_hdr, lrh_len));
-        LASSERTF((int)sizeof(((struct llog_rec_hdr *)0)->lrh_len) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_rec_hdr *)0)->lrh_len));
-        LASSERTF((int)offsetof(struct llog_rec_hdr, lrh_index) == 4, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_rec_hdr, lrh_index));
-        LASSERTF((int)sizeof(((struct llog_rec_hdr *)0)->lrh_index) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_rec_hdr *)0)->lrh_index));
-        LASSERTF((int)offsetof(struct llog_rec_hdr, lrh_type) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_rec_hdr, lrh_type));
-        LASSERTF((int)sizeof(((struct llog_rec_hdr *)0)->lrh_type) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_rec_hdr *)0)->lrh_type));
-        LASSERTF((int)offsetof(struct llog_rec_hdr, padding) == 12, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_rec_hdr, padding));
-        LASSERTF((int)sizeof(((struct llog_rec_hdr *)0)->padding) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_rec_hdr *)0)->padding));
-
-        /* Checks for struct llog_rec_tail */
-        LASSERTF((int)sizeof(struct llog_rec_tail) == 8, " found %lld\n",
-                 (long long)(int)sizeof(struct llog_rec_tail));
-        LASSERTF((int)offsetof(struct llog_rec_tail, lrt_len) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_rec_tail, lrt_len));
-        LASSERTF((int)sizeof(((struct llog_rec_tail *)0)->lrt_len) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_rec_tail *)0)->lrt_len));
-        LASSERTF((int)offsetof(struct llog_rec_tail, lrt_index) == 4, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_rec_tail, lrt_index));
-        LASSERTF((int)sizeof(((struct llog_rec_tail *)0)->lrt_index) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_rec_tail *)0)->lrt_index));
-
-        /* Checks for struct llog_logid_rec */
-        LASSERTF((int)sizeof(struct llog_logid_rec) == 64, " found %lld\n",
-                 (long long)(int)sizeof(struct llog_logid_rec));
-        LASSERTF((int)offsetof(struct llog_logid_rec, lid_hdr) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_logid_rec, lid_hdr));
-        LASSERTF((int)sizeof(((struct llog_logid_rec *)0)->lid_hdr) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_logid_rec *)0)->lid_hdr));
-        LASSERTF((int)offsetof(struct llog_logid_rec, lid_id) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_logid_rec, lid_id));
-        LASSERTF((int)sizeof(((struct llog_logid_rec *)0)->lid_id) == 20, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_logid_rec *)0)->lid_id));
-        LASSERTF((int)offsetof(struct llog_logid_rec, padding1) == 36, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_logid_rec, padding1));
-        LASSERTF((int)sizeof(((struct llog_logid_rec *)0)->padding1) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_logid_rec *)0)->padding1));
-        LASSERTF((int)offsetof(struct llog_logid_rec, padding2) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_logid_rec, padding2));
-        LASSERTF((int)sizeof(((struct llog_logid_rec *)0)->padding2) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_logid_rec *)0)->padding2));
-        LASSERTF((int)offsetof(struct llog_logid_rec, padding3) == 44, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_logid_rec, padding3));
-        LASSERTF((int)sizeof(((struct llog_logid_rec *)0)->padding3) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_logid_rec *)0)->padding3));
-        LASSERTF((int)offsetof(struct llog_logid_rec, padding4) == 48, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_logid_rec, padding4));
-        LASSERTF((int)sizeof(((struct llog_logid_rec *)0)->padding4) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_logid_rec *)0)->padding4));
-        LASSERTF((int)offsetof(struct llog_logid_rec, padding5) == 52, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_logid_rec, padding5));
-        LASSERTF((int)sizeof(((struct llog_logid_rec *)0)->padding5) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_logid_rec *)0)->padding5));
-        LASSERTF((int)offsetof(struct llog_logid_rec, lid_tail) == 56, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_logid_rec, lid_tail));
-        LASSERTF((int)sizeof(((struct llog_logid_rec *)0)->lid_tail) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_logid_rec *)0)->lid_tail));
-
-        /* Checks for struct llog_create_rec */
-        LASSERTF((int)sizeof(struct llog_create_rec) == 56, " found %lld\n",
-                 (long long)(int)sizeof(struct llog_create_rec));
-        LASSERTF((int)offsetof(struct llog_create_rec, lcr_hdr) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_create_rec, lcr_hdr));
-        LASSERTF((int)sizeof(((struct llog_create_rec *)0)->lcr_hdr) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_create_rec *)0)->lcr_hdr));
-        LASSERTF((int)offsetof(struct llog_create_rec, lcr_fid) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_create_rec, lcr_fid));
-        LASSERTF((int)sizeof(((struct llog_create_rec *)0)->lcr_fid) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_create_rec *)0)->lcr_fid));
-        LASSERTF((int)offsetof(struct llog_create_rec, lcr_oid) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_create_rec, lcr_oid));
-        LASSERTF((int)sizeof(((struct llog_create_rec *)0)->lcr_oid) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_create_rec *)0)->lcr_oid));
-        LASSERTF((int)offsetof(struct llog_create_rec, lcr_ogen) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_create_rec, lcr_ogen));
-        LASSERTF((int)sizeof(((struct llog_create_rec *)0)->lcr_ogen) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_create_rec *)0)->lcr_ogen));
-        LASSERTF((int)offsetof(struct llog_create_rec, padding) == 44, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_create_rec, padding));
-        LASSERTF((int)sizeof(((struct llog_create_rec *)0)->padding) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_create_rec *)0)->padding));
-
-        /* Checks for struct llog_orphan_rec */
-        LASSERTF((int)sizeof(struct llog_orphan_rec) == 40, " found %lld\n",
-                 (long long)(int)sizeof(struct llog_orphan_rec));
-        LASSERTF((int)offsetof(struct llog_orphan_rec, lor_hdr) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_orphan_rec, lor_hdr));
-        LASSERTF((int)sizeof(((struct llog_orphan_rec *)0)->lor_hdr) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_orphan_rec *)0)->lor_hdr));
-        LASSERTF((int)offsetof(struct llog_orphan_rec, lor_oid) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_orphan_rec, lor_oid));
-        LASSERTF((int)sizeof(((struct llog_orphan_rec *)0)->lor_oid) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_orphan_rec *)0)->lor_oid));
-        LASSERTF((int)offsetof(struct llog_orphan_rec, lor_ogen) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_orphan_rec, lor_ogen));
-        LASSERTF((int)sizeof(((struct llog_orphan_rec *)0)->lor_ogen) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_orphan_rec *)0)->lor_ogen));
-        LASSERTF((int)offsetof(struct llog_orphan_rec, padding) == 28, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_orphan_rec, padding));
-        LASSERTF((int)sizeof(((struct llog_orphan_rec *)0)->padding) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_orphan_rec *)0)->padding));
-        LASSERTF((int)offsetof(struct llog_orphan_rec, lor_tail) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_orphan_rec, lor_tail));
-        LASSERTF((int)sizeof(((struct llog_orphan_rec *)0)->lor_tail) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_orphan_rec *)0)->lor_tail));
-
-        /* Checks for struct llog_unlink_rec */
-        LASSERTF((int)sizeof(struct llog_unlink_rec) == 40, " found %lld\n",
-                 (long long)(int)sizeof(struct llog_unlink_rec));
-        LASSERTF((int)offsetof(struct llog_unlink_rec, lur_hdr) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_unlink_rec, lur_hdr));
-        LASSERTF((int)sizeof(((struct llog_unlink_rec *)0)->lur_hdr) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_unlink_rec *)0)->lur_hdr));
-        LASSERTF((int)offsetof(struct llog_unlink_rec, lur_oid) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_unlink_rec, lur_oid));
-        LASSERTF((int)sizeof(((struct llog_unlink_rec *)0)->lur_oid) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_unlink_rec *)0)->lur_oid));
-        LASSERTF((int)offsetof(struct llog_unlink_rec, lur_ogen) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_unlink_rec, lur_ogen));
-        LASSERTF((int)sizeof(((struct llog_unlink_rec *)0)->lur_ogen) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_unlink_rec *)0)->lur_ogen));
-        LASSERTF((int)offsetof(struct llog_unlink_rec, padding) == 28, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_unlink_rec, padding));
-        LASSERTF((int)sizeof(((struct llog_unlink_rec *)0)->padding) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_unlink_rec *)0)->padding));
-        LASSERTF((int)offsetof(struct llog_unlink_rec, lur_tail) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_unlink_rec, lur_tail));
-        LASSERTF((int)sizeof(((struct llog_unlink_rec *)0)->lur_tail) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_unlink_rec *)0)->lur_tail));
-
-        /* Checks for struct llog_setattr_rec */
-        LASSERTF((int)sizeof(struct llog_setattr_rec) == 48, " found %lld\n",
-                 (long long)(int)sizeof(struct llog_setattr_rec));
-        LASSERTF((int)offsetof(struct llog_setattr_rec, lsr_hdr) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_setattr_rec, lsr_hdr));
-        LASSERTF((int)sizeof(((struct llog_setattr_rec *)0)->lsr_hdr) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_setattr_rec *)0)->lsr_hdr));
-        LASSERTF((int)offsetof(struct llog_setattr_rec, lsr_oid) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_setattr_rec, lsr_oid));
-        LASSERTF((int)sizeof(((struct llog_setattr_rec *)0)->lsr_oid) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_setattr_rec *)0)->lsr_oid));
-        LASSERTF((int)offsetof(struct llog_setattr_rec, lsr_ogen) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_setattr_rec, lsr_ogen));
-        LASSERTF((int)sizeof(((struct llog_setattr_rec *)0)->lsr_ogen) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_setattr_rec *)0)->lsr_ogen));
-        LASSERTF((int)offsetof(struct llog_setattr_rec, lsr_uid) == 28, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_setattr_rec, lsr_uid));
-        LASSERTF((int)sizeof(((struct llog_setattr_rec *)0)->lsr_uid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_setattr_rec *)0)->lsr_uid));
-        LASSERTF((int)offsetof(struct llog_setattr_rec, lsr_gid) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_setattr_rec, lsr_gid));
-        LASSERTF((int)sizeof(((struct llog_setattr_rec *)0)->lsr_gid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_setattr_rec *)0)->lsr_gid));
-        LASSERTF((int)offsetof(struct llog_setattr_rec, padding) == 36, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_setattr_rec, padding));
-        LASSERTF((int)sizeof(((struct llog_setattr_rec *)0)->padding) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_setattr_rec *)0)->padding));
-        LASSERTF((int)offsetof(struct llog_setattr_rec, lsr_tail) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_setattr_rec, lsr_tail));
-        LASSERTF((int)sizeof(((struct llog_setattr_rec *)0)->lsr_tail) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_setattr_rec *)0)->lsr_tail));
-
-        /* Checks for struct llog_size_change_rec */
-        LASSERTF((int)sizeof(struct llog_size_change_rec) == 48, " found %lld\n",
-                 (long long)(int)sizeof(struct llog_size_change_rec));
-        LASSERTF((int)offsetof(struct llog_size_change_rec, lsc_hdr) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_size_change_rec, lsc_hdr));
-        LASSERTF((int)sizeof(((struct llog_size_change_rec *)0)->lsc_hdr) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_size_change_rec *)0)->lsc_hdr));
-        LASSERTF((int)offsetof(struct llog_size_change_rec, lsc_fid) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_size_change_rec, lsc_fid));
-        LASSERTF((int)sizeof(((struct llog_size_change_rec *)0)->lsc_fid) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_size_change_rec *)0)->lsc_fid));
-        LASSERTF((int)offsetof(struct llog_size_change_rec, lsc_io_epoch) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_size_change_rec, lsc_io_epoch));
-        LASSERTF((int)sizeof(((struct llog_size_change_rec *)0)->lsc_io_epoch) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_size_change_rec *)0)->lsc_io_epoch));
-        LASSERTF((int)offsetof(struct llog_size_change_rec, padding) == 36, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_size_change_rec, padding));
-        LASSERTF((int)sizeof(((struct llog_size_change_rec *)0)->padding) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_size_change_rec *)0)->padding));
-        LASSERTF((int)offsetof(struct llog_size_change_rec, lsc_tail) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_size_change_rec, lsc_tail));
-        LASSERTF((int)sizeof(((struct llog_size_change_rec *)0)->lsc_tail) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_size_change_rec *)0)->lsc_tail));
-
-        /* Checks for struct llog_gen */
-        LASSERTF((int)sizeof(struct llog_gen) == 16, " found %lld\n",
-                 (long long)(int)sizeof(struct llog_gen));
-        LASSERTF((int)offsetof(struct llog_gen, mnt_cnt) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_gen, mnt_cnt));
-        LASSERTF((int)sizeof(((struct llog_gen *)0)->mnt_cnt) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_gen *)0)->mnt_cnt));
-        LASSERTF((int)offsetof(struct llog_gen, conn_cnt) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_gen, conn_cnt));
-        LASSERTF((int)sizeof(((struct llog_gen *)0)->conn_cnt) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_gen *)0)->conn_cnt));
-
-        /* Checks for struct llog_gen_rec */
-        LASSERTF((int)sizeof(struct llog_gen_rec) == 40, " found %lld\n",
-                 (long long)(int)sizeof(struct llog_gen_rec));
-        LASSERTF((int)offsetof(struct llog_gen_rec, lgr_hdr) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_gen_rec, lgr_hdr));
-        LASSERTF((int)sizeof(((struct llog_gen_rec *)0)->lgr_hdr) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_gen_rec *)0)->lgr_hdr));
-        LASSERTF((int)offsetof(struct llog_gen_rec, lgr_gen) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_gen_rec, lgr_gen));
-        LASSERTF((int)sizeof(((struct llog_gen_rec *)0)->lgr_gen) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_gen_rec *)0)->lgr_gen));
-        LASSERTF((int)offsetof(struct llog_gen_rec, lgr_tail) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_gen_rec, lgr_tail));
-        LASSERTF((int)sizeof(((struct llog_gen_rec *)0)->lgr_tail) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_gen_rec *)0)->lgr_tail));
-
-        /* Checks for struct llog_log_hdr */
-        LASSERTF((int)sizeof(struct llog_log_hdr) == 8192, " found %lld\n",
-                 (long long)(int)sizeof(struct llog_log_hdr));
-        LASSERTF((int)offsetof(struct llog_log_hdr, llh_hdr) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_log_hdr, llh_hdr));
-        LASSERTF((int)sizeof(((struct llog_log_hdr *)0)->llh_hdr) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_log_hdr *)0)->llh_hdr));
-        LASSERTF((int)offsetof(struct llog_log_hdr, llh_timestamp) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_log_hdr, llh_timestamp));
-        LASSERTF((int)sizeof(((struct llog_log_hdr *)0)->llh_timestamp) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_log_hdr *)0)->llh_timestamp));
-        LASSERTF((int)offsetof(struct llog_log_hdr, llh_count) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_log_hdr, llh_count));
-        LASSERTF((int)sizeof(((struct llog_log_hdr *)0)->llh_count) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_log_hdr *)0)->llh_count));
-        LASSERTF((int)offsetof(struct llog_log_hdr, llh_bitmap_offset) == 28, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_log_hdr, llh_bitmap_offset));
-        LASSERTF((int)sizeof(((struct llog_log_hdr *)0)->llh_bitmap_offset) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_log_hdr *)0)->llh_bitmap_offset));
-        LASSERTF((int)offsetof(struct llog_log_hdr, llh_size) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_log_hdr, llh_size));
-        LASSERTF((int)sizeof(((struct llog_log_hdr *)0)->llh_size) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_log_hdr *)0)->llh_size));
-        LASSERTF((int)offsetof(struct llog_log_hdr, llh_flags) == 36, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_log_hdr, llh_flags));
-        LASSERTF((int)sizeof(((struct llog_log_hdr *)0)->llh_flags) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_log_hdr *)0)->llh_flags));
-        LASSERTF((int)offsetof(struct llog_log_hdr, llh_cat_idx) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_log_hdr, llh_cat_idx));
-        LASSERTF((int)sizeof(((struct llog_log_hdr *)0)->llh_cat_idx) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_log_hdr *)0)->llh_cat_idx));
-        LASSERTF((int)offsetof(struct llog_log_hdr, llh_tgtuuid) == 44, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_log_hdr, llh_tgtuuid));
-        LASSERTF((int)sizeof(((struct llog_log_hdr *)0)->llh_tgtuuid) == 40, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_log_hdr *)0)->llh_tgtuuid));
-        LASSERTF((int)offsetof(struct llog_log_hdr, llh_reserved) == 84, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_log_hdr, llh_reserved));
-        LASSERTF((int)sizeof(((struct llog_log_hdr *)0)->llh_reserved) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_log_hdr *)0)->llh_reserved));
-        LASSERTF((int)offsetof(struct llog_log_hdr, llh_bitmap) == 88, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_log_hdr, llh_bitmap));
-        LASSERTF((int)sizeof(((struct llog_log_hdr *)0)->llh_bitmap) == 8096, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_log_hdr *)0)->llh_bitmap));
-        LASSERTF((int)offsetof(struct llog_log_hdr, llh_tail) == 8184, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_log_hdr, llh_tail));
-        LASSERTF((int)sizeof(((struct llog_log_hdr *)0)->llh_tail) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_log_hdr *)0)->llh_tail));
-
-        /* Checks for struct llog_cookie */
-        LASSERTF((int)sizeof(struct llog_cookie) == 32, " found %lld\n",
-                 (long long)(int)sizeof(struct llog_cookie));
-        LASSERTF((int)offsetof(struct llog_cookie, lgc_lgl) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_cookie, lgc_lgl));
-        LASSERTF((int)sizeof(((struct llog_cookie *)0)->lgc_lgl) == 20, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_cookie *)0)->lgc_lgl));
-        LASSERTF((int)offsetof(struct llog_cookie, lgc_subsys) == 20, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_cookie, lgc_subsys));
-        LASSERTF((int)sizeof(((struct llog_cookie *)0)->lgc_subsys) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_cookie *)0)->lgc_subsys));
-        LASSERTF((int)offsetof(struct llog_cookie, lgc_index) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_cookie, lgc_index));
-        LASSERTF((int)sizeof(((struct llog_cookie *)0)->lgc_index) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_cookie *)0)->lgc_index));
-        LASSERTF((int)offsetof(struct llog_cookie, lgc_padding) == 28, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_cookie, lgc_padding));
-        LASSERTF((int)sizeof(((struct llog_cookie *)0)->lgc_padding) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_cookie *)0)->lgc_padding));
-
-        /* Checks for struct llogd_body */
-        LASSERTF((int)sizeof(struct llogd_body) == 48, " found %lld\n",
-                 (long long)(int)sizeof(struct llogd_body));
-        LASSERTF((int)offsetof(struct llogd_body, lgd_logid) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llogd_body, lgd_logid));
-        LASSERTF((int)sizeof(((struct llogd_body *)0)->lgd_logid) == 20, " found %lld\n",
-                 (long long)(int)sizeof(((struct llogd_body *)0)->lgd_logid));
-        LASSERTF((int)offsetof(struct llogd_body, lgd_ctxt_idx) == 20, " found %lld\n",
-                 (long long)(int)offsetof(struct llogd_body, lgd_ctxt_idx));
-        LASSERTF((int)sizeof(((struct llogd_body *)0)->lgd_ctxt_idx) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llogd_body *)0)->lgd_ctxt_idx));
-        LASSERTF((int)offsetof(struct llogd_body, lgd_llh_flags) == 24, " found %lld\n",
-                 (long long)(int)offsetof(struct llogd_body, lgd_llh_flags));
-        LASSERTF((int)sizeof(((struct llogd_body *)0)->lgd_llh_flags) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llogd_body *)0)->lgd_llh_flags));
-        LASSERTF((int)offsetof(struct llogd_body, lgd_index) == 28, " found %lld\n",
-                 (long long)(int)offsetof(struct llogd_body, lgd_index));
-        LASSERTF((int)sizeof(((struct llogd_body *)0)->lgd_index) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llogd_body *)0)->lgd_index));
-        LASSERTF((int)offsetof(struct llogd_body, lgd_saved_index) == 32, " found %lld\n",
-                 (long long)(int)offsetof(struct llogd_body, lgd_saved_index));
-        LASSERTF((int)sizeof(((struct llogd_body *)0)->lgd_saved_index) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llogd_body *)0)->lgd_saved_index));
-        LASSERTF((int)offsetof(struct llogd_body, lgd_len) == 36, " found %lld\n",
-                 (long long)(int)offsetof(struct llogd_body, lgd_len));
-        LASSERTF((int)sizeof(((struct llogd_body *)0)->lgd_len) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llogd_body *)0)->lgd_len));
-        LASSERTF((int)offsetof(struct llogd_body, lgd_cur_offset) == 40, " found %lld\n",
-                 (long long)(int)offsetof(struct llogd_body, lgd_cur_offset));
-        LASSERTF((int)sizeof(((struct llogd_body *)0)->lgd_cur_offset) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llogd_body *)0)->lgd_cur_offset));
-        CLASSERT(LLOG_ORIGIN_HANDLE_CREATE == 501);
-        CLASSERT(LLOG_ORIGIN_HANDLE_NEXT_BLOCK == 502);
-        CLASSERT(LLOG_ORIGIN_HANDLE_READ_HEADER == 503);
-        CLASSERT(LLOG_ORIGIN_HANDLE_WRITE_REC == 504);
-        CLASSERT(LLOG_ORIGIN_HANDLE_CLOSE == 505);
-        CLASSERT(LLOG_ORIGIN_CONNECT == 506);
-        CLASSERT(LLOG_CATINFO == 507);
-        CLASSERT(LLOG_ORIGIN_HANDLE_PREV_BLOCK == 508);
-        CLASSERT(LLOG_ORIGIN_HANDLE_DESTROY == 509);
-
-        /* Checks for struct llogd_conn_body */
-        LASSERTF((int)sizeof(struct llogd_conn_body) == 40, " found %lld\n",
-                 (long long)(int)sizeof(struct llogd_conn_body));
-        LASSERTF((int)offsetof(struct llogd_conn_body, lgdc_gen) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llogd_conn_body, lgdc_gen));
-        LASSERTF((int)sizeof(((struct llogd_conn_body *)0)->lgdc_gen) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct llogd_conn_body *)0)->lgdc_gen));
-        LASSERTF((int)offsetof(struct llogd_conn_body, lgdc_logid) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct llogd_conn_body, lgdc_logid));
-        LASSERTF((int)sizeof(((struct llogd_conn_body *)0)->lgdc_logid) == 20, " found %lld\n",
-                 (long long)(int)sizeof(((struct llogd_conn_body *)0)->lgdc_logid));
-        LASSERTF((int)offsetof(struct llogd_conn_body, lgdc_ctxt_idx) == 36, " found %lld\n",
-                 (long long)(int)offsetof(struct llogd_conn_body, lgdc_ctxt_idx));
-        LASSERTF((int)sizeof(((struct llogd_conn_body *)0)->lgdc_ctxt_idx) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct llogd_conn_body *)0)->lgdc_ctxt_idx));
-
-        /* Checks for struct llog_array_rec */
-        LASSERTF((int)sizeof(struct llog_array_rec) == 72, " found %lld\n",
-                 (long long)(int)sizeof(struct llog_array_rec));
-        LASSERTF((int)offsetof(struct llog_array_rec, lmr_hdr) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_array_rec, lmr_hdr));
-        LASSERTF((int)sizeof(((struct llog_array_rec *)0)->lmr_hdr) == 16, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_array_rec *)0)->lmr_hdr));
-        LASSERTF((int)offsetof(struct llog_array_rec, lmr_med) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_array_rec, lmr_med));
-        LASSERTF((int)sizeof(((struct llog_array_rec *)0)->lmr_med) == 48, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_array_rec *)0)->lmr_med));
-        LASSERTF((int)offsetof(struct llog_array_rec, lmr_tail) == 64, " found %lld\n",
-                 (long long)(int)offsetof(struct llog_array_rec, lmr_tail));
-        LASSERTF((int)sizeof(((struct llog_array_rec *)0)->lmr_tail) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct llog_array_rec *)0)->lmr_tail));
-
-        /* Checks for struct mds_extent_desc */
-        LASSERTF((int)sizeof(struct mds_extent_desc) == 48, " found %lld\n",
-                 (long long)(int)sizeof(struct mds_extent_desc));
-        LASSERTF((int)offsetof(struct mds_extent_desc, med_start) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_extent_desc, med_start));
-        LASSERTF((int)sizeof(((struct mds_extent_desc *)0)->med_start) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_extent_desc *)0)->med_start));
-        LASSERTF((int)offsetof(struct mds_extent_desc, med_len) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_extent_desc, med_len));
-        LASSERTF((int)sizeof(((struct mds_extent_desc *)0)->med_len) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_extent_desc *)0)->med_len));
-        LASSERTF((int)offsetof(struct mds_extent_desc, med_lmm) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct mds_extent_desc, med_lmm));
-        LASSERTF((int)sizeof(((struct mds_extent_desc *)0)->med_lmm) == 32, " found %lld\n",
-                 (long long)(int)sizeof(((struct mds_extent_desc *)0)->med_lmm));
-
-        /* Checks for struct qunit_data */
-        LASSERTF((int)sizeof(struct qunit_data) == 16, " found %lld\n",
-                 (long long)(int)sizeof(struct qunit_data));
-        LASSERTF((int)offsetof(struct qunit_data, qd_id) == 0, " found %lld\n",
-                 (long long)(int)offsetof(struct qunit_data, qd_id));
-        LASSERTF((int)sizeof(((struct qunit_data *)0)->qd_id) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct qunit_data *)0)->qd_id));
-        LASSERTF((int)offsetof(struct qunit_data, qd_type) == 4, " found %lld\n",
-                 (long long)(int)offsetof(struct qunit_data, qd_type));
-        LASSERTF((int)sizeof(((struct qunit_data *)0)->qd_type) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct qunit_data *)0)->qd_type));
-        LASSERTF((int)offsetof(struct qunit_data, qd_count) == 8, " found %lld\n",
-                 (long long)(int)offsetof(struct qunit_data, qd_count));
-        LASSERTF((int)sizeof(((struct qunit_data *)0)->qd_count) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct qunit_data *)0)->qd_count));
-        LASSERTF((int)offsetof(struct qunit_data, qd_isblk) == 12, " found %lld\n",
-                 (long long)(int)offsetof(struct qunit_data, qd_isblk));
-        LASSERTF((int)sizeof(((struct qunit_data *)0)->qd_isblk) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct qunit_data *)0)->qd_isblk));
 }