diff options
Diffstat (limited to 'sys-cluster/lustre')
25 files changed, 3788 insertions, 12325 deletions
diff --git a/sys-cluster/lustre/ChangeLog b/sys-cluster/lustre/ChangeLog index ea473e4f6..e5fdda46f 100644 --- a/sys-cluster/lustre/ChangeLog +++ b/sys-cluster/lustre/ChangeLog @@ -2,6 +2,40 @@ # Copyright 1999-2014 Gentoo Foundation; Distributed under the GPL v2 # $Header: $ + 04 Feb 2014; Alexey Shvetsov <alexxy@gentoo.org> + +files/0002-LU-3319-lprocfs-client-side-cleanups.patch, + +files/0003-LU-3319-procfs-fix-symlink-handling.patch, + +files/0004-LU-3319-procfs-move-mgs-proc-handling-to-seq_files.patch, + +files/0005-LU-3319-procfs-update-zfs-proc-handling-to-seq_files.patch, + +files/0006-LU-3319-procfs-move-osp-proc-handling-to-seq_files.patch, + +files/0007-LU-3319-procfs-move-lod-proc-handling-to-seq_files.patch, + +files/0008-LU-3319-procfs-move-mdt-mds-proc-handling-to-seq_fil.patch, + +files/0009-LU-3319-procfs-move-mdd-ofd-proc-handling-to-seq_fil.patch, + +files/0010-LU-3319-procfs-update-ldiskfs-proc-handling-to-seq_f.patch, + +files/0011-LU-3373-osd-ldiskfs-readdir-replace-by-iterate.patch, + +files/0012-LU-3974-llite-use-new-struct-dir_context.patch, + +files/0013-LU-3974-llite-invalidatepage-api-changed.patch, + -files/0002-LU-3373-ldiskfs-ldiskfs-patches-for-3.11.1-fc19.patch, + -files/0003-LU-3974-llite-dentry-d_compare-changes-in-3.11.patch, + -files/0004-LU-3974-llite-use-new-struct-dir_context.patch, + -files/0005-LU-3974-llite-invalidatepage-api-changed.patch, + -files/0006-LU-3319-procfs-move-llite-proc-handling-over-to-seq_.patch, + -files/0007-LU-3319-procfs-move-lmv-proc-handling-over-to-seq_fi.patch, + -files/0008-LU-3319-procfs-move-ldlm-proc-handling-over-to-seq_f.patch, + -files/0009-LU-3319-procfs-move-ost-proc-handling-over-to-seq_fi.patch, + -files/0010-LU-3319-procfs-update-shared-server-side-core-proc-h.patch, + -files/0011-LU-3319-procfs-update-zfs-proc-handling-to-seq_files.patch, + -files/0012-LU-3319-procfs-move-mgs-proc-handling-to-seq_files.patch, + -files/0013-LU-3319-procfs-move-ofd-proc-handling-to-seq_files.patch, + -files/0014-LU-3319-procfs-move-lod-proc-handling-to-seq_files.patch, + -files/0015-LU-3319-procfs-move-osp-proc-handling-to-seq_files.patch, + -files/0016-LU-3319-procfs-move-mdt-mds-proc-handling-to-seq_fil.patch, + -files/0017-LU-3319-procfs-move-mdd-proc-handling-to-seq_files.patch, + -files/0018-LU-3319-procfs-update-ldiskfs-proc-handling-to-seq_f.patch, + files/0001-LU-2982-build-make-AC-check-for-linux-arch-sandbox-f.patch, + lustre-9999.ebuild: + Make lustre build with 3.11 kernel + 06 Jan 2014; Justin Lecher <jlec@gentoo.org> lustre-9999.ebuild: Switch from git-2 to git-r3 diff --git a/sys-cluster/lustre/files/0001-LU-2982-build-make-AC-check-for-linux-arch-sandbox-f.patch b/sys-cluster/lustre/files/0001-LU-2982-build-make-AC-check-for-linux-arch-sandbox-f.patch index e4897334b..eaec9aa7b 100644 --- a/sys-cluster/lustre/files/0001-LU-2982-build-make-AC-check-for-linux-arch-sandbox-f.patch +++ b/sys-cluster/lustre/files/0001-LU-2982-build-make-AC-check-for-linux-arch-sandbox-f.patch @@ -1,7 +1,7 @@ -From a607b37a64f797b766825ccb6f41176685cd843f Mon Sep 17 00:00:00 2001 +From 03643a33bd4d6a6fc3f8412f3e5f7f9a4bbd445b Mon Sep 17 00:00:00 2001 From: Alexey Shvetsov <alexxy@gentoo.org> Date: Mon, 18 Mar 2013 16:22:27 +0400 -Subject: [PATCH 01/18] LU-2982 build: make AC check for linux arch sandbox +Subject: [PATCH 01/13] LU-2982 build: make AC check for linux arch sandbox friendly this commit makes AC check for linux kernel arch sandbox friendly @@ -14,7 +14,7 @@ Signed-off-by: Alexey Shvetsov <alexxy@gentoo.org> 1 file changed, 58 insertions(+), 8 deletions(-) diff --git a/config/lustre-build-linux.m4 b/config/lustre-build-linux.m4 -index b1ec10e..4a835ea 100644 +index 894101c..8062ace 100644 --- a/config/lustre-build-linux.m4 +++ b/config/lustre-build-linux.m4 @@ -394,14 +394,64 @@ rm -f build/conftest.o build/conftest.mod.c build/conftest.mod.o build/conftest. @@ -91,5 +91,5 @@ index b1ec10e..4a835ea 100644 # # LB_LINUX_TRY_COMPILE -- -1.8.5.1 +1.8.5.3 diff --git a/sys-cluster/lustre/files/0002-LU-3319-lprocfs-client-side-cleanups.patch b/sys-cluster/lustre/files/0002-LU-3319-lprocfs-client-side-cleanups.patch new file mode 100644 index 000000000..5dd4981ab --- /dev/null +++ b/sys-cluster/lustre/files/0002-LU-3319-lprocfs-client-side-cleanups.patch @@ -0,0 +1,463 @@ +From cc1b44ff52af1f78705c18169e951b2b626906b4 Mon Sep 17 00:00:00 2001 +From: James Simmons <uja.ornl@gmail.com> +Date: Tue, 21 Jan 2014 12:06:59 -0500 +Subject: [PATCH 02/13] LU-3319 lprocfs: client side cleanups + +Now that all the client side seq_file patches it is +time to handle the issue that people pointed out but +were not severe enough to prevent landing. This patch +addresses all the concerns as well and move all struct +lprocfs_seq_var to be initialized C99 style. + +Change-Id: I89e8b719bd067ecf4e3cab481a2d4c62d5052af0 +Signed-off-by: James Simmons <uja.ornl@gmail.com> +--- + lustre/fid/lproc_fid.c | 21 ++++++--- + lustre/lmv/lproc_lmv.c | 15 ++++--- + lustre/lov/lproc_lov.c | 42 ++++++++++++------ + lustre/mdc/lproc_mdc.c | 52 ++++++++++++++-------- + lustre/mgc/lproc_mgc.c | 25 +++++++---- + lustre/obdclass/lprocfs_status.c | 1 - + lustre/obdecho/echo.c | 3 +- + lustre/osc/lproc_osc.c | 94 +++++++++++++++++++++++++++------------- + lustre/osc/osc_request.c | 2 +- + lustre/ost/ost_handler.c | 3 +- + lustre/ptlrpc/lproc_ptlrpc.c | 2 +- + lustre/quota/qmt_pool.c | 3 +- + lustre/quota/qsd_lib.c | 12 +++-- + 13 files changed, 183 insertions(+), 92 deletions(-) + +diff --git a/lustre/fid/lproc_fid.c b/lustre/fid/lproc_fid.c +index d89c4f6..3b9d170 100644 +--- a/lustre/fid/lproc_fid.c ++++ b/lustre/fid/lproc_fid.c +@@ -203,9 +203,12 @@ LPROC_SEQ_FOPS(lprocfs_server_fid_width); + LPROC_SEQ_FOPS_RO(lprocfs_server_fid_server); + + struct lprocfs_seq_vars seq_server_proc_list[] = { +- { "space", &lprocfs_server_fid_space_fops }, +- { "width", &lprocfs_server_fid_width_fops }, +- { "server", &lprocfs_server_fid_server_fops }, ++ { .name = "space", ++ .fops = &lprocfs_server_fid_space_fops }, ++ { .name = "width", ++ .fops = &lprocfs_server_fid_width_fops }, ++ { .name = "server", ++ .fops = &lprocfs_server_fid_server_fops }, + { NULL } + }; + +@@ -623,10 +626,14 @@ LPROC_SEQ_FOPS_RO(lprocfs_client_fid_server); + LPROC_SEQ_FOPS_RO(lprocfs_client_fid_fid); + + struct lprocfs_seq_vars seq_client_proc_list[] = { +- { "space", &lprocfs_client_fid_space_fops }, +- { "width", &lprocfs_client_fid_width_fops }, +- { "server", &lprocfs_client_fid_server_fops }, +- { "fid", &lprocfs_client_fid_fid_fops }, ++ { .name = "space", ++ .fops = &lprocfs_client_fid_space_fops }, ++ { .name = "width", ++ .fops = &lprocfs_client_fid_width_fops }, ++ { .name = "server", ++ .fops = &lprocfs_client_fid_server_fops }, ++ { .name = "fid", ++ .fops = &lprocfs_client_fid_fid_fops }, + { NULL } + }; + #endif +diff --git a/lustre/lmv/lproc_lmv.c b/lustre/lmv/lproc_lmv.c +index eea5927..5a7271a 100644 +--- a/lustre/lmv/lproc_lmv.c ++++ b/lustre/lmv/lproc_lmv.c +@@ -203,11 +203,16 @@ static int lmv_target_seq_open(struct inode *inode, struct file *file) + LPROC_SEQ_FOPS_RO_TYPE(lmv, uuid); + + struct lprocfs_seq_vars lprocfs_lmv_obd_vars[] = { +- { "numobd", &lmv_numobd_fops }, +- { "placement", &lmv_placement_fops }, +- { "activeobd", &lmv_activeobd_fops }, +- { "uuid", &lmv_uuid_fops }, +- { "desc_uuid", &lmv_desc_uuid_fops }, ++ { .name = "numobd", ++ .fops = &lmv_numobd_fops }, ++ { .name = "placement", ++ .fops = &lmv_placement_fops }, ++ { .name = "activeobd", ++ .fops = &lmv_activeobd_fops }, ++ { .name = "uuid", ++ .fops = &lmv_uuid_fops }, ++ { .name = "desc_uuid", ++ .fops = &lmv_desc_uuid_fops }, + { 0 } + }; + +diff --git a/lustre/lov/lproc_lov.c b/lustre/lov/lproc_lov.c +index e400faf..7786513 100644 +--- a/lustre/lov/lproc_lov.c ++++ b/lustre/lov/lproc_lov.c +@@ -263,20 +263,34 @@ LPROC_SEQ_FOPS_RO_TYPE(lov, kbytesfree); + LPROC_SEQ_FOPS_RO_TYPE(lov, kbytesavail); + + struct lprocfs_seq_vars lprocfs_lov_obd_vars[] = { +- { "uuid", &lov_uuid_fops }, +- { "stripesize", &lov_stripesize_fops }, +- { "stripeoffset", &lov_stripeoffset_fops }, +- { "stripecount", &lov_stripecount_fops }, +- { "stripetype", &lov_stripetype_fops }, +- { "numobd", &lov_numobd_fops }, +- { "activeobd", &lov_activeobd_fops }, +- { "filestotal", &lov_filestotal_fops }, +- { "filesfree", &lov_filesfree_fops }, +- { "blocksize", &lov_blksize_fops }, +- { "kbytestotal", &lov_kbytestotal_fops }, +- { "kbytesfree", &lov_kbytesfree_fops }, +- { "kbytesavail", &lov_kbytesavail_fops }, +- { "desc_uuid", &lov_desc_uuid_fops }, ++ { .name = "uuid", ++ .fops = &lov_uuid_fops }, ++ { .name = "stripesize", ++ .fops = &lov_stripesize_fops }, ++ { .name = "stripeoffset", ++ .fops = &lov_stripeoffset_fops }, ++ { .name = "stripecount", ++ .fops = &lov_stripecount_fops }, ++ { .name = "stripetype", ++ .fops = &lov_stripetype_fops }, ++ { .name = "numobd", ++ .fops = &lov_numobd_fops }, ++ { .name = "activeobd", ++ .fops = &lov_activeobd_fops }, ++ { .name = "filestotal", ++ .fops = &lov_filestotal_fops }, ++ { .name = "filesfree", ++ .fops = &lov_filesfree_fops }, ++ { .name = "blocksize", ++ .fops = &lov_blksize_fops }, ++ { .name = "kbytestotal", ++ .fops = &lov_kbytestotal_fops }, ++ { .name = "kbytesfree", ++ .fops = &lov_kbytesfree_fops }, ++ { .name = "kbytesavail", ++ .fops = &lov_kbytesavail_fops }, ++ { .name = "desc_uuid", ++ .fops = &lov_desc_uuid_fops }, + { 0 } + }; + +diff --git a/lustre/mdc/lproc_mdc.c b/lustre/mdc/lproc_mdc.c +index cba4f61..69e377f 100644 +--- a/lustre/mdc/lproc_mdc.c ++++ b/lustre/mdc/lproc_mdc.c +@@ -103,29 +103,47 @@ LPROC_SEQ_FOPS_RW_TYPE(mdc, import); + LPROC_SEQ_FOPS_RW_TYPE(mdc, pinger_recov); + + struct lprocfs_seq_vars lprocfs_mdc_obd_vars[] = { +- { "uuid", &mdc_uuid_fops, 0, 0 }, +- { "ping", &mdc_ping_fops, 0, 0222 }, +- { "connect_flags", &mdc_connect_flags_fops,0, 0 }, +- { "blocksize", &mdc_blksize_fops, 0, 0 }, +- { "kbytestotal", &mdc_kbytestotal_fops, 0, 0 }, +- { "kbytesfree", &mdc_kbytesfree_fops, 0, 0 }, +- { "kbytesavail", &mdc_kbytesavail_fops, 0, 0 }, +- { "filestotal", &mdc_filestotal_fops, 0, 0 }, +- { "filesfree", &mdc_filesfree_fops, 0, 0 }, +- { "mds_server_uuid", &mdc_server_uuid_fops, 0, 0 }, +- { "mds_conn_uuid", &mdc_conn_uuid_fops, 0, 0 }, ++ { .name = "uuid", ++ .fops = &mdc_uuid_fops }, ++ { .name = "ping", ++ .fops = &mdc_ping_fops, ++ .proc_mode = 0222 }, ++ { .name = "connect_flags", ++ .fops = &mdc_connect_flags_fops }, ++ { .name = "blocksize", ++ .fops = &mdc_blksize_fops }, ++ { .name = "kbytestotal", ++ .fops = &mdc_kbytestotal_fops }, ++ { .name = "kbytesfree", ++ .fops = &mdc_kbytesfree_fops }, ++ { .name = "kbytesavail", ++ .fops = &mdc_kbytesavail_fops }, ++ { .name = "filestotal", ++ .fops = &mdc_filestotal_fops }, ++ { .name = "filesfree", ++ .fops = &mdc_filesfree_fops }, ++ { .name = "mds_server_uuid", ++ .fops = &mdc_server_uuid_fops }, ++ { .name = "mds_conn_uuid", ++ .fops = &mdc_conn_uuid_fops }, + /* + * FIXME: below proc entry is provided, but not in used, instead + * sbi->sb_md_brw_size is used, the per obd variable should be used + * when CMD is enabled, and dir pages are managed in MDC layer. + * Remember to enable proc write function. + */ +- { "max_pages_per_rpc", &mdc_obd_max_pages_per_rpc_fops }, +- { "max_rpcs_in_flight", &mdc_max_rpcs_in_flight_fops }, +- { "timeouts", &mdc_timeouts_fops }, +- { "import", &mdc_import_fops }, +- { "state", &mdc_state_fops }, +- { "pinger_recov", &mdc_pinger_recov_fops }, ++ { .name = "max_pages_per_rpc", ++ .fops = &mdc_obd_max_pages_per_rpc_fops }, ++ { .name = "max_rpcs_in_flight", ++ .fops = &mdc_max_rpcs_in_flight_fops }, ++ { .name = "timeouts", ++ .fops = &mdc_timeouts_fops }, ++ { .name = "import", ++ .fops = &mdc_import_fops }, ++ { .name = "state", ++ .fops = &mdc_state_fops }, ++ { .name = "pinger_recov", ++ .fops = &mdc_pinger_recov_fops }, + { 0 } + }; + #endif /* LPROCFS */ +diff --git a/lustre/mgc/lproc_mgc.c b/lustre/mgc/lproc_mgc.c +index 648b6e5..f818def 100644 +--- a/lustre/mgc/lproc_mgc.c ++++ b/lustre/mgc/lproc_mgc.c +@@ -59,14 +59,23 @@ static int mgc_ir_state_seq_show(struct seq_file *m, void *v) + LPROC_SEQ_FOPS_RO(mgc_ir_state); + + struct lprocfs_seq_vars lprocfs_mgc_obd_vars[] = { +- { "uuid", &mgc_uuid_fops, 0, 0 }, +- { "ping", &mgc_ping_fops, 0, 0222 }, +- { "connect_flags", &mgc_connect_flags_fops,0, 0 }, +- { "mgs_server_uuid", &mgc_server_uuid_fops, 0, 0 }, +- { "mgs_conn_uuid", &mgc_conn_uuid_fops, 0, 0 }, +- { "import", &mgc_import_fops, 0, 0 }, +- { "state", &mgc_state_fops, 0, 0 }, +- { "ir_state", &mgc_ir_state_fops, 0, 0 }, ++ { .name = "uuid", ++ .fops = &mgc_uuid_fops }, ++ { .name = "ping", ++ .fops = &mgc_ping_fops, ++ .proc_mode = 0222 }, ++ { .name = "connect_flags", ++ .fops = &mgc_connect_flags_fops }, ++ { .name = "mgs_server_uuid", ++ .fops = &mgc_server_uuid_fops }, ++ { .name = "mgs_conn_uuid", ++ .fops = &mgc_conn_uuid_fops }, ++ { .name = "import", ++ .fops = &mgc_import_fops }, ++ { .name = "state", ++ .fops = &mgc_state_fops }, ++ { .name = "ir_state", ++ .fops = &mgc_ir_state_fops }, + { 0 } + }; + #endif /* LPROCFS */ +diff --git a/lustre/obdclass/lprocfs_status.c b/lustre/obdclass/lprocfs_status.c +index 7cd7870..63d01cc 100644 +--- a/lustre/obdclass/lprocfs_status.c ++++ b/lustre/obdclass/lprocfs_status.c +@@ -2582,7 +2582,6 @@ void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats) + EXPORT_SYMBOL(lprocfs_init_ldlm_stats); + + #ifdef HAVE_SERVER_SUPPORT +-/* No one appears to be using this ?? */ + int lprocfs_exp_nid_seq_show(struct seq_file *m, void *data) + { + struct obd_export *exp = m->private; +diff --git a/lustre/obdecho/echo.c b/lustre/obdecho/echo.c +index 6d63aff..8563e68 100644 +--- a/lustre/obdecho/echo.c ++++ b/lustre/obdecho/echo.c +@@ -561,7 +561,8 @@ commitrw_cleanup: + + LPROC_SEQ_FOPS_RO_TYPE(echo, uuid); + static struct lprocfs_seq_vars lprocfs_echo_obd_vars[] = { +- { "uuid", &echo_uuid_fops }, ++ { .name = "uuid", ++ .fops = &echo_uuid_fops }, + { 0 } + }; + +diff --git a/lustre/osc/lproc_osc.c b/lustre/osc/lproc_osc.c +index d6e3703..ccfc212 100644 +--- a/lustre/osc/lproc_osc.c ++++ b/lustre/osc/lproc_osc.c +@@ -543,37 +543,69 @@ LPROC_SEQ_FOPS_RW_TYPE(osc, import); + LPROC_SEQ_FOPS_RW_TYPE(osc, pinger_recov); + + struct lprocfs_seq_vars lprocfs_osc_obd_vars[] = { +- { "uuid", &osc_uuid_fops }, +- { "ping", &osc_ping_fops, 0, 0222 }, +- { "connect_flags", &osc_connect_flags_fops }, +- { "blocksize", &osc_blksize_fops }, +- { "kbytestotal", &osc_kbytestotal_fops }, +- { "kbytesfree", &osc_kbytesfree_fops }, +- { "kbytesavail", &osc_kbytesavail_fops }, +- { "filestotal", &osc_filestotal_fops }, +- { "filesfree", &osc_filesfree_fops }, +- { "ost_server_uuid", &osc_server_uuid_fops }, +- { "ost_conn_uuid", &osc_conn_uuid_fops }, +- { "active", &osc_active_fops }, +- { "max_pages_per_rpc", &osc_obd_max_pages_per_rpc_fops }, +- { "max_rpcs_in_flight", &osc_max_rpcs_in_flight_fops }, +- { "destroys_in_flight", &osc_destroys_in_flight_fops }, +- { "max_dirty_mb", &osc_max_dirty_mb_fops }, +- { "osc_cached_mb", &osc_cached_mb_fops }, +- { "cur_dirty_bytes", &osc_cur_dirty_bytes_fops }, +- { "cur_grant_bytes", &osc_cur_grant_bytes_fops }, +- { "cur_lost_grant_bytes", &osc_cur_lost_grant_bytes_fops }, +- { "grant_shrink_interval", &osc_grant_shrink_interval_fops }, +- { "checksums", &osc_checksum_fops }, +- { "checksum_type", &osc_checksum_type_fops }, +- { "resend_count", &osc_resend_count_fops }, +- { "timeouts", &osc_timeouts_fops }, +- { "contention_seconds", &osc_contention_seconds_fops }, +- { "lockless_truncate", &osc_lockless_truncate_fops }, +- { "import", &osc_import_fops }, +- { "state", &osc_state_fops }, +- { "pinger_recov", &osc_pinger_recov_fops }, +- { "unstable_stats", &osc_unstable_stats_fops }, ++ { .name = "uuid", ++ .fops = &osc_uuid_fops }, ++ { .name = "ping", ++ .fops = &osc_ping_fops, ++ .proc_mode = 0222 }, ++ { .name = "connect_flags", ++ .fops = &osc_connect_flags_fops }, ++ { .name = "blocksize", ++ .fops = &osc_blksize_fops }, ++ { .name = "kbytestotal", ++ .fops = &osc_kbytestotal_fops }, ++ { .name = "kbytesfree", ++ .fops = &osc_kbytesfree_fops }, ++ { .name = "kbytesavail", ++ .fops = &osc_kbytesavail_fops }, ++ { .name = "filestotal", ++ .fops = &osc_filestotal_fops }, ++ { .name = "filesfree", ++ .fops = &osc_filesfree_fops }, ++ { .name = "ost_server_uuid", ++ .fops = &osc_server_uuid_fops }, ++ { .name = "ost_conn_uuid", ++ .fops = &osc_conn_uuid_fops }, ++ { .name = "active", ++ .fops = &osc_active_fops }, ++ { .name = "max_pages_per_rpc", ++ .fops = &osc_obd_max_pages_per_rpc_fops }, ++ { .name = "max_rpcs_in_flight", ++ .fops = &osc_max_rpcs_in_flight_fops }, ++ { .name = "destroys_in_flight", ++ .fops = &osc_destroys_in_flight_fops }, ++ { .name = "max_dirty_mb", ++ .fops = &osc_max_dirty_mb_fops }, ++ { .name = "osc_cached_mb", ++ .fops = &osc_cached_mb_fops }, ++ { .name = "cur_dirty_bytes", ++ .fops = &osc_cur_dirty_bytes_fops }, ++ { .name = "cur_grant_bytes", ++ .fops = &osc_cur_grant_bytes_fops }, ++ { .name = "cur_lost_grant_bytes", ++ .fops = &osc_cur_lost_grant_bytes_fops }, ++ { .name = "grant_shrink_interval", ++ .fops = &osc_grant_shrink_interval_fops }, ++ { .name = "checksums", ++ .fops = &osc_checksum_fops }, ++ { .name = "checksum_type", ++ .fops = &osc_checksum_type_fops }, ++ { .name = "resend_count", ++ .fops = &osc_resend_count_fops }, ++ { .name = "timeouts", ++ .fops = &osc_timeouts_fops }, ++ { .name = "contention_seconds", ++ .fops = &osc_contention_seconds_fops }, ++ { .name = "lockless_truncate", ++ .fops = &osc_lockless_truncate_fops }, ++ { .name = "import", ++ .fops = &osc_import_fops }, ++ { .name = "state", ++ .fops = &osc_state_fops }, ++ { .name = "pinger_recov", ++ .fops = &osc_pinger_recov_fops }, ++ { .name = "unstable_stats", ++ .fops = &osc_unstable_stats_fops }, + { 0 } + }; + +diff --git a/lustre/osc/osc_request.c b/lustre/osc/osc_request.c +index b9d1b71..f95fb55 100644 +--- a/lustre/osc/osc_request.c ++++ b/lustre/osc/osc_request.c +@@ -3669,7 +3669,7 @@ int osc_process_config_base(struct obd_device *obd, struct lustre_cfg *lcfg) + { + int rc = class_process_proc_seq_param(PARAM_OSC, obd->obd_vars, + lcfg, obd); +- return(rc > 0 ? 0: rc); ++ return rc > 0 ? 0: rc; + } + + static int osc_process_config(struct obd_device *obd, obd_count len, void *buf) +diff --git a/lustre/ost/ost_handler.c b/lustre/ost/ost_handler.c +index d4da00d..d20a30f 100644 +--- a/lustre/ost/ost_handler.c ++++ b/lustre/ost/ost_handler.c +@@ -75,7 +75,8 @@ static struct cfs_cpt_table *ost_io_cptable; + LPROC_SEQ_FOPS_RO_TYPE(ost, uuid); + + static struct lprocfs_seq_vars lprocfs_ost_obd_vars[] = { +- { "uuid", &ost_uuid_fops }, ++ { .name = "uuid", ++ .fops = &ost_uuid_fops }, + { 0 } + }; + #endif /* LPROCFS */ +diff --git a/lustre/ptlrpc/lproc_ptlrpc.c b/lustre/ptlrpc/lproc_ptlrpc.c +index 8e5a397..bf21958 100644 +--- a/lustre/ptlrpc/lproc_ptlrpc.c ++++ b/lustre/ptlrpc/lproc_ptlrpc.c +@@ -1382,7 +1382,7 @@ lprocfs_import_seq_write(struct file *file, const char *buffer, size_t count, + + *ptr = 0; + do_reconn = 0; +- ptr += strlen("::"); ++ ptr += 2; /* Skip :: */ + inst = simple_strtol(ptr, &endptr, 10); + if (*endptr) { + CERROR("config: wrong instance # %s\n", ptr); +diff --git a/lustre/quota/qmt_pool.c b/lustre/quota/qmt_pool.c +index afd450c..df6d6fc 100644 +--- a/lustre/quota/qmt_pool.c ++++ b/lustre/quota/qmt_pool.c +@@ -171,7 +171,8 @@ static int qpi_state_seq_show(struct seq_file *m, void *data) + LPROC_SEQ_FOPS_RO(qpi_state); + + static struct lprocfs_seq_vars lprocfs_quota_qpi_vars[] = { +- { "info", &qpi_state_fops }, ++ { .name = "info", ++ .fops = &qpi_state_fops }, + { NULL } + }; + +diff --git a/lustre/quota/qsd_lib.c b/lustre/quota/qsd_lib.c +index 990cfee..573473c 100644 +--- a/lustre/quota/qsd_lib.c ++++ b/lustre/quota/qsd_lib.c +@@ -208,10 +208,14 @@ qsd_timeout_seq_write(struct file *file, const char *buffer, + LPROC_SEQ_FOPS(qsd_timeout); + + static struct lprocfs_seq_vars lprocfs_quota_qsd_vars[] = { +- { "info", &qsd_state_fops }, +- { "enabled", &qsd_enabled_fops }, +- { "force_reint", &qsd_force_reint_fops }, +- { "timeout", &qsd_timeout_fops }, ++ { .name = "info", ++ .fops = &qsd_state_fops }, ++ { .name = "enabled", ++ .fops = &qsd_enabled_fops }, ++ { .name = "force_reint", ++ .fops = &qsd_force_reint_fops }, ++ { .name = "timeout", ++ .fops = &qsd_timeout_fops }, + { NULL } + }; + +-- +1.8.5.3 + diff --git a/sys-cluster/lustre/files/0002-LU-3373-ldiskfs-ldiskfs-patches-for-3.11.1-fc19.patch b/sys-cluster/lustre/files/0002-LU-3373-ldiskfs-ldiskfs-patches-for-3.11.1-fc19.patch deleted file mode 100644 index 8f3258a86..000000000 --- a/sys-cluster/lustre/files/0002-LU-3373-ldiskfs-ldiskfs-patches-for-3.11.1-fc19.patch +++ /dev/null @@ -1,5997 +0,0 @@ -From e53207df22261a635315a62f1405eb8c7b700963 Mon Sep 17 00:00:00 2001 -From: James Simmons <uja.ornl@gmail.com> -Date: Thu, 5 Dec 2013 09:05:22 -0500 -Subject: [PATCH 02/18] LU-3373 ldiskfs: ldiskfs patches for 3.11.1 fc19 - -ldiskfs patches - -Signed-off-by: yang sheng <yang.sheng@intel.com> -Signed-off-by: James Simmons <uja.ornl@gmail.com> -Change-Id: I59a8e7086c4567f1fe493ac7f0086365b5a6535c ---- - config/lustre-build-ldiskfs.m4 | 15 +- - config/lustre-build-linux.m4 | 12 +- - .../fc19/ext4-change-entry-avoid-conflict.patch | 71 + - .../patches/fc19/ext4-disable-mb-cache.patch | 150 ++ - .../kernel_patches/patches/fc19/ext4-fiemap.patch | 111 + - .../patches/fc19/ext4-force_over_128tb.patch | 57 + - .../patches/fc19/ext4-inode-version.patch | 59 + - .../patches/fc19/ext4-kill-dx_root.patch | 235 ++ - .../patches/fc19/ext4-large-eas.patch | 785 +++++++ - .../patches/fc19/ext4-lookup-dotdot.patch | 37 + - .../patches/fc19/ext4-max-dir-size.patch | 44 + - .../patches/fc19/ext4-mballoc-extra-checks.patch | 315 +++ - .../fc19/ext4-mballoc-pa_free-mismatch.patch | 109 + - .../kernel_patches/patches/fc19/ext4-misc.patch | 193 ++ - .../patches/fc19/ext4-nocmtime.patch | 28 + - .../patches/fc19/ext4-osd-iam-exports.patch | 56 + - .../patches/fc19/ext4-osd-iop-common.patch | 135 ++ - .../patches/fc19/ext4-pdir-fix.patch | 61 + - .../patches/fc19/ext4-prealloc.patch | 387 ++++ - .../patches/fc19/ext4_data_in_dirent.patch | 649 ++++++ - .../kernel_patches/patches/fc19/ext4_pdirop.patch | 2252 ++++++++++++++++++++ - .../kernel_patches/series/ldiskfs-3.x-fc19.series | 22 + - 22 files changed, 5781 insertions(+), 2 deletions(-) - create mode 100644 ldiskfs/kernel_patches/patches/fc19/ext4-change-entry-avoid-conflict.patch - create mode 100644 ldiskfs/kernel_patches/patches/fc19/ext4-disable-mb-cache.patch - create mode 100644 ldiskfs/kernel_patches/patches/fc19/ext4-fiemap.patch - create mode 100644 ldiskfs/kernel_patches/patches/fc19/ext4-force_over_128tb.patch - create mode 100644 ldiskfs/kernel_patches/patches/fc19/ext4-inode-version.patch - create mode 100644 ldiskfs/kernel_patches/patches/fc19/ext4-kill-dx_root.patch - create mode 100644 ldiskfs/kernel_patches/patches/fc19/ext4-large-eas.patch - create mode 100644 ldiskfs/kernel_patches/patches/fc19/ext4-lookup-dotdot.patch - create mode 100644 ldiskfs/kernel_patches/patches/fc19/ext4-max-dir-size.patch - create mode 100644 ldiskfs/kernel_patches/patches/fc19/ext4-mballoc-extra-checks.patch - create mode 100644 ldiskfs/kernel_patches/patches/fc19/ext4-mballoc-pa_free-mismatch.patch - create mode 100644 ldiskfs/kernel_patches/patches/fc19/ext4-misc.patch - create mode 100644 ldiskfs/kernel_patches/patches/fc19/ext4-nocmtime.patch - create mode 100644 ldiskfs/kernel_patches/patches/fc19/ext4-osd-iam-exports.patch - create mode 100644 ldiskfs/kernel_patches/patches/fc19/ext4-osd-iop-common.patch - create mode 100644 ldiskfs/kernel_patches/patches/fc19/ext4-pdir-fix.patch - create mode 100644 ldiskfs/kernel_patches/patches/fc19/ext4-prealloc.patch - create mode 100644 ldiskfs/kernel_patches/patches/fc19/ext4_data_in_dirent.patch - create mode 100644 ldiskfs/kernel_patches/patches/fc19/ext4_pdirop.patch - create mode 100644 ldiskfs/kernel_patches/series/ldiskfs-3.x-fc19.series - -diff --git a/config/lustre-build-ldiskfs.m4 b/config/lustre-build-ldiskfs.m4 -index 4b15de3..c979bab 100644 ---- a/config/lustre-build-ldiskfs.m4 -+++ b/config/lustre-build-ldiskfs.m4 -@@ -9,7 +9,7 @@ AS_IF([test x$RHEL_KERNEL = xyes], [ - AS_VERSION_COMPARE([$RHEL_KERNEL_VERSION],[2.6.32],[], - [SER="2.6-rhel6.series"],[SER="2.6-rhel6.series"])], - [SER="2.6-rhel6.4.series"],[SER="2.6-rhel6.4.series"]) --], [test x$SUSE_KERNEL = xyes], [ -+], [ AS_IF([test x$SUSE_KERNEL = xyes], [ - AS_VERSION_COMPARE([$LINUXRELEASE],[3.0.0],[ - AS_VERSION_COMPARE([$LINUXRELEASE],[2.6.32],[], - [SER="2.6-sles11.series"],[SER="2.6-sles11.series"])], -@@ -22,6 +22,19 @@ AS_IF([test x$RHEL_KERNEL = xyes], [ - ;; - esac - ]) -+], [ AS_IF([test x$FEDORA_KERNEL = xyes], [ -+ AS_VERSION_COMPARE([$LINUXRELEASE],[3.11],[], -+ [SER="3.x-fc19.series"],[SER="3.x-fc19.series"]) -+]) -+]) -+]) -+ -+# -+# Handle the case were someone uses their own kernel -+# -+AS_IF([test -z "$SER"], [ -+ AS_VERSION_COMPARE([$LINUXRELEASE],[3.11],[], -+ [SER="3.x-fc19.series"],[SER="3.x-fc19.series"]) - ]) - LDISKFS_SERIES=$SER - -diff --git a/config/lustre-build-linux.m4 b/config/lustre-build-linux.m4 -index 4a835ea..9afda9c 100644 ---- a/config/lustre-build-linux.m4 -+++ b/config/lustre-build-linux.m4 -@@ -109,7 +109,16 @@ AC_MSG_CHECKING([for RedHat kernel version]) - AC_MSG_RESULT([${RHEL_KERNEL_VERSION}]) - ], [ - AC_MSG_RESULT([not found]) -- LB_LINUX_CONFIG([SUSE_KERNEL],[SUSE_KERNEL="yes"],[]) -+ LB_LINUX_CONFIG([SUSE_KERNEL],[SUSE_KERNEL="yes"],[ -+ AC_MSG_CHECKING([for Fedora 19 kernel]) -+ AS_IF([test "$(echo $LINUXRELEASE | grep fc19)" == "$LINUXRELEASE" ],[ -+ AC_MSG_RESULT([yes]) -+ FEDORA_KERNEL="yes" -+ ], [ -+ FEDORA_KERNEL="no" -+ AC_MSG_RESULT([no]) -+ ]) -+ ]) - ]) - - AC_MSG_CHECKING([for kernel module package directory]) -@@ -118,6 +127,7 @@ AC_ARG_WITH([kmp-moddir], - [set the kmod updates or extra directory]), - [KMP_MODDIR=$withval],[ - AS_IF([test x$RHEL_KERNEL = xyes], [KMP_MODDIR="extra"], -+ [test x$FEDORA_KERNEL = xyes], [KMP_MODDIR="extra"], - [test x$SUSE_KERNEL = xyes], [KMP_MODDIR="updates"])]) - - AC_MSG_RESULT($KMP_MODDIR) -diff --git a/ldiskfs/kernel_patches/patches/fc19/ext4-change-entry-avoid-conflict.patch b/ldiskfs/kernel_patches/patches/fc19/ext4-change-entry-avoid-conflict.patch -new file mode 100644 -index 0000000..b1e4b9f ---- /dev/null -+++ b/ldiskfs/kernel_patches/patches/fc19/ext4-change-entry-avoid-conflict.patch -@@ -0,0 +1,71 @@ -+Index: linux-3.10.9-200.fc17.x86_64/fs/ext4/xattr.c -+=================================================================== -+--- linux-3.10.9-200.fc17.x86_64.orig/fs/ext4/xattr.c -++++ linux-3.10.9-200.fc17.x86_64/fs/ext4/xattr.c -+@@ -945,7 +945,7 @@ ext4_xattr_set_entry(struct ext4_xattr_i -+ if (!i->value) { -+ /* Remove the old name. */ -+ size_t size = EXT4_XATTR_LEN(name_len); -+- last = ENTRY((void *)last - size); -++ last = XA_ENTRY((void *)last - size); -+ memmove(s->here, (void *)s->here + size, -+ (void *)last - (void *)s->here + sizeof(__u32)); -+ memset(last, 0, size); -+@@ -1086,9 +1086,9 @@ ext4_xattr_block_set(handle_t *handle, s -+ if (s->base == NULL) -+ goto cleanup; -+ memcpy(s->base, BHDR(bs->bh), bs->bh->b_size); -+- s->first = ENTRY(header(s->base)+1); -++ s->first = XA_ENTRY(header(s->base)+1); -+ header(s->base)->h_refcount = cpu_to_le32(1); -+- s->here = ENTRY(s->base + offset); -++ s->here = XA_ENTRY(s->base + offset); -+ s->end = s->base + bs->bh->b_size; -+ } -+ } else { -+@@ -1101,8 +1101,8 @@ ext4_xattr_block_set(handle_t *handle, s -+ header(s->base)->h_magic = cpu_to_le32(EXT4_XATTR_MAGIC); -+ header(s->base)->h_blocks = cpu_to_le32(1); -+ header(s->base)->h_refcount = cpu_to_le32(1); -+- s->first = ENTRY(header(s->base)+1); -+- s->here = ENTRY(header(s->base)+1); -++ s->first = XA_ENTRY(header(s->base)+1); -++ s->here = XA_ENTRY(header(s->base)+1); -+ s->end = s->base + sb->s_blocksize; -+ } -+ -+@@ -1884,8 +1884,8 @@ ext4_xattr_cmp(struct ext4_xattr_header -+ { -+ struct ext4_xattr_entry *entry1, *entry2; -+ -+- entry1 = ENTRY(header1+1); -+- entry2 = ENTRY(header2+1); -++ entry1 = XA_ENTRY(header1+1); -++ entry2 = XA_ENTRY(header2+1); -+ while (!IS_LAST_ENTRY(entry1)) { -+ if (IS_LAST_ENTRY(entry2)) -+ return 1; -+@@ -2011,7 +2011,7 @@ static void ext4_xattr_rehash(struct ext -+ __u32 hash = 0; -+ -+ ext4_xattr_hash_entry(header, entry); -+- here = ENTRY(header+1); -++ here = XA_ENTRY(header+1); -+ while (!IS_LAST_ENTRY(here)) { -+ if (!here->e_hash) { -+ /* Block is not shared if an entry's hash value == 0 */ -+Index: linux-3.10.9-200.fc17.x86_64/fs/ext4/xattr.h -+=================================================================== -+--- linux-3.10.9-200.fc17.x86_64.orig/fs/ext4/xattr.h -++++ linux-3.10.9-200.fc17.x86_64/fs/ext4/xattr.h -+@@ -77,8 +77,8 @@ struct ext4_xattr_entry { -+ ((b) - EXT4_XATTR_LEN(3) - sizeof(struct ext4_xattr_header) - 4) -+ -+ #define BHDR(bh) ((struct ext4_xattr_header *)((bh)->b_data)) -+-#define ENTRY(ptr) ((struct ext4_xattr_entry *)(ptr)) -+-#define BFIRST(bh) ENTRY(BHDR(bh)+1) -++#define XA_ENTRY(ptr) ((struct ext4_xattr_entry *)(ptr)) -++#define BFIRST(bh) XA_ENTRY(BHDR(bh)+1) -+ #define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0) -+ -+ #define EXT4_ZERO_XATTR_VALUE ((void *)-1) -diff --git a/ldiskfs/kernel_patches/patches/fc19/ext4-disable-mb-cache.patch b/ldiskfs/kernel_patches/patches/fc19/ext4-disable-mb-cache.patch -new file mode 100644 -index 0000000..93a9022 ---- /dev/null -+++ b/ldiskfs/kernel_patches/patches/fc19/ext4-disable-mb-cache.patch -@@ -0,0 +1,150 @@ -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/ext4.h -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/ext4.h -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/ext4.h -+@@ -941,6 +941,7 @@ struct ext4_inode_info { -+ /* -+ * Mount flags set via mount options or defaults -+ */ -++#define EXT4_MOUNT_NO_MBCACHE 0x00001 /* Disable mbcache */ -+ #define EXT4_MOUNT_GRPID 0x00004 /* Create files with directory's group */ -+ #define EXT4_MOUNT_DEBUG 0x00008 /* Some debugging messages */ -+ #define EXT4_MOUNT_ERRORS_CONT 0x00010 /* Continue on errors */ -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/super.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/super.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/super.c -+@@ -1152,6 +1152,7 @@ enum { -+ Opt_inode_readahead_blks, Opt_journal_ioprio, -+ Opt_mballoc, Opt_force_over_128tb, -+ Opt_dioread_nolock, Opt_dioread_lock, -++ Opt_no_mbcache, -+ Opt_discard, Opt_nodiscard, Opt_init_itable, Opt_noinit_itable, -+ Opt_max_dir_size_kb, -+ }; -+@@ -1230,6 +1231,7 @@ static const match_table_t tokens = { -+ {Opt_discard, "discard"}, -+ {Opt_nodiscard, "nodiscard"}, -+ {Opt_init_itable, "init_itable=%u"}, -++ {Opt_no_mbcache, "no_mbcache"}, -+ {Opt_init_itable, "init_itable"}, -+ {Opt_noinit_itable, "noinit_itable"}, -+ {Opt_max_dir_size_kb, "max_dir_size_kb=%u"}, -+@@ -1389,6 +1391,7 @@ static const struct mount_opts { -+ {Opt_noauto_da_alloc, EXT4_MOUNT_NO_AUTO_DA_ALLOC, MOPT_SET}, -+ {Opt_auto_da_alloc, EXT4_MOUNT_NO_AUTO_DA_ALLOC, MOPT_CLEAR}, -+ {Opt_noinit_itable, EXT4_MOUNT_INIT_INODE_TABLE, MOPT_CLEAR}, -++ {Opt_no_mbcache, EXT4_MOUNT_NO_MBCACHE, MOPT_SET}, -+ {Opt_commit, 0, MOPT_GTE0}, -+ {Opt_max_batch_time, 0, MOPT_GTE0}, -+ {Opt_min_batch_time, 0, MOPT_GTE0}, -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/xattr.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/xattr.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/xattr.c -+@@ -81,7 +81,8 @@ -+ # define ea_bdebug(bh, fmt, ...) no_printk(fmt, ##__VA_ARGS__) -+ #endif -+ -+-static void ext4_xattr_cache_insert(struct buffer_head *); -++static void ext4_xattr_cache_insert(struct super_block *, -++ struct buffer_head *); -+ static struct buffer_head *ext4_xattr_cache_find(struct inode *, -+ struct ext4_xattr_header *, -+ struct mb_cache_entry **); -+@@ -385,7 +386,7 @@ bad_block: -+ error = -EIO; -+ goto cleanup; -+ } -+- ext4_xattr_cache_insert(bh); -++ ext4_xattr_cache_insert(inode->i_sb, bh); -+ entry = BFIRST(bh); -+ error = ext4_xattr_find_entry(&entry, name_index, name, bh->b_size, 1, -+ inode); -+@@ -546,7 +547,7 @@ ext4_xattr_block_list(struct dentry *den -+ error = -EIO; -+ goto cleanup; -+ } -+- ext4_xattr_cache_insert(bh); -++ ext4_xattr_cache_insert(inode->i_sb, bh); -+ error = ext4_xattr_list_entries(dentry, BFIRST(bh), buffer, buffer_size); -+ -+ cleanup: -+@@ -643,7 +644,9 @@ ext4_xattr_release_block(handle_t *handl -+ struct mb_cache_entry *ce = NULL; -+ int error = 0; -+ -+- ce = mb_cache_entry_get(ext4_xattr_cache, bh->b_bdev, bh->b_blocknr); -++ if (!test_opt(inode->i_sb, NO_MBCACHE)) -++ ce = mb_cache_entry_get(ext4_xattr_cache, bh->b_bdev, -++ bh->b_blocknr); -+ error = ext4_journal_get_write_access(handle, bh); -+ if (error) -+ goto out; -+@@ -1037,8 +1040,10 @@ ext4_xattr_block_set(handle_t *handle, s -+ #define header(x) ((struct ext4_xattr_header *)(x)) -+ -+ if (s->base) { -+- ce = mb_cache_entry_get(ext4_xattr_cache, bs->bh->b_bdev, -+- bs->bh->b_blocknr); -++ if (!test_opt(inode->i_sb, NO_MBCACHE)) -++ ce = mb_cache_entry_get(ext4_xattr_cache, -++ bs->bh->b_bdev, -++ bs->bh->b_blocknr); -+ error = ext4_journal_get_write_access(handle, bs->bh); -+ if (error) -+ goto cleanup; -+@@ -1055,7 +1060,7 @@ ext4_xattr_block_set(handle_t *handle, s -+ if (!IS_LAST_ENTRY(s->first)) -+ ext4_xattr_rehash(header(s->base), -+ s->here); -+- ext4_xattr_cache_insert(bs->bh); -++ ext4_xattr_cache_insert(sb, bs->bh); -+ } -+ unlock_buffer(bs->bh); -+ if (error == -EIO) -+@@ -1138,7 +1143,8 @@ inserted: -+ if (error) -+ goto cleanup_dquot; -+ } -+- mb_cache_entry_release(ce); -++ if (ce) -++ mb_cache_entry_release(ce); -+ ce = NULL; -+ } else if (bs->bh && s->base == bs->bh->b_data) { -+ /* We were modifying this block in-place. */ -+@@ -1191,7 +1197,7 @@ getblk_failed: -+ memcpy(new_bh->b_data, s->base, new_bh->b_size); -+ set_buffer_uptodate(new_bh); -+ unlock_buffer(new_bh); -+- ext4_xattr_cache_insert(new_bh); -++ ext4_xattr_cache_insert(sb, new_bh); -+ error = ext4_handle_dirty_xattr_block(handle, -+ inode, new_bh); -+ if (error) -+@@ -1837,12 +1843,15 @@ ext4_xattr_put_super(struct super_block -+ * Returns 0, or a negative error number on failure. -+ */ -+ static void -+-ext4_xattr_cache_insert(struct buffer_head *bh) -++ext4_xattr_cache_insert(struct super_block *sb, struct buffer_head *bh) -+ { -+ __u32 hash = le32_to_cpu(BHDR(bh)->h_hash); -+ struct mb_cache_entry *ce; -+ int error; -+ -++ if (test_opt(sb, NO_MBCACHE)) -++ return; -++ -+ ce = mb_cache_entry_alloc(ext4_xattr_cache, GFP_NOFS); -+ if (!ce) { -+ ea_bdebug(bh, "out of memory"); -+@@ -1915,6 +1924,8 @@ ext4_xattr_cache_find(struct inode *inod -+ __u32 hash = le32_to_cpu(header->h_hash); -+ struct mb_cache_entry *ce; -+ -++ if (test_opt(inode->i_sb, NO_MBCACHE)) -++ return NULL; -+ if (!header->h_hash) -+ return NULL; /* never share */ -+ ea_idebug(inode, "looking for cached blocks [%x]", (int)hash); -diff --git a/ldiskfs/kernel_patches/patches/fc19/ext4-fiemap.patch b/ldiskfs/kernel_patches/patches/fc19/ext4-fiemap.patch -new file mode 100644 -index 0000000..11d6d93 ---- /dev/null -+++ b/ldiskfs/kernel_patches/patches/fc19/ext4-fiemap.patch -@@ -0,0 +1,111 @@ -+This patch adds direct EXT4_IOC_FIEMAP support to ldiskfs, for Lustre to call -+without having to go through do_vfs_ioctl() (which isn't exported, and has a -+number of other ioctls which are not suitable for Lustre). The actual FIEMAP -+support is already in the kernel/ext4 for normal usage. -+ -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/ext4.h -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/ext4.h -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/ext4.h -+@@ -585,7 +585,7 @@ enum { -+ #define EXT4_IOC_GROUP_ADD _IOW('f', 8, struct ext4_new_group_input) -+ #define EXT4_IOC_MIGRATE _IO('f', 9) -+ /* note ioctl 10 reserved for an early version of the FIEMAP ioctl */ -+- /* note ioctl 11 reserved for filesystem-independent FIEMAP ioctl */ -++#define EXT4_IOC_FIEMAP _IOWR('f', 11, struct fiemap) -+ #define EXT4_IOC_ALLOC_DA_BLKS _IO('f', 12) -+ #define EXT4_IOC_MOVE_EXT _IOWR('f', 15, struct move_extent) -+ #define EXT4_IOC_RESIZE_FS _IOW('f', 16, __u64) -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/ioctl.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/ioctl.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/ioctl.c -+@@ -214,6 +214,71 @@ swap_boot_out: -+ return err; -+ } -+ -++/* So that the fiemap access checks can't overflow on 32 bit machines. */ -++#define FIEMAP_MAX_EXTENTS (UINT_MAX / sizeof(struct fiemap_extent)) -++ -++static int fiemap_check_ranges(struct super_block *sb, -++ u64 start, u64 len, u64 *new_len) -++{ -++ *new_len = len; -++ -++ if (len == 0) -++ return -EINVAL; -++ -++ if (start > sb->s_maxbytes) -++ return -EFBIG; -++ -++ /* -++ * Shrink request scope to what the fs can actually handle. -++ */ -++ if ((len > sb->s_maxbytes) || -++ (sb->s_maxbytes - len) < start) -++ *new_len = sb->s_maxbytes - start; -++ -++ return 0; -++} -++ -++int ioctl_fiemap(struct inode *inode, struct file *filp, unsigned long arg) -++{ -++ struct fiemap fiemap; -++ u64 len; -++ struct fiemap_extent_info fieinfo = {0, }; -++ struct super_block *sb = inode->i_sb; -++ int error = 0; -++ -++ if (copy_from_user(&fiemap, (struct fiemap __user *) arg, -++ sizeof(struct fiemap))) -++ return -EFAULT; -++ -++ if (fiemap.fm_extent_count > FIEMAP_MAX_EXTENTS) -++ return -EINVAL; -++ -++ error = fiemap_check_ranges(sb, fiemap.fm_start, fiemap.fm_length, -++ &len); -++ if (error) -++ return error; -++ -++ fieinfo.fi_flags = fiemap.fm_flags; -++ fieinfo.fi_extents_max = fiemap.fm_extent_count; -++ fieinfo.fi_extents_start = (struct fiemap_extent *)(arg + sizeof(fiemap)); -++ -++ if (fiemap.fm_extent_count != 0 && -++ !access_ok(VERIFY_WRITE, (void *)arg, -++ offsetof(typeof(fiemap), fm_extents[fiemap.fm_extent_count]))) -++ return -EFAULT; -++ -++ if (fieinfo.fi_flags & FIEMAP_FLAG_SYNC) -++ filemap_write_and_wait(inode->i_mapping); -++ -++ error = ext4_fiemap(inode, &fieinfo, fiemap.fm_start, len); -++ fiemap.fm_flags = fieinfo.fi_flags; -++ fiemap.fm_mapped_extents = fieinfo.fi_extents_mapped; -++ if (copy_to_user((char *)arg, &fiemap, sizeof(fiemap))) -++ error = -EFAULT; -++ -++ return error; -++} -++ -+ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -+ { -+ struct inode *inode = file_inode(filp); -+@@ -532,6 +597,9 @@ group_add_out: -+ mnt_drop_write_file(filp); -+ return err; -+ } -++ case EXT4_IOC_FIEMAP: { -++ return ioctl_fiemap(inode, filp, arg); -++ } -+ -+ case EXT4_IOC_ALLOC_DA_BLKS: -+ { -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/fiemap.h -+=================================================================== -+--- /dev/null -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/fiemap.h -+@@ -0,0 +1,2 @@ -++ -++#include_next <fiemap.h> -diff --git a/ldiskfs/kernel_patches/patches/fc19/ext4-force_over_128tb.patch b/ldiskfs/kernel_patches/patches/fc19/ext4-force_over_128tb.patch -new file mode 100644 -index 0000000..84e75e5 ---- /dev/null -+++ b/ldiskfs/kernel_patches/patches/fc19/ext4-force_over_128tb.patch -@@ -0,0 +1,57 @@ -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/super.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/super.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/super.c -+@@ -60,6 +60,8 @@ static struct ext4_lazy_init *ext4_li_in -+ static struct mutex ext4_li_mtx; -+ static struct ext4_features *ext4_feat; -+ -++static int force_over_128tb; -++ -+ static int ext4_load_journal(struct super_block *, struct ext4_super_block *, -+ unsigned long journal_devnum); -+ static int ext4_show_options(struct seq_file *seq, struct dentry *root); -+@@ -1146,7 +1148,7 @@ enum { -+ Opt_stripe, Opt_delalloc, Opt_nodelalloc, Opt_mblk_io_submit, -+ Opt_nomblk_io_submit, Opt_block_validity, Opt_noblock_validity, -+ Opt_inode_readahead_blks, Opt_journal_ioprio, -+- Opt_mballoc, -++ Opt_mballoc, Opt_force_over_128tb, -+ Opt_dioread_nolock, Opt_dioread_lock, -+ Opt_discard, Opt_nodiscard, Opt_init_itable, Opt_noinit_itable, -+ Opt_max_dir_size_kb, -+@@ -1222,6 +1224,7 @@ static const match_table_t tokens = { -+ {Opt_noauto_da_alloc, "noauto_da_alloc"}, -+ {Opt_dioread_nolock, "dioread_nolock"}, -+ {Opt_dioread_lock, "dioread_lock"}, -++ {Opt_force_over_128tb, "force_over_128tb"}, -+ {Opt_discard, "discard"}, -+ {Opt_nodiscard, "nodiscard"}, -+ {Opt_init_itable, "init_itable=%u"}, -+@@ -1468,6 +1471,9 @@ static int handle_mount_opt(struct super -+ case Opt_iopen_nopriv: -+ case Opt_mballoc: -+ return 1; -++ case Opt_force_over_128tb: -++ force_over_128tb = 1; -++ break; -+ } -+ -+ for (m = ext4_mount_opts; m->token != Opt_err; m++) -+@@ -3718,6 +3724,16 @@ static int ext4_fill_super(struct super_ -+ goto failed_mount; -+ } -+ -++ if (ext4_blocks_count(es) > (8ULL << 32)) { -++ if (force_over_128tb == 0) { -++ printk(KERN_ERR "EXT4-fs does not support filesystems " -++ "greater than 128TB and can cause data corruption." -++ "Use \"force_over_128tb\" mount option to override." -++ "\n"); -++ goto failed_mount; -++ } -++ } -++ -+ if (EXT4_BLOCKS_PER_GROUP(sb) == 0) -+ goto cantfind_ext4; -+ -diff --git a/ldiskfs/kernel_patches/patches/fc19/ext4-inode-version.patch b/ldiskfs/kernel_patches/patches/fc19/ext4-inode-version.patch -new file mode 100644 -index 0000000..2cae2f0 ---- /dev/null -+++ b/ldiskfs/kernel_patches/patches/fc19/ext4-inode-version.patch -@@ -0,0 +1,59 @@ -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/inode.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/inode.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/inode.c -+@@ -4145,11 +4145,11 @@ struct inode *ext4_iget(struct super_blo -+ EXT4_INODE_GET_XTIME(i_atime, inode, raw_inode); -+ EXT4_EINODE_GET_XTIME(i_crtime, ei, raw_inode); -+ -+- inode->i_version = le32_to_cpu(raw_inode->i_disk_version); -++ ei->i_fs_version = le32_to_cpu(raw_inode->i_disk_version); -+ if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE) { -+ if (EXT4_FITS_IN_INODE(raw_inode, ei, i_version_hi)) -+- inode->i_version |= -+- (__u64)(le32_to_cpu(raw_inode->i_version_hi)) << 32; -++ ei->i_fs_version |= (__u64)(le32_to_cpu(raw_inode->i_version_hi)) -++ << 32; -+ } -+ -+ ret = 0; -+@@ -4365,11 +4365,11 @@ static int ext4_do_update_inode(handle_t -+ raw_inode->i_block[block] = ei->i_data[block]; -+ } -+ -+- raw_inode->i_disk_version = cpu_to_le32(inode->i_version); -++ raw_inode->i_disk_version = cpu_to_le32(ei->i_fs_version); -+ if (ei->i_extra_isize) { -+ if (EXT4_FITS_IN_INODE(raw_inode, ei, i_version_hi)) -+- raw_inode->i_version_hi = -+- cpu_to_le32(inode->i_version >> 32); -++ raw_inode->i_version_hi = cpu_to_le32(ei->i_fs_version -++ >> 32); -+ raw_inode->i_extra_isize = cpu_to_le16(ei->i_extra_isize); -+ } -+ -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/ialloc.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/ialloc.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/ialloc.c -+@@ -899,6 +899,7 @@ got: -+ ei->i_dtime = 0; -+ ei->i_block_group = group; -+ ei->i_last_alloc_group = ~0; -++ ei->i_fs_version = 0; -+ -+ ext4_set_inode_flags(inode); -+ if (IS_DIRSYNC(inode)) -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/ext4.h -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/ext4.h -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/ext4.h -+@@ -915,6 +915,8 @@ struct ext4_inode_info { -+ tid_t i_sync_tid; -+ tid_t i_datasync_tid; -+ -++ __u64 i_fs_version; -++ -+ /* Precomputed uuid+inum+igen checksum for seeding inode checksums */ -+ __u32 i_csum_seed; -+ }; -diff --git a/ldiskfs/kernel_patches/patches/fc19/ext4-kill-dx_root.patch b/ldiskfs/kernel_patches/patches/fc19/ext4-kill-dx_root.patch -new file mode 100644 -index 0000000..f9c65d0 ---- /dev/null -+++ b/ldiskfs/kernel_patches/patches/fc19/ext4-kill-dx_root.patch -@@ -0,0 +1,235 @@ -+removes static definition of dx_root struct. so that "." and ".." dirent can -+have extra data. This patch does not change any functionality but is required for -+ext4_data_in_dirent patch. -+ -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/namei.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/namei.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/namei.c -+@@ -201,22 +201,13 @@ struct dx_entry -+ * hash version mod 4 should never be 0. Sincerely, the paranoia department. -+ */ -+ -+-struct dx_root -++struct dx_root_info -+ { -+- struct fake_dirent dot; -+- char dot_name[4]; -+- struct fake_dirent dotdot; -+- char dotdot_name[4]; -+- struct dx_root_info -+- { -+- __le32 reserved_zero; -+- u8 hash_version; -+- u8 info_length; /* 8 */ -+- u8 indirect_levels; -+- u8 unused_flags; -+- } -+- info; -+- struct dx_entry entries[0]; -++ __le32 reserved_zero; -++ u8 hash_version; -++ u8 info_length; /* 8 */ -++ u8 indirect_levels; -++ u8 unused_flags; -+ }; -+ -+ struct dx_node -+@@ -519,6 +510,16 @@ ext4_next_entry(struct ext4_dir_entry_2 -+ * Future: use high four bits of block for coalesce-on-delete flags -+ * Mask them off for now. -+ */ -++struct dx_root_info * dx_get_dx_info(struct ext4_dir_entry_2 *de) -++{ -++ /* get dotdot first */ -++ de = (struct ext4_dir_entry_2 *)((char *)de + EXT4_DIR_REC_LEN(1)); -++ -++ /* dx root info is after dotdot entry */ -++ de = (struct ext4_dir_entry_2 *)((char *)de + EXT4_DIR_REC_LEN(2)); -++ -++ return (struct dx_root_info *) de; -++} -+ -+ static inline ext4_lblk_t dx_get_block(struct dx_entry *entry) -+ { -+@@ -681,7 +682,7 @@ dx_probe(const struct qstr *d_name, stru -+ { -+ unsigned count, indirect; -+ struct dx_entry *at, *entries, *p, *q, *m; -+- struct dx_root *root; -++ struct dx_root_info * info; -+ struct buffer_head *bh; -+ struct dx_frame *frame = frame_in; -+ u32 hash; -+@@ -692,17 +693,18 @@ dx_probe(const struct qstr *d_name, stru -+ *err = PTR_ERR(bh); -+ goto fail; -+ } -+- root = (struct dx_root *) bh->b_data; -+- if (root->info.hash_version != DX_HASH_TEA && -+- root->info.hash_version != DX_HASH_HALF_MD4 && -+- root->info.hash_version != DX_HASH_LEGACY) { -++ -++ info = dx_get_dx_info((struct ext4_dir_entry_2*)bh->b_data); -++ if (info->hash_version != DX_HASH_TEA && -++ info->hash_version != DX_HASH_HALF_MD4 && -++ info->hash_version != DX_HASH_LEGACY) { -+ ext4_warning(dir->i_sb, "Unrecognised inode hash code %d for directory " -+- "#%lu", root->info.hash_version, dir->i_ino); -++ "#%lu", info->hash_version, dir->i_ino); -+ brelse(bh); -+ *err = ERR_BAD_DX_DIR; -+ goto fail; -+ } -+- hinfo->hash_version = root->info.hash_version; -++ hinfo->hash_version = info->hash_version; -+ if (hinfo->hash_version <= DX_HASH_TEA) -+ hinfo->hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned; -+ hinfo->seed = EXT4_SB(dir->i_sb)->s_hash_seed; -+@@ -710,27 +712,26 @@ dx_probe(const struct qstr *d_name, stru -+ ext4fs_dirhash(d_name->name, d_name->len, hinfo); -+ hash = hinfo->hash; -+ -+- if (root->info.unused_flags & 1) { -++ if (info->unused_flags & 1) { -+ ext4_warning(dir->i_sb, "Unimplemented inode hash flags: %#06x", -+- root->info.unused_flags); -++ info->unused_flags); -+ brelse(bh); -+ *err = ERR_BAD_DX_DIR; -+ goto fail; -+ } -+ -+- if ((indirect = root->info.indirect_levels) > 1) { -++ if ((indirect = info->indirect_levels) > 1) { -+ ext4_warning(dir->i_sb, "Unimplemented inode hash depth: %#06x", -+- root->info.indirect_levels); -++ info->indirect_levels); -+ brelse(bh); -+ *err = ERR_BAD_DX_DIR; -+ goto fail; -+ } -+ -+- entries = (struct dx_entry *) (((char *)&root->info) + -+- root->info.info_length); -++ entries = (struct dx_entry *) (((char *)info) + info->info_length); -+ -+ if (dx_get_limit(entries) != dx_root_limit(dir, -+- root->info.info_length)) { -++ info->info_length)) { -+ ext4_warning(dir->i_sb, "dx entry: limit != root limit"); -+ brelse(bh); -+ *err = ERR_BAD_DX_DIR; -+@@ -815,10 +816,12 @@ fail: -+ -+ static void dx_release (struct dx_frame *frames) -+ { -++ struct dx_root_info *info; -+ if (frames[0].bh == NULL) -+ return; -+ -+- if (((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels) -++ info = dx_get_dx_info((struct ext4_dir_entry_2*)frames[0].bh->b_data); -++ if (info->indirect_levels) -+ brelse(frames[1].bh); -+ brelse(frames[0].bh); -+ } -+@@ -1795,10 +1798,9 @@ static int make_indexed_dir(handle_t *ha -+ const char *name = dentry->d_name.name; -+ int namelen = dentry->d_name.len; -+ struct buffer_head *bh2; -+- struct dx_root *root; -+ struct dx_frame frames[2], *frame; -+ struct dx_entry *entries; -+- struct ext4_dir_entry_2 *de, *de2; -++ struct ext4_dir_entry_2 *de, *de2, *dot_de, *dotdot_de; -+ struct ext4_dir_entry_tail *t; -+ char *data1, *top; -+ unsigned len; -+@@ -1806,7 +1808,7 @@ static int make_indexed_dir(handle_t *ha -+ unsigned blocksize; -+ struct dx_hash_info hinfo; -+ ext4_lblk_t block; -+- struct fake_dirent *fde; -++ struct dx_root_info *dx_info; -+ int csum_size = 0; -+ -+ if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, -+@@ -1821,18 +1823,19 @@ static int make_indexed_dir(handle_t *ha -+ brelse(bh); -+ return retval; -+ } -+- root = (struct dx_root *) bh->b_data; -++ -++ dot_de = (struct ext4_dir_entry_2 *) bh->b_data; -++ dotdot_de = ext4_next_entry(dot_de, blocksize); -+ -+ /* The 0th block becomes the root, move the dirents out */ -+- fde = &root->dotdot; -+- de = (struct ext4_dir_entry_2 *)((char *)fde + -+- ext4_rec_len_from_disk(fde->rec_len, blocksize)); -+- if ((char *) de >= (((char *) root) + blocksize)) { -++ de = (struct ext4_dir_entry_2 *)((char *)dotdot_de + -++ ext4_rec_len_from_disk(dotdot_de->rec_len, blocksize)); -++ if ((char *) de >= (((char *) dot_de) + blocksize)) { -+ EXT4_ERROR_INODE(dir, "invalid rec_len for '..'"); -+ brelse(bh); -+ return -EIO; -+ } -+- len = ((char *) root) + (blocksize - csum_size) - (char *) de; -++ len = ((char *) dot_de) + (blocksize - csum_size) - (char *) de; -+ -+ /* Allocate new block for the 0th block's dirents */ -+ bh2 = ext4_append(handle, dir, &block); -+@@ -1858,19 +1861,23 @@ static int make_indexed_dir(handle_t *ha -+ } -+ -+ /* Initialize the root; the dot dirents already exist */ -+- de = (struct ext4_dir_entry_2 *) (&root->dotdot); -+- de->rec_len = ext4_rec_len_to_disk(blocksize - EXT4_DIR_REC_LEN(2), -+- blocksize); -+- memset (&root->info, 0, sizeof(root->info)); -+- root->info.info_length = sizeof(root->info); -+- root->info.hash_version = EXT4_SB(dir->i_sb)->s_def_hash_version; -+- entries = root->entries; -++ dotdot_de->rec_len = ext4_rec_len_to_disk(blocksize - -++ le16_to_cpu(dot_de->rec_len), blocksize); -++ -++ /* initialize hashing info */ -++ dx_info = dx_get_dx_info(dot_de); -++ memset (dx_info, 0, sizeof(*dx_info)); -++ dx_info->info_length = sizeof(*dx_info); -++ dx_info->hash_version = EXT4_SB(dir->i_sb)->s_def_hash_version; -++ -++ entries = (void *)dx_info + sizeof(*dx_info); -++ -+ dx_set_block(entries, 1); -+ dx_set_count(entries, 1); -+- dx_set_limit(entries, dx_root_limit(dir, sizeof(root->info))); -++ dx_set_limit(entries, dx_root_limit(dir, sizeof(*dx_info))); -+ -+ /* Initialize as for dx_probe */ -+- hinfo.hash_version = root->info.hash_version; -++ hinfo.hash_version = dx_info->hash_version; -+ if (hinfo.hash_version <= DX_HASH_TEA) -+ hinfo.hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned; -+ hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed; -+@@ -2160,6 +2167,7 @@ static int ext4_dx_add_entry(handle_t *h -+ goto journal_error; -+ brelse (bh2); -+ } else { -++ struct dx_root_info * info; -+ dxtrace(printk(KERN_DEBUG -+ "Creating second level index...\n")); -+ memcpy((char *) entries2, (char *) entries, -+@@ -2169,7 +2177,9 @@ static int ext4_dx_add_entry(handle_t *h -+ /* Set up root */ -+ dx_set_count(entries, 1); -+ dx_set_block(entries + 0, newblock); -+- ((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels = 1; -++ info = dx_get_dx_info((struct ext4_dir_entry_2*) -++ frames[0].bh->b_data); -++ info->indirect_levels = 1; -+ -+ /* Add new access path frame */ -+ frame = frames + 1; -diff --git a/ldiskfs/kernel_patches/patches/fc19/ext4-large-eas.patch b/ldiskfs/kernel_patches/patches/fc19/ext4-large-eas.patch -new file mode 100644 -index 0000000..4bbb6f5 ---- /dev/null -+++ b/ldiskfs/kernel_patches/patches/fc19/ext4-large-eas.patch -@@ -0,0 +1,785 @@ -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/ext4.h -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/ext4.h -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/ext4.h -+@@ -1533,6 +1533,7 @@ static inline void ext4_clear_state_flag -+ EXT4_FEATURE_INCOMPAT_EXTENTS| \ -+ EXT4_FEATURE_INCOMPAT_64BIT| \ -+ EXT4_FEATURE_INCOMPAT_FLEX_BG| \ -++ EXT4_FEATURE_INCOMPAT_EA_INODE| \ -+ EXT4_FEATURE_INCOMPAT_MMP | \ -+ EXT4_FEATURE_INCOMPAT_DIRDATA| \ -+ EXT4_FEATURE_INCOMPAT_INLINE_DATA) -+@@ -1940,6 +1941,12 @@ struct mmpd_data { -+ #endif -+ -+ /* -++ * Maximum size of xattr attributes for FEATURE_INCOMPAT_EA_INODE 1Mb -++ * This limit is arbitrary, but is reasonable for the xattr API. -++ */ -++#define EXT4_XATTR_MAX_LARGE_EA_SIZE (1024 * 1024) -++ -++/* -+ * Function prototypes -+ */ -+ -+@@ -2163,6 +2170,7 @@ extern void ext4_set_inode_flags(struct -+ extern void ext4_get_inode_flags(struct ext4_inode_info *); -+ extern int ext4_alloc_da_blocks(struct inode *inode); -+ extern void ext4_set_aops(struct inode *inode); -++extern int ext4_meta_trans_blocks(struct inode *, int nrblocks, int chunk); -+ extern int ext4_writepage_trans_blocks(struct inode *); -+ extern int ext4_chunk_trans_blocks(struct inode *, int nrblocks); -+ extern int ext4_block_truncate_page(handle_t *handle, -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/inode.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/inode.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/inode.c -+@@ -136,8 +136,6 @@ static void ext4_invalidatepage(struct p -+ unsigned int length); -+ static int __ext4_journalled_writepage(struct page *page, unsigned int len); -+ static int ext4_bh_delay_or_unwritten(handle_t *handle, struct buffer_head *bh); -+-static int ext4_meta_trans_blocks(struct inode *inode, int lblocks, -+- int pextents); -+ -+ /* -+ * Test whether an inode is a fast symlink. -+@@ -4716,7 +4714,7 @@ static int ext4_index_trans_blocks(struc -+ * -+ * Also account for superblock, inode, quota and xattr blocks -+ */ -+-static int ext4_meta_trans_blocks(struct inode *inode, int lblocks, -++int ext4_meta_trans_blocks(struct inode *inode, int lblocks, -+ int pextents) -+ { -+ ext4_group_t groups, ngroups = ext4_get_groups_count(inode->i_sb); -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/xattr.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/xattr.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/xattr.c -+@@ -220,19 +220,26 @@ ext4_xattr_check_block(struct inode *ino -+ } -+ -+ static inline int -+-ext4_xattr_check_entry(struct ext4_xattr_entry *entry, size_t size) -++ext4_xattr_check_entry(struct ext4_xattr_entry *entry, size_t size, -++ struct inode *inode) -+ { -+ size_t value_size = le32_to_cpu(entry->e_value_size); -+ -+- if (entry->e_value_block != 0 || value_size > size || -+- le16_to_cpu(entry->e_value_offs) + value_size > size) -++ if ((entry->e_value_inum == 0) && -++ (le16_to_cpu(entry->e_value_offs) + value_size > size)) -++ return -EIO; -++ if (entry->e_value_inum != 0 && -++ (le32_to_cpu(entry->e_value_inum) < EXT4_FIRST_INO(inode->i_sb) || -++ le32_to_cpu(entry->e_value_inum) > -++ le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_inodes_count))) -+ return -EIO; -+ return 0; -+ } -+ -+ static int -+ ext4_xattr_find_entry(struct ext4_xattr_entry **pentry, int name_index, -+- const char *name, size_t size, int sorted) -++ const char *name, size_t size, int sorted, -++ struct inode *inode) -+ { -+ struct ext4_xattr_entry *entry; -+ size_t name_len; -+@@ -252,11 +259,103 @@ ext4_xattr_find_entry(struct ext4_xattr_ -+ break; -+ } -+ *pentry = entry; -+- if (!cmp && ext4_xattr_check_entry(entry, size)) -++ if (!cmp && ext4_xattr_check_entry(entry, size, inode)) -+ return -EIO; -+ return cmp ? -ENODATA : 0; -+ } -+ -++/* -++ * Read the EA value from an inode. -++ */ -++static int -++ext4_xattr_inode_read(struct inode *ea_inode, void *buf, size_t *size) -++{ -++ unsigned long block = 0; -++ struct buffer_head *bh = NULL; -++ int err, blocksize; -++ size_t csize, ret_size = 0; -++ -++ if (*size == 0) -++ return 0; -++ -++ blocksize = ea_inode->i_sb->s_blocksize; -++ -++ while (ret_size < *size) { -++ csize = (*size - ret_size) > blocksize ? blocksize : -++ *size - ret_size; -++ bh = ext4_bread(NULL, ea_inode, block, 0, &err); -++ if (!bh) { -++ *size = ret_size; -++ return err; -++ } -++ memcpy(buf, bh->b_data, csize); -++ brelse(bh); -++ -++ buf += csize; -++ block += 1; -++ ret_size += csize; -++ } -++ -++ *size = ret_size; -++ -++ return err; -++} -++ -++struct inode *ext4_xattr_inode_iget(struct inode *parent, int ea_ino, int *err) -++{ -++ struct inode *ea_inode = NULL; -++ -++ ea_inode = ext4_iget(parent->i_sb, ea_ino); -++ if (IS_ERR(ea_inode) || is_bad_inode(ea_inode)) { -++ ext4_error(parent->i_sb, "error while reading EA inode %d", -++ ea_ino); -++ *err = -EIO; -++ return NULL; -++ } -++ -++ if (ea_inode->i_xattr_inode_parent != parent->i_ino || -++ ea_inode->i_generation != parent->i_generation) { -++ ext4_error(parent->i_sb, "Backpointer from EA inode %d " -++ "to parent invalid.", ea_ino); -++ *err = -EINVAL; -++ goto error; -++ } -++ -++ if (!(EXT4_I(ea_inode)->i_flags & EXT4_EA_INODE_FL)) { -++ ext4_error(parent->i_sb, "EA inode %d does not have " -++ "EXT4_EA_INODE_FL flag set.\n", ea_ino); -++ *err = -EINVAL; -++ goto error; -++ } -++ -++ *err = 0; -++ return ea_inode; -++ -++error: -++ iput(ea_inode); -++ return NULL; -++} -++ -++/* -++ * Read the value from the EA inode. -++ */ -++static int -++ext4_xattr_inode_get(struct inode *inode, int ea_ino, void *buffer, -++ size_t *size) -++{ -++ struct inode *ea_inode = NULL; -++ int err; -++ -++ ea_inode = ext4_xattr_inode_iget(inode, ea_ino, &err); -++ if (err) -++ return err; -++ -++ err = ext4_xattr_inode_read(ea_inode, buffer, size); -++ iput(ea_inode); -++ -++ return err; -++} -++ -+ static int -+ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name, -+ void *buffer, size_t buffer_size) -+@@ -288,7 +387,8 @@ bad_block: -+ } -+ ext4_xattr_cache_insert(bh); -+ entry = BFIRST(bh); -+- error = ext4_xattr_find_entry(&entry, name_index, name, bh->b_size, 1); -++ error = ext4_xattr_find_entry(&entry, name_index, name, bh->b_size, 1, -++ inode); -+ if (error == -EIO) -+ goto bad_block; -+ if (error) -+@@ -298,8 +398,16 @@ bad_block: -+ error = -ERANGE; -+ if (size > buffer_size) -+ goto cleanup; -+- memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs), -+- size); -++ if (entry->e_value_inum != 0) { -++ error = ext4_xattr_inode_get(inode, -++ le32_to_cpu(entry->e_value_inum), -++ buffer, &size); -++ if (error) -++ goto cleanup; -++ } else { -++ memcpy(buffer, bh->b_data + -++ le16_to_cpu(entry->e_value_offs), size); -++ } -+ } -+ error = size; -+ -+@@ -333,7 +441,7 @@ ext4_xattr_ibody_get(struct inode *inode -+ if (error) -+ goto cleanup; -+ error = ext4_xattr_find_entry(&entry, name_index, name, -+- end - (void *)entry, 0); -++ end - (void *)entry, 0, inode); -+ if (error) -+ goto cleanup; -+ size = le32_to_cpu(entry->e_value_size); -+@@ -341,8 +449,16 @@ ext4_xattr_ibody_get(struct inode *inode -+ error = -ERANGE; -+ if (size > buffer_size) -+ goto cleanup; -+- memcpy(buffer, (void *)IFIRST(header) + -+- le16_to_cpu(entry->e_value_offs), size); -++ if (entry->e_value_inum != 0) { -++ error = ext4_xattr_inode_get(inode, -++ le32_to_cpu(entry->e_value_inum), -++ buffer, &size); -++ if (error) -++ goto cleanup; -++ } else { -++ memcpy(buffer, (void *)IFIRST(header) + -++ le16_to_cpu(entry->e_value_offs), size); -++ } -+ } -+ error = size; -+ -+@@ -568,7 +684,7 @@ static size_t ext4_xattr_free_space(stru -+ { -+ for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) { -+ *total += EXT4_XATTR_LEN(last->e_name_len); -+- if (!last->e_value_block && last->e_value_size) { -++ if (last->e_value_inum == 0 && last->e_value_size > 0) { -+ size_t offs = le16_to_cpu(last->e_value_offs); -+ if (offs < *min_offs) -+ *min_offs = offs; -+@@ -577,16 +693,171 @@ static size_t ext4_xattr_free_space(stru -+ return (*min_offs - ((void *)last - base) - sizeof(__u32)); -+ } -+ -++/* -++ * Write the value of the EA in an inode. -++ */ -++static int -++ext4_xattr_inode_write(handle_t *handle, struct inode *ea_inode, -++ const void *buf, int bufsize) -++{ -++ struct buffer_head *bh = NULL; -++ unsigned long block = 0; -++ unsigned blocksize = ea_inode->i_sb->s_blocksize; -++ unsigned max_blocks = (bufsize + blocksize - 1) >> ea_inode->i_blkbits; -++ int csize, wsize = 0; -++ int ret = 0; -++ int retries = 0; -++ -++retry: -++ while (ret >= 0 && ret < max_blocks) { -++ struct ext4_map_blocks map; -++ map.m_lblk = block += ret; -++ map.m_len = max_blocks -= ret; -++ -++ ret = ext4_map_blocks(handle, ea_inode, &map, EXT4_GET_BLOCKS_CREATE); -++ if (ret <= 0) { -++ ext4_mark_inode_dirty(handle, ea_inode); -++ if (ret == -ENOSPC && -++ ext4_should_retry_alloc(ea_inode->i_sb, &retries)) { -++ ret = 0; -++ goto retry; -++ } -++ break; -++ } -++ } -++ -++ if (ret < 0) -++ return ret; -++ -++ block = 0; -++ while (wsize < bufsize) { -++ if (bh != NULL) -++ brelse(bh); -++ csize = (bufsize - wsize) > blocksize ? blocksize : -++ bufsize - wsize; -++ bh = ext4_getblk(handle, ea_inode, block, 0, &ret); -++ if (!bh) -++ goto out; -++ ret = ext4_journal_get_write_access(handle, bh); -++ if (ret) -++ goto out; -++ -++ memcpy(bh->b_data, buf, csize); -++ set_buffer_uptodate(bh); -++ ext4_journal_dirty_metadata(handle, bh); -++ -++ buf += csize; -++ wsize += csize; -++ block += 1; -++ } -++ -++ i_size_write(ea_inode, wsize); -++ ext4_update_i_disksize(ea_inode, wsize); -++ -++ ext4_mark_inode_dirty(handle, ea_inode); -++ -++out: -++ brelse(bh); -++ -++ return ret; -++} -++ -++/* -++ * Create an inode to store the value of a large EA. -++ */ -++static struct inode * -++ext4_xattr_inode_create(handle_t *handle, struct inode *inode) -++{ -++ struct inode *ea_inode = NULL; -++ -++ /* -++ * Let the next inode be the goal, so we try and allocate the EA inode -++ * in the same group, or nearby one. -++ */ -++ ea_inode = ext4_new_inode(handle, inode->i_sb->s_root->d_inode, -++ S_IFREG|0600, NULL, inode->i_ino + 1, NULL); -++ -++ if (!IS_ERR(ea_inode)) { -++ ea_inode->i_op = &ext4_file_inode_operations; -++ ea_inode->i_fop = &ext4_file_operations; -++ ext4_set_aops(ea_inode); -++ ea_inode->i_generation = inode->i_generation; -++ EXT4_I(ea_inode)->i_flags |= EXT4_EA_INODE_FL; -++ -++ /* -++ * A back-pointer from EA inode to parent inode will be useful -++ * for e2fsck. -++ */ -++ ea_inode->i_xattr_inode_parent = inode->i_ino; -++ unlock_new_inode(ea_inode); -++ } -++ -++ return ea_inode; -++} -++ -++/* -++ * Unlink the inode storing the value of the EA. -++ */ -+ static int -+-ext4_xattr_set_entry(struct ext4_xattr_info *i, struct ext4_xattr_search *s) -++ext4_xattr_inode_unlink(struct inode *inode, int ea_ino) -++{ -++ struct inode *ea_inode = NULL; -++ int err; -++ -++ ea_inode = ext4_xattr_inode_iget(inode, ea_ino, &err); -++ if (err) -++ return err; -++ -++ clear_nlink(ea_inode); -++ iput(ea_inode); -++ -++ return 0; -++} -++ -++/* -++ * Add value of the EA in an inode. -++ */ -++static int -++ext4_xattr_inode_set(handle_t *handle, struct inode *inode, int *ea_ino, -++ const void *value, size_t value_len) -++{ -++ struct inode *ea_inode = NULL; -++ int err; -++ -++ /* Create an inode for the EA value */ -++ ea_inode = ext4_xattr_inode_create(handle, inode); -++ if (IS_ERR(ea_inode)) -++ return -1; -++ -++ err = ext4_xattr_inode_write(handle, ea_inode, value, value_len); -++ if (err) -++ clear_nlink(ea_inode); -++ else -++ *ea_ino = ea_inode->i_ino; -++ -++ iput(ea_inode); -++ -++ return err; -++} -++ -++static int -++ext4_xattr_set_entry(struct ext4_xattr_info *i, struct ext4_xattr_search *s, -++ handle_t *handle, struct inode *inode) -+ { -+ struct ext4_xattr_entry *last; -+ size_t free, min_offs = s->end - s->base, name_len = strlen(i->name); -++ int in_inode = i->in_inode; -++ -++ if (EXT4_HAS_INCOMPAT_FEATURE(inode->i_sb, -++ EXT4_FEATURE_INCOMPAT_EA_INODE) && -++ (EXT4_XATTR_SIZE(i->value_len) > -++ EXT4_XATTR_MIN_LARGE_EA_SIZE(inode->i_sb->s_blocksize))) -++ in_inode = 1; -+ -+ /* Compute min_offs and last. */ -+ last = s->first; -+ for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) { -+- if (!last->e_value_block && last->e_value_size) { -++ if (last->e_value_inum == 0 && last->e_value_size > 0) { -+ size_t offs = le16_to_cpu(last->e_value_offs); -+ if (offs < min_offs) -+ min_offs = offs; -+@@ -594,16 +865,21 @@ ext4_xattr_set_entry(struct ext4_xattr_i -+ } -+ free = min_offs - ((void *)last - s->base) - sizeof(__u32); -+ if (!s->not_found) { -+- if (!s->here->e_value_block && s->here->e_value_size) { -++ if (!in_inode && s->here->e_value_inum == 0 && -++ s->here->e_value_size > 0) { -+ size_t size = le32_to_cpu(s->here->e_value_size); -+ free += EXT4_XATTR_SIZE(size); -+ } -+ free += EXT4_XATTR_LEN(name_len); -+ } -+ if (i->value) { -+- if (free < EXT4_XATTR_SIZE(i->value_len) || -+- free < EXT4_XATTR_LEN(name_len) + -+- EXT4_XATTR_SIZE(i->value_len)) -++ size_t value_len = EXT4_XATTR_SIZE(i->value_len); -++ -++ if (in_inode) -++ value_len = 0; -++ -++ if (free < value_len || -++ free < EXT4_XATTR_LEN(name_len) + value_len) -+ return -ENOSPC; -+ } -+ -+@@ -617,7 +893,8 @@ ext4_xattr_set_entry(struct ext4_xattr_i -+ s->here->e_name_len = name_len; -+ memcpy(s->here->e_name, i->name, name_len); -+ } else { -+- if (!s->here->e_value_block && s->here->e_value_size) { -++ if (s->here->e_value_offs > 0 && s->here->e_value_inum == 0 && -++ s->here->e_value_size > 0) { -+ void *first_val = s->base + min_offs; -+ size_t offs = le16_to_cpu(s->here->e_value_offs); -+ void *val = s->base + offs; -+@@ -651,13 +928,17 @@ ext4_xattr_set_entry(struct ext4_xattr_i -+ last = s->first; -+ while (!IS_LAST_ENTRY(last)) { -+ size_t o = le16_to_cpu(last->e_value_offs); -+- if (!last->e_value_block && -+- last->e_value_size && o < offs) -++ if (last->e_value_size > 0 && o < offs) -+ last->e_value_offs = -+ cpu_to_le16(o + size); -+ last = EXT4_XATTR_NEXT(last); -+ } -+ } -++ if (s->here->e_value_inum != 0) { -++ ext4_xattr_inode_unlink(inode, -++ le32_to_cpu(s->here->e_value_inum)); -++ s->here->e_value_inum = 0; -++ } -+ if (!i->value) { -+ /* Remove the old name. */ -+ size_t size = EXT4_XATTR_LEN(name_len); -+@@ -671,10 +952,17 @@ ext4_xattr_set_entry(struct ext4_xattr_i -+ if (i->value) { -+ /* Insert the new value. */ -+ s->here->e_value_size = cpu_to_le32(i->value_len); -+- if (i->value_len) { -++ if (in_inode) { -++ int ea_ino = le32_to_cpu(s->here->e_value_inum); -++ ext4_xattr_inode_set(handle, inode, &ea_ino, i->value, -++ i->value_len); -++ s->here->e_value_inum = cpu_to_le32(ea_ino); -++ s->here->e_value_offs = 0; -++ } else if (i->value_len) { -+ size_t size = EXT4_XATTR_SIZE(i->value_len); -+ void *val = s->base + min_offs - size; -+ s->here->e_value_offs = cpu_to_le16(min_offs - size); -++ s->here->e_value_inum = 0; -+ if (i->value == EXT4_ZERO_XATTR_VALUE) { -+ memset(val, 0, size); -+ } else { -+@@ -724,7 +1012,7 @@ ext4_xattr_block_find(struct inode *inod -+ bs->s.end = bs->bh->b_data + bs->bh->b_size; -+ bs->s.here = bs->s.first; -+ error = ext4_xattr_find_entry(&bs->s.here, i->name_index, -+- i->name, bs->bh->b_size, 1); -++ i->name, bs->bh->b_size, 1, inode); -+ if (error && error != -ENODATA) -+ goto cleanup; -+ bs->s.not_found = error; -+@@ -748,8 +1036,6 @@ ext4_xattr_block_set(handle_t *handle, s -+ -+ #define header(x) ((struct ext4_xattr_header *)(x)) -+ -+- if (i->value && i->value_len > sb->s_blocksize) -+- return -ENOSPC; -+ if (s->base) { -+ ce = mb_cache_entry_get(ext4_xattr_cache, bs->bh->b_bdev, -+ bs->bh->b_blocknr); -+@@ -764,7 +1050,7 @@ ext4_xattr_block_set(handle_t *handle, s -+ ce = NULL; -+ } -+ ea_bdebug(bs->bh, "modifying in-place"); -+- error = ext4_xattr_set_entry(i, s); -++ error = ext4_xattr_set_entry(i, s, handle, inode); -+ if (!error) { -+ if (!IS_LAST_ENTRY(s->first)) -+ ext4_xattr_rehash(header(s->base), -+@@ -815,7 +1101,7 @@ ext4_xattr_block_set(handle_t *handle, s -+ s->end = s->base + sb->s_blocksize; -+ } -+ -+- error = ext4_xattr_set_entry(i, s); -++ error = ext4_xattr_set_entry(i, s, handle, inode); -+ if (error == -EIO) -+ goto bad_block; -+ if (error) -+@@ -963,7 +1249,7 @@ int ext4_xattr_ibody_find(struct inode * -+ /* Find the named attribute. */ -+ error = ext4_xattr_find_entry(&is->s.here, i->name_index, -+ i->name, is->s.end - -+- (void *)is->s.base, 0); -++ (void *)is->s.base, 0, inode); -+ if (error && error != -ENODATA) -+ return error; -+ is->s.not_found = error; -+@@ -981,7 +1267,7 @@ int ext4_xattr_ibody_inline_set(handle_t -+ -+ if (EXT4_I(inode)->i_extra_isize == 0) -+ return -ENOSPC; -+- error = ext4_xattr_set_entry(i, s); -++ error = ext4_xattr_set_entry(i, s, handle, inode); -+ if (error) { -+ if (error == -ENOSPC && -+ ext4_has_inline_data(inode)) { -+@@ -993,7 +1279,7 @@ int ext4_xattr_ibody_inline_set(handle_t -+ error = ext4_xattr_ibody_find(inode, i, is); -+ if (error) -+ return error; -+- error = ext4_xattr_set_entry(i, s); -++ error = ext4_xattr_set_entry(i, s, handle, inode); -+ } -+ if (error) -+ return error; -+@@ -1019,7 +1305,7 @@ static int ext4_xattr_ibody_set(handle_t -+ -+ if (EXT4_I(inode)->i_extra_isize == 0) -+ return -ENOSPC; -+- error = ext4_xattr_set_entry(i, s); -++ error = ext4_xattr_set_entry(i, s, handle, inode); -+ if (error) -+ return error; -+ header = IHDR(inode, ext4_raw_inode(&is->iloc)); -+@@ -1055,7 +1341,7 @@ ext4_xattr_set_handle(handle_t *handle, -+ .name = name, -+ .value = value, -+ .value_len = value_len, -+- -++ .in_inode = 0, -+ }; -+ struct ext4_xattr_ibody_find is = { -+ .s = { .not_found = -ENODATA, }, -+@@ -1120,6 +1406,15 @@ ext4_xattr_set_handle(handle_t *handle, -+ goto cleanup; -+ } -+ error = ext4_xattr_block_set(handle, inode, &i, &bs); -++ if (EXT4_HAS_INCOMPAT_FEATURE(inode->i_sb, -++ EXT4_FEATURE_INCOMPAT_EA_INODE) && -++ error == -ENOSPC) { -++ /* xattr not fit to block, store at external -++ * inode */ -++ i.in_inode = 1; -++ error = ext4_xattr_ibody_set(handle, inode, -++ &i, &is); -++ } -+ if (error) -+ goto cleanup; -+ if (!is.s.not_found) { -+@@ -1167,9 +1462,22 @@ ext4_xattr_set(struct inode *inode, int -+ const void *value, size_t value_len, int flags) -+ { -+ handle_t *handle; -++ struct super_block *sb = inode->i_sb; -+ int error, retries = 0; -+ int credits = ext4_jbd2_credits_xattr(inode); -+ -++ if ((value_len >= EXT4_XATTR_MIN_LARGE_EA_SIZE(sb->s_blocksize)) && -++ EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EA_INODE)) { -++ int nrblocks = (value_len + sb->s_blocksize - 1) >> -++ sb->s_blocksize_bits; -++ -++ /* For new inode */ -++ credits += EXT4_SINGLEDATA_TRANS_BLOCKS(sb) + 3; -++ -++ /* For data blocks of EA inode */ -++ credits += ext4_meta_trans_blocks(inode, nrblocks, 0); -++ } -++ -+ retry: -+ handle = ext4_journal_start(inode, EXT4_HT_XATTR, credits); -+ if (IS_ERR(handle)) { -+@@ -1181,7 +1489,7 @@ retry: -+ value, value_len, flags); -+ error2 = ext4_journal_stop(handle); -+ if (error == -ENOSPC && -+- ext4_should_retry_alloc(inode->i_sb, &retries)) -++ ext4_should_retry_alloc(sb, &retries)) -+ goto retry; -+ if (error == 0) -+ error = error2; -+@@ -1203,7 +1511,7 @@ static void ext4_xattr_shift_entries(str -+ -+ /* Adjust the value offsets of the entries */ -+ for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) { -+- if (!last->e_value_block && last->e_value_size) { -++ if (last->e_value_inum == 0 && last->e_value_size > 0) { -+ new_offs = le16_to_cpu(last->e_value_offs) + -+ value_offs_shift; -+ BUG_ON(new_offs + le32_to_cpu(last->e_value_size) -+@@ -1443,15 +1751,41 @@ cleanup: -+ /* -+ * ext4_xattr_delete_inode() -+ * -+- * Free extended attribute resources associated with this inode. This -++ * Free extended attribute resources associated with this inode. Traverse -++ * all entries and unlink any xattr inodes associated with this inode. This -+ * is called immediately before an inode is freed. We have exclusive -+- * access to the inode. -++ * access to the inode. If an orphan inode is deleted it will also delete any -++ * xattr block and all xattr inodes. They are checked by ext4_xattr_inode_iget() -++ * to ensure they belong to the parent inode and were not deleted already. -+ */ -+ void -+ ext4_xattr_delete_inode(handle_t *handle, struct inode *inode) -+ { -+ struct buffer_head *bh = NULL; -++ struct ext4_xattr_ibody_header *header; -++ struct ext4_inode *raw_inode; -++ struct ext4_iloc iloc; -++ struct ext4_xattr_entry *entry; -++ int error; -++ -++ if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR)) -++ goto delete_external_ea; -++ -++ error = ext4_get_inode_loc(inode, &iloc); -++ if (error) -++ goto cleanup; -++ raw_inode = ext4_raw_inode(&iloc); -++ header = IHDR(inode, raw_inode); -++ entry = IFIRST(header); -++ for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) { -++ if (entry->e_value_inum != 0) { -++ ext4_xattr_inode_unlink(inode, -++ le32_to_cpu(entry->e_value_inum)); -++ entry->e_value_inum = 0; -++ } -++ } -+ -++delete_external_ea: -+ if (!EXT4_I(inode)->i_file_acl) -+ goto cleanup; -+ bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl); -+@@ -1466,6 +1800,16 @@ ext4_xattr_delete_inode(handle_t *handle -+ EXT4_I(inode)->i_file_acl); -+ goto cleanup; -+ } -++ -++ entry = BFIRST(bh); -++ for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) { -++ if (entry->e_value_inum != 0) { -++ ext4_xattr_inode_unlink(inode, -++ le32_to_cpu(entry->e_value_inum)); -++ entry->e_value_inum = 0; -++ } -++ } -++ -+ ext4_xattr_release_block(handle, inode, bh); -+ EXT4_I(inode)->i_file_acl = 0; -+ -+@@ -1540,10 +1884,9 @@ ext4_xattr_cmp(struct ext4_xattr_header -+ entry1->e_name_index != entry2->e_name_index || -+ entry1->e_name_len != entry2->e_name_len || -+ entry1->e_value_size != entry2->e_value_size || -++ entry1->e_value_inum != entry2->e_value_inum || -+ memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len)) -+ return 1; -+- if (entry1->e_value_block != 0 || entry2->e_value_block != 0) -+- return -EIO; -+ if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs), -+ (char *)header2 + le16_to_cpu(entry2->e_value_offs), -+ le32_to_cpu(entry1->e_value_size))) -+@@ -1627,7 +1970,7 @@ static inline void ext4_xattr_hash_entry -+ *name++; -+ } -+ -+- if (entry->e_value_block == 0 && entry->e_value_size != 0) { -++ if (entry->e_value_inum == 0 && entry->e_value_size != 0) { -+ __le32 *value = (__le32 *)((char *)header + -+ le16_to_cpu(entry->e_value_offs)); -+ for (n = (le32_to_cpu(entry->e_value_size) + -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/xattr.h -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/xattr.h -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/xattr.h -+@@ -42,7 +42,7 @@ struct ext4_xattr_entry { -+ __u8 e_name_len; /* length of name */ -+ __u8 e_name_index; /* attribute name index */ -+ __le16 e_value_offs; /* offset in disk block of value */ -+- __le32 e_value_block; /* disk block attribute is stored on (n/i) */ -++ __le32 e_value_inum; /* inode in which the value is stored */ -+ __le32 e_value_size; /* size of attribute value */ -+ __le32 e_hash; /* hash value of name and value */ -+ char e_name[0]; /* attribute name */ -+@@ -67,6 +67,15 @@ struct ext4_xattr_entry { -+ EXT4_I(inode)->i_extra_isize)) -+ #define IFIRST(hdr) ((struct ext4_xattr_entry *)((hdr)+1)) -+ -++#define i_xattr_inode_parent i_mtime.tv_sec -++ -++/* -++ * The minimum size of EA value when you start storing it in an external inode -++ * size of block - size of header - size of 1 entry - 4 null bytes -++*/ -++#define EXT4_XATTR_MIN_LARGE_EA_SIZE(b) \ -++ ((b) - EXT4_XATTR_LEN(3) - sizeof(struct ext4_xattr_header) - 4) -++ -+ #define BHDR(bh) ((struct ext4_xattr_header *)((bh)->b_data)) -+ #define ENTRY(ptr) ((struct ext4_xattr_entry *)(ptr)) -+ #define BFIRST(bh) ENTRY(BHDR(bh)+1) -+@@ -75,10 +84,11 @@ struct ext4_xattr_entry { -+ #define EXT4_ZERO_XATTR_VALUE ((void *)-1) -+ -+ struct ext4_xattr_info { -+- int name_index; -+ const char *name; -+ const void *value; -+ size_t value_len; -++ int name_index; -++ int in_inode; -+ }; -+ -+ struct ext4_xattr_search { -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/inline.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/inline.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/inline.c -+@@ -59,7 +59,7 @@ static int get_max_inline_xattr_value_si -+ -+ /* Compute min_offs. */ -+ for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) { -+- if (!entry->e_value_block && entry->e_value_size) { -++ if (!entry->e_value_inum && entry->e_value_size) { -+ size_t offs = le16_to_cpu(entry->e_value_offs); -+ if (offs < min_offs) -+ min_offs = offs; -diff --git a/ldiskfs/kernel_patches/patches/fc19/ext4-lookup-dotdot.patch b/ldiskfs/kernel_patches/patches/fc19/ext4-lookup-dotdot.patch -new file mode 100644 -index 0000000..f4318c5 ---- /dev/null -+++ b/ldiskfs/kernel_patches/patches/fc19/ext4-lookup-dotdot.patch -@@ -0,0 +1,37 @@ -+Index: linux-3.10.9-200.fc17.x86_64/fs/ext4/namei.c -+=================================================================== -+--- linux-3.10.9-200.fc17.x86_64.orig/fs/ext4/namei.c -++++ linux-3.10.9-200.fc17.x86_64/fs/ext4/namei.c -+@@ -1438,6 +1438,32 @@ static struct dentry *ext4_lookup(struct -+ return ERR_PTR(-EIO); -+ } -+ } -++ /* ".." 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 *goal = NULL; -++ -++ /* first, look for an existing dentry - any one is good */ -++ goal = d_find_any_alias(inode); -++ if (goal == NULL) { -++ spin_lock(&dentry->d_lock); -++ /* there is no alias, we need to make current dentry: -++ * a) inaccessible for __d_lookup() -++ * b) inaccessible for iopen */ -++ J_ASSERT(hlist_unhashed(&dentry->d_alias)); -++ dentry->d_flags |= DCACHE_NFSFS_RENAMED; -++ /* this is d_instantiate() ... */ -++ hlist_add_head(&dentry->d_alias, &inode->i_dentry); -++ dentry->d_inode = inode; -++ spin_unlock(&dentry->d_lock); -++ } -++ if (goal) -++ iput(inode); -++ return goal; -++ } -++ -+ return d_splice_alias(inode, dentry); -+ } -+ -diff --git a/ldiskfs/kernel_patches/patches/fc19/ext4-max-dir-size.patch b/ldiskfs/kernel_patches/patches/fc19/ext4-max-dir-size.patch -new file mode 100644 -index 0000000..a1e12a8 ---- /dev/null -+++ b/ldiskfs/kernel_patches/patches/fc19/ext4-max-dir-size.patch -@@ -0,0 +1,44 @@ -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/super.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/super.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/super.c -+@@ -2485,8 +2485,11 @@ static ssize_t sbi_ui_show(struct ext4_a -+ struct ext4_sb_info *sbi, char *buf) -+ { -+ unsigned int *ui = (unsigned int *) (((char *) sbi) + a->u.offset); -++ unsigned int v = *ui; -+ -+- return snprintf(buf, PAGE_SIZE, "%u\n", *ui); -++ if (strcmp("max_dir_size", a->attr.name) == 0) -++ v <<= 10; -++ return snprintf(buf, PAGE_SIZE, "%u\n", v); -+ } -+ -+ static ssize_t sbi_ui_store(struct ext4_attr *a, -+@@ -2500,6 +2503,8 @@ static ssize_t sbi_ui_store(struct ext4_ -+ ret = kstrtoul(skip_spaces(buf), 0, &t); -+ if (ret) -+ return ret; -++ if (strcmp("max_dir_size", a->attr.name) == 0) -++ t >>= 10; -+ *ui = t; -+ return count; -+ } -+@@ -2582,6 +2587,8 @@ EXT4_RW_ATTR(reserved_clusters); -+ EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, sbi_ui_show, -+ inode_readahead_blks_store, s_inode_readahead_blks); -+ EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal); -++EXT4_RW_ATTR_SBI_UI(max_dir_size, s_max_dir_size_kb); -++EXT4_RW_ATTR_SBI_UI(max_dir_size_kb, s_max_dir_size_kb); -+ EXT4_RW_ATTR_SBI_UI(mb_stats, s_mb_stats); -+ EXT4_RW_ATTR_SBI_UI(mb_max_to_scan, s_mb_max_to_scan); -+ EXT4_RW_ATTR_SBI_UI(mb_min_to_scan, s_mb_min_to_scan); -+@@ -2600,6 +2607,8 @@ static struct attribute *ext4_attrs[] = -+ ATTR_LIST(reserved_clusters), -+ ATTR_LIST(inode_readahead_blks), -+ ATTR_LIST(inode_goal), -++ ATTR_LIST(max_dir_size), -++ ATTR_LIST(max_dir_size_kb), -+ ATTR_LIST(mb_stats), -+ ATTR_LIST(mb_max_to_scan), -+ ATTR_LIST(mb_min_to_scan), -diff --git a/ldiskfs/kernel_patches/patches/fc19/ext4-mballoc-extra-checks.patch b/ldiskfs/kernel_patches/patches/fc19/ext4-mballoc-extra-checks.patch -new file mode 100644 -index 0000000..a0eb883 ---- /dev/null -+++ b/ldiskfs/kernel_patches/patches/fc19/ext4-mballoc-extra-checks.patch -@@ -0,0 +1,315 @@ -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/ext4.h -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/ext4.h -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/ext4.h -+@@ -2449,6 +2449,7 @@ struct ext4_group_info { -+ ext4_grpblk_t bb_fragments; /* nr of freespace fragments */ -+ ext4_grpblk_t bb_largest_free_order;/* order of largest frag in BG */ -+ struct list_head bb_prealloc_list; -++ unsigned long bb_prealloc_nr; -+ #ifdef DOUBLE_CHECK -+ void *bb_bitmap; -+ #endif -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/mballoc.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/mballoc.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/mballoc.c -+@@ -362,7 +362,7 @@ static const char *ext4_groupinfo_slab_n -+ "ext4_groupinfo_64k", "ext4_groupinfo_128k" -+ }; -+ -+-static void ext4_mb_generate_from_pa(struct super_block *sb, void *bitmap, -++static int ext4_mb_generate_from_pa(struct super_block *sb, void *bitmap, -+ ext4_group_t group); -+ static void ext4_mb_generate_from_freelist(struct super_block *sb, void *bitmap, -+ ext4_group_t group); -+@@ -718,7 +718,7 @@ mb_set_largest_free_order(struct super_b -+ } -+ -+ static noinline_for_stack -+-void ext4_mb_generate_buddy(struct super_block *sb, -++int ext4_mb_generate_buddy(struct super_block *sb, -+ void *buddy, void *bitmap, ext4_group_t group) -+ { -+ struct ext4_group_info *grp = ext4_get_group_info(sb, group); -+@@ -750,14 +750,13 @@ void ext4_mb_generate_buddy(struct super -+ grp->bb_fragments = fragments; -+ -+ if (free != grp->bb_free) { -+- ext4_grp_locked_error(sb, group, 0, 0, -+- "%u clusters in bitmap, %u in gd", -+- free, grp->bb_free); -+- /* -+- * If we intent to continue, we consider group descritor -+- * corrupt and update bb_free using bitmap value -+- */ -+- grp->bb_free = free; -++ struct ext4_group_desc *gdp; -++ gdp = ext4_get_group_desc (sb, group, NULL); -++ ext4_error(sb, "group %lu: %u blocks in bitmap, %u in bb, " -++ "%u in gd, %lu pa's\n", (long unsigned int)group, -++ free, grp->bb_free, ext4_free_group_clusters(sb, gdp), -++ grp->bb_prealloc_nr); -++ return -EIO; -+ } -+ mb_set_largest_free_order(sb, grp); -+ -+@@ -768,6 +767,8 @@ void ext4_mb_generate_buddy(struct super -+ EXT4_SB(sb)->s_mb_buddies_generated++; -+ EXT4_SB(sb)->s_mb_generation_time += period; -+ spin_unlock(&EXT4_SB(sb)->s_bal_lock); -++ -++ return 0; -+ } -+ -+ static void mb_regenerate_buddy(struct ext4_buddy *e4b) -+@@ -883,7 +884,7 @@ static int ext4_mb_init_cache(struct pag -+ } -+ -+ first_block = page->index * blocks_per_page; -+- for (i = 0; i < blocks_per_page; i++) { -++ for (i = 0; i < blocks_per_page && err == 0; i++) { -+ group = (first_block + i) >> 1; -+ if (group >= ngroups) -+ break; -+@@ -922,7 +923,7 @@ static int ext4_mb_init_cache(struct pag -+ ext4_lock_group(sb, group); -+ /* init the buddy */ -+ memset(data, 0xff, blocksize); -+- ext4_mb_generate_buddy(sb, data, incore, group); -++ err = ext4_mb_generate_buddy(sb, data, incore, group); -+ ext4_unlock_group(sb, group); -+ incore = NULL; -+ } else { -+@@ -937,7 +938,7 @@ static int ext4_mb_init_cache(struct pag -+ memcpy(data, bitmap, blocksize); -+ -+ /* mark all preallocated blks used in in-core bitmap */ -+- ext4_mb_generate_from_pa(sb, data, group); -++ err = ext4_mb_generate_from_pa(sb, data, group); -+ ext4_mb_generate_from_freelist(sb, data, group); -+ ext4_unlock_group(sb, group); -+ -+@@ -947,7 +948,8 @@ static int ext4_mb_init_cache(struct pag -+ incore = data; -+ } -+ } -+- SetPageUptodate(page); -++ if (likely(err == 0)) -++ SetPageUptodate(page); -+ -+ out: -+ if (bh) { -+@@ -2224,9 +2226,11 @@ static void *ext4_mb_seq_groups_next(str -+ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v) -+ { -+ struct super_block *sb = seq->private; -++ struct ext4_group_desc *gdp; -+ ext4_group_t group = (ext4_group_t) ((unsigned long) v); -+ int i; -+ int err, buddy_loaded = 0; -++ int free = 0; -+ struct ext4_buddy e4b; -+ struct ext4_group_info *grinfo; -+ struct sg { -+@@ -2236,10 +2240,10 @@ static int ext4_mb_seq_groups_show(struc -+ -+ group--; -+ if (group == 0) -+- seq_printf(seq, "#%-5s: %-5s %-5s %-5s " -++ seq_printf(seq, "#%-5s: %-5s %-5s %-5s %-5s %-5s" -+ "[ %-5s %-5s %-5s %-5s %-5s %-5s %-5s " -+ "%-5s %-5s %-5s %-5s %-5s %-5s %-5s ]\n", -+- "group", "free", "frags", "first", -++ "group", "free", "frags", "first", "first", "pa", -+ "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"); -+ -+@@ -2256,13 +2260,19 @@ static int ext4_mb_seq_groups_show(struc -+ buddy_loaded = 1; -+ } -+ -++ gdp = ext4_get_group_desc(sb, group, NULL); -++ if (gdp != NULL) -++ free = ext4_free_group_clusters(sb, gdp); -++ -+ memcpy(&sg, ext4_get_group_info(sb, group), i); -+ -+ if (buddy_loaded) -+ ext4_mb_unload_buddy(&e4b); -+ -+- seq_printf(seq, "#%-5u: %-5u %-5u %-5u [", group, sg.info.bb_free, -+- sg.info.bb_fragments, sg.info.bb_first_free); -++ seq_printf(seq, "#%-5lu: %-5u %-5u %-5u %-5u %-5lu [", -++ (long unsigned int)group, sg.info.bb_free, free, -++ sg.info.bb_fragments, sg.info.bb_first_free, -++ sg.info.bb_prealloc_nr); -+ for (i = 0; i <= 13; i++) -+ seq_printf(seq, " %-5u", i <= sb->s_blocksize_bits + 1 ? -+ sg.info.bb_counters[i] : 0); -+@@ -3507,22 +3517,67 @@ static void ext4_mb_generate_from_freeli -+ } -+ -+ /* -++ * check free blocks in bitmap match free block in group descriptor -++ * do this before taking preallocated blocks into account to be able -++ * to detect on-disk corruptions. The group lock should be hold by the -++ * caller. -++ */ -++int ext4_mb_check_ondisk_bitmap(struct super_block *sb, void *bitmap, -++ struct ext4_group_desc *gdp, int group) -++{ -++ unsigned short max = EXT4_BLOCKS_PER_GROUP(sb); -++ unsigned short i, first, free = 0; -++ -++ i = mb_find_next_zero_bit(bitmap, max, 0); -++ -++ while (i < max) { -++ first = i; -++ i = mb_find_next_bit(bitmap, max, i); -++ if (i > max) -++ i = max; -++ free += i - first; -++ if (i < max) -++ i = mb_find_next_zero_bit(bitmap, max, i); -++ } -++ -++ if (free != ext4_free_group_clusters(sb, gdp)) { -++ ext4_error(sb, "on-disk bitmap for group %d" -++ "corrupted: %u blocks free in bitmap, %u - in gd\n", -++ group, free, ext4_free_group_clusters(sb, gdp)); -++ return -EIO; -++ } -++ return 0; -++} -++ -++/* -+ * the function goes through all preallocation in this group and marks them -+ * used in in-core bitmap. buddy must be generated from this bitmap -+ * Need to be called with ext4 group lock held -+ */ -+ static noinline_for_stack -+-void ext4_mb_generate_from_pa(struct super_block *sb, void *bitmap, -++int ext4_mb_generate_from_pa(struct super_block *sb, void *bitmap, -+ ext4_group_t group) -+ { -+ struct ext4_group_info *grp = ext4_get_group_info(sb, group); -+ struct ext4_prealloc_space *pa; -++ struct ext4_group_desc *gdp; -+ struct list_head *cur; -+ ext4_group_t groupnr; -+ ext4_grpblk_t start; -+ int preallocated = 0; -++ int skip = 0, count = 0; -++ int err; -+ int len; -+ -++ gdp = ext4_get_group_desc (sb, group, NULL); -++ if (gdp == NULL) -++ return -EIO; -++ -++ /* before applying preallocations, check bitmap consistency */ -++ err = ext4_mb_check_ondisk_bitmap(sb, bitmap, gdp, group); -++ if (err) -++ return err; -++ -+ /* all form of preallocation discards first load group, -+ * so the only competing code is preallocation use. -+ * we don't need any locking here -+@@ -3538,13 +3593,23 @@ void ext4_mb_generate_from_pa(struct sup -+ &groupnr, &start); -+ len = pa->pa_len; -+ spin_unlock(&pa->pa_lock); -+- if (unlikely(len == 0)) -++ if (unlikely(len == 0)) { -++ skip++; -+ continue; -++ } -+ BUG_ON(groupnr != group); -+ ext4_set_bits(bitmap, start, len); -+ preallocated += len; -++ count ++; -++ } -++ if (count + skip != grp->bb_prealloc_nr) { -++ ext4_error(sb, "lost preallocations: " -++ "count %d, bb_prealloc_nr %lu, skip %d\n", -++ count, grp->bb_prealloc_nr, skip); -++ return -EIO; -+ } -+ mb_debug(1, "prellocated %u for group %u\n", preallocated, group); -++ return 0; -+ } -+ -+ static void ext4_mb_pa_callback(struct rcu_head *head) -+@@ -3603,6 +3668,7 @@ static void ext4_mb_put_pa(struct ext4_a -+ */ -+ ext4_lock_group(sb, grp); -+ list_del(&pa->pa_group_list); -++ ext4_get_group_info(sb, grp)->bb_prealloc_nr--; -+ ext4_unlock_group(sb, grp); -+ -+ spin_lock(pa->pa_obj_lock); -+@@ -3697,6 +3763,7 @@ ext4_mb_new_inode_pa(struct ext4_allocat -+ -+ ext4_lock_group(sb, ac->ac_b_ex.fe_group); -+ list_add(&pa->pa_group_list, &grp->bb_prealloc_list); -++ grp->bb_prealloc_nr++; -+ ext4_unlock_group(sb, ac->ac_b_ex.fe_group); -+ -+ spin_lock(pa->pa_obj_lock); -+@@ -3758,6 +3825,7 @@ ext4_mb_new_group_pa(struct ext4_allocat -+ -+ ext4_lock_group(sb, ac->ac_b_ex.fe_group); -+ list_add(&pa->pa_group_list, &grp->bb_prealloc_list); -++ grp->bb_prealloc_nr++; -+ ext4_unlock_group(sb, ac->ac_b_ex.fe_group); -+ -+ /* -+@@ -3927,6 +3995,8 @@ repeat: -+ -+ spin_unlock(&pa->pa_lock); -+ -++ BUG_ON(grp->bb_prealloc_nr == 0); -++ grp->bb_prealloc_nr--; -+ list_del(&pa->pa_group_list); -+ list_add(&pa->u.pa_tmp_list, &list); -+ } -+@@ -4056,7 +4126,7 @@ repeat: -+ if (err) { -+ ext4_error(sb, "Error loading buddy information for %u", -+ group); -+- continue; -++ return; -+ } -+ -+ bitmap_bh = ext4_read_block_bitmap(sb, group); -+@@ -4068,6 +4138,8 @@ repeat: -+ } -+ -+ ext4_lock_group(sb, group); -++ BUG_ON(e4b.bd_info->bb_prealloc_nr == 0); -++ e4b.bd_info->bb_prealloc_nr--; -+ list_del(&pa->pa_group_list); -+ ext4_mb_release_inode_pa(&e4b, bitmap_bh, pa); -+ ext4_unlock_group(sb, group); -+@@ -4328,6 +4400,7 @@ ext4_mb_discard_lg_preallocations(struct -+ } -+ ext4_lock_group(sb, group); -+ list_del(&pa->pa_group_list); -++ ext4_get_group_info(sb, group)->bb_prealloc_nr--; -+ ext4_mb_release_group_pa(&e4b, pa); -+ ext4_unlock_group(sb, group); -+ -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/mballoc.h -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/mballoc.h -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/mballoc.h -+@@ -82,7 +82,7 @@ extern ushort ext4_mballoc_debug; -+ /* -+ * for which requests use 2^N search using buddies -+ */ -+-#define MB_DEFAULT_ORDER2_REQS 2 -++#define MB_DEFAULT_ORDER2_REQS 8 -+ -+ /* -+ * default group prealloc size 512 blocks -diff --git a/ldiskfs/kernel_patches/patches/fc19/ext4-mballoc-pa_free-mismatch.patch b/ldiskfs/kernel_patches/patches/fc19/ext4-mballoc-pa_free-mismatch.patch -new file mode 100644 -index 0000000..df69372 ---- /dev/null -+++ b/ldiskfs/kernel_patches/patches/fc19/ext4-mballoc-pa_free-mismatch.patch -@@ -0,0 +1,109 @@ -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/mballoc.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/mballoc.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/mballoc.c -+@@ -3747,6 +3747,7 @@ ext4_mb_new_inode_pa(struct ext4_allocat -+ INIT_LIST_HEAD(&pa->pa_group_list); -+ pa->pa_deleted = 0; -+ pa->pa_type = MB_INODE_PA; -++ pa->pa_error = 0; -+ -+ mb_debug(1, "new inode pa %p: %llu/%u for %u\n", pa, -+ pa->pa_pstart, pa->pa_len, pa->pa_lstart); -+@@ -3808,6 +3809,7 @@ ext4_mb_new_group_pa(struct ext4_allocat -+ INIT_LIST_HEAD(&pa->pa_group_list); -+ pa->pa_deleted = 0; -+ pa->pa_type = MB_GROUP_PA; -++ pa->pa_error = 0; -+ -+ mb_debug(1, "new group pa %p: %llu/%u for %u\n", pa, -+ pa->pa_pstart, pa->pa_len, pa->pa_lstart); -+@@ -3868,7 +3870,9 @@ ext4_mb_release_inode_pa(struct ext4_bud -+ int err = 0; -+ int free = 0; -+ -++ assert_spin_locked(ext4_group_lock_ptr(sb, e4b->bd_group)); -+ BUG_ON(pa->pa_deleted == 0); -++ BUG_ON(pa->pa_inode == NULL); -+ ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, &bit); -+ grp_blk_start = pa->pa_pstart - EXT4_C2B(sbi, bit); -+ BUG_ON(group != e4b->bd_group && pa->pa_len != 0); -+@@ -3891,12 +3895,18 @@ ext4_mb_release_inode_pa(struct ext4_bud -+ mb_free_blocks(pa->pa_inode, e4b, bit, next - bit); -+ bit = next + 1; -+ } -+- if (free != pa->pa_free) { -+- ext4_msg(e4b->bd_sb, KERN_CRIT, -+- "pa %p: logic %lu, phys. %lu, len %lu", -+- pa, (unsigned long) pa->pa_lstart, -+- (unsigned long) pa->pa_pstart, -+- (unsigned long) pa->pa_len); -++ -++ /* "free < pa->pa_free" means we maybe double alloc the same blocks, -++ * otherwise maybe leave some free blocks unavailable, no need to BUG.*/ -++ if ((free > pa->pa_free && !pa->pa_error) || (free < pa->pa_free)) { -++ ext4_error(sb, "pa free mismatch: [pa %p] " -++ "[phy %lu] [logic %lu] [len %u] [free %u] " -++ "[error %u] [inode %lu] [freed %u]", pa, -++ (unsigned long)pa->pa_pstart, -++ (unsigned long)pa->pa_lstart, -++ (unsigned)pa->pa_len, (unsigned)pa->pa_free, -++ (unsigned)pa->pa_error, pa->pa_inode->i_ino, -++ free); -+ ext4_grp_locked_error(sb, group, 0, 0, "free %u, pa_free %u", -+ free, pa->pa_free); -+ /* -+@@ -3904,6 +3914,7 @@ ext4_mb_release_inode_pa(struct ext4_bud -+ * from the bitmap and continue. -+ */ -+ } -++ BUG_ON(pa->pa_free != free); -+ atomic_add(free, &sbi->s_mb_discarded); -+ -+ return err; -+@@ -4661,6 +4672,25 @@ errout: -+ ac->ac_b_ex.fe_len = 0; -+ ar->len = 0; -+ ext4_mb_show_ac(ac); -++ if (ac->ac_pa) { -++ struct ext4_prealloc_space *pa = ac->ac_pa; -++ -++ /* We can not make sure whether the bitmap has -++ * been updated or not when fail case. So can -++ * not revert pa_free back, just mark pa_error*/ -++ pa->pa_error++; -++ ext4_error(sb, -++ "Updating bitmap error: [err %d] " -++ "[pa %p] [phy %lu] [logic %lu] " -++ "[len %u] [free %u] [error %u] " -++ "[inode %lu]", *errp, pa, -++ (unsigned long)pa->pa_pstart, -++ (unsigned long)pa->pa_lstart, -++ (unsigned)pa->pa_len, -++ (unsigned)pa->pa_free, -++ (unsigned)pa->pa_error, -++ pa->pa_inode ? pa->pa_inode->i_ino : 0); -++ } -+ } -+ ext4_mb_release_context(ac); -+ out: -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/mballoc.h -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/mballoc.h -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/mballoc.h -+@@ -19,6 +19,7 @@ -+ #include <linux/seq_file.h> -+ #include <linux/blkdev.h> -+ #include <linux/mutex.h> -++#include <linux/genhd.h> -+ #include "ext4_jbd2.h" -+ #include "ext4.h" -+ -+@@ -126,6 +127,7 @@ struct ext4_prealloc_space { -+ ext4_grpblk_t pa_free; /* how many blocks are free */ -+ unsigned short pa_type; /* pa type. inode or group */ -+ spinlock_t *pa_obj_lock; -++ unsigned short pa_error; -+ struct inode *pa_inode; /* hack, for history only */ -+ }; -+ -diff --git a/ldiskfs/kernel_patches/patches/fc19/ext4-misc.patch b/ldiskfs/kernel_patches/patches/fc19/ext4-misc.patch -new file mode 100644 -index 0000000..1f0ab31 ---- /dev/null -+++ b/ldiskfs/kernel_patches/patches/fc19/ext4-misc.patch -@@ -0,0 +1,193 @@ -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/ext4.h -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/ext4.h -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/ext4.h -+@@ -1421,6 +1421,11 @@ static inline void ext4_clear_state_flag -+ -+ #define NEXT_ORPHAN(inode) EXT4_I(inode)->i_dtime -+ -++/* Has been moved to linux/magic.h but we need it for Lustre */ -++#define EXT4_SUPER_MAGIC 0xEF53 -++#define JOURNAL_START_HAS_3ARGS 1 -++#define HAVE_LDISKFS_MAP_BLOCKS 1 -++ -+ /* -+ * Codes for operating systems -+ */ -+@@ -2670,6 +2675,8 @@ struct ext4_extent; -+ -+ extern int ext4_ext_tree_init(handle_t *handle, struct inode *); -+ extern int ext4_ext_writepage_trans_blocks(struct inode *, int); -++extern struct buffer_head *ext4_read_inode_bitmap(struct super_block *sb, -++ ext4_group_t block_group); -+ extern int ext4_ext_index_trans_blocks(struct inode *inode, int extents); -+ extern int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, -+ struct ext4_map_blocks *map, int flags); -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/ext4_jbd2.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/ext4_jbd2.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/ext4_jbd2.c -+@@ -34,6 +34,8 @@ static void ext4_put_nojournal(handle_t -+ -+ current->journal_info = handle; -+ } -++EXPORT_SYMBOL(__ext4_journal_get_write_access); -++EXPORT_SYMBOL(__ext4_journal_start_sb); -+ -+ /* -+ * Wrappers for jbd2_journal_start/end. -+@@ -299,3 +301,4 @@ int __ext4_handle_dirty_super(const char -+ mark_buffer_dirty(bh); -+ return err; -+ } -++EXPORT_SYMBOL(__ext4_handle_dirty_metadata); -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/ext4_jbd2.h -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/ext4_jbd2.h -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/ext4_jbd2.h -+@@ -37,6 +37,8 @@ -+ (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS) \ -+ ? 20U : 8U) -+ -++#define ext4_journal_dirty_metadata(handle, bh) \ -++ ext4_handle_dirty_metadata(handle, NULL, bh) -+ /* Extended attribute operations touch at most two data buffers, -+ * two bitmap buffers, and two group summaries, in addition to the inode -+ * and the superblock, which are already accounted for. */ -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/inode.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/inode.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/inode.c -+@@ -4222,6 +4222,9 @@ bad_inode: -+ iget_failed(inode); -+ return ERR_PTR(ret); -+ } -++EXPORT_SYMBOL(ext4_iget); -++EXPORT_SYMBOL(ext4_map_blocks); -++EXPORT_SYMBOL(ext4_truncate); -+ -+ static int ext4_inode_blocks_set(handle_t *handle, -+ struct ext4_inode *raw_inode, -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/super.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/super.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/super.c -+@@ -1141,10 +1141,12 @@ enum { -+ Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, -+ Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota, -+ Opt_noquota, Opt_barrier, Opt_nobarrier, Opt_err, -++ Opt_iopen, Opt_noiopen, Opt_iopen_nopriv, -+ Opt_usrquota, Opt_grpquota, Opt_i_version, -+ Opt_stripe, Opt_delalloc, Opt_nodelalloc, Opt_mblk_io_submit, -+ Opt_nomblk_io_submit, Opt_block_validity, Opt_noblock_validity, -+ Opt_inode_readahead_blks, Opt_journal_ioprio, -++ Opt_mballoc, -+ Opt_dioread_nolock, Opt_dioread_lock, -+ Opt_discard, Opt_nodiscard, Opt_init_itable, Opt_noinit_itable, -+ Opt_max_dir_size_kb, -+@@ -1198,6 +1200,10 @@ static const match_table_t tokens = { -+ {Opt_noquota, "noquota"}, -+ {Opt_quota, "quota"}, -+ {Opt_usrquota, "usrquota"}, -++ {Opt_iopen, "iopen"}, -++ {Opt_noiopen, "noiopen"}, -++ {Opt_iopen_nopriv, "iopen_nopriv"}, -++ {Opt_mballoc, "mballoc"}, -+ {Opt_barrier, "barrier=%u"}, -+ {Opt_barrier, "barrier"}, -+ {Opt_nobarrier, "nobarrier"}, -+@@ -1457,6 +1463,11 @@ static int handle_mount_opt(struct super -+ case Opt_i_version: -+ sb->s_flags |= MS_I_VERSION; -+ return 1; -++ case Opt_iopen: -++ case Opt_noiopen: -++ case Opt_iopen_nopriv: -++ case Opt_mballoc: -++ return 1; -+ } -+ -+ for (m = ext4_mount_opts; m->token != Opt_err; m++) -+@@ -4162,6 +4173,8 @@ out_free_orig: -+ return err ? err : ret; -+ } -+ -++EXPORT_SYMBOL(ext4_force_commit); -++ -+ /* -+ * Setup any per-fs journal parameters now. We'll do this both on -+ * initial mount, once the journal has been initialised but before we've -+@@ -5501,6 +5514,9 @@ static void __exit ext4_exit_fs(void) -+ ext4_exit_es(); -+ } -+ -++EXPORT_SYMBOL(ext4_bread); -++EXPORT_SYMBOL(__ext4_journal_stop); -++ -+ MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); -+ MODULE_DESCRIPTION("Fourth Extended Filesystem"); -+ MODULE_LICENSE("GPL"); -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/namei.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/namei.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/namei.c -+@@ -2210,7 +2210,7 @@ out: -+ * DIR_NLINK feature is set if 1) nlinks > EXT4_LINK_MAX or 2) nlinks == 2, -+ * since this indicates that nlinks count was previously 1. -+ */ -+-static void ext4_inc_count(handle_t *handle, struct inode *inode) -++void ext4_inc_count(handle_t *handle, struct inode *inode) -+ { -+ inc_nlink(inode); -+ if (is_dx(inode) && inode->i_nlink > 1) { -+@@ -2222,16 +2222,18 @@ static void ext4_inc_count(handle_t *han -+ } -+ } -+ } -++EXPORT_SYMBOL(ext4_inc_count); -+ -+ /* -+ * If a directory had nlink == 1, then we should let it be 1. This indicates -+ * directory has >EXT4_LINK_MAX subdirs. -+ */ -+-static void ext4_dec_count(handle_t *handle, struct inode *inode) -++void ext4_dec_count(handle_t *handle, struct inode *inode) -+ { -+ if (!S_ISDIR(inode->i_mode) || inode->i_nlink > 2) -+ drop_nlink(inode); -+ } -++EXPORT_SYMBOL(ext4_dec_count); -+ -+ -+ static int ext4_add_nondir(handle_t *handle, -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/ialloc.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/ialloc.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/ialloc.c -+@@ -111,7 +111,7 @@ void ext4_end_bitmap_read(struct buffer_ -+ * -+ * Return buffer_head of bitmap on success or NULL. -+ */ -+-static struct buffer_head * -++struct buffer_head * -+ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group) -+ { -+ struct ext4_group_desc *desc; -+@@ -191,6 +191,7 @@ verify: -+ set_buffer_verified(bh); -+ return bh; -+ } -++EXPORT_SYMBOL(ext4_read_inode_bitmap); -+ -+ /* -+ * NOTE! When we get the inode, we're the only people -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/extents.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/extents.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/extents.c -+@@ -4774,3 +4774,5 @@ int ext4_fiemap(struct inode *inode, str -+ -+ return error; -+ } -++ -++EXPORT_SYMBOL(ext4_mark_inode_dirty); -diff --git a/ldiskfs/kernel_patches/patches/fc19/ext4-nocmtime.patch b/ldiskfs/kernel_patches/patches/fc19/ext4-nocmtime.patch -new file mode 100644 -index 0000000..0717d15 ---- /dev/null -+++ b/ldiskfs/kernel_patches/patches/fc19/ext4-nocmtime.patch -@@ -0,0 +1,28 @@ -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/xattr.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/xattr.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/xattr.c -+@@ -1432,7 +1432,8 @@ ext4_xattr_set_handle(handle_t *handle, -+ } -+ if (!error) { -+ ext4_xattr_update_super_block(handle, inode->i_sb); -+- inode->i_ctime = ext4_current_time(inode); -++ if (!IS_NOCMTIME(inode)) -++ inode->i_ctime = ext4_current_time(inode); -+ if (!value) -+ ext4_clear_inode_state(inode, EXT4_STATE_NO_EXPAND); -+ error = ext4_mark_iloc_dirty(handle, inode, &is.iloc); -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/namei.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/namei.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/namei.c -+@@ -1797,7 +1797,8 @@ static int add_dirent_to_buf(handle_t *h -+ * happen is that the times are slightly out of date -+ * and/or different from the directory change time. -+ */ -+- dir->i_mtime = dir->i_ctime = ext4_current_time(dir); -++ if (!IS_NOCMTIME(dir)) -++ dir->i_mtime = dir->i_ctime = ext4_current_time(dir); -+ ext4_update_dx_flag(dir); -+ dir->i_version++; -+ ext4_mark_inode_dirty(handle, dir); -diff --git a/ldiskfs/kernel_patches/patches/fc19/ext4-osd-iam-exports.patch b/ldiskfs/kernel_patches/patches/fc19/ext4-osd-iam-exports.patch -new file mode 100644 -index 0000000..1f2cf1a ---- /dev/null -+++ b/ldiskfs/kernel_patches/patches/fc19/ext4-osd-iam-exports.patch -@@ -0,0 +1,56 @@ -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/ext4.h -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/ext4.h -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/ext4.h -+@@ -2167,6 +2167,9 @@ extern struct buffer_head * ext4_find_en -+ struct ext4_dir_entry_2 ** res_dir, -+ int *inlined); -+ #define ll_ext4_find_entry(inode, dentry, res_dir) ext4_find_entry(inode, &(dentry)->d_name, res_dir, NULL) -++extern struct buffer_head *ext4_append(handle_t *handle, -++ struct inode *inode, -++ ext4_lblk_t *block); -+ extern int ext4_add_dot_dotdot(handle_t *handle, struct inode *dir, -+ struct inode *inode); -+ extern int search_dir(struct buffer_head *bh, -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/hash.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/hash.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/hash.c -+@@ -206,3 +206,4 @@ int ext4fs_dirhash(const char *name, int -+ hinfo->minor_hash = minor_hash; -+ return 0; -+ } -++EXPORT_SYMBOL(ext4fs_dirhash); -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/namei.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/namei.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/namei.c -+@@ -48,7 +48,7 @@ -+ #define NAMEI_RA_BLOCKS 4 -+ #define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS) -+ -+-static struct buffer_head *ext4_append(handle_t *handle, -++struct buffer_head *ext4_append(handle_t *handle, -+ struct inode *inode, -+ ext4_lblk_t *block) -+ { -+@@ -163,6 +163,7 @@ static struct buffer_head *__ext4_read_d -+ } -+ return bh; -+ } -++EXPORT_SYMBOL(ext4_append); -+ -+ #ifndef assert -+ #define assert(test) J_ASSERT(test) -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/super.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/super.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/super.c -+@@ -552,6 +552,7 @@ void __ext4_std_error(struct super_block -+ -+ ext4_handle_error(sb); -+ } -++EXPORT_SYMBOL(__ext4_std_error); -+ -+ /* -+ * ext4_abort is a much stronger failure handler than ext4_error. The -diff --git a/ldiskfs/kernel_patches/patches/fc19/ext4-osd-iop-common.patch b/ldiskfs/kernel_patches/patches/fc19/ext4-osd-iop-common.patch -new file mode 100644 -index 0000000..64e82d7 ---- /dev/null -+++ b/ldiskfs/kernel_patches/patches/fc19/ext4-osd-iop-common.patch -@@ -0,0 +1,135 @@ -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/ext4.h -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/ext4.h -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/ext4.h -+@@ -2155,6 +2155,20 @@ extern int ext4_orphan_add(handle_t *, s -+ extern int ext4_orphan_del(handle_t *, struct inode *); -+ extern int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash, -+ __u32 start_minor_hash, __u32 *next_hash); -++extern struct inode *ext4_create_inode(handle_t *handle, -++ struct inode * dir, int mode); -++extern int ext4_add_entry(handle_t *handle, struct dentry *dentry, -++ struct inode *inode); -++extern int ext4_delete_entry(handle_t *handle, struct inode * dir, -++ struct ext4_dir_entry_2 * de_del, -++ struct buffer_head * bh); -++extern struct buffer_head * ext4_find_entry(struct inode *dir, -++ const struct qstr *d_name, -++ struct ext4_dir_entry_2 ** res_dir, -++ int *inlined); -++#define ll_ext4_find_entry(inode, dentry, res_dir) ext4_find_entry(inode, &(dentry)->d_name, res_dir, NULL) -++extern int ext4_add_dot_dotdot(handle_t *handle, struct inode *dir, -++ struct inode *inode); -+ extern int search_dir(struct buffer_head *bh, -+ char *search_buf, -+ int buf_size, -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/namei.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/namei.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/namei.c -+@@ -1218,7 +1218,7 @@ static int is_dx_internal_node(struct in -+ * The returned buffer_head has ->b_count elevated. The caller is expected -+ * to brelse() it when appropriate. -+ */ -+-static struct buffer_head * ext4_find_entry (struct inode *dir, -++struct buffer_head * ext4_find_entry(struct inode *dir, -+ const struct qstr *d_name, -+ struct ext4_dir_entry_2 **res_dir, -+ int *inlined) -+@@ -1362,6 +1362,7 @@ cleanup_and_exit: -+ brelse(bh_use[ra_ptr]); -+ return ret; -+ } -++EXPORT_SYMBOL(ext4_find_entry); -+ -+ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct qstr *d_name, -+ struct ext4_dir_entry_2 **res_dir, int *err) -+@@ -1910,8 +1911,8 @@ static int make_indexed_dir(handle_t *ha -+ * may not sleep between calling this and putting something into -+ * the entry, as someone else might have used it while you slept. -+ */ -+-static int ext4_add_entry(handle_t *handle, struct dentry *dentry, -+- struct inode *inode) -++int ext4_add_entry(handle_t *handle, struct dentry *dentry, -++ struct inode *inode) -+ { -+ struct inode *dir = dentry->d_parent->d_inode; -+ struct buffer_head *bh; -+@@ -1986,6 +1987,7 @@ static int ext4_add_entry(handle_t *hand -+ ext4_set_inode_state(inode, EXT4_STATE_NEWENTRY); -+ return retval; -+ } -++EXPORT_SYMBOL(ext4_add_entry); -+ -+ /* -+ * Returns 0 for success, or a negative error value -+@@ -2172,7 +2174,7 @@ int ext4_generic_delete_entry(handle_t * -+ return -ENOENT; -+ } -+ -+-static int ext4_delete_entry(handle_t *handle, -++int ext4_delete_entry(handle_t *handle, -+ struct inode *dir, -+ struct ext4_dir_entry_2 *de_del, -+ struct buffer_head *bh) -+@@ -2213,7 +2215,7 @@ out: -+ ext4_std_error(dir->i_sb, err); -+ return err; -+ } -+- -++EXPORT_SYMBOL(ext4_delete_entry); -+ /* -+ * DIR_NLINK feature is set if 1) nlinks > EXT4_LINK_MAX or 2) nlinks == 2, -+ * since this indicates that nlinks count was previously 1. -+@@ -2260,6 +2262,27 @@ static int ext4_add_nondir(handle_t *han -+ return err; -+ } -+ -++struct inode * ext4_create_inode(handle_t *handle, struct inode * dir, int mode) -++{ -++ struct inode *inode; -++ -++ inode = ext4_new_inode(handle, dir, mode, NULL, 0, NULL); -++ if (!IS_ERR(inode)) { -++ if (S_ISCHR(mode) || S_ISBLK(mode) || S_ISFIFO(mode)) { -++#ifdef CONFIG_LDISKFS_FS_XATTR -++ inode->i_op = &ext4_special_inode_operations; -++#endif -++ } else { -++ inode->i_op = &ext4_file_inode_operations; -++ inode->i_fop = &ext4_file_operations; -++ ext4_set_aops(inode); -++ } -++ unlock_new_inode(inode); -++ } -++ return inode; -++} -++EXPORT_SYMBOL(ext4_create_inode); -++ -+ /* -+ * By the time this is called, we already have created -+ * the directory cache entry for the new file, but it -+@@ -2448,6 +2471,23 @@ out: -+ return err; -+ } -+ -++/* Initialize @inode as a subdirectory of @dir, and add the -++ * "." and ".." entries into the first directory block. */ -++int ext4_add_dot_dotdot(handle_t *handle, struct inode * dir, -++ struct inode *inode) -++{ -++ if (IS_ERR(handle)) -++ return PTR_ERR(handle); -++ -++ if (IS_DIRSYNC(dir)) -++ ext4_handle_sync(handle); -++ -++ inode->i_op = &ext4_dir_inode_operations; -++ inode->i_fop = &ext4_dir_operations; -++ return ext4_init_new_dir(handle, dir, inode); -++} -++EXPORT_SYMBOL(ext4_add_dot_dotdot); -++ -+ static int ext4_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) -+ { -+ handle_t *handle; -diff --git a/ldiskfs/kernel_patches/patches/fc19/ext4-pdir-fix.patch b/ldiskfs/kernel_patches/patches/fc19/ext4-pdir-fix.patch -new file mode 100644 -index 0000000..db24d01 ---- /dev/null -+++ b/ldiskfs/kernel_patches/patches/fc19/ext4-pdir-fix.patch -@@ -0,0 +1,61 @@ -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/ext4.h -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/ext4.h -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/ext4.h -+@@ -793,6 +793,9 @@ struct ext4_inode_info { -+ __u32 i_dtime; -+ ext4_fsblk_t i_file_acl; -+ -++ /* following fields for parallel directory operations -bzzz */ -++ struct semaphore i_append_sem; -++ -+ /* -+ * i_block_group is the number of the block group which contains -+ * this file's inode. Constant across the lifetime of the inode, -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/namei.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/namei.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/namei.c -+@@ -53,6 +53,7 @@ static struct buffer_head *ext4_append(h -+ ext4_lblk_t *block) -+ { -+ struct buffer_head *bh; -++ struct ext4_inode_info *ei = EXT4_I(inode); -+ int err = 0; -+ -+ if (unlikely(EXT4_SB(inode->i_sb)->s_max_dir_size_kb && -+@@ -60,14 +61,21 @@ static struct buffer_head *ext4_append(h -+ EXT4_SB(inode->i_sb)->s_max_dir_size_kb))) -+ return ERR_PTR(-ENOSPC); -+ -++ /* with parallel dir operations all appends -++ * have to be serialized -bzzz */ -++ down(&ei->i_append_sem); -++ -+ *block = inode->i_size >> inode->i_sb->s_blocksize_bits; -+ -+ bh = ext4_bread(handle, inode, *block, 1, &err); -+- if (!bh) -++ if (!bh) { -++ up(&ei->i_append_sem); -+ return ERR_PTR(err); -++ } -+ inode->i_size += inode->i_sb->s_blocksize; -+ EXT4_I(inode)->i_disksize = inode->i_size; -+ err = ext4_journal_get_write_access(handle, bh); -++ up(&ei->i_append_sem); -+ if (err) { -+ brelse(bh); -+ ext4_std_error(inode->i_sb, err); -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/super.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/super.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/super.c -+@@ -859,6 +859,7 @@ static struct inode *ext4_alloc_inode(st -+ return NULL; -+ -+ ei->vfs_inode.i_version = 1; -++ sema_init(&ei->i_append_sem, 1); -+ INIT_LIST_HEAD(&ei->i_prealloc_list); -+ spin_lock_init(&ei->i_prealloc_lock); -+ ext4_es_init_tree(&ei->i_es_tree); -diff --git a/ldiskfs/kernel_patches/patches/fc19/ext4-prealloc.patch b/ldiskfs/kernel_patches/patches/fc19/ext4-prealloc.patch -new file mode 100644 -index 0000000..cb54844 ---- /dev/null -+++ b/ldiskfs/kernel_patches/patches/fc19/ext4-prealloc.patch -@@ -0,0 +1,387 @@ -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/ext4.h -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/ext4.h -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/ext4.h -+@@ -1237,11 +1237,14 @@ struct ext4_sb_info { -+ -+ /* tunables */ -+ unsigned long s_stripe; -+- unsigned int s_mb_stream_request; -++ unsigned long s_mb_small_req; -++ unsigned long s_mb_large_req; -+ unsigned int s_mb_max_to_scan; -+ unsigned int s_mb_min_to_scan; -+ unsigned int s_mb_stats; -+ unsigned int s_mb_order2_reqs; -++ unsigned long *s_mb_prealloc_table; -++ unsigned long s_mb_prealloc_table_size; -+ unsigned int s_mb_group_prealloc; -+ unsigned int s_max_dir_size_kb; -+ /* where last allocation was done - for stream allocation */ -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/mballoc.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/mballoc.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/mballoc.c -+@@ -1828,6 +1828,25 @@ int ext4_mb_find_by_goal(struct ext4_all -+ return 0; -+ } -+ -++static void ext4_mb_prealloc_table_add(struct ext4_sb_info *sbi, int value) -++{ -++ int i; -++ -++ if (value > (sbi->s_blocks_per_group - 1 - 1 - sbi->s_itb_per_group)) -++ return; -++ -++ for (i = 0; i < sbi->s_mb_prealloc_table_size; i++) { -++ if (sbi->s_mb_prealloc_table[i] == 0) { -++ sbi->s_mb_prealloc_table[i] = value; -++ return; -++ } -++ -++ /* they should add values in order */ -++ if (value <= sbi->s_mb_prealloc_table[i]) -++ return; -++ } -++} -++ -+ /* -+ * The routine scans buddy structures (not bitmap!) from given order -+ * to max order and tries to find big enough chunk to satisfy the req -+@@ -2263,6 +2282,86 @@ static const struct seq_operations ext4_ -+ .show = ext4_mb_seq_groups_show, -+ }; -+ -++#define EXT4_MB_PREALLOC_TABLE "prealloc_table" -++ -++static ssize_t ext4_mb_prealloc_table_proc_write(struct file *file, -++ const char __user *buf, -++ size_t cnt, loff_t *pos) -++{ -++ struct ext4_sb_info *sbi = EXT4_SB(PDE_DATA(file_inode(file))); -++ unsigned long value; -++ unsigned long prev = 0; -++ char str[128]; -++ char *cur; -++ char *end; -++ unsigned long *new_table; -++ int num = 0; -++ int i = 0; -++ -++ if (cnt >= sizeof(str)) -++ return -EINVAL; -++ if (copy_from_user(str, buf, cnt)) -++ return -EFAULT; -++ -++ num = 0; -++ cur = str; -++ end = str + cnt; -++ while (cur < end) { -++ while ((cur < end) && (*cur == ' ')) cur++; -++ value = simple_strtol(cur, &cur, 0); -++ if (value == 0) -++ break; -++ if (value <= prev) -++ return -EINVAL; -++ prev = value; -++ num++; -++ } -++ -++ new_table = kmalloc(num * sizeof(*new_table), GFP_KERNEL); -++ if (new_table == NULL) -++ return -ENOMEM; -++ kfree(sbi->s_mb_prealloc_table); -++ memset(new_table, 0, num * sizeof(*new_table)); -++ sbi->s_mb_prealloc_table = new_table; -++ sbi->s_mb_prealloc_table_size = num; -++ cur = str; -++ end = str + cnt; -++ while (cur < end && i < num) { -++ while ((cur < end) && (*cur == ' ')) cur++; -++ value = simple_strtol(cur, &cur, 0); -++ ext4_mb_prealloc_table_add(sbi, value); -++ i++; -++ } -++ -++ return cnt; -++} -++ -++static int mb_prealloc_table_seq_show(struct seq_file *m, void *v) -++{ -++ struct ext4_sb_info *sbi = EXT4_SB(m->private); -++ int i; -++ -++ for (i = 0; i < sbi->s_mb_prealloc_table_size; i++) -++ seq_printf(m, "%ld ", sbi->s_mb_prealloc_table[i]); -++ seq_printf(m, "\n"); -++ -++ return 0; -++} -++ -++static int mb_prealloc_table_seq_open(struct inode *inode, struct file *file) -++{ -++ return single_open(file, mb_prealloc_table_seq_show, PDE_DATA(inode)); -++} -++ -++struct file_operations ext4_mb_prealloc_seq_fops = { -++ .owner = THIS_MODULE, -++ .open = mb_prealloc_table_seq_open, -++ .read = seq_read, -++ .llseek = seq_lseek, -++ .release = single_release, -++ .write = ext4_mb_prealloc_table_proc_write, -++}; -++ -+ static int ext4_mb_seq_groups_open(struct inode *inode, struct file *file) -+ { -+ struct super_block *sb = PDE_DATA(inode); -+@@ -2557,7 +2656,6 @@ int ext4_mb_init(struct super_block *sb) -+ sbi->s_mb_max_to_scan = MB_DEFAULT_MAX_TO_SCAN; -+ sbi->s_mb_min_to_scan = MB_DEFAULT_MIN_TO_SCAN; -+ sbi->s_mb_stats = MB_DEFAULT_STATS; -+- sbi->s_mb_stream_request = MB_DEFAULT_STREAM_THRESHOLD; -+ sbi->s_mb_order2_reqs = MB_DEFAULT_ORDER2_REQS; -+ /* -+ * The default group preallocation is 512, which for 4k block -+@@ -2581,9 +2679,48 @@ int ext4_mb_init(struct super_block *sb) -+ * RAID stripe size so that preallocations don't fragment -+ * the stripes. -+ */ -+- if (sbi->s_stripe > 1) { -+- sbi->s_mb_group_prealloc = roundup( -+- sbi->s_mb_group_prealloc, sbi->s_stripe); -++ -++ if (sbi->s_stripe == 0) { -++ sbi->s_mb_prealloc_table_size = 10; -++ i = sbi->s_mb_prealloc_table_size * sizeof(unsigned long); -++ sbi->s_mb_prealloc_table = kmalloc(i, GFP_NOFS); -++ if (sbi->s_mb_prealloc_table == NULL) { -++ ret = -ENOMEM; -++ goto out; -++ } -++ memset(sbi->s_mb_prealloc_table, 0, i); -++ -++ ext4_mb_prealloc_table_add(sbi, 4); -++ ext4_mb_prealloc_table_add(sbi, 8); -++ ext4_mb_prealloc_table_add(sbi, 16); -++ ext4_mb_prealloc_table_add(sbi, 32); -++ ext4_mb_prealloc_table_add(sbi, 64); -++ ext4_mb_prealloc_table_add(sbi, 128); -++ ext4_mb_prealloc_table_add(sbi, 256); -++ ext4_mb_prealloc_table_add(sbi, 512); -++ ext4_mb_prealloc_table_add(sbi, 1024); -++ ext4_mb_prealloc_table_add(sbi, 2048); -++ -++ sbi->s_mb_small_req = 256; -++ sbi->s_mb_large_req = 1024; -++ sbi->s_mb_group_prealloc = 512; -++ } else { -++ sbi->s_mb_prealloc_table_size = 3; -++ i = sbi->s_mb_prealloc_table_size * sizeof(unsigned long); -++ sbi->s_mb_prealloc_table = kmalloc(i, GFP_NOFS); -++ if (sbi->s_mb_prealloc_table == NULL) { -++ ret = -ENOMEM; -++ goto out; -++ } -++ memset(sbi->s_mb_prealloc_table, 0, i); -++ -++ ext4_mb_prealloc_table_add(sbi, sbi->s_stripe); -++ ext4_mb_prealloc_table_add(sbi, sbi->s_stripe * 2); -++ ext4_mb_prealloc_table_add(sbi, sbi->s_stripe * 4); -++ -++ sbi->s_mb_small_req = sbi->s_stripe; -++ sbi->s_mb_large_req = sbi->s_stripe * 8; -++ sbi->s_mb_group_prealloc = sbi->s_stripe * 4; -+ } -+ -+ sbi->s_locality_groups = alloc_percpu(struct ext4_locality_group); -+@@ -2605,9 +2742,13 @@ int ext4_mb_init(struct super_block *sb) -+ if (ret != 0) -+ goto out_free_locality_groups; -+ -+- if (sbi->s_proc) -++ if (sbi->s_proc) { -+ proc_create_data("mb_groups", S_IRUGO, sbi->s_proc, -+ &ext4_mb_seq_groups_fops, sb); -++ proc_create_data(EXT4_MB_PREALLOC_TABLE, S_IFREG | S_IRUGO | -++ S_IWUSR, sbi->s_proc, -++ &ext4_mb_prealloc_seq_fops, sb); -++ } -+ -+ return 0; -+ -+@@ -2615,6 +2756,7 @@ out_free_locality_groups: -+ free_percpu(sbi->s_locality_groups); -+ sbi->s_locality_groups = NULL; -+ out_free_groupinfo_slab: -++ kfree(sbi->s_mb_prealloc_table); -+ ext4_groupinfo_destroy_slabs(); -+ out: -+ kfree(sbi->s_mb_offsets); -+@@ -2651,8 +2793,10 @@ int ext4_mb_release(struct super_block * -+ struct ext4_sb_info *sbi = EXT4_SB(sb); -+ struct kmem_cache *cachep = get_groupinfo_cache(sb->s_blocksize_bits); -+ -+- if (sbi->s_proc) -++ if (sbi->s_proc) { -+ remove_proc_entry("mb_groups", sbi->s_proc); -++ remove_proc_entry(EXT4_MB_PREALLOC_TABLE, sbi->s_proc); -++ } -+ -+ if (sbi->s_group_info) { -+ for (i = 0; i < ngroups; i++) { -+@@ -2963,9 +3107,9 @@ ext4_mb_normalize_request(struct ext4_al -+ struct ext4_allocation_request *ar) -+ { -+ struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb); -+- int bsbits, max; -++ int bsbits, i, wind; -+ ext4_lblk_t end; -+- loff_t size, start_off; -++ loff_t size; -+ loff_t orig_size __maybe_unused; -+ ext4_lblk_t start; -+ struct ext4_inode_info *ei = EXT4_I(ac->ac_inode); -+@@ -2998,50 +3142,34 @@ ext4_mb_normalize_request(struct ext4_al -+ size = size << bsbits; -+ if (size < i_size_read(ac->ac_inode)) -+ size = i_size_read(ac->ac_inode); -+- orig_size = size; -++ size = (size + ac->ac_sb->s_blocksize - 1) >> bsbits; -+ -+- /* max size of free chunks */ -+- max = 2 << bsbits; -++ start = wind = 0; -+ -+-#define NRL_CHECK_SIZE(req, size, max, chunk_size) \ -+- (req <= (size) || max <= (chunk_size)) -++ /* let's choose preallocation window depending on file size */ -++ for (i = 0; i < sbi->s_mb_prealloc_table_size; i++) { -++ if (size <= sbi->s_mb_prealloc_table[i]) { -++ wind = sbi->s_mb_prealloc_table[i]; -++ break; -++ } -++ } -++ size = wind; -+ -+- /* first, try to predict filesize */ -+- /* XXX: should this table be tunable? */ -+- start_off = 0; -+- if (size <= 16 * 1024) { -+- size = 16 * 1024; -+- } else if (size <= 32 * 1024) { -+- size = 32 * 1024; -+- } else if (size <= 64 * 1024) { -+- size = 64 * 1024; -+- } else if (size <= 128 * 1024) { -+- size = 128 * 1024; -+- } else if (size <= 256 * 1024) { -+- size = 256 * 1024; -+- } else if (size <= 512 * 1024) { -+- size = 512 * 1024; -+- } else if (size <= 1024 * 1024) { -+- size = 1024 * 1024; -+- } else if (NRL_CHECK_SIZE(size, 4 * 1024 * 1024, max, 2 * 1024)) { -+- start_off = ((loff_t)ac->ac_o_ex.fe_logical >> -+- (21 - bsbits)) << 21; -+- size = 2 * 1024 * 1024; -+- } else if (NRL_CHECK_SIZE(size, 8 * 1024 * 1024, max, 4 * 1024)) { -+- start_off = ((loff_t)ac->ac_o_ex.fe_logical >> -+- (22 - bsbits)) << 22; -+- size = 4 * 1024 * 1024; -+- } else if (NRL_CHECK_SIZE(ac->ac_o_ex.fe_len, -+- (8<<20)>>bsbits, max, 8 * 1024)) { -+- start_off = ((loff_t)ac->ac_o_ex.fe_logical >> -+- (23 - bsbits)) << 23; -+- size = 8 * 1024 * 1024; -+- } else { -+- start_off = (loff_t)ac->ac_o_ex.fe_logical << bsbits; -+- size = ac->ac_o_ex.fe_len << bsbits; -++ if (wind == 0) { -++ __u64 tstart, tend; -++ /* file is quite large, we now preallocate with -++ * the biggest configured window with regart to -++ * logical offset */ -++ wind = sbi->s_mb_prealloc_table[i - 1]; -++ tstart = ac->ac_o_ex.fe_logical; -++ do_div(tstart, wind); -++ start = tstart * wind; -++ tend = ac->ac_o_ex.fe_logical + ac->ac_o_ex.fe_len - 1; -++ do_div(tend, wind); -++ tend = tend * wind + wind; -++ size = tend - start; -+ } -+- size = size >> bsbits; -+- start = start_off >> bsbits; -++ orig_size = size; -+ -+ /* don't cover already allocated blocks in selected range */ -+ if (ar->pleft && start <= ar->lleft) { -+@@ -3117,7 +3245,6 @@ ext4_mb_normalize_request(struct ext4_al -+ } -+ BUG_ON(start + size <= ac->ac_o_ex.fe_logical && -+ start > ac->ac_o_ex.fe_logical); -+- BUG_ON(size <= 0 || size > EXT4_CLUSTERS_PER_GROUP(ac->ac_sb)); -+ -+ /* now prepare goal request */ -+ -+@@ -4056,11 +4183,19 @@ static void ext4_mb_group_or_file(struct -+ -+ /* don't use group allocation for large files */ -+ size = max(size, isize); -+- if (size > sbi->s_mb_stream_request) { -++ if ((ac->ac_o_ex.fe_len >= sbi->s_mb_small_req) || -++ (size >= sbi->s_mb_large_req)) { -+ ac->ac_flags |= EXT4_MB_STREAM_ALLOC; -+ return; -+ } -+ -++ /* -++ * request is so large that we don't care about -++ * streaming - it overweights any possible seek -++ */ -++ if (ac->ac_o_ex.fe_len >= sbi->s_mb_large_req) -++ return; -++ -+ BUG_ON(ac->ac_lg != NULL); -+ /* -+ * locality group prealloc space are per cpu. The reason for having -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/super.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/super.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/super.c -+@@ -2564,7 +2564,8 @@ EXT4_RW_ATTR_SBI_UI(mb_stats, s_mb_stats -+ EXT4_RW_ATTR_SBI_UI(mb_max_to_scan, s_mb_max_to_scan); -+ EXT4_RW_ATTR_SBI_UI(mb_min_to_scan, s_mb_min_to_scan); -+ EXT4_RW_ATTR_SBI_UI(mb_order2_req, s_mb_order2_reqs); -+-EXT4_RW_ATTR_SBI_UI(mb_stream_req, s_mb_stream_request); -++EXT4_RW_ATTR_SBI_UI(mb_small_req, s_mb_small_req); -++EXT4_RW_ATTR_SBI_UI(mb_large_req, s_mb_large_req); -+ EXT4_RW_ATTR_SBI_UI(mb_group_prealloc, s_mb_group_prealloc); -+ EXT4_DEPRECATED_ATTR(max_writeback_mb_bump, 128); -+ EXT4_RW_ATTR_SBI_UI(extent_max_zeroout_kb, s_extent_max_zeroout_kb); -+@@ -2581,7 +2582,8 @@ static struct attribute *ext4_attrs[] = -+ ATTR_LIST(mb_max_to_scan), -+ ATTR_LIST(mb_min_to_scan), -+ ATTR_LIST(mb_order2_req), -+- ATTR_LIST(mb_stream_req), -++ ATTR_LIST(mb_small_req), -++ ATTR_LIST(mb_large_req), -+ ATTR_LIST(mb_group_prealloc), -+ ATTR_LIST(max_writeback_mb_bump), -+ ATTR_LIST(extent_max_zeroout_kb), -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/inode.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/inode.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/inode.c -+@@ -2434,6 +2434,10 @@ static int ext4_writepages(struct addres -+ ext4_journal_stop(handle); -+ } -+ -++ if (wbc->nr_to_write < sbi->s_mb_small_req) { -++ wbc->nr_to_write = sbi->s_mb_small_req; -++ } -++ -+ if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX) -+ range_whole = 1; -+ -diff --git a/ldiskfs/kernel_patches/patches/fc19/ext4_data_in_dirent.patch b/ldiskfs/kernel_patches/patches/fc19/ext4_data_in_dirent.patch -new file mode 100644 -index 0000000..7e8e94d ---- /dev/null -+++ b/ldiskfs/kernel_patches/patches/fc19/ext4_data_in_dirent.patch -@@ -0,0 +1,649 @@ -+this patch implements feature which allows ext4 fs users (e.g. Lustre) -+to store data in ext4 dirent. -+data is stored in ext4 dirent after file-name, this space is accounted -+in de->rec_len. flag EXT4_DIRENT_LUFID added to d_type if extra data -+is present. -+ -+make use of dentry->d_fsdata to pass fid to ext4. so no -+changes in ext4_add_entry() interface required. -+ -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/dir.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/dir.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/dir.c -+@@ -70,11 +70,11 @@ int __ext4_check_dir_entry(const char *f -+ const int rlen = ext4_rec_len_from_disk(de->rec_len, -+ dir->i_sb->s_blocksize); -+ -+- if (unlikely(rlen < EXT4_DIR_REC_LEN(1))) -++ if (unlikely(rlen < __EXT4_DIR_REC_LEN(1))) -+ error_msg = "rec_len is smaller than minimal"; -+ else if (unlikely(rlen % 4 != 0)) -+ error_msg = "rec_len % 4 != 0"; -+- else if (unlikely(rlen < EXT4_DIR_REC_LEN(de->name_len))) -++ else if (unlikely(rlen < EXT4_DIR_REC_LEN(de))) -+ error_msg = "rec_len is too small for name_len"; -+ else if (unlikely(((char *) de - buf) + rlen > size)) -+ error_msg = "directory entry across range"; -+@@ -202,7 +202,7 @@ static int ext4_readdir(struct file *fil -+ * failure will be detected in the -+ * dirent test below. */ -+ if (ext4_rec_len_from_disk(de->rec_len, -+- sb->s_blocksize) < EXT4_DIR_REC_LEN(1)) -++ sb->s_blocksize) < __EXT4_DIR_REC_LEN(1)) -+ break; -+ i += ext4_rec_len_from_disk(de->rec_len, -+ sb->s_blocksize); -+@@ -421,12 +421,17 @@ int ext4_htree_store_dirent(struct file -+ struct fname *fname, *new_fn; -+ struct dir_private_info *info; -+ int len; -++ int extra_data = 1; -+ -+ info = dir_file->private_data; -+ p = &info->root.rb_node; -+ -+ /* Create and allocate the fname structure */ -+- len = sizeof(struct fname) + dirent->name_len + 1; -++ if (dirent->file_type & EXT4_DIRENT_LUFID) -++ extra_data = ext4_get_dirent_data_len(dirent); -++ -++ len = sizeof(struct fname) + dirent->name_len + extra_data; -++ -+ new_fn = kzalloc(len, GFP_KERNEL); -+ if (!new_fn) -+ return -ENOMEM; -+@@ -435,7 +440,7 @@ int ext4_htree_store_dirent(struct file -+ new_fn->inode = le32_to_cpu(dirent->inode); -+ new_fn->name_len = dirent->name_len; -+ new_fn->file_type = dirent->file_type; -+- memcpy(new_fn->name, dirent->name, dirent->name_len); -++ memcpy(new_fn->name, dirent->name, dirent->name_len + extra_data); -+ new_fn->name[dirent->name_len] = 0; -+ -+ while (*p) { -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/ext4.h -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/ext4.h -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/ext4.h -+@@ -1534,6 +1534,7 @@ static inline void ext4_clear_state_flag -+ EXT4_FEATURE_INCOMPAT_64BIT| \ -+ EXT4_FEATURE_INCOMPAT_FLEX_BG| \ -+ EXT4_FEATURE_INCOMPAT_MMP | \ -++ EXT4_FEATURE_INCOMPAT_DIRDATA| \ -+ EXT4_FEATURE_INCOMPAT_INLINE_DATA) -+ #define EXT4_FEATURE_RO_COMPAT_SUPP (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \ -+ EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \ -+@@ -1640,6 +1641,43 @@ struct ext4_dir_entry_tail { -+ #define EXT4_FT_SYMLINK 7 -+ -+ #define EXT4_FT_MAX 8 -++#define EXT4_FT_MASK 0xf -++ -++#if EXT4_FT_MAX > EXT4_FT_MASK -++#error "conflicting EXT4_FT_MAX and EXT4_FT_MASK" -++#endif -++ -++/* -++ * d_type has 4 unused bits, so it can hold four types data. these different -++ * type of data (e.g. lustre data, high 32 bits of 64-bit inode number) can be -++ * stored, in flag order, after file-name in ext4 dirent. -++*/ -++/* -++ * this flag is added to d_type if ext4 dirent has extra data after -++ * filename. this data length is variable and length is stored in first byte -++ * of data. data start after filename NUL byte. -++ * This is used by Lustre FS. -++ */ -++#define EXT4_DIRENT_LUFID 0x10 -++ -++#define EXT4_LUFID_MAGIC 0xAD200907UL -++struct ext4_dentry_param { -++ __u32 edp_magic; /* EXT4_LUFID_MAGIC */ -++ char edp_len; /* size of edp_data in bytes */ -++ char edp_data[0]; /* packed array of data */ -++} __attribute__((packed)); -++ -++static inline unsigned char *ext4_dentry_get_data(struct super_block *sb, -++ struct ext4_dentry_param* p) -++ -++{ -++ if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_DIRDATA)) -++ return NULL; -++ if (p && p->edp_magic == EXT4_LUFID_MAGIC) -++ return &p->edp_len; -++ else -++ return NULL; -++} -+ -+ #define EXT4_FT_DIR_CSUM 0xDE -+ -+@@ -1650,8 +1688,11 @@ struct ext4_dir_entry_tail { -+ */ -+ #define EXT4_DIR_PAD 4 -+ #define EXT4_DIR_ROUND (EXT4_DIR_PAD - 1) -+-#define EXT4_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT4_DIR_ROUND) & \ -++#define __EXT4_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT4_DIR_ROUND) & \ -+ ~EXT4_DIR_ROUND) -++#define EXT4_DIR_REC_LEN(de) (__EXT4_DIR_REC_LEN((de)->name_len +\ -++ ext4_get_dirent_data_len(de))) -++ -+ #define EXT4_MAX_REC_LEN ((1<<16)-1) -+ -+ /* -+@@ -1998,7 +2039,7 @@ extern int ext4_find_dest_de(struct inod -+ void ext4_insert_dentry(struct inode *inode, -+ struct ext4_dir_entry_2 *de, -+ int buf_size, -+- const char *name, int namelen); -++ const char *name, int namelen, void *data); -+ static inline void ext4_update_dx_flag(struct inode *inode) -+ { -+ if (!EXT4_HAS_COMPAT_FEATURE(inode->i_sb, -+@@ -2011,11 +2052,18 @@ static unsigned char ext4_filetype_table -+ -+ static inline unsigned char get_dtype(struct super_block *sb, int filetype) -+ { -++ int fl_index = filetype & EXT4_FT_MASK; -++ -+ if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FILETYPE) || -+- (filetype >= EXT4_FT_MAX)) -++ (fl_index >= EXT4_FT_MAX)) -+ return DT_UNKNOWN; -+ -+- return ext4_filetype_table[filetype]; -++ if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_DIRDATA)) -++ return (ext4_filetype_table[fl_index]); -++ -++ return (ext4_filetype_table[fl_index]) | -++ (filetype & EXT4_DIRENT_LUFID); -++ -+ } -+ -+ /* fsync.c */ -+@@ -2171,7 +2219,7 @@ extern struct buffer_head *ext4_append(h -+ struct inode *inode, -+ ext4_lblk_t *block); -+ extern int ext4_add_dot_dotdot(handle_t *handle, struct inode *dir, -+- struct inode *inode); -++ struct inode *inode, const void *, const void *); -+ extern int search_dir(struct buffer_head *bh, -+ char *search_buf, -+ int buf_size, -+@@ -2827,6 +2875,28 @@ extern struct mutex ext4__aio_mutex[EXT4 -+ extern int ext4_resize_begin(struct super_block *sb); -+ extern void ext4_resize_end(struct super_block *sb); -+ -++/* -++ * Compute the total directory entry data length. -++ * This includes the filename and an implicit NUL terminator (always present), -++ * and optional extensions. Each extension has a bit set in the high 4 bits of -++ * de->file_type, and the extension length is the first byte in each entry. -++ */ -++static inline int ext4_get_dirent_data_len(struct ext4_dir_entry_2 *de) -++{ -++ char *len = de->name + de->name_len + 1 /* NUL terminator */; -++ int dlen = 0; -++ __u8 extra_data_flags = (de->file_type & ~EXT4_FT_MASK) >> 4; -++ -++ while (extra_data_flags) { -++ if (extra_data_flags & 1) { -++ dlen += *len + (dlen == 0); -++ len += *len; -++ } -++ extra_data_flags >>= 1; -++ } -++ return dlen; -++} -++ -+ #endif /* __KERNEL__ */ -+ -+ #endif /* _EXT4_H */ -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/namei.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/namei.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/namei.c -+@@ -247,7 +247,8 @@ static unsigned dx_get_count(struct dx_e -+ static unsigned dx_get_limit(struct dx_entry *entries); -+ static void dx_set_count(struct dx_entry *entries, unsigned value); -+ static void dx_set_limit(struct dx_entry *entries, unsigned value); -+-static unsigned dx_root_limit(struct inode *dir, unsigned infosize); -++static inline unsigned dx_root_limit(struct inode *dir, -++ struct ext4_dir_entry_2 *dot_de, unsigned infosize); -+ static unsigned dx_node_limit(struct inode *dir); -+ static struct dx_frame *dx_probe(const struct qstr *d_name, -+ struct inode *dir, -+@@ -512,11 +513,12 @@ ext4_next_entry(struct ext4_dir_entry_2 -+ */ -+ struct dx_root_info * dx_get_dx_info(struct ext4_dir_entry_2 *de) -+ { -+- /* get dotdot first */ -+- de = (struct ext4_dir_entry_2 *)((char *)de + EXT4_DIR_REC_LEN(1)); -++ BUG_ON(de->name_len != 1); -++ /* get dotdot first */ -++ de = (struct ext4_dir_entry_2 *)((char *)de + EXT4_DIR_REC_LEN(de)); -+ -+- /* dx root info is after dotdot entry */ -+- de = (struct ext4_dir_entry_2 *)((char *)de + EXT4_DIR_REC_LEN(2)); -++ /* dx root info is after dotdot entry */ -++ de = (struct ext4_dir_entry_2 *)((char *)de + EXT4_DIR_REC_LEN(de)); -+ -+ return (struct dx_root_info *) de; -+ } -+@@ -561,10 +563,16 @@ static inline void dx_set_limit(struct d -+ ((struct dx_countlimit *) entries)->limit = cpu_to_le16(value); -+ } -+ -+-static inline unsigned dx_root_limit(struct inode *dir, unsigned infosize) -++static inline unsigned dx_root_limit(struct inode *dir, -++ struct ext4_dir_entry_2 *dot_de, unsigned infosize) -+ { -+- unsigned entry_space = dir->i_sb->s_blocksize - EXT4_DIR_REC_LEN(1) - -+- EXT4_DIR_REC_LEN(2) - infosize; -++ struct ext4_dir_entry_2 *dotdot_de; -++ unsigned entry_space; -++ -++ BUG_ON(dot_de->name_len != 1); -++ dotdot_de = ext4_next_entry(dot_de, dir->i_sb->s_blocksize); -++ entry_space = dir->i_sb->s_blocksize - EXT4_DIR_REC_LEN(dot_de) - -++ EXT4_DIR_REC_LEN(dotdot_de) - infosize; -+ -+ if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb, -+ EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) -+@@ -574,7 +582,7 @@ static inline unsigned dx_root_limit(str -+ -+ static inline unsigned dx_node_limit(struct inode *dir) -+ { -+- unsigned entry_space = dir->i_sb->s_blocksize - EXT4_DIR_REC_LEN(0); -++ unsigned entry_space = dir->i_sb->s_blocksize - __EXT4_DIR_REC_LEN(0); -+ -+ if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb, -+ EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) -+@@ -625,7 +633,7 @@ static struct stats dx_show_leaf(struct -+ printk(":%x.%u ", h.hash, -+ (unsigned) ((char *) de - base)); -+ } -+- space += EXT4_DIR_REC_LEN(de->name_len); -++ space += EXT4_DIR_REC_LEN(de); -+ names++; -+ } -+ de = ext4_next_entry(de, size); -+@@ -731,6 +739,7 @@ dx_probe(const struct qstr *d_name, stru -+ entries = (struct dx_entry *) (((char *)info) + info->info_length); -+ -+ if (dx_get_limit(entries) != dx_root_limit(dir, -++ (struct ext4_dir_entry_2*)bh->b_data, -+ info->info_length)) { -+ ext4_warning(dir->i_sb, "dx entry: limit != root limit"); -+ brelse(bh); -+@@ -924,7 +933,7 @@ static int htree_dirblock_to_tree(struct -+ de = (struct ext4_dir_entry_2 *) bh->b_data; -+ top = (struct ext4_dir_entry_2 *) ((char *) de + -+ dir->i_sb->s_blocksize - -+- EXT4_DIR_REC_LEN(0)); -++ __EXT4_DIR_REC_LEN(0)); -+ for (; de < top; de = ext4_next_entry(de, dir->i_sb->s_blocksize)) { -+ if (ext4_check_dir_entry(dir, NULL, de, bh, -+ bh->b_data, bh->b_size, -+@@ -1516,7 +1525,7 @@ dx_move_dirents(char *from, char *to, st -+ while (count--) { -+ struct ext4_dir_entry_2 *de = (struct ext4_dir_entry_2 *) -+ (from + (map->offs<<2)); -+- rec_len = EXT4_DIR_REC_LEN(de->name_len); -++ rec_len = EXT4_DIR_REC_LEN(de); -+ memcpy (to, de, rec_len); -+ ((struct ext4_dir_entry_2 *) to)->rec_len = -+ ext4_rec_len_to_disk(rec_len, blocksize); -+@@ -1540,7 +1549,7 @@ static struct ext4_dir_entry_2* dx_pack_ -+ while ((char*)de < base + blocksize) { -+ next = ext4_next_entry(de, blocksize); -+ if (de->inode && de->name_len) { -+- rec_len = EXT4_DIR_REC_LEN(de->name_len); -++ rec_len = EXT4_DIR_REC_LEN(de); -+ if (de > to) -+ memmove(to, de, rec_len); -+ to->rec_len = ext4_rec_len_to_disk(rec_len, blocksize); -+@@ -1675,11 +1684,12 @@ int ext4_find_dest_de(struct inode *dir, -+ struct ext4_dir_entry_2 **dest_de) -+ { -+ struct ext4_dir_entry_2 *de; -+- unsigned short reclen = EXT4_DIR_REC_LEN(namelen); -++ unsigned short reclen = __EXT4_DIR_REC_LEN((namelen & 0xffff) + (namelen >> 16)); -+ int nlen, rlen; -+ unsigned int offset = 0; -+ char *top; -+ -++ namelen &= 0xffff; -+ de = (struct ext4_dir_entry_2 *)buf; -+ top = buf + buf_size - reclen; -+ while ((char *) de <= top) { -+@@ -1688,7 +1698,7 @@ int ext4_find_dest_de(struct inode *dir, -+ return -EIO; -+ if (ext4_match(namelen, name, de)) -+ return -EEXIST; -+- nlen = EXT4_DIR_REC_LEN(de->name_len); -++ nlen = EXT4_DIR_REC_LEN(de); -+ rlen = ext4_rec_len_from_disk(de->rec_len, buf_size); -+ if ((de->inode ? rlen - nlen : rlen) >= reclen) -+ break; -+@@ -1705,12 +1715,12 @@ int ext4_find_dest_de(struct inode *dir, -+ void ext4_insert_dentry(struct inode *inode, -+ struct ext4_dir_entry_2 *de, -+ int buf_size, -+- const char *name, int namelen) -++ const char *name, int namelen, void *data) -+ { -+ -+ int nlen, rlen; -+ -+- nlen = EXT4_DIR_REC_LEN(de->name_len); -++ nlen = EXT4_DIR_REC_LEN(de); -+ rlen = ext4_rec_len_from_disk(de->rec_len, buf_size); -+ if (de->inode) { -+ struct ext4_dir_entry_2 *de1 = -+@@ -1724,6 +1734,11 @@ void ext4_insert_dentry(struct inode *in -+ ext4_set_de_type(inode->i_sb, de, inode->i_mode); -+ de->name_len = namelen; -+ memcpy(de->name, name, namelen); -++ if (data) { -++ de->name[namelen] = 0; -++ memcpy(&de->name[namelen + 1], data, *(char *)data); -++ de->file_type |= EXT4_DIRENT_LUFID; -++ } -+ } -+ /* -+ * Add a new entry into a directory (leaf) block. If de is non-NULL, -+@@ -1743,15 +1758,21 @@ static int add_dirent_to_buf(handle_t *h -+ unsigned int blocksize = dir->i_sb->s_blocksize; -+ int csum_size = 0; -+ int err; -++ unsigned char *data; -+ -++ data = ext4_dentry_get_data(inode->i_sb, (struct ext4_dentry_param *) -++ dentry->d_fsdata); -+ if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, -+ EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) -+ csum_size = sizeof(struct ext4_dir_entry_tail); -+ -+ if (!de) { -++ int dlen = 0; -++ if (data) -++ dlen = (*data) + 1; -+ err = ext4_find_dest_de(dir, inode, -+ bh, bh->b_data, blocksize - csum_size, -+- name, namelen, &de); -++ name, namelen + (dlen << 16), &de); -+ if (err) -+ return err; -+ } -+@@ -1763,7 +1784,7 @@ static int add_dirent_to_buf(handle_t *h -+ } -+ -+ /* By now the buffer is marked for journaling */ -+- ext4_insert_dentry(inode, de, blocksize, name, namelen); -++ ext4_insert_dentry(inode, de, blocksize, name, namelen, data); -+ -+ /* -+ * XXX shouldn't update any times until successful -+@@ -1874,7 +1895,8 @@ static int make_indexed_dir(handle_t *ha -+ -+ dx_set_block(entries, 1); -+ dx_set_count(entries, 1); -+- dx_set_limit(entries, dx_root_limit(dir, sizeof(*dx_info))); -++ dx_set_limit(entries, dx_root_limit(dir, -++ dot_de, sizeof(*dx_info))); -+ -+ /* Initialize as for dx_probe */ -+ hinfo.hash_version = dx_info->hash_version; -+@@ -1917,6 +1939,8 @@ static int ext4_update_dotdot(handle_t * -+ struct buffer_head * dir_block; -+ struct ext4_dir_entry_2 * de; -+ int len, journal = 0, err = 0; -++ int dlen = 0; -++ char *data; -+ -+ if (IS_ERR(handle)) -+ return PTR_ERR(handle); -+@@ -1932,19 +1956,24 @@ static int ext4_update_dotdot(handle_t * -+ /* the first item must be "." */ -+ assert(de->name_len == 1 && de->name[0] == '.'); -+ len = le16_to_cpu(de->rec_len); -+- assert(len >= EXT4_DIR_REC_LEN(1)); -+- if (len > EXT4_DIR_REC_LEN(1)) { -++ assert(len >= __EXT4_DIR_REC_LEN(1)); -++ if (len > __EXT4_DIR_REC_LEN(1)) { -+ BUFFER_TRACE(dir_block, "get_write_access"); -+ err = ext4_journal_get_write_access(handle, dir_block); -+ if (err) -+ goto out_journal; -+ -+ journal = 1; -+- de->rec_len = cpu_to_le16(EXT4_DIR_REC_LEN(1)); -++ de->rec_len = cpu_to_le16(EXT4_DIR_REC_LEN(de)); -+ } -+ -+- len -= EXT4_DIR_REC_LEN(1); -+- assert(len == 0 || len >= EXT4_DIR_REC_LEN(2)); -++ len -= EXT4_DIR_REC_LEN(de); -++ data = ext4_dentry_get_data(dir->i_sb, -++ (struct ext4_dentry_param *) dentry->d_fsdata); -++ if (data) -++ dlen = *data + 1; -++ assert(len == 0 || len >= __EXT4_DIR_REC_LEN(2 + dlen)); -++ -+ de = (struct ext4_dir_entry_2 *) -+ ((char *) de + le16_to_cpu(de->rec_len)); -+ if (!journal) { -+@@ -1958,10 +1987,15 @@ static int ext4_update_dotdot(handle_t * -+ if (len > 0) -+ de->rec_len = cpu_to_le16(len); -+ else -+- assert(le16_to_cpu(de->rec_len) >= EXT4_DIR_REC_LEN(2)); -++ assert(le16_to_cpu(de->rec_len) >= __EXT4_DIR_REC_LEN(2)); -+ de->name_len = 2; -+ strcpy (de->name, ".."); -+- ext4_set_de_type(dir->i_sb, de, S_IFDIR); -++ if (data != NULL && ext4_get_dirent_data_len(de) >= dlen) { -++ de->name[2] = 0; -++ memcpy(&de->name[2 + 1], data, *data); -++ ext4_set_de_type(dir->i_sb, de, S_IFDIR); -++ de->file_type |= EXT4_DIRENT_LUFID; -++ } -+ -+ out_journal: -+ if (journal) { -+@@ -2474,37 +2508,70 @@ err_drop_inode: -+ return err; -+ } -+ -++struct tp_block { -++ struct inode *inode; -++ void *data1; -++ void *data2; -++}; -++ -+ struct ext4_dir_entry_2 *ext4_init_dot_dotdot(struct inode *inode, -+ struct ext4_dir_entry_2 *de, -+ int blocksize, int csum_size, -+ unsigned int parent_ino, int dotdot_real_len) -+ { -++ void *data1 = NULL, *data2 = NULL; -++ int dot_reclen = 0; -++ -++ if (dotdot_real_len == 10) { -++ struct tp_block *tpb = (struct tp_block*)inode; -++ data1 = tpb->data1; -++ data2 = tpb->data2; -++ inode = tpb->inode; -++ dotdot_real_len = 0; -++ } -+ de->inode = cpu_to_le32(inode->i_ino); -+ de->name_len = 1; -+- de->rec_len = ext4_rec_len_to_disk(EXT4_DIR_REC_LEN(de->name_len), -+- blocksize); -+ strcpy(de->name, "."); -+ ext4_set_de_type(inode->i_sb, de, S_IFDIR); -+ -++ /* get packed fid data*/ -++ data1 = ext4_dentry_get_data(inode->i_sb, -++ (struct ext4_dentry_param *) data1); -++ if (data1) { -++ de->name[1] = 0; -++ memcpy(&de->name[2], data1, *(char *) data1); -++ de->file_type |= EXT4_DIRENT_LUFID; -++ } -++ de->rec_len = cpu_to_le16(EXT4_DIR_REC_LEN(de)); -++ dot_reclen = cpu_to_le16(de->rec_len); -+ de = ext4_next_entry(de, blocksize); -+ de->inode = cpu_to_le32(parent_ino); -+ de->name_len = 2; -+ if (!dotdot_real_len) -+ de->rec_len = ext4_rec_len_to_disk(blocksize - -+- (csum_size + EXT4_DIR_REC_LEN(1)), -++ (csum_size + dot_reclen), -+ blocksize); -+ else -+ de->rec_len = ext4_rec_len_to_disk( -+- EXT4_DIR_REC_LEN(de->name_len), blocksize); -++ EXT4_DIR_REC_LEN(de), blocksize); -+ strcpy(de->name, ".."); -+ ext4_set_de_type(inode->i_sb, de, S_IFDIR); -++ data2 = ext4_dentry_get_data(inode->i_sb, -++ (struct ext4_dentry_param *) data2); -++ if (data2) { -++ de->name[2] = 0; -++ memcpy(&de->name[3], data2, *(char *) data2); -++ de->file_type |= EXT4_DIRENT_LUFID; -++ } -+ -+ return ext4_next_entry(de, blocksize); -+ } -+ -+ static int ext4_init_new_dir(handle_t *handle, struct inode *dir, -+- struct inode *inode) -++ struct inode *inode, -++ const void *data1, const void *data2) -+ { -++ struct tp_block param; -+ struct buffer_head *dir_block = NULL; -+ struct ext4_dir_entry_2 *de; -+ struct ext4_dir_entry_tail *t; -+@@ -2534,7 +2601,11 @@ static int ext4_init_new_dir(handle_t *h -+ if (err) -+ goto out; -+ de = (struct ext4_dir_entry_2 *)dir_block->b_data; -+- ext4_init_dot_dotdot(inode, de, blocksize, csum_size, dir->i_ino, 0); -++ param.inode = inode; -++ param.data1 = (void *)data1; -++ param.data2 = (void *)data2; -++ ext4_init_dot_dotdot((struct inode *)(¶m), de, blocksize, -++ csum_size, dir->i_ino, 10); -+ set_nlink(inode, 2); -+ if (csum_size) { -+ t = EXT4_DIRENT_TAIL(dir_block->b_data, blocksize); -+@@ -2554,7 +2625,8 @@ out: -+ /* Initialize @inode as a subdirectory of @dir, and add the -+ * "." and ".." entries into the first directory block. */ -+ int ext4_add_dot_dotdot(handle_t *handle, struct inode * dir, -+- struct inode *inode) -++ struct inode *inode, -++ const void *data1, const void *data2) -+ { -+ if (IS_ERR(handle)) -+ return PTR_ERR(handle); -+@@ -2564,7 +2636,7 @@ int ext4_add_dot_dotdot(handle_t *handle -+ -+ inode->i_op = &ext4_dir_inode_operations; -+ inode->i_fop = &ext4_dir_operations; -+- return ext4_init_new_dir(handle, dir, inode); -++ return ext4_init_new_dir(handle, dir, inode, data1, data2); -+ } -+ EXPORT_SYMBOL(ext4_add_dot_dotdot); -+ -+@@ -2592,7 +2664,7 @@ retry: -+ -+ inode->i_op = &ext4_dir_inode_operations; -+ inode->i_fop = &ext4_dir_operations; -+- err = ext4_init_new_dir(handle, dir, inode); -++ err = ext4_init_new_dir(handle, dir, inode, NULL, NULL); -+ if (err) -+ goto out_clear_inode; -+ err = ext4_mark_inode_dirty(handle, inode); -+@@ -2644,7 +2716,7 @@ static int empty_dir(struct inode *inode -+ } -+ -+ sb = inode->i_sb; -+- if (inode->i_size < EXT4_DIR_REC_LEN(1) + EXT4_DIR_REC_LEN(2)) { -++ if (inode->i_size < __EXT4_DIR_REC_LEN(1) + __EXT4_DIR_REC_LEN(2)) { -+ EXT4_ERROR_INODE(inode, "invalid size"); -+ return 1; -+ } -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/inline.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/inline.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/inline.c -+@@ -998,7 +998,7 @@ static int ext4_add_dirent_to_inline(han -+ int err; -+ struct ext4_dir_entry_2 *de; -+ -+- reclen = EXT4_DIR_REC_LEN(namelen); -++ reclen = __EXT4_DIR_REC_LEN(namelen); -+ err = ext4_find_dest_de(dir, inode, iloc->bh, -+ inline_start, inline_size, -+ name, namelen, &de); -+@@ -1008,7 +1008,7 @@ static int ext4_add_dirent_to_inline(han -+ err = ext4_journal_get_write_access(handle, iloc->bh); -+ if (err) -+ return err; -+- ext4_insert_dentry(inode, de, inline_size, name, namelen); -++ ext4_insert_dentry(inode, de, inline_size, name, namelen, NULL); -+ -+ ext4_show_inline_dir(dir, iloc->bh, inline_start, inline_size); -+ -+@@ -1078,7 +1078,7 @@ static int ext4_update_inline_dir(handle -+ int old_size = EXT4_I(dir)->i_inline_size - EXT4_MIN_INLINE_DATA_SIZE; -+ int new_size = get_max_inline_xattr_value_size(dir, iloc); -+ -+- if (new_size - old_size <= EXT4_DIR_REC_LEN(1)) -++ if (new_size - old_size <= __EXT4_DIR_REC_LEN(1)) -+ return -ENOSPC; -+ -+ ret = ext4_update_inline_data(handle, dir, -+@@ -1348,7 +1348,7 @@ int htree_inlinedir_to_tree(struct file -+ fake.name_len = 1; -+ strcpy(fake.name, "."); -+ fake.rec_len = ext4_rec_len_to_disk( -+- EXT4_DIR_REC_LEN(fake.name_len), -++ EXT4_DIR_REC_LEN(&fake), -+ inline_size); -+ ext4_set_de_type(inode->i_sb, &fake, S_IFDIR); -+ de = &fake; -+@@ -1358,7 +1358,7 @@ int htree_inlinedir_to_tree(struct file -+ fake.name_len = 2; -+ strcpy(fake.name, ".."); -+ fake.rec_len = ext4_rec_len_to_disk( -+- EXT4_DIR_REC_LEN(fake.name_len), -++ EXT4_DIR_REC_LEN(&fake), -+ inline_size); -+ ext4_set_de_type(inode->i_sb, &fake, S_IFDIR); -+ de = &fake; -+@@ -1453,8 +1453,8 @@ int ext4_read_inline_dir(struct file *fi -+ * So we will use extra_offset and extra_size to indicate them -+ * during the inline dir iteration. -+ */ -+- dotdot_offset = EXT4_DIR_REC_LEN(1); -+- dotdot_size = dotdot_offset + EXT4_DIR_REC_LEN(2); -++ dotdot_offset = __EXT4_DIR_REC_LEN(1); -++ dotdot_size = dotdot_offset + __EXT4_DIR_REC_LEN(2); -+ extra_offset = dotdot_size - EXT4_INLINE_DOTDOT_SIZE; -+ extra_size = extra_offset + inline_size; -+ -+@@ -1489,7 +1489,7 @@ int ext4_read_inline_dir(struct file *fi -+ * failure will be detected in the -+ * dirent test below. */ -+ if (ext4_rec_len_from_disk(de->rec_len, extra_size) -+- < EXT4_DIR_REC_LEN(1)) -++ < __EXT4_DIR_REC_LEN(1)) -+ break; -+ i += ext4_rec_len_from_disk(de->rec_len, -+ extra_size); -diff --git a/ldiskfs/kernel_patches/patches/fc19/ext4_pdirop.patch b/ldiskfs/kernel_patches/patches/fc19/ext4_pdirop.patch -new file mode 100644 -index 0000000..3af9392 ---- /dev/null -+++ b/ldiskfs/kernel_patches/patches/fc19/ext4_pdirop.patch -@@ -0,0 +1,2252 @@ -+Index: linux-3.11.1-200.fc19.x86_64/include/linux/htree_lock.h -+=================================================================== -+--- /dev/null -++++ linux-3.11.1-200.fc19.x86_64/include/linux/htree_lock.h -+@@ -0,0 +1,187 @@ -++/* -++ * include/linux/htree_lock.h -++ * -++ * Copyright (c) 2011, 2012, Intel Corporation. -++ * -++ * Author: Liang Zhen <liang@whamcloud.com> -++ */ -++ -++/* -++ * htree lock -++ * -++ * htree_lock is an advanced lock, it can support five lock modes (concept is -++ * taken from DLM) and it's a sleeping lock. -++ * -++ * most common use case is: -++ * - create a htree_lock_head for data -++ * - each thread (contender) creates it's own htree_lock -++ * - contender needs to call htree_lock(lock_node, mode) to protect data and -++ * call htree_unlock to release lock -++ * -++ * Also, there is advanced use-case which is more complex, user can have -++ * PW/PR lock on particular key, it's mostly used while user holding shared -++ * lock on the htree (CW, CR) -++ * -++ * htree_lock(lock_node, HTREE_LOCK_CR); lock the htree with CR -++ * htree_node_lock(lock_node, HTREE_LOCK_PR, key...); lock @key with PR -++ * ... -++ * htree_node_unlock(lock_node);; unlock the key -++ * -++ * Another tip is, we can have N-levels of this kind of keys, all we need to -++ * do is specifying N-levels while creating htree_lock_head, then we can -++ * lock/unlock a specific level by: -++ * htree_node_lock(lock_node, mode1, key1, level1...); -++ * do something; -++ * htree_node_lock(lock_node, mode1, key2, level2...); -++ * do something; -++ * htree_node_unlock(lock_node, level2); -++ * htree_node_unlock(lock_node, level1); -++ * -++ * NB: for multi-level, should be careful about locking order to avoid deadlock -++ */ -++ -++#ifndef _LINUX_HTREE_LOCK_H -++#define _LINUX_HTREE_LOCK_H -++ -++#include <linux/list.h> -++#include <linux/spinlock.h> -++#include <linux/sched.h> -++ -++/* -++ * Lock Modes -++ * more details can be found here: -++ * http://en.wikipedia.org/wiki/Distributed_lock_manager -++ */ -++typedef enum { -++ HTREE_LOCK_EX = 0, /* exclusive lock: incompatible with all others */ -++ HTREE_LOCK_PW, /* protected write: allows only CR users */ -++ HTREE_LOCK_PR, /* protected read: allow PR, CR users */ -++ HTREE_LOCK_CW, /* concurrent write: allow CR, CW users */ -++ HTREE_LOCK_CR, /* concurrent read: allow all but EX users */ -++ HTREE_LOCK_MAX, /* number of lock modes */ -++} htree_lock_mode_t; -++ -++#define HTREE_LOCK_NL HTREE_LOCK_MAX -++#define HTREE_LOCK_INVAL 0xdead10c -++ -++enum { -++ HTREE_HBITS_MIN = 2, -++ HTREE_HBITS_DEF = 14, -++ HTREE_HBITS_MAX = 32, -++}; -++ -++enum { -++ HTREE_EVENT_DISABLE = (0), -++ HTREE_EVENT_RD = (1 << HTREE_LOCK_PR), -++ HTREE_EVENT_WR = (1 << HTREE_LOCK_PW), -++ HTREE_EVENT_RDWR = (HTREE_EVENT_RD | HTREE_EVENT_WR), -++}; -++ -++struct htree_lock; -++ -++typedef void (*htree_event_cb_t)(void *target, void *event); -++ -++struct htree_lock_child { -++ struct list_head lc_list; /* granted list */ -++ htree_event_cb_t lc_callback; /* event callback */ -++ unsigned lc_events; /* event types */ -++}; -++ -++struct htree_lock_head { -++ unsigned long lh_lock; /* bits lock */ -++ /* blocked lock list (htree_lock) */ -++ struct list_head lh_blocked_list; -++ /* # key levels */ -++ u16 lh_depth; -++ /* hash bits for key and limit number of locks */ -++ u16 lh_hbits; -++ /* counters for blocked locks */ -++ u16 lh_nblocked[HTREE_LOCK_MAX]; -++ /* counters for granted locks */ -++ u16 lh_ngranted[HTREE_LOCK_MAX]; -++ /* private data */ -++ void *lh_private; -++ /* array of children locks */ -++ struct htree_lock_child lh_children[0]; -++}; -++ -++/* htree_lock_node_t is child-lock for a specific key (ln_value) */ -++struct htree_lock_node { -++ htree_lock_mode_t ln_mode; -++ /* major hash key */ -++ u16 ln_major_key; -++ /* minor hash key */ -++ u16 ln_minor_key; -++ struct list_head ln_major_list; -++ struct list_head ln_minor_list; -++ /* alive list, all locks (granted, blocked, listening) are on it */ -++ struct list_head ln_alive_list; -++ /* blocked list */ -++ struct list_head ln_blocked_list; -++ /* granted list */ -++ struct list_head ln_granted_list; -++ void *ln_ev_target; -++}; -++ -++struct htree_lock { -++ struct task_struct *lk_task; -++ struct htree_lock_head *lk_head; -++ void *lk_private; -++ unsigned lk_depth; -++ htree_lock_mode_t lk_mode; -++ struct list_head lk_blocked_list; -++ struct htree_lock_node lk_nodes[0]; -++}; -++ -++/* create a lock head, which stands for a resource */ -++struct htree_lock_head *htree_lock_head_alloc(unsigned depth, -++ unsigned hbits, unsigned priv); -++/* free a lock head */ -++void htree_lock_head_free(struct htree_lock_head *lhead); -++/* register event callback for child lock at level @depth */ -++void htree_lock_event_attach(struct htree_lock_head *lhead, unsigned depth, -++ unsigned events, htree_event_cb_t callback); -++/* create a lock handle, which stands for a thread */ -++struct htree_lock *htree_lock_alloc(unsigned depth, unsigned pbytes); -++/* free a lock handle */ -++void htree_lock_free(struct htree_lock *lck); -++/* lock htree, when @wait is true, 0 is returned if the lock can't -++ * be granted immediately */ -++int htree_lock_try(struct htree_lock *lck, struct htree_lock_head *lhead, -++ htree_lock_mode_t mode, int wait); -++/* unlock htree */ -++void htree_unlock(struct htree_lock *lck); -++/* unlock and relock htree with @new_mode */ -++int htree_change_lock_try(struct htree_lock *lck, -++ htree_lock_mode_t new_mode, int wait); -++void htree_change_mode(struct htree_lock *lck, htree_lock_mode_t mode); -++/* require child lock (key) of htree at level @dep, @event will be sent to all -++ * listeners on this @key while lock being granted */ -++int htree_node_lock_try(struct htree_lock *lck, htree_lock_mode_t mode, -++ u32 key, unsigned dep, int wait, void *event); -++/* release child lock at level @dep, this lock will listen on it's key -++ * if @event isn't NULL, event_cb will be called against @lck while granting -++ * any other lock at level @dep with the same key */ -++void htree_node_unlock(struct htree_lock *lck, unsigned dep, void *event); -++/* stop listening on child lock at level @dep */ -++void htree_node_stop_listen(struct htree_lock *lck, unsigned dep); -++/* for debug */ -++void htree_lock_stat_print(int depth); -++void htree_lock_stat_reset(void); -++ -++#define htree_lock(lck, lh, mode) htree_lock_try(lck, lh, mode, 1) -++#define htree_change_lock(lck, mode) htree_change_lock_try(lck, mode, 1) -++ -++#define htree_lock_mode(lck) ((lck)->lk_mode) -++ -++#define htree_node_lock(lck, mode, key, dep) \ -++ htree_node_lock_try(lck, mode, key, dep, 1, NULL) -++/* this is only safe in thread context of lock owner */ -++#define htree_node_is_granted(lck, dep) \ -++ ((lck)->lk_nodes[dep].ln_mode != HTREE_LOCK_INVAL && \ -++ (lck)->lk_nodes[dep].ln_mode != HTREE_LOCK_NL) -++/* this is only safe in thread context of lock owner */ -++#define htree_node_is_listening(lck, dep) \ -++ ((lck)->lk_nodes[dep].ln_mode == HTREE_LOCK_NL) -++ -++#endif -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/htree_lock.c -+=================================================================== -+--- /dev/null -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/htree_lock.c -+@@ -0,0 +1,880 @@ -++/* -++ * fs/ext4/htree_lock.c -++ * -++ * Copyright (c) 2011, 2012, Intel Corporation. -++ * -++ * Author: Liang Zhen <liang@whamcloud.com> -++ */ -++#include <linux/jbd2.h> -++#include <linux/hash.h> -++#include <linux/module.h> -++#include <linux/htree_lock.h> -++ -++enum { -++ HTREE_LOCK_BIT_EX = (1 << HTREE_LOCK_EX), -++ HTREE_LOCK_BIT_PW = (1 << HTREE_LOCK_PW), -++ HTREE_LOCK_BIT_PR = (1 << HTREE_LOCK_PR), -++ HTREE_LOCK_BIT_CW = (1 << HTREE_LOCK_CW), -++ HTREE_LOCK_BIT_CR = (1 << HTREE_LOCK_CR), -++}; -++ -++enum { -++ HTREE_LOCK_COMPAT_EX = 0, -++ HTREE_LOCK_COMPAT_PW = HTREE_LOCK_COMPAT_EX | HTREE_LOCK_BIT_CR, -++ HTREE_LOCK_COMPAT_PR = HTREE_LOCK_COMPAT_PW | HTREE_LOCK_BIT_PR, -++ HTREE_LOCK_COMPAT_CW = HTREE_LOCK_COMPAT_PW | HTREE_LOCK_BIT_CW, -++ HTREE_LOCK_COMPAT_CR = HTREE_LOCK_COMPAT_CW | HTREE_LOCK_BIT_PR | -++ HTREE_LOCK_BIT_PW, -++}; -++ -++static int htree_lock_compat[] = { -++ [HTREE_LOCK_EX] HTREE_LOCK_COMPAT_EX, -++ [HTREE_LOCK_PW] HTREE_LOCK_COMPAT_PW, -++ [HTREE_LOCK_PR] HTREE_LOCK_COMPAT_PR, -++ [HTREE_LOCK_CW] HTREE_LOCK_COMPAT_CW, -++ [HTREE_LOCK_CR] HTREE_LOCK_COMPAT_CR, -++}; -++ -++/* max allowed htree-lock depth. -++ * We only need depth=3 for ext4 although user can have higher value. */ -++#define HTREE_LOCK_DEP_MAX 16 -++ -++#ifdef HTREE_LOCK_DEBUG -++ -++static char *hl_name[] = { -++ [HTREE_LOCK_EX] "EX", -++ [HTREE_LOCK_PW] "PW", -++ [HTREE_LOCK_PR] "PR", -++ [HTREE_LOCK_CW] "CW", -++ [HTREE_LOCK_CR] "CR", -++}; -++ -++/* lock stats */ -++struct htree_lock_node_stats { -++ unsigned long long blocked[HTREE_LOCK_MAX]; -++ unsigned long long granted[HTREE_LOCK_MAX]; -++ unsigned long long retried[HTREE_LOCK_MAX]; -++ unsigned long long events; -++}; -++ -++struct htree_lock_stats { -++ struct htree_lock_node_stats nodes[HTREE_LOCK_DEP_MAX]; -++ unsigned long long granted[HTREE_LOCK_MAX]; -++ unsigned long long blocked[HTREE_LOCK_MAX]; -++}; -++ -++static struct htree_lock_stats hl_stats; -++ -++void htree_lock_stat_reset(void) -++{ -++ memset(&hl_stats, 0, sizeof(hl_stats)); -++} -++ -++void htree_lock_stat_print(int depth) -++{ -++ int i; -++ int j; -++ -++ printk(KERN_DEBUG "HTREE LOCK STATS:\n"); -++ for (i = 0; i < HTREE_LOCK_MAX; i++) { -++ printk(KERN_DEBUG "[%s]: G [%10llu], B [%10llu]\n", -++ hl_name[i], hl_stats.granted[i], hl_stats.blocked[i]); -++ } -++ for (i = 0; i < depth; i++) { -++ printk(KERN_DEBUG "HTREE CHILD [%d] STATS:\n", i); -++ for (j = 0; j < HTREE_LOCK_MAX; j++) { -++ printk(KERN_DEBUG -++ "[%s]: G [%10llu], B [%10llu], R [%10llu]\n", -++ hl_name[j], hl_stats.nodes[i].granted[j], -++ hl_stats.nodes[i].blocked[j], -++ hl_stats.nodes[i].retried[j]); -++ } -++ } -++} -++ -++#define lk_grant_inc(m) do { hl_stats.granted[m]++; } while (0) -++#define lk_block_inc(m) do { hl_stats.blocked[m]++; } while (0) -++#define ln_grant_inc(d, m) do { hl_stats.nodes[d].granted[m]++; } while (0) -++#define ln_block_inc(d, m) do { hl_stats.nodes[d].blocked[m]++; } while (0) -++#define ln_retry_inc(d, m) do { hl_stats.nodes[d].retried[m]++; } while (0) -++#define ln_event_inc(d) do { hl_stats.nodes[d].events++; } while (0) -++ -++#else /* !DEBUG */ -++ -++void htree_lock_stat_reset(void) {} -++void htree_lock_stat_print(int depth) {} -++ -++#define lk_grant_inc(m) do {} while (0) -++#define lk_block_inc(m) do {} while (0) -++#define ln_grant_inc(d, m) do {} while (0) -++#define ln_block_inc(d, m) do {} while (0) -++#define ln_retry_inc(d, m) do {} while (0) -++#define ln_event_inc(d) do {} while (0) -++ -++#endif /* DEBUG */ -++ -++EXPORT_SYMBOL(htree_lock_stat_reset); -++EXPORT_SYMBOL(htree_lock_stat_print); -++ -++#define HTREE_DEP_ROOT (-1) -++ -++#define htree_spin_lock(lhead, dep) \ -++ bit_spin_lock((dep) + 1, &(lhead)->lh_lock) -++#define htree_spin_unlock(lhead, dep) \ -++ bit_spin_unlock((dep) + 1, &(lhead)->lh_lock) -++ -++#define htree_key_event_ignore(child, ln) \ -++ (!((child)->lc_events & (1 << (ln)->ln_mode))) -++ -++static int -++htree_key_list_empty(struct htree_lock_node *ln) -++{ -++ return list_empty(&ln->ln_major_list) && list_empty(&ln->ln_minor_list); -++} -++ -++static void -++htree_key_list_del_init(struct htree_lock_node *ln) -++{ -++ struct htree_lock_node *tmp = NULL; -++ -++ if (!list_empty(&ln->ln_minor_list)) { -++ tmp = list_entry(ln->ln_minor_list.next, -++ struct htree_lock_node, ln_minor_list); -++ list_del_init(&ln->ln_minor_list); -++ } -++ -++ if (list_empty(&ln->ln_major_list)) -++ return; -++ -++ if (tmp == NULL) { /* not on minor key list */ -++ list_del_init(&ln->ln_major_list); -++ } else { -++ BUG_ON(!list_empty(&tmp->ln_major_list)); -++ list_replace_init(&ln->ln_major_list, &tmp->ln_major_list); -++ } -++} -++ -++static void -++htree_key_list_replace_init(struct htree_lock_node *old, -++ struct htree_lock_node *new) -++{ -++ if (!list_empty(&old->ln_major_list)) -++ list_replace_init(&old->ln_major_list, &new->ln_major_list); -++ -++ if (!list_empty(&old->ln_minor_list)) -++ list_replace_init(&old->ln_minor_list, &new->ln_minor_list); -++} -++ -++static void -++htree_key_event_enqueue(struct htree_lock_child *child, -++ struct htree_lock_node *ln, int dep, void *event) -++{ -++ struct htree_lock_node *tmp; -++ -++ /* NB: ALWAYS called holding lhead::lh_lock(dep) */ -++ BUG_ON(ln->ln_mode == HTREE_LOCK_NL); -++ if (event == NULL || htree_key_event_ignore(child, ln)) -++ return; -++ -++ /* shouldn't be a very long list */ -++ list_for_each_entry(tmp, &ln->ln_alive_list, ln_alive_list) { -++ if (tmp->ln_mode == HTREE_LOCK_NL) { -++ ln_event_inc(dep); -++ if (child->lc_callback != NULL) -++ child->lc_callback(tmp->ln_ev_target, event); -++ } -++ } -++} -++ -++static int -++htree_node_lock_enqueue(struct htree_lock *newlk, struct htree_lock *curlk, -++ unsigned dep, int wait, void *event) -++{ -++ struct htree_lock_child *child = &newlk->lk_head->lh_children[dep]; -++ struct htree_lock_node *newln = &newlk->lk_nodes[dep]; -++ struct htree_lock_node *curln = &curlk->lk_nodes[dep]; -++ -++ /* NB: ALWAYS called holding lhead::lh_lock(dep) */ -++ /* NB: we only expect PR/PW lock mode at here, only these two modes are -++ * allowed for htree_node_lock(asserted in htree_node_lock_internal), -++ * NL is only used for listener, user can't directly require NL mode */ -++ if ((curln->ln_mode == HTREE_LOCK_NL) || -++ (curln->ln_mode != HTREE_LOCK_PW && -++ newln->ln_mode != HTREE_LOCK_PW)) { -++ /* no conflict, attach it on granted list of @curlk */ -++ if (curln->ln_mode != HTREE_LOCK_NL) { -++ list_add(&newln->ln_granted_list, -++ &curln->ln_granted_list); -++ } else { -++ /* replace key owner */ -++ htree_key_list_replace_init(curln, newln); -++ } -++ -++ list_add(&newln->ln_alive_list, &curln->ln_alive_list); -++ htree_key_event_enqueue(child, newln, dep, event); -++ ln_grant_inc(dep, newln->ln_mode); -++ return 1; /* still hold lh_lock */ -++ } -++ -++ if (!wait) { /* can't grant and don't want to wait */ -++ ln_retry_inc(dep, newln->ln_mode); -++ newln->ln_mode = HTREE_LOCK_INVAL; -++ return -1; /* don't wait and just return -1 */ -++ } -++ -++ newlk->lk_task = current; -++ set_current_state(TASK_UNINTERRUPTIBLE); -++ /* conflict, attach it on blocked list of curlk */ -++ list_add_tail(&newln->ln_blocked_list, &curln->ln_blocked_list); -++ list_add(&newln->ln_alive_list, &curln->ln_alive_list); -++ ln_block_inc(dep, newln->ln_mode); -++ -++ htree_spin_unlock(newlk->lk_head, dep); -++ /* wait to be given the lock */ -++ if (newlk->lk_task != NULL) -++ schedule(); -++ /* granted, no doubt, wake up will set me RUNNING */ -++ if (event == NULL || htree_key_event_ignore(child, newln)) -++ return 0; /* granted without lh_lock */ -++ -++ htree_spin_lock(newlk->lk_head, dep); -++ htree_key_event_enqueue(child, newln, dep, event); -++ return 1; /* still hold lh_lock */ -++} -++ -++/* -++ * get PR/PW access to particular tree-node according to @dep and @key, -++ * it will return -1 if @wait is false and can't immediately grant this lock. -++ * All listeners(HTREE_LOCK_NL) on @dep and with the same @key will get -++ * @event if it's not NULL. -++ * NB: ALWAYS called holding lhead::lh_lock -++ */ -++static int -++htree_node_lock_internal(struct htree_lock_head *lhead, struct htree_lock *lck, -++ htree_lock_mode_t mode, u32 key, unsigned dep, -++ int wait, void *event) -++{ -++ LIST_HEAD (list); -++ struct htree_lock *tmp; -++ struct htree_lock *tmp2; -++ u16 major; -++ u16 minor; -++ u8 reverse; -++ u8 ma_bits; -++ u8 mi_bits; -++ -++ BUG_ON(mode != HTREE_LOCK_PW && mode != HTREE_LOCK_PR); -++ BUG_ON(htree_node_is_granted(lck, dep)); -++ -++ key = hash_long(key, lhead->lh_hbits); -++ -++ mi_bits = lhead->lh_hbits >> 1; -++ ma_bits = lhead->lh_hbits - mi_bits; -++ -++ lck->lk_nodes[dep].ln_major_key = major = key & ((1U << ma_bits) - 1); -++ lck->lk_nodes[dep].ln_minor_key = minor = key >> ma_bits; -++ lck->lk_nodes[dep].ln_mode = mode; -++ -++ /* -++ * The major key list is an ordered list, so searches are started -++ * at the end of the list that is numerically closer to major_key, -++ * so at most half of the list will be walked (for well-distributed -++ * keys). The list traversal aborts early if the expected key -++ * location is passed. -++ */ -++ reverse = (major >= (1 << (ma_bits - 1))); -++ -++ if (reverse) { -++ list_for_each_entry_reverse(tmp, -++ &lhead->lh_children[dep].lc_list, -++ lk_nodes[dep].ln_major_list) { -++ if (tmp->lk_nodes[dep].ln_major_key == major) { -++ goto search_minor; -++ -++ } else if (tmp->lk_nodes[dep].ln_major_key < major) { -++ /* attach _after_ @tmp */ -++ list_add(&lck->lk_nodes[dep].ln_major_list, -++ &tmp->lk_nodes[dep].ln_major_list); -++ goto out_grant_major; -++ } -++ } -++ -++ list_add(&lck->lk_nodes[dep].ln_major_list, -++ &lhead->lh_children[dep].lc_list); -++ goto out_grant_major; -++ -++ } else { -++ list_for_each_entry(tmp, &lhead->lh_children[dep].lc_list, -++ lk_nodes[dep].ln_major_list) { -++ if (tmp->lk_nodes[dep].ln_major_key == major) { -++ goto search_minor; -++ -++ } else if (tmp->lk_nodes[dep].ln_major_key > major) { -++ /* insert _before_ @tmp */ -++ list_add_tail(&lck->lk_nodes[dep].ln_major_list, -++ &tmp->lk_nodes[dep].ln_major_list); -++ goto out_grant_major; -++ } -++ } -++ -++ list_add_tail(&lck->lk_nodes[dep].ln_major_list, -++ &lhead->lh_children[dep].lc_list); -++ goto out_grant_major; -++ } -++ -++ search_minor: -++ /* -++ * NB: minor_key list doesn't have a "head", @list is just a -++ * temporary stub for helping list searching, make sure it's removed -++ * after searching. -++ * minor_key list is an ordered list too. -++ */ -++ list_add_tail(&list, &tmp->lk_nodes[dep].ln_minor_list); -++ -++ reverse = (minor >= (1 << (mi_bits - 1))); -++ -++ if (reverse) { -++ list_for_each_entry_reverse(tmp2, &list, -++ lk_nodes[dep].ln_minor_list) { -++ if (tmp2->lk_nodes[dep].ln_minor_key == minor) { -++ goto out_enqueue; -++ -++ } else if (tmp2->lk_nodes[dep].ln_minor_key < minor) { -++ /* attach _after_ @tmp2 */ -++ list_add(&lck->lk_nodes[dep].ln_minor_list, -++ &tmp2->lk_nodes[dep].ln_minor_list); -++ goto out_grant_minor; -++ } -++ } -++ -++ list_add(&lck->lk_nodes[dep].ln_minor_list, &list); -++ -++ } else { -++ list_for_each_entry(tmp2, &list, -++ lk_nodes[dep].ln_minor_list) { -++ if (tmp2->lk_nodes[dep].ln_minor_key == minor) { -++ goto out_enqueue; -++ -++ } else if (tmp2->lk_nodes[dep].ln_minor_key > minor) { -++ /* insert _before_ @tmp2 */ -++ list_add_tail(&lck->lk_nodes[dep].ln_minor_list, -++ &tmp2->lk_nodes[dep].ln_minor_list); -++ goto out_grant_minor; -++ } -++ } -++ -++ list_add_tail(&lck->lk_nodes[dep].ln_minor_list, &list); -++ } -++ -++ out_grant_minor: -++ if (list.next == &lck->lk_nodes[dep].ln_minor_list) { -++ /* new lock @lck is the first one on minor_key list, which -++ * means it has the smallest minor_key and it should -++ * replace @tmp as minor_key owner */ -++ list_replace_init(&tmp->lk_nodes[dep].ln_major_list, -++ &lck->lk_nodes[dep].ln_major_list); -++ } -++ /* remove the temporary head */ -++ list_del(&list); -++ -++ out_grant_major: -++ ln_grant_inc(dep, lck->lk_nodes[dep].ln_mode); -++ return 1; /* granted with holding lh_lock */ -++ -++ out_enqueue: -++ list_del(&list); /* remove temprary head */ -++ return htree_node_lock_enqueue(lck, tmp2, dep, wait, event); -++} -++ -++/* -++ * release the key of @lck at level @dep, and grant any blocked locks. -++ * caller will still listen on @key if @event is not NULL, which means -++ * caller can see a event (by event_cb) while granting any lock with -++ * the same key at level @dep. -++ * NB: ALWAYS called holding lhead::lh_lock -++ * NB: listener will not block anyone because listening mode is HTREE_LOCK_NL -++ */ -++static void -++htree_node_unlock_internal(struct htree_lock_head *lhead, -++ struct htree_lock *curlk, unsigned dep, void *event) -++{ -++ struct htree_lock_node *curln = &curlk->lk_nodes[dep]; -++ struct htree_lock *grtlk = NULL; -++ struct htree_lock_node *grtln; -++ struct htree_lock *poslk; -++ struct htree_lock *tmplk; -++ -++ if (!htree_node_is_granted(curlk, dep)) -++ return; -++ -++ if (!list_empty(&curln->ln_granted_list)) { -++ /* there is another granted lock */ -++ grtlk = list_entry(curln->ln_granted_list.next, -++ struct htree_lock, -++ lk_nodes[dep].ln_granted_list); -++ list_del_init(&curln->ln_granted_list); -++ } -++ -++ if (grtlk == NULL && !list_empty(&curln->ln_blocked_list)) { -++ /* -++ * @curlk is the only granted lock, so we confirmed: -++ * a) curln is key owner (attached on major/minor_list), -++ * so if there is any blocked lock, it should be attached -++ * on curln->ln_blocked_list -++ * b) we always can grant the first blocked lock -++ */ -++ grtlk = list_entry(curln->ln_blocked_list.next, -++ struct htree_lock, -++ lk_nodes[dep].ln_blocked_list); -++ BUG_ON(grtlk->lk_task == NULL); -++ wake_up_process(grtlk->lk_task); -++ } -++ -++ if (event != NULL && -++ lhead->lh_children[dep].lc_events != HTREE_EVENT_DISABLE) { -++ curln->ln_ev_target = event; -++ curln->ln_mode = HTREE_LOCK_NL; /* listen! */ -++ } else { -++ curln->ln_mode = HTREE_LOCK_INVAL; -++ } -++ -++ if (grtlk == NULL) { /* I must be the only one locking this key */ -++ struct htree_lock_node *tmpln; -++ -++ BUG_ON(htree_key_list_empty(curln)); -++ -++ if (curln->ln_mode == HTREE_LOCK_NL) /* listening */ -++ return; -++ -++ /* not listening */ -++ if (list_empty(&curln->ln_alive_list)) { /* no more listener */ -++ htree_key_list_del_init(curln); -++ return; -++ } -++ -++ tmpln = list_entry(curln->ln_alive_list.next, -++ struct htree_lock_node, ln_alive_list); -++ -++ BUG_ON(tmpln->ln_mode != HTREE_LOCK_NL); -++ -++ htree_key_list_replace_init(curln, tmpln); -++ list_del_init(&curln->ln_alive_list); -++ -++ return; -++ } -++ -++ /* have a granted lock */ -++ grtln = &grtlk->lk_nodes[dep]; -++ if (!list_empty(&curln->ln_blocked_list)) { -++ /* only key owner can be on both lists */ -++ BUG_ON(htree_key_list_empty(curln)); -++ -++ if (list_empty(&grtln->ln_blocked_list)) { -++ list_add(&grtln->ln_blocked_list, -++ &curln->ln_blocked_list); -++ } -++ list_del_init(&curln->ln_blocked_list); -++ } -++ /* -++ * NB: this is the tricky part: -++ * We have only two modes for child-lock (PR and PW), also, -++ * only owner of the key (attached on major/minor_list) can be on -++ * both blocked_list and granted_list, so @grtlk must be one -++ * of these two cases: -++ * -++ * a) @grtlk is taken from granted_list, which means we've granted -++ * more than one lock so @grtlk has to be PR, the first blocked -++ * lock must be PW and we can't grant it at all. -++ * So even @grtlk is not owner of the key (empty blocked_list), -++ * we don't care because we can't grant any lock. -++ * b) we just grant a new lock which is taken from head of blocked -++ * list, and it should be the first granted lock, and it should -++ * be the first one linked on blocked_list. -++ * -++ * Either way, we can get correct result by iterating blocked_list -++ * of @grtlk, and don't have to bother on how to find out -++ * owner of current key. -++ */ -++ list_for_each_entry_safe(poslk, tmplk, &grtln->ln_blocked_list, -++ lk_nodes[dep].ln_blocked_list) { -++ if (grtlk->lk_nodes[dep].ln_mode == HTREE_LOCK_PW || -++ poslk->lk_nodes[dep].ln_mode == HTREE_LOCK_PW) -++ break; -++ /* grant all readers */ -++ list_del_init(&poslk->lk_nodes[dep].ln_blocked_list); -++ list_add(&poslk->lk_nodes[dep].ln_granted_list, -++ &grtln->ln_granted_list); -++ -++ BUG_ON(poslk->lk_task == NULL); -++ wake_up_process(poslk->lk_task); -++ } -++ -++ /* if @curln is the owner of this key, replace it with @grtln */ -++ if (!htree_key_list_empty(curln)) -++ htree_key_list_replace_init(curln, grtln); -++ -++ if (curln->ln_mode == HTREE_LOCK_INVAL) -++ list_del_init(&curln->ln_alive_list); -++} -++ -++/* -++ * it's just wrapper of htree_node_lock_internal, it returns 1 on granted -++ * and 0 only if @wait is false and can't grant it immediately -++ */ -++int -++htree_node_lock_try(struct htree_lock *lck, htree_lock_mode_t mode, -++ u32 key, unsigned dep, int wait, void *event) -++{ -++ struct htree_lock_head *lhead = lck->lk_head; -++ int rc; -++ -++ BUG_ON(dep >= lck->lk_depth); -++ BUG_ON(lck->lk_mode == HTREE_LOCK_INVAL); -++ -++ htree_spin_lock(lhead, dep); -++ rc = htree_node_lock_internal(lhead, lck, mode, key, dep, wait, event); -++ if (rc != 0) -++ htree_spin_unlock(lhead, dep); -++ return rc >= 0; -++} -++EXPORT_SYMBOL(htree_node_lock_try); -++ -++/* it's wrapper of htree_node_unlock_internal */ -++void -++htree_node_unlock(struct htree_lock *lck, unsigned dep, void *event) -++{ -++ struct htree_lock_head *lhead = lck->lk_head; -++ -++ BUG_ON(dep >= lck->lk_depth); -++ BUG_ON(lck->lk_mode == HTREE_LOCK_INVAL); -++ -++ htree_spin_lock(lhead, dep); -++ htree_node_unlock_internal(lhead, lck, dep, event); -++ htree_spin_unlock(lhead, dep); -++} -++EXPORT_SYMBOL(htree_node_unlock); -++ -++/* stop listening on child-lock level @dep */ -++void -++htree_node_stop_listen(struct htree_lock *lck, unsigned dep) -++{ -++ struct htree_lock_node *ln = &lck->lk_nodes[dep]; -++ struct htree_lock_node *tmp; -++ -++ BUG_ON(htree_node_is_granted(lck, dep)); -++ BUG_ON(!list_empty(&ln->ln_blocked_list)); -++ BUG_ON(!list_empty(&ln->ln_granted_list)); -++ -++ if (!htree_node_is_listening(lck, dep)) -++ return; -++ -++ htree_spin_lock(lck->lk_head, dep); -++ ln->ln_mode = HTREE_LOCK_INVAL; -++ ln->ln_ev_target = NULL; -++ -++ if (htree_key_list_empty(ln)) { /* not owner */ -++ list_del_init(&ln->ln_alive_list); -++ goto out; -++ } -++ -++ /* I'm the owner... */ -++ if (list_empty(&ln->ln_alive_list)) { /* no more listener */ -++ htree_key_list_del_init(ln); -++ goto out; -++ } -++ -++ tmp = list_entry(ln->ln_alive_list.next, -++ struct htree_lock_node, ln_alive_list); -++ -++ BUG_ON(tmp->ln_mode != HTREE_LOCK_NL); -++ htree_key_list_replace_init(ln, tmp); -++ list_del_init(&ln->ln_alive_list); -++ out: -++ htree_spin_unlock(lck->lk_head, dep); -++} -++EXPORT_SYMBOL(htree_node_stop_listen); -++ -++/* release all child-locks if we have any */ -++static void -++htree_node_release_all(struct htree_lock *lck) -++{ -++ int i; -++ -++ for (i = 0; i < lck->lk_depth; i++) { -++ if (htree_node_is_granted(lck, i)) -++ htree_node_unlock(lck, i, NULL); -++ else if (htree_node_is_listening(lck, i)) -++ htree_node_stop_listen(lck, i); -++ } -++} -++ -++/* -++ * obtain htree lock, it could be blocked inside if there's conflict -++ * with any granted or blocked lock and @wait is true. -++ * NB: ALWAYS called holding lhead::lh_lock -++ */ -++static int -++htree_lock_internal(struct htree_lock *lck, int wait) -++{ -++ struct htree_lock_head *lhead = lck->lk_head; -++ int granted = 0; -++ int blocked = 0; -++ int i; -++ -++ for (i = 0; i < HTREE_LOCK_MAX; i++) { -++ if (lhead->lh_ngranted[i] != 0) -++ granted |= 1 << i; -++ if (lhead->lh_nblocked[i] != 0) -++ blocked |= 1 << i; -++ } -++ if ((htree_lock_compat[lck->lk_mode] & granted) != granted || -++ (htree_lock_compat[lck->lk_mode] & blocked) != blocked) { -++ /* will block current lock even it just conflicts with any -++ * other blocked lock, so lock like EX wouldn't starve */ -++ if (!wait) -++ return -1; -++ lhead->lh_nblocked[lck->lk_mode]++; -++ lk_block_inc(lck->lk_mode); -++ -++ lck->lk_task = current; -++ list_add_tail(&lck->lk_blocked_list, &lhead->lh_blocked_list); -++ -++ set_current_state(TASK_UNINTERRUPTIBLE); -++ htree_spin_unlock(lhead, HTREE_DEP_ROOT); -++ /* wait to be given the lock */ -++ if (lck->lk_task != NULL) -++ schedule(); -++ /* granted, no doubt. wake up will set me RUNNING */ -++ return 0; /* without lh_lock */ -++ } -++ lhead->lh_ngranted[lck->lk_mode]++; -++ lk_grant_inc(lck->lk_mode); -++ return 1; -++} -++ -++/* release htree lock. NB: ALWAYS called holding lhead::lh_lock */ -++static void -++htree_unlock_internal(struct htree_lock *lck) -++{ -++ struct htree_lock_head *lhead = lck->lk_head; -++ struct htree_lock *tmp; -++ struct htree_lock *tmp2; -++ int granted = 0; -++ int i; -++ -++ BUG_ON(lhead->lh_ngranted[lck->lk_mode] == 0); -++ -++ lhead->lh_ngranted[lck->lk_mode]--; -++ lck->lk_mode = HTREE_LOCK_INVAL; -++ -++ for (i = 0; i < HTREE_LOCK_MAX; i++) { -++ if (lhead->lh_ngranted[i] != 0) -++ granted |= 1 << i; -++ } -++ list_for_each_entry_safe(tmp, tmp2, -++ &lhead->lh_blocked_list, lk_blocked_list) { -++ /* conflict with any granted lock? */ -++ if ((htree_lock_compat[tmp->lk_mode] & granted) != granted) -++ break; -++ -++ list_del_init(&tmp->lk_blocked_list); -++ -++ BUG_ON(lhead->lh_nblocked[tmp->lk_mode] == 0); -++ -++ lhead->lh_nblocked[tmp->lk_mode]--; -++ lhead->lh_ngranted[tmp->lk_mode]++; -++ granted |= 1 << tmp->lk_mode; -++ -++ BUG_ON(tmp->lk_task == NULL); -++ wake_up_process(tmp->lk_task); -++ } -++} -++ -++/* it's wrapper of htree_lock_internal and exported interface. -++ * It always return 1 with granted lock if @wait is true, it can return 0 -++ * if @wait is false and locking request can't be granted immediately */ -++int -++htree_lock_try(struct htree_lock *lck, struct htree_lock_head *lhead, -++ htree_lock_mode_t mode, int wait) -++{ -++ int rc; -++ -++ BUG_ON(lck->lk_depth > lhead->lh_depth); -++ BUG_ON(lck->lk_head != NULL); -++ BUG_ON(lck->lk_task != NULL); -++ -++ lck->lk_head = lhead; -++ lck->lk_mode = mode; -++ -++ htree_spin_lock(lhead, HTREE_DEP_ROOT); -++ rc = htree_lock_internal(lck, wait); -++ if (rc != 0) -++ htree_spin_unlock(lhead, HTREE_DEP_ROOT); -++ return rc >= 0; -++} -++EXPORT_SYMBOL(htree_lock_try); -++ -++/* it's wrapper of htree_unlock_internal and exported interface. -++ * It will release all htree_node_locks and htree_lock */ -++void -++htree_unlock(struct htree_lock *lck) -++{ -++ BUG_ON(lck->lk_head == NULL); -++ BUG_ON(lck->lk_mode == HTREE_LOCK_INVAL); -++ -++ htree_node_release_all(lck); -++ -++ htree_spin_lock(lck->lk_head, HTREE_DEP_ROOT); -++ htree_unlock_internal(lck); -++ htree_spin_unlock(lck->lk_head, HTREE_DEP_ROOT); -++ lck->lk_head = NULL; -++ lck->lk_task = NULL; -++} -++EXPORT_SYMBOL(htree_unlock); -++ -++/* change lock mode */ -++void -++htree_change_mode(struct htree_lock *lck, htree_lock_mode_t mode) -++{ -++ BUG_ON(lck->lk_mode == HTREE_LOCK_INVAL); -++ lck->lk_mode = mode; -++} -++EXPORT_SYMBOL(htree_change_mode); -++ -++/* release htree lock, and lock it again with new mode. -++ * This function will first release all htree_node_locks and htree_lock, -++ * then try to gain htree_lock with new @mode. -++ * It always return 1 with granted lock if @wait is true, it can return 0 -++ * if @wait is false and locking request can't be granted immediately */ -++int -++htree_change_lock_try(struct htree_lock *lck, htree_lock_mode_t mode, int wait) -++{ -++ struct htree_lock_head *lhead = lck->lk_head; -++ int rc; -++ -++ BUG_ON(lhead == NULL); -++ BUG_ON(lck->lk_mode == mode); -++ BUG_ON(lck->lk_mode == HTREE_LOCK_INVAL || mode == HTREE_LOCK_INVAL); -++ -++ htree_node_release_all(lck); -++ -++ htree_spin_lock(lhead, HTREE_DEP_ROOT); -++ htree_unlock_internal(lck); -++ lck->lk_mode = mode; -++ rc = htree_lock_internal(lck, wait); -++ if (rc != 0) -++ htree_spin_unlock(lhead, HTREE_DEP_ROOT); -++ return rc >= 0; -++} -++EXPORT_SYMBOL(htree_change_lock_try); -++ -++/* create a htree_lock head with @depth levels (number of child-locks), -++ * it is a per resoruce structure */ -++struct htree_lock_head * -++htree_lock_head_alloc(unsigned depth, unsigned hbits, unsigned priv) -++{ -++ struct htree_lock_head *lhead; -++ int i; -++ -++ if (depth > HTREE_LOCK_DEP_MAX) { -++ printk(KERN_ERR "%d is larger than max htree_lock depth %d\n", -++ depth, HTREE_LOCK_DEP_MAX); -++ return NULL; -++ } -++ -++ lhead = kzalloc(offsetof(struct htree_lock_head, -++ lh_children[depth]) + priv, GFP_NOFS); -++ if (lhead == NULL) -++ return NULL; -++ -++ if (hbits < HTREE_HBITS_MIN) -++ lhead->lh_hbits = HTREE_HBITS_MIN; -++ else if (hbits > HTREE_HBITS_MAX) -++ lhead->lh_hbits = HTREE_HBITS_MAX; -++ -++ lhead->lh_lock = 0; -++ lhead->lh_depth = depth; -++ INIT_LIST_HEAD(&lhead->lh_blocked_list); -++ if (priv > 0) { -++ lhead->lh_private = (void *)lhead + -++ offsetof(struct htree_lock_head, lh_children[depth]); -++ } -++ -++ for (i = 0; i < depth; i++) { -++ INIT_LIST_HEAD(&lhead->lh_children[i].lc_list); -++ lhead->lh_children[i].lc_events = HTREE_EVENT_DISABLE; -++ } -++ return lhead; -++} -++EXPORT_SYMBOL(htree_lock_head_alloc); -++ -++/* free the htree_lock head */ -++void -++htree_lock_head_free(struct htree_lock_head *lhead) -++{ -++ int i; -++ -++ BUG_ON(!list_empty(&lhead->lh_blocked_list)); -++ for (i = 0; i < lhead->lh_depth; i++) -++ BUG_ON(!list_empty(&lhead->lh_children[i].lc_list)); -++ kfree(lhead); -++} -++EXPORT_SYMBOL(htree_lock_head_free); -++ -++/* register event callback for @events of child-lock at level @dep */ -++void -++htree_lock_event_attach(struct htree_lock_head *lhead, unsigned dep, -++ unsigned events, htree_event_cb_t callback) -++{ -++ BUG_ON(lhead->lh_depth <= dep); -++ lhead->lh_children[dep].lc_events = events; -++ lhead->lh_children[dep].lc_callback = callback; -++} -++EXPORT_SYMBOL(htree_lock_event_attach); -++ -++/* allocate a htree_lock, which is per-thread structure, @pbytes is some -++ * extra-bytes as private data for caller */ -++struct htree_lock * -++htree_lock_alloc(unsigned depth, unsigned pbytes) -++{ -++ struct htree_lock *lck; -++ int i = offsetof(struct htree_lock, lk_nodes[depth]); -++ -++ if (depth > HTREE_LOCK_DEP_MAX) { -++ printk(KERN_ERR "%d is larger than max htree_lock depth %d\n", -++ depth, HTREE_LOCK_DEP_MAX); -++ return NULL; -++ } -++ lck = kzalloc(i + pbytes, GFP_NOFS); -++ if (lck == NULL) -++ return NULL; -++ -++ if (pbytes != 0) -++ lck->lk_private = (void *)lck + i; -++ lck->lk_mode = HTREE_LOCK_INVAL; -++ lck->lk_depth = depth; -++ INIT_LIST_HEAD(&lck->lk_blocked_list); -++ -++ for (i = 0; i < depth; i++) { -++ struct htree_lock_node *node = &lck->lk_nodes[i]; -++ -++ node->ln_mode = HTREE_LOCK_INVAL; -++ INIT_LIST_HEAD(&node->ln_major_list); -++ INIT_LIST_HEAD(&node->ln_minor_list); -++ INIT_LIST_HEAD(&node->ln_alive_list); -++ INIT_LIST_HEAD(&node->ln_blocked_list); -++ INIT_LIST_HEAD(&node->ln_granted_list); -++ } -++ -++ return lck; -++} -++EXPORT_SYMBOL(htree_lock_alloc); -++ -++/* free htree_lock node */ -++void -++htree_lock_free(struct htree_lock *lck) -++{ -++ BUG_ON(lck->lk_mode != HTREE_LOCK_INVAL); -++ kfree(lck); -++} -++EXPORT_SYMBOL(htree_lock_free); -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/ext4.h -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/ext4.h -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/ext4.h -+@@ -27,6 +27,7 @@ -+ #include <linux/mutex.h> -+ #include <linux/timer.h> -+ #include <linux/wait.h> -++#include <linux/htree_lock.h> -+ #include <linux/blockgroup_lock.h> -+ #include <linux/percpu_counter.h> -+ #include <crypto/hash.h> -+@@ -1533,6 +1534,7 @@ static inline void ext4_clear_state_flag -+ EXT4_FEATURE_INCOMPAT_META_BG| \ -+ EXT4_FEATURE_INCOMPAT_EXTENTS| \ -+ EXT4_FEATURE_INCOMPAT_64BIT| \ -++ EXT4_FEATURE_INCOMPAT_LARGEDIR|\ -+ EXT4_FEATURE_INCOMPAT_FLEX_BG| \ -+ EXT4_FEATURE_INCOMPAT_EA_INODE| \ -+ EXT4_FEATURE_INCOMPAT_MMP | \ -+@@ -1958,6 +1960,76 @@ struct mmpd_data { -+ # define NORET_TYPE /**/ -+ # define ATTRIB_NORET __attribute__((noreturn)) -+ # define NORET_AND noreturn, -++/* htree levels for ext4 */ -++#define EXT4_HTREE_LEVEL_COMPAT 2 -++#define EXT4_HTREE_LEVEL 3 -++ -++static inline int -++ext4_dir_htree_level(struct super_block *sb) -++{ -++ return EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_LARGEDIR) ? -++ EXT4_HTREE_LEVEL : EXT4_HTREE_LEVEL_COMPAT; -++} -++ -++/* assume name-hash is protected by upper layer */ -++#define EXT4_HTREE_LOCK_HASH 0 -++ -++enum ext4_pdo_lk_types { -++#if EXT4_HTREE_LOCK_HASH -++ EXT4_LK_HASH, -++#endif -++ EXT4_LK_DX, /* index block */ -++ EXT4_LK_DE, /* directory entry block */ -++ EXT4_LK_SPIN, /* spinlock */ -++ EXT4_LK_MAX, -++}; -++ -++/* read-only bit */ -++#define EXT4_LB_RO(b) (1 << (b)) -++/* read + write, high bits for writer */ -++#define EXT4_LB_RW(b) ((1 << (b)) | (1 << (EXT4_LK_MAX + (b)))) -++ -++enum ext4_pdo_lock_bits { -++ /* DX lock bits */ -++ EXT4_LB_DX_RO = EXT4_LB_RO(EXT4_LK_DX), -++ EXT4_LB_DX = EXT4_LB_RW(EXT4_LK_DX), -++ /* DE lock bits */ -++ EXT4_LB_DE_RO = EXT4_LB_RO(EXT4_LK_DE), -++ EXT4_LB_DE = EXT4_LB_RW(EXT4_LK_DE), -++ /* DX spinlock bits */ -++ EXT4_LB_SPIN_RO = EXT4_LB_RO(EXT4_LK_SPIN), -++ EXT4_LB_SPIN = EXT4_LB_RW(EXT4_LK_SPIN), -++ /* accurate searching */ -++ EXT4_LB_EXACT = EXT4_LB_RO(EXT4_LK_MAX << 1), -++}; -++ -++enum ext4_pdo_lock_opc { -++ /* external */ -++ EXT4_HLOCK_READDIR = (EXT4_LB_DE_RO | EXT4_LB_DX_RO), -++ EXT4_HLOCK_LOOKUP = (EXT4_LB_DE_RO | EXT4_LB_SPIN_RO | -++ EXT4_LB_EXACT), -++ EXT4_HLOCK_DEL = (EXT4_LB_DE | EXT4_LB_SPIN_RO | -++ EXT4_LB_EXACT), -++ EXT4_HLOCK_ADD = (EXT4_LB_DE | EXT4_LB_SPIN_RO), -++ -++ /* internal */ -++ EXT4_HLOCK_LOOKUP_SAFE = (EXT4_LB_DE_RO | EXT4_LB_DX_RO | -++ EXT4_LB_EXACT), -++ EXT4_HLOCK_DEL_SAFE = (EXT4_LB_DE | EXT4_LB_DX_RO | EXT4_LB_EXACT), -++ EXT4_HLOCK_SPLIT = (EXT4_LB_DE | EXT4_LB_DX | EXT4_LB_SPIN), -++}; -++ -++extern struct htree_lock_head *ext4_htree_lock_head_alloc(unsigned hbits); -++#define ext4_htree_lock_head_free(lhead) htree_lock_head_free(lhead) -++ -++extern struct htree_lock *ext4_htree_lock_alloc(void); -++#define ext4_htree_lock_free(lck) htree_lock_free(lck) -++ -++extern void ext4_htree_lock(struct htree_lock *lck, -++ struct htree_lock_head *lhead, -++ struct inode *dir, unsigned flags); -++#define ext4_htree_unlock(lck) htree_unlock(lck) -++ -+ -+ /* bitmap.c */ -+ extern unsigned int ext4_count_free(char *bitmap, unsigned numchars); -+@@ -2050,9 +2122,17 @@ void ext4_insert_dentry(struct inode *in -+ const char *name, int namelen, void *data); -+ static inline void ext4_update_dx_flag(struct inode *inode) -+ { -++ /* Disable it for ldiskfs, because going from a DX directory to -++ * a non-DX directory while it is in use will completely break -++ * the htree-locking. -++ * If we really want to support this operation in the future, -++ * we need to exclusively lock the directory at here which will -++ * increase complexity of code */ -++#if 0 -+ if (!EXT4_HAS_COMPAT_FEATURE(inode->i_sb, -+ EXT4_FEATURE_COMPAT_DIR_INDEX)) -+ ext4_clear_inode_flag(inode, EXT4_INODE_INDEX); -++#endif -+ } -+ static unsigned char ext4_filetype_table[] = { -+ DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK -+@@ -2215,15 +2295,16 @@ extern int ext4_htree_fill_tree(struct f -+ extern struct inode *ext4_create_inode(handle_t *handle, -+ struct inode * dir, int mode); -+ extern int ext4_add_entry(handle_t *handle, struct dentry *dentry, -+- struct inode *inode); -++ struct inode *inode, struct htree_lock *lck); -+ extern int ext4_delete_entry(handle_t *handle, struct inode * dir, -+ struct ext4_dir_entry_2 * de_del, -+ struct buffer_head * bh); -+ extern struct buffer_head * ext4_find_entry(struct inode *dir, -+ const struct qstr *d_name, -+ struct ext4_dir_entry_2 ** res_dir, -+- int *inlined); -+-#define ll_ext4_find_entry(inode, dentry, res_dir) ext4_find_entry(inode, &(dentry)->d_name, res_dir, NULL) -++ int *inlined, struct htree_lock *lck); -++#define ll_ext4_find_entry(inode, dentry, res_dir, lck) \ -++ ext4_find_entry(inode, &(dentry)->d_name, res_dir, NULL, lck) -+ extern struct buffer_head *ext4_append(handle_t *handle, -+ struct inode *inode, -+ ext4_lblk_t *block); -+@@ -2443,13 +2524,15 @@ static inline void ext4_r_blocks_count_s -+ es->s_r_blocks_count_hi = cpu_to_le32(blk >> 32); -+ } -+ -+-static inline loff_t ext4_isize(struct ext4_inode *raw_inode) -++static inline loff_t ext4_isize(struct super_block *sb, -++ struct ext4_inode *raw_inode) -+ { -+- if (S_ISREG(le16_to_cpu(raw_inode->i_mode))) -++ if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_LARGEDIR) || -++ S_ISREG(le16_to_cpu(raw_inode->i_mode))) -+ return ((loff_t)le32_to_cpu(raw_inode->i_size_high) << 32) | -+ le32_to_cpu(raw_inode->i_size_lo); -+- else -+- return (loff_t) le32_to_cpu(raw_inode->i_size_lo); -++ -++ return (loff_t) le32_to_cpu(raw_inode->i_size_lo); -+ } -+ -+ static inline void ext4_isize_set(struct ext4_inode *raw_inode, loff_t i_size) -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/namei.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/namei.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/namei.c -+@@ -254,7 +254,7 @@ static struct dx_frame *dx_probe(const s -+ struct inode *dir, -+ struct dx_hash_info *hinfo, -+ struct dx_frame *frame, -+- int *err); -++ struct htree_lock *lck, int *err); -+ static void dx_release(struct dx_frame *frames); -+ static int dx_make_map(struct ext4_dir_entry_2 *de, unsigned blocksize, -+ struct dx_hash_info *hinfo, struct dx_map_entry map[]); -+@@ -267,13 +267,13 @@ static void dx_insert_block(struct dx_fr -+ static int ext4_htree_next_block(struct inode *dir, __u32 hash, -+ struct dx_frame *frame, -+ struct dx_frame *frames, -+- __u32 *start_hash); -++ __u32 *start_hash, struct htree_lock *lck); -+ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, -+ const struct qstr *d_name, -+ struct ext4_dir_entry_2 **res_dir, -+- int *err); -++ struct htree_lock *lck, int *err); -+ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry, -+- struct inode *inode); -++ struct inode *inode, struct htree_lock *lck); -+ -+ /* checksumming functions */ -+ void initialize_dirent_tail(struct ext4_dir_entry_tail *t, -+@@ -525,7 +525,7 @@ struct dx_root_info * dx_get_dx_info(str -+ -+ static inline ext4_lblk_t dx_get_block(struct dx_entry *entry) -+ { -+- return le32_to_cpu(entry->block) & 0x00ffffff; -++ return le32_to_cpu(entry->block) & 0x0fffffff; -+ } -+ -+ static inline void dx_set_block(struct dx_entry *entry, ext4_lblk_t value) -+@@ -675,6 +675,223 @@ struct stats dx_show_entries(struct dx_h -+ } -+ #endif /* DX_DEBUG */ -+ -++/* private data for htree_lock */ -++struct ext4_dir_lock_data { -++ unsigned ld_flags; /* bits-map for lock types */ -++ unsigned ld_count; /* # entries of the last DX block */ -++ struct dx_entry ld_at_entry; /* copy of leaf dx_entry */ -++ struct dx_entry *ld_at; /* position of leaf dx_entry */ -++}; -++ -++#define ext4_htree_lock_data(l) ((struct ext4_dir_lock_data *)(l)->lk_private) -++ -++/* NB: ext4_lblk_t is 32 bits so we use high bits to identify invalid blk */ -++#define EXT4_HTREE_NODE_CHANGED (0xcafeULL << 32) -++ -++static void ext4_htree_event_cb(void *target, void *event) -++{ -++ u64 *block = (u64 *)target; -++ -++ if (*block == dx_get_block((struct dx_entry *)event)) -++ *block = EXT4_HTREE_NODE_CHANGED; -++} -++ -++struct htree_lock_head *ext4_htree_lock_head_alloc(unsigned hbits) -++{ -++ struct htree_lock_head *lhead; -++ -++ lhead = htree_lock_head_alloc(EXT4_LK_MAX, hbits, 0); -++ if (lhead != NULL) { -++ htree_lock_event_attach(lhead, EXT4_LK_SPIN, HTREE_EVENT_WR, -++ ext4_htree_event_cb); -++ } -++ return lhead; -++} -++EXPORT_SYMBOL(ext4_htree_lock_head_alloc); -++ -++struct htree_lock *ext4_htree_lock_alloc(void) -++{ -++ return htree_lock_alloc(EXT4_LK_MAX, -++ sizeof(struct ext4_dir_lock_data)); -++} -++EXPORT_SYMBOL(ext4_htree_lock_alloc); -++ -++static htree_lock_mode_t ext4_htree_mode(unsigned flags) -++{ -++ switch (flags) { -++ default: /* 0 or unknown flags require EX lock */ -++ return HTREE_LOCK_EX; -++ case EXT4_HLOCK_READDIR: -++ return HTREE_LOCK_PR; -++ case EXT4_HLOCK_LOOKUP: -++ return HTREE_LOCK_CR; -++ case EXT4_HLOCK_DEL: -++ case EXT4_HLOCK_ADD: -++ return HTREE_LOCK_CW; -++ } -++} -++ -++/* return PR for read-only operations, otherwise return EX */ -++static inline htree_lock_mode_t ext4_htree_safe_mode(unsigned flags) -++{ -++ int writer = (flags & EXT4_LB_DE) == EXT4_LB_DE; -++ -++ /* 0 requires EX lock */ -++ return (flags == 0 || writer) ? HTREE_LOCK_EX : HTREE_LOCK_PR; -++} -++ -++static int ext4_htree_safe_locked(struct htree_lock *lck) -++{ -++ int writer; -++ -++ if (lck == NULL || lck->lk_mode == HTREE_LOCK_EX) -++ return 1; -++ -++ writer = (ext4_htree_lock_data(lck)->ld_flags & EXT4_LB_DE) == -++ EXT4_LB_DE; -++ if (writer) /* all readers & writers are excluded? */ -++ return lck->lk_mode == HTREE_LOCK_EX; -++ -++ /* all writers are excluded? */ -++ return lck->lk_mode == HTREE_LOCK_PR || -++ lck->lk_mode == HTREE_LOCK_PW || -++ lck->lk_mode == HTREE_LOCK_EX; -++} -++ -++/* relock htree_lock with EX mode if it's change operation, otherwise -++ * relock it with PR mode. It's noop if PDO is disabled. */ -++static void ext4_htree_safe_relock(struct htree_lock *lck) -++{ -++ if (!ext4_htree_safe_locked(lck)) { -++ unsigned flags = ext4_htree_lock_data(lck)->ld_flags; -++ -++ htree_change_lock(lck, ext4_htree_safe_mode(flags)); -++ } -++} -++ -++void ext4_htree_lock(struct htree_lock *lck, struct htree_lock_head *lhead, -++ struct inode *dir, unsigned flags) -++{ -++ htree_lock_mode_t mode = is_dx(dir) ? ext4_htree_mode(flags) : -++ ext4_htree_safe_mode(flags); -++ -++ ext4_htree_lock_data(lck)->ld_flags = flags; -++ htree_lock(lck, lhead, mode); -++ if (!is_dx(dir)) -++ ext4_htree_safe_relock(lck); /* make sure it's safe locked */ -++} -++EXPORT_SYMBOL(ext4_htree_lock); -++ -++static int ext4_htree_node_lock(struct htree_lock *lck, struct dx_entry *at, -++ unsigned lmask, int wait, void *ev) -++{ -++ u32 key = (at == NULL) ? 0 : dx_get_block(at); -++ u32 mode; -++ -++ /* NOOP if htree is well protected or caller doesn't require the lock */ -++ if (ext4_htree_safe_locked(lck) || -++ !(ext4_htree_lock_data(lck)->ld_flags & lmask)) -++ return 1; -++ -++ mode = (ext4_htree_lock_data(lck)->ld_flags & lmask) == lmask ? -++ HTREE_LOCK_PW : HTREE_LOCK_PR; -++ while (1) { -++ if (htree_node_lock_try(lck, mode, key, ffz(~lmask), wait, ev)) -++ return 1; -++ if (!(lmask & EXT4_LB_SPIN)) /* not a spinlock */ -++ return 0; -++ cpu_relax(); /* spin until granted */ -++ } -++} -++ -++static int ext4_htree_node_locked(struct htree_lock *lck, unsigned lmask) -++{ -++ return ext4_htree_safe_locked(lck) || -++ htree_node_is_granted(lck, ffz(~lmask)); -++} -++ -++static void ext4_htree_node_unlock(struct htree_lock *lck, -++ unsigned lmask, void *buf) -++{ -++ /* NB: it's safe to call mutiple times or even it's not locked */ -++ if (!ext4_htree_safe_locked(lck) && -++ htree_node_is_granted(lck, ffz(~lmask))) -++ htree_node_unlock(lck, ffz(~lmask), buf); -++} -++ -++#define ext4_htree_dx_lock(lck, key) \ -++ ext4_htree_node_lock(lck, key, EXT4_LB_DX, 1, NULL) -++#define ext4_htree_dx_lock_try(lck, key) \ -++ ext4_htree_node_lock(lck, key, EXT4_LB_DX, 0, NULL) -++#define ext4_htree_dx_unlock(lck) \ -++ ext4_htree_node_unlock(lck, EXT4_LB_DX, NULL) -++#define ext4_htree_dx_locked(lck) \ -++ ext4_htree_node_locked(lck, EXT4_LB_DX) -++ -++static void ext4_htree_dx_need_lock(struct htree_lock *lck) -++{ -++ struct ext4_dir_lock_data *ld; -++ -++ if (ext4_htree_safe_locked(lck)) -++ return; -++ -++ ld = ext4_htree_lock_data(lck); -++ switch (ld->ld_flags) { -++ default: -++ return; -++ case EXT4_HLOCK_LOOKUP: -++ ld->ld_flags = EXT4_HLOCK_LOOKUP_SAFE; -++ return; -++ case EXT4_HLOCK_DEL: -++ ld->ld_flags = EXT4_HLOCK_DEL_SAFE; -++ return; -++ case EXT4_HLOCK_ADD: -++ ld->ld_flags = EXT4_HLOCK_SPLIT; -++ return; -++ } -++} -++ -++#define ext4_htree_de_lock(lck, key) \ -++ ext4_htree_node_lock(lck, key, EXT4_LB_DE, 1, NULL) -++#define ext4_htree_de_unlock(lck) \ -++ ext4_htree_node_unlock(lck, EXT4_LB_DE, NULL) -++ -++#define ext4_htree_spin_lock(lck, key, event) \ -++ ext4_htree_node_lock(lck, key, EXT4_LB_SPIN, 0, event) -++#define ext4_htree_spin_unlock(lck) \ -++ ext4_htree_node_unlock(lck, EXT4_LB_SPIN, NULL) -++#define ext4_htree_spin_unlock_listen(lck, p) \ -++ ext4_htree_node_unlock(lck, EXT4_LB_SPIN, p) -++ -++static void ext4_htree_spin_stop_listen(struct htree_lock *lck) -++{ -++ if (!ext4_htree_safe_locked(lck) && -++ htree_node_is_listening(lck, ffz(~EXT4_LB_SPIN))) -++ htree_node_stop_listen(lck, ffz(~EXT4_LB_SPIN)); -++} -++ -++enum { -++ DX_HASH_COL_IGNORE, /* ignore collision while probing frames */ -++ DX_HASH_COL_YES, /* there is collision and it does matter */ -++ DX_HASH_COL_NO, /* there is no collision */ -++}; -++ -++static int dx_probe_hash_collision(struct htree_lock *lck, -++ struct dx_entry *entries, -++ struct dx_entry *at, u32 hash) -++{ -++ if (!(ext4_htree_lock_data(lck)->ld_flags & EXT4_LB_EXACT)) { -++ return DX_HASH_COL_IGNORE; /* don't care about collision */ -++ -++ } else if (at == entries + dx_get_count(entries) - 1) { -++ return DX_HASH_COL_IGNORE; /* not in any leaf of this DX */ -++ -++ } else { /* hash collision? */ -++ return ((dx_get_hash(at + 1) & ~1) == hash) ? -++ DX_HASH_COL_YES : DX_HASH_COL_NO; -++ } -++} -++ -+ /* -+ * Probe for a directory leaf block to search. -+ * -+@@ -686,16 +903,17 @@ struct stats dx_show_entries(struct dx_h -+ */ -+ static struct dx_frame * -+ dx_probe(const struct qstr *d_name, struct inode *dir, -+- struct dx_hash_info *hinfo, struct dx_frame *frame_in, int *err) -++ struct dx_hash_info *hinfo, struct dx_frame *frame_in, -++ struct htree_lock *lck, int *err) -+ { -+ unsigned count, indirect; -+- struct dx_entry *at, *entries, *p, *q, *m; -++ struct dx_entry *at, *entries, *p, *q, *m, *dx = NULL; -+ struct dx_root_info * info; -+ struct buffer_head *bh; -+ struct dx_frame *frame = frame_in; -+ u32 hash; -+ -+- frame->bh = NULL; -++ memset(frame_in, 0, EXT4_HTREE_LEVEL * sizeof(frame_in[0])); -+ bh = ext4_read_dirblock(dir, 0, INDEX); -+ if (IS_ERR(bh)) { -+ *err = PTR_ERR(bh); -+@@ -728,9 +946,16 @@ dx_probe(const struct qstr *d_name, stru -+ goto fail; -+ } -+ -+- if ((indirect = info->indirect_levels) > 1) { -+- ext4_warning(dir->i_sb, "Unimplemented inode hash depth: %#06x", -+- info->indirect_levels); -++ indirect = info->indirect_levels; -++ if (indirect >= ext4_dir_htree_level(dir->i_sb)) { -++ ext4_warning(dir->i_sb, -++ "Directory (ino: %lu) htree depth %#06x exceed " -++ "supported value", dir->i_ino, -++ ext4_dir_htree_level(dir->i_sb)); -++ if (ext4_dir_htree_level(dir->i_sb) < EXT4_HTREE_LEVEL) { -++ ext4_warning(dir->i_sb, "Enable large directory " -++ "feature to access it"); -++ } -+ brelse(bh); -+ *err = ERR_BAD_DX_DIR; -+ goto fail; -+@@ -750,8 +975,15 @@ dx_probe(const struct qstr *d_name, stru -+ dxtrace(printk("Look up %x", hash)); -+ while (1) -+ { -++ if (indirect == 0) { /* the last index level */ -++ /* NB: ext4_htree_dx_lock() could be noop if -++ * DX-lock flag is not set for current operation */ -++ ext4_htree_dx_lock(lck, dx); -++ ext4_htree_spin_lock(lck, dx, NULL); -++ } -+ count = dx_get_count(entries); -+- if (!count || count > dx_get_limit(entries)) { -++ if (count == 0 || count > dx_get_limit(entries)) { -++ ext4_htree_spin_unlock(lck); /* release spin */ -+ ext4_warning(dir->i_sb, -+ "dx entry: no count or count > limit"); -+ brelse(bh); -+@@ -792,7 +1024,70 @@ dx_probe(const struct qstr *d_name, stru -+ frame->bh = bh; -+ frame->entries = entries; -+ frame->at = at; -+- if (!indirect--) return frame; -++ -++ if (indirect == 0) { /* the last index level */ -++ struct ext4_dir_lock_data *ld; -++ u64 myblock; -++ -++ /* By default we only lock DE-block, however, we will -++ * also lock the last level DX-block if: -++ * a) there is hash collision -++ * we will set DX-lock flag (a few lines below) -++ * and redo to lock DX-block -++ * see detail in dx_probe_hash_collision() -++ * b) it's a retry from splitting -++ * we need to lock the last level DX-block so nobody -++ * else can split any leaf blocks under the same -++ * DX-block, see detail in ext4_dx_add_entry() -++ */ -++ if (ext4_htree_dx_locked(lck)) { -++ /* DX-block is locked, just lock DE-block -++ * and return */ -++ ext4_htree_spin_unlock(lck); -++ if (!ext4_htree_safe_locked(lck)) -++ ext4_htree_de_lock(lck, frame->at); -++ return frame; -++ } -++ /* it's pdirop and no DX lock */ -++ if (dx_probe_hash_collision(lck, entries, at, hash) == -++ DX_HASH_COL_YES) { -++ /* found hash collision, set DX-lock flag -++ * and retry to abtain DX-lock */ -++ ext4_htree_spin_unlock(lck); -++ ext4_htree_dx_need_lock(lck); -++ continue; -++ } -++ ld = ext4_htree_lock_data(lck); -++ /* because I don't lock DX, so @at can't be trusted -++ * after I release spinlock so I have to save it */ -++ ld->ld_at = at; -++ ld->ld_at_entry = *at; -++ ld->ld_count = dx_get_count(entries); -++ -++ frame->at = &ld->ld_at_entry; -++ myblock = dx_get_block(at); -++ -++ /* NB: ordering locking */ -++ ext4_htree_spin_unlock_listen(lck, &myblock); -++ /* other thread can split this DE-block because: -++ * a) I don't have lock for the DE-block yet -++ * b) I released spinlock on DX-block -++ * if it happened I can detect it by listening -++ * splitting event on this DE-block */ -++ ext4_htree_de_lock(lck, frame->at); -++ ext4_htree_spin_stop_listen(lck); -++ -++ if (myblock == EXT4_HTREE_NODE_CHANGED) { -++ /* someone split this DE-block before -++ * I locked it, I need to retry and lock -++ * valid DE-block */ -++ ext4_htree_de_unlock(lck); -++ continue; -++ } -++ return frame; -++ } -++ dx = at; -++ indirect--; -+ bh = ext4_read_dirblock(dir, dx_get_block(at), INDEX); -+ if (IS_ERR(bh)) { -+ *err = PTR_ERR(bh); -+@@ -826,13 +1121,18 @@ fail: -+ static void dx_release (struct dx_frame *frames) -+ { -+ struct dx_root_info *info; -++ int i; -++ -+ if (frames[0].bh == NULL) -+ return; -+ -+ info = dx_get_dx_info((struct ext4_dir_entry_2*)frames[0].bh->b_data); -+- if (info->indirect_levels) -+- brelse(frames[1].bh); -+- brelse(frames[0].bh); -++ for (i = 0; i <= info->indirect_levels; i++) { -++ if (frames[i].bh == NULL) -++ break; -++ brelse(frames[i].bh); -++ frames[i].bh = NULL; -++ } -+ } -+ -+ /* -+@@ -855,7 +1155,7 @@ static void dx_release (struct dx_frame -+ static int ext4_htree_next_block(struct inode *dir, __u32 hash, -+ struct dx_frame *frame, -+ struct dx_frame *frames, -+- __u32 *start_hash) -++ __u32 *start_hash, struct htree_lock *lck) -+ { -+ struct dx_frame *p; -+ struct buffer_head *bh; -+@@ -870,12 +1170,22 @@ static int ext4_htree_next_block(struct -+ * this loop, num_frames indicates the number of interior -+ * nodes need to be read. -+ */ -++ ext4_htree_de_unlock(lck); -+ while (1) { -+- if (++(p->at) < p->entries + dx_get_count(p->entries)) -+- break; -++ if (num_frames > 0 || ext4_htree_dx_locked(lck)) { -++ /* num_frames > 0 : -++ * DX block -++ * ext4_htree_dx_locked: -++ * frame->at is reliable pointer returned by dx_probe, -++ * otherwise dx_probe already knew no collision */ -++ if (++(p->at) < p->entries + dx_get_count(p->entries)) -++ break; -++ } -+ if (p == frames) -+ return 0; -+ num_frames++; -++ if (num_frames == 1) -++ ext4_htree_dx_unlock(lck); -+ p--; -+ } -+ -+@@ -898,6 +1208,13 @@ static int ext4_htree_next_block(struct -+ * block so no check is necessary -+ */ -+ while (num_frames--) { -++ if (num_frames == 0) { -++ /* it's not always necessary, we just don't want to -++ * detect hash collision again */ -++ ext4_htree_dx_need_lock(lck); -++ ext4_htree_dx_lock(lck, p->at); -++ } -++ -+ bh = ext4_read_dirblock(dir, dx_get_block(p->at), INDEX); -+ if (IS_ERR(bh)) -+ return PTR_ERR(bh); -+@@ -906,6 +1223,7 @@ static int ext4_htree_next_block(struct -+ p->bh = bh; -+ p->at = p->entries = ((struct dx_node *) bh->b_data)->entries; -+ } -++ ext4_htree_de_lock(lck, p->at); -+ return 1; -+ } -+ -+@@ -974,7 +1292,7 @@ int ext4_htree_fill_tree(struct file *di -+ { -+ struct dx_hash_info hinfo; -+ struct ext4_dir_entry_2 *de; -+- struct dx_frame frames[2], *frame; -++ struct dx_frame frames[EXT4_HTREE_LEVEL], *frame; -+ struct inode *dir; -+ ext4_lblk_t block; -+ int count = 0; -+@@ -1008,10 +1326,10 @@ int ext4_htree_fill_tree(struct file *di -+ } -+ hinfo.hash = start_hash; -+ hinfo.minor_hash = 0; -+- frame = dx_probe(NULL, dir, &hinfo, frames, &err); -++ /* assume it's PR locked */ -++ frame = dx_probe(NULL, dir, &hinfo, frames, NULL, &err); -+ if (!frame) -+ return err; -+- -+ /* Add '.' and '..' from the htree header */ -+ if (!start_hash && !start_minor_hash) { -+ de = (struct ext4_dir_entry_2 *) frames[0].bh->b_data; -+@@ -1038,7 +1356,7 @@ int ext4_htree_fill_tree(struct file *di -+ count += ret; -+ hashval = ~0; -+ ret = ext4_htree_next_block(dir, HASH_NB_ALWAYS, -+- frame, frames, &hashval); -++ frame, frames, &hashval, NULL); -+ *next_hash = hashval; -+ if (ret < 0) { -+ err = ret; -+@@ -1234,7 +1552,7 @@ static int is_dx_internal_node(struct in -+ struct buffer_head * ext4_find_entry(struct inode *dir, -+ const struct qstr *d_name, -+ struct ext4_dir_entry_2 **res_dir, -+- int *inlined) -++ int *inlined, struct htree_lock *lck) -+ { -+ struct super_block *sb; -+ struct buffer_head *bh_use[NAMEI_RA_SIZE]; -+@@ -1278,7 +1596,7 @@ struct buffer_head * ext4_find_entry(str -+ goto restart; -+ } -+ if (is_dx(dir)) { -+- bh = ext4_dx_find_entry(dir, d_name, res_dir, &err); -++ bh = ext4_dx_find_entry(dir, d_name, res_dir, lck, &err); -+ /* -+ * On success, or if the error was file not found, -+ * return. Otherwise, fall back to doing a search the -+@@ -1288,6 +1606,7 @@ struct buffer_head * ext4_find_entry(str -+ return bh; -+ dxtrace(printk(KERN_DEBUG "ext4_find_entry: dx failed, " -+ "falling back\n")); -++ ext4_htree_safe_relock(lck); -+ } -+ nblocks = dir->i_size >> EXT4_BLOCK_SIZE_BITS(sb); -+ start = EXT4_I(dir)->i_dir_start_lookup; -+@@ -1377,17 +1696,19 @@ cleanup_and_exit: -+ } -+ EXPORT_SYMBOL(ext4_find_entry); -+ -+-static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct qstr *d_name, -+- struct ext4_dir_entry_2 **res_dir, int *err) -++static struct buffer_head * ext4_dx_find_entry(struct inode *dir, -++ const struct qstr *d_name, -++ struct ext4_dir_entry_2 **res_dir, -++ struct htree_lock *lck, int *err) -+ { -+ struct super_block * sb = dir->i_sb; -+ struct dx_hash_info hinfo; -+- struct dx_frame frames[2], *frame; -++ struct dx_frame frames[EXT4_HTREE_LEVEL], *frame; -+ struct buffer_head *bh; -+ ext4_lblk_t block; -+ int retval; -+ -+- if (!(frame = dx_probe(d_name, dir, &hinfo, frames, err))) -++ if (!(frame = dx_probe(d_name, dir, &hinfo, frames, lck, err))) -+ return NULL; -+ do { -+ block = dx_get_block(frame->at); -+@@ -1411,7 +1732,7 @@ static struct buffer_head * ext4_dx_find -+ -+ /* Check to see if we should continue to search */ -+ retval = ext4_htree_next_block(dir, hinfo.hash, frame, -+- frames, NULL); -++ frames, NULL, lck); -+ if (retval < 0) { -+ ext4_warning(sb, -+ "error reading index page in directory #%lu", -+@@ -1437,7 +1758,7 @@ static struct dentry *ext4_lookup(struct -+ if (dentry->d_name.len > EXT4_NAME_LEN) -+ return ERR_PTR(-ENAMETOOLONG); -+ -+- bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL); -++ bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL, NULL); -+ inode = NULL; -+ if (bh) { -+ __u32 ino = le32_to_cpu(de->inode); -+@@ -1497,7 +1818,7 @@ struct dentry *ext4_get_parent(struct de -+ struct ext4_dir_entry_2 * de; -+ struct buffer_head *bh; -+ -+- bh = ext4_find_entry(child->d_inode, &dotdot, &de, NULL); -++ bh = ext4_find_entry(child->d_inode, &dotdot, &de, NULL, NULL); -+ if (!bh) -+ return ERR_PTR(-ENOENT); -+ ino = le32_to_cpu(de->inode); -+@@ -1567,8 +1888,9 @@ static struct ext4_dir_entry_2* dx_pack_ -+ * Returns pointer to de in block into which the new entry will be inserted. -+ */ -+ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, -+- struct buffer_head **bh,struct dx_frame *frame, -+- struct dx_hash_info *hinfo, int *error) -++ struct buffer_head **bh, struct dx_frame *frames, -++ struct dx_frame *frame, struct dx_hash_info *hinfo, -++ struct htree_lock *lck, int *error) -+ { -+ unsigned blocksize = dir->i_sb->s_blocksize; -+ unsigned count, continued; -+@@ -1632,7 +1954,14 @@ static struct ext4_dir_entry_2 *do_split -+ hash2, split, count-split)); -+ -+ /* Fancy dance to stay within two buffers */ -+- de2 = dx_move_dirents(data1, data2, map + split, count - split, blocksize); -++ if (hinfo->hash < hash2) { -++ de2 = dx_move_dirents(data1, data2, map + split, -++ count - split, blocksize); -++ } else { -++ /* make sure we will add entry to the same block which -++ * we have already locked */ -++ de2 = dx_move_dirents(data1, data2, map, split, blocksize); -++ } -+ de = dx_pack_dirents(data1, blocksize); -+ de->rec_len = ext4_rec_len_to_disk(data1 + (blocksize - csum_size) - -+ (char *) de, -+@@ -1651,13 +1980,21 @@ static struct ext4_dir_entry_2 *do_split -+ dxtrace(dx_show_leaf (hinfo, (struct ext4_dir_entry_2 *) data1, blocksize, 1)); -+ dxtrace(dx_show_leaf (hinfo, (struct ext4_dir_entry_2 *) data2, blocksize, 1)); -+ -+- /* Which block gets the new entry? */ -+- if (hinfo->hash >= hash2) -+- { -+- swap(*bh, bh2); -+- de = de2; -++ ext4_htree_spin_lock(lck, frame > frames ? (frame - 1)->at : NULL, -++ frame->at); /* notify block is being split */ -++ if (hinfo->hash < hash2) { -++ dx_insert_block(frame, hash2 + continued, newblock); -++ -++ } else { -++ /* switch block number */ -++ dx_insert_block(frame, hash2 + continued, -++ dx_get_block(frame->at)); -++ dx_set_block(frame->at, newblock); -++ (frame->at)++; -+ } -+- dx_insert_block(frame, hash2 + continued, newblock); -++ ext4_htree_spin_unlock(lck); -++ ext4_htree_dx_unlock(lck); -++ -+ err = ext4_handle_dirty_dirent_node(handle, dir, bh2); -+ if (err) -+ goto journal_error; -+@@ -1800,7 +2137,7 @@ static int add_dirent_to_buf(handle_t *h -+ if (!IS_NOCMTIME(dir)) -+ dir->i_mtime = dir->i_ctime = ext4_current_time(dir); -+ ext4_update_dx_flag(dir); -+- dir->i_version++; -++ inode_inc_iversion(dir); -+ ext4_mark_inode_dirty(handle, dir); -+ BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); -+ err = ext4_handle_dirty_dirent_node(handle, dir, bh); -+@@ -1820,7 +2157,7 @@ static int make_indexed_dir(handle_t *ha -+ const char *name = dentry->d_name.name; -+ int namelen = dentry->d_name.len; -+ struct buffer_head *bh2; -+- struct dx_frame frames[2], *frame; -++ struct dx_frame frames[EXT4_HTREE_LEVEL], *frame; -+ struct dx_entry *entries; -+ struct ext4_dir_entry_2 *de, *de2, *dot_de, *dotdot_de; -+ struct ext4_dir_entry_tail *t; -+@@ -1914,7 +2251,7 @@ static int make_indexed_dir(handle_t *ha -+ ext4_handle_dirty_dx_node(handle, dir, frame->bh); -+ ext4_handle_dirty_dirent_node(handle, dir, bh); -+ -+- de = do_split(handle,dir, &bh, frame, &hinfo, &retval); -++ de = do_split(handle,dir, &bh, frames, frame, &hinfo, NULL, &retval); -+ if (!de) { -+ /* -+ * Even if the block split failed, we have to properly write -+@@ -2021,7 +2358,7 @@ out: -+ * the entry, as someone else might have used it while you slept. -+ */ -+ int ext4_add_entry(handle_t *handle, struct dentry *dentry, -+- struct inode *inode) -++ struct inode *inode, struct htree_lock *lck) -+ { -+ struct inode *dir = dentry->d_parent->d_inode; -+ struct buffer_head *bh; -+@@ -2057,9 +2394,10 @@ int ext4_add_entry(handle_t *handle, str -+ if (dentry->d_name.len == 2 && -+ memcmp(dentry->d_name.name, "..", 2) == 0) -+ return ext4_update_dotdot(handle, dentry, inode); -+- retval = ext4_dx_add_entry(handle, dentry, inode); -++ retval = ext4_dx_add_entry(handle, dentry, inode, lck); -+ if (!retval || (retval != ERR_BAD_DX_DIR)) -+ return retval; -++ ext4_htree_safe_relock(lck); -+ ext4_clear_inode_flag(dir, EXT4_INODE_INDEX); -+ dx_fallback++; -+ ext4_mark_inode_dirty(handle, dir); -+@@ -2105,18 +2443,21 @@ EXPORT_SYMBOL(ext4_add_entry); -+ * Returns 0 for success, or a negative error value -+ */ -+ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry, -+- struct inode *inode) -++ struct inode *inode, struct htree_lock *lck) -+ { -+- struct dx_frame frames[2], *frame; -++ struct dx_frame frames[EXT4_HTREE_LEVEL], *frame; -+ struct dx_entry *entries, *at; -+ struct dx_hash_info hinfo; -+ struct buffer_head *bh; -+ struct inode *dir = dentry->d_parent->d_inode; -+ struct super_block *sb = dir->i_sb; -+ struct ext4_dir_entry_2 *de; -++ int restart; -+ int err; -+ -+- frame = dx_probe(&dentry->d_name, dir, &hinfo, frames, &err); -++again: -++ restart = 0; -++ frame = dx_probe(&dentry->d_name, dir, &hinfo, frames, lck, &err); -+ if (!frame) -+ return err; -+ entries = frame->entries; -+@@ -2128,33 +2469,53 @@ static int ext4_dx_add_entry(handle_t *h -+ goto cleanup; -+ } -+ -+- BUFFER_TRACE(bh, "get_write_access"); -+- err = ext4_journal_get_write_access(handle, bh); -+- if (err) -+- goto journal_error; -+- -+ err = add_dirent_to_buf(handle, dentry, inode, NULL, bh); -+ if (err != -ENOSPC) -+ goto cleanup; -+ -++ err = 0; -+ /* Block full, should compress but for now just split */ -+ dxtrace(printk(KERN_DEBUG "using %u of %u node entries\n", -+ dx_get_count(entries), dx_get_limit(entries))); -+ /* Need to split index? */ -+ if (dx_get_count(entries) == dx_get_limit(entries)) { -+ ext4_lblk_t newblock; -+- unsigned icount = dx_get_count(entries); -+- int levels = frame - frames; -++ int levels = frame - frames + 1; -++ unsigned icount; -++ int add_level = 1; -+ struct dx_entry *entries2; -+ struct dx_node *node2; -+ struct buffer_head *bh2; -+ -+- if (levels && (dx_get_count(frames->entries) == -+- dx_get_limit(frames->entries))) { -+- ext4_warning(sb, "Directory index full!"); -++ if (!ext4_htree_safe_locked(lck)) { /* retry with EX lock */ -++ ext4_htree_safe_relock(lck); -++ restart = 1; -++ goto cleanup; -++ } -++ while (frame > frames) { -++ if (dx_get_count((frame - 1)->entries) < -++ dx_get_limit((frame - 1)->entries)) { -++ add_level = 0; -++ break; -++ } -++ frame--; /* split higher index block */ -++ at = frame->at; -++ entries = frame->entries; -++ restart = 1; -++ } -++ if (add_level && levels == ext4_dir_htree_level(sb)) { -++ ext4_warning(sb, "Directory (ino: %lu) index full, " -++ "reach max htree level :%d", -++ dir->i_ino, levels); -++ if (ext4_dir_htree_level(sb) < EXT4_HTREE_LEVEL) { -++ ext4_warning(sb, "Large directory feature is" -++ "not enabled on this " -++ "filesystem"); -++ } -+ err = -ENOSPC; -+ goto cleanup; -+ } -++ icount = dx_get_count(entries); -+ bh2 = ext4_append(handle, dir, &newblock); -+ if (IS_ERR(bh2)) { -+ err = PTR_ERR(bh2); -+@@ -2169,7 +2530,7 @@ static int ext4_dx_add_entry(handle_t *h -+ err = ext4_journal_get_write_access(handle, frame->bh); -+ if (err) -+ goto journal_error; -+- if (levels) { -++ if (!add_level) { -+ unsigned icount1 = icount/2, icount2 = icount - icount1; -+ unsigned hash2 = dx_get_hash(entries + icount1); -+ dxtrace(printk(KERN_DEBUG "Split index %i/%i\n", -+@@ -2177,7 +2538,7 @@ static int ext4_dx_add_entry(handle_t *h -+ -+ BUFFER_TRACE(frame->bh, "get_write_access"); /* index root */ -+ err = ext4_journal_get_write_access(handle, -+- frames[0].bh); -++ (frame - 1)->bh); -+ if (err) -+ goto journal_error; -+ -+@@ -2193,18 +2554,24 @@ static int ext4_dx_add_entry(handle_t *h -+ frame->entries = entries = entries2; -+ swap(frame->bh, bh2); -+ } -+- dx_insert_block(frames + 0, hash2, newblock); -+- dxtrace(dx_show_index("node", frames[1].entries)); -++ dx_insert_block((frame - 1), hash2, newblock); -++ dxtrace(dx_show_index("node", frame->entries)); -+ dxtrace(dx_show_index("node", -+ ((struct dx_node *) bh2->b_data)->entries)); -+ err = ext4_handle_dirty_dx_node(handle, dir, bh2); -+ if (err) -+ goto journal_error; -+ brelse (bh2); -++ ext4_handle_dirty_metadata(handle, inode, -++ (frame - 1)->bh); -++ if (restart) { -++ ext4_handle_dirty_metadata(handle, inode, -++ frame->bh); -++ goto cleanup; -++ } -+ } else { -+ struct dx_root_info * info; -+- dxtrace(printk(KERN_DEBUG -+- "Creating second level index...\n")); -++ -+ memcpy((char *) entries2, (char *) entries, -+ icount * sizeof(struct dx_entry)); -+ dx_set_limit(entries2, dx_node_limit(dir)); -+@@ -2214,35 +2581,63 @@ static int ext4_dx_add_entry(handle_t *h -+ dx_set_block(entries + 0, newblock); -+ info = dx_get_dx_info((struct ext4_dir_entry_2*) -+ frames[0].bh->b_data); -+- info->indirect_levels = 1; -++ info->indirect_levels += 1; -++ dxtrace(printk(KERN_DEBUG -++ "Creating %d level index...\n", -++ info->indirect_levels)); -++ ext4_handle_dirty_metadata(handle, inode, frame->bh); -++ ext4_handle_dirty_metadata(handle, inode, bh2); -++ brelse(bh2); -++ restart = 1; -++ goto cleanup; -++ } -++ } else if (!ext4_htree_dx_locked(lck)) { -++ struct ext4_dir_lock_data *ld = ext4_htree_lock_data(lck); -+ -+- /* Add new access path frame */ -+- frame = frames + 1; -+- frame->at = at = at - entries + entries2; -+- frame->entries = entries = entries2; -+- frame->bh = bh2; -+- err = ext4_journal_get_write_access(handle, -+- frame->bh); -+- if (err) -+- goto journal_error; -++ /* not well protected, require DX lock */ -++ ext4_htree_dx_need_lock(lck); -++ at = frame > frames ? (frame - 1)->at : NULL; -++ -++ /* NB: no risk of deadlock because it's just a try. -++ * -++ * NB: we check ld_count for twice, the first time before -++ * having DX lock, the second time after holding DX lock. -++ * -++ * NB: We never free blocks for directory so far, which -++ * means value returned by dx_get_count() should equal to -++ * ld->ld_count if nobody split any DE-block under @at, -++ * and ld->ld_at still points to valid dx_entry. */ -++ if ((ld->ld_count != dx_get_count(entries)) || -++ !ext4_htree_dx_lock_try(lck, at) || -++ (ld->ld_count != dx_get_count(entries))) { -++ restart = 1; -++ goto cleanup; -+ } -+- err = ext4_handle_dirty_dx_node(handle, dir, frames[0].bh); -++ /* OK, I've got DX lock and nothing changed */ -++ frame->at = ld->ld_at; -+ if (err) { -+ ext4_std_error(inode->i_sb, err); -+ goto cleanup; -+ } -+ } -+- de = do_split(handle, dir, &bh, frame, &hinfo, &err); -++ de = do_split(handle, dir, &bh, frames, frame, &hinfo, lck, &err); -+ if (!de) -+ goto cleanup; -++ -+ err = add_dirent_to_buf(handle, dentry, inode, de, bh); -+ goto cleanup; -+ -+ journal_error: -+ ext4_std_error(dir->i_sb, err); -+ cleanup: -++ ext4_htree_dx_unlock(lck); -++ ext4_htree_de_unlock(lck); -+ brelse(bh); -+ dx_release(frames); -++ /* @restart is true means htree-path has been changed, we need to -++ * repeat dx_probe() to find out valid htree-path */ -++ if (restart && err == 0) -++ goto again; -+ return err; -+ } -+ -+@@ -2279,7 +2674,7 @@ int ext4_generic_delete_entry(handle_t * -+ blocksize); -+ else -+ de->inode = 0; -+- dir->i_version++; -++ inode_inc_iversion(dir); -+ return 0; -+ } -+ i += ext4_rec_len_from_disk(de->rec_len, blocksize); -+@@ -2364,7 +2759,7 @@ EXPORT_SYMBOL(ext4_dec_count); -+ static int ext4_add_nondir(handle_t *handle, -+ struct dentry *dentry, struct inode *inode) -+ { -+- int err = ext4_add_entry(handle, dentry, inode); -++ int err = ext4_add_entry(handle, dentry, inode, NULL); -+ if (!err) { -+ ext4_mark_inode_dirty(handle, inode); -+ unlock_new_inode(inode); -+@@ -2670,7 +3065,7 @@ retry: -+ goto out_clear_inode; -+ err = ext4_mark_inode_dirty(handle, inode); -+ if (!err) -+- err = ext4_add_entry(handle, dentry, inode); -++ err = ext4_add_entry(handle, dentry, inode, NULL); -+ if (err) { -+ out_clear_inode: -+ clear_nlink(inode); -+@@ -2936,7 +3331,7 @@ static int ext4_rmdir(struct inode *dir, -+ dquot_initialize(dentry->d_inode); -+ -+ retval = -ENOENT; -+- bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL); -++ bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL, NULL); -+ if (!bh) -+ goto end_rmdir; -+ -+@@ -3003,7 +3398,7 @@ static int ext4_unlink(struct inode *dir -+ dquot_initialize(dentry->d_inode); -+ -+ retval = -ENOENT; -+- bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL); -++ bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL, NULL); -+ if (!bh) -+ goto end_unlink; -+ -+@@ -3182,7 +3577,7 @@ retry: -+ ext4_inc_count(handle, inode); -+ ihold(inode); -+ -+- err = ext4_add_entry(handle, dentry, inode); -++ err = ext4_add_entry(handle, dentry, inode, NULL); -+ if (!err) { -+ ext4_mark_inode_dirty(handle, inode); -+ /* this can happen only for tmpfile being -+@@ -3264,7 +3659,7 @@ static int ext4_rename(struct inode *old -+ if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir)) -+ ext4_handle_sync(handle); -+ -+- old_bh = ext4_find_entry(old_dir, &old_dentry->d_name, &old_de, NULL); -++ old_bh = ext4_find_entry(old_dir, &old_dentry->d_name, &old_de, NULL, NULL); -+ /* -+ * Check for inode number is _not_ due to possible IO errors. -+ * We might rmdir the source, keep it as pwd of some process -+@@ -3278,7 +3673,7 @@ static int ext4_rename(struct inode *old -+ -+ new_inode = new_dentry->d_inode; -+ new_bh = ext4_find_entry(new_dir, &new_dentry->d_name, -+- &new_de, &new_inlined); -++ &new_de, &new_inlined, NULL); -+ if (new_bh) { -+ if (!new_inode) { -+ brelse(new_bh); -+@@ -3309,7 +3704,7 @@ static int ext4_rename(struct inode *old -+ goto end_rename; -+ } -+ if (!new_bh) { -+- retval = ext4_add_entry(handle, new_dentry, old_inode); -++ retval = ext4_add_entry(handle, new_dentry, old_inode, NULL); -+ if (retval) -+ goto end_rename; -+ } else { -+@@ -3361,7 +3756,7 @@ static int ext4_rename(struct inode *old -+ struct ext4_dir_entry_2 *old_de2; -+ -+ old_bh2 = ext4_find_entry(old_dir, &old_dentry->d_name, -+- &old_de2, NULL); -++ &old_de2, NULL, NULL); -+ if (old_bh2) { -+ retval = ext4_delete_entry(handle, old_dir, -+ old_de2, old_bh2); -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/inode.c -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/inode.c -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/inode.c -+@@ -4091,7 +4091,7 @@ struct inode *ext4_iget(struct super_blo -+ if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_64BIT)) -+ ei->i_file_acl |= -+ ((__u64)le16_to_cpu(raw_inode->i_file_acl_high)) << 32; -+- inode->i_size = ext4_isize(raw_inode); -++ inode->i_size = ext4_isize(sb, raw_inode); -+ ei->i_disksize = inode->i_size; -+ #ifdef CONFIG_QUOTA -+ ei->i_reserved_quota = 0; -+@@ -4329,7 +4329,7 @@ static int ext4_do_update_inode(handle_t -+ raw_inode->i_file_acl_high = -+ cpu_to_le16(ei->i_file_acl >> 32); -+ raw_inode->i_file_acl_lo = cpu_to_le32(ei->i_file_acl); -+- if (ei->i_disksize != ext4_isize(raw_inode)) { -++ if (ei->i_disksize != ext4_isize(inode->i_sb, raw_inode)) { -+ ext4_isize_set(raw_inode, ei->i_disksize); -+ need_datasync = 1; -+ } -+Index: linux-3.11.1-200.fc19.x86_64/fs/ext4/Makefile -+=================================================================== -+--- linux-3.11.1-200.fc19.x86_64.orig/fs/ext4/Makefile -++++ linux-3.11.1-200.fc19.x86_64/fs/ext4/Makefile -+@@ -8,7 +8,7 @@ ext4-y := balloc.o bitmap.o dir.o file.o -+ ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \ -+ ext4_jbd2.o migrate.o mballoc.o block_validity.o move_extent.o \ -+ mmp.o indirect.o extents_status.o xattr.o xattr_user.o \ -+- xattr_trusted.o inline.o -++ xattr_trusted.o inline.o htree_lock.o -+ -+ ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o -+ ext4-$(CONFIG_EXT4_FS_SECURITY) += xattr_security.o -diff --git a/ldiskfs/kernel_patches/series/ldiskfs-3.x-fc19.series b/ldiskfs/kernel_patches/series/ldiskfs-3.x-fc19.series -new file mode 100644 -index 0000000..5d0d7b0 ---- /dev/null -+++ b/ldiskfs/kernel_patches/series/ldiskfs-3.x-fc19.series -@@ -0,0 +1,22 @@ -+fc19/ext4-inode-version.patch -+fc19/ext4-lookup-dotdot.patch -+rhel6.3/ext4-print-inum-in-htree-warning.patch -+fc19/ext4-prealloc.patch -+fc19/ext4-mballoc-extra-checks.patch -+fc19/ext4-misc.patch -+fc19/ext4-force_over_128tb.patch -+fc19/ext4-pdir-fix.patch -+fc19/ext4-osd-iop-common.patch -+fc19/ext4-osd-iam-exports.patch -+rhel6.3/ext4-hash-indexed-dir-dotdot-update.patch -+fc19/ext4-kill-dx_root.patch -+fc19/ext4-fiemap.patch -+fc19/ext4-mballoc-pa_free-mismatch.patch -+fc19/ext4_data_in_dirent.patch -+fc19/ext4-large-eas.patch -+fc19/ext4-disable-mb-cache.patch -+fc19/ext4-nocmtime.patch -+fc19/ext4_pdirop.patch -+rhel6.3/ext4-not-discard-preallocation-umount.patch -+fc19/ext4-change-entry-avoid-conflict.patch -+fc19/ext4-max-dir-size.patch --- -1.8.5.1 - diff --git a/sys-cluster/lustre/files/0003-LU-3319-procfs-fix-symlink-handling.patch b/sys-cluster/lustre/files/0003-LU-3319-procfs-fix-symlink-handling.patch new file mode 100644 index 000000000..8d1a0df42 --- /dev/null +++ b/sys-cluster/lustre/files/0003-LU-3319-procfs-fix-symlink-handling.patch @@ -0,0 +1,358 @@ +From ce693d2759e274a114a668e477264d1af8181159 Mon Sep 17 00:00:00 2001 +From: James Simmons <uja.ornl@gmail.com> +Date: Fri, 31 Jan 2014 11:37:53 -0500 +Subject: [PATCH 03/13] LU-3319 procfs: fix symlink handling + +While working on symlink handling for seq files I noticed a +long outstanding bug. Code was developed to link osc obds +to target_obds of the lov layer. The target_obds directory +was never created for the symlinks. This patches enables +this long forgotten feature. Also addressed is the race +condition experinced with server side code ported to +seq_files that used symlinks. To avoid the race the handle +obd_proc_private was moved from struct obd_device to +struct obd_type which now allows earlier registeration that +only happens once. + +Change-Id: Ib158ec4444ed7abc0f3c3e820ee4a333631a58d1 +Signed-off-by: James Simmons <uja.ornl@gmail.com> +--- + lustre/include/obd.h | 17 ++++---- + lustre/lmv/lmv_obd.c | 49 +++++++++-------------- + lustre/lov/lov_obd.c | 100 +++++++++++++++++++++++++++-------------------- + lustre/obdclass/genops.c | 3 ++ + 4 files changed, 87 insertions(+), 82 deletions(-) + +diff --git a/lustre/include/obd.h b/lustre/include/obd.h +index c18052b..8fd2ce7 100644 +--- a/lustre/include/obd.h ++++ b/lustre/include/obd.h +@@ -183,13 +183,15 @@ struct obd_info { + }; + + struct obd_type { +- cfs_list_t typ_chain; +- struct obd_ops *typ_dt_ops; +- struct md_ops *typ_md_ops; +- cfs_proc_dir_entry_t *typ_procroot; +- char *typ_name; +- int typ_refcnt; +- struct lu_device_type *typ_lu; ++ struct list_head typ_chain; ++ struct obd_ops *typ_dt_ops; ++ struct md_ops *typ_md_ops; ++ cfs_proc_dir_entry_t *typ_procroot; ++ cfs_proc_dir_entry_t *typ_procsym; ++ __u32 typ_sym_filter; ++ char *typ_name; ++ int typ_refcnt; ++ struct lu_device_type *typ_lu; + spinlock_t obd_type_lock; + }; + +@@ -825,7 +827,6 @@ struct obd_device { + + struct proc_dir_entry *obd_proc_entry; + struct proc_dir_entry *obd_proc_exports_entry; +- void *obd_proc_private; /* type private PDEs */ + struct proc_dir_entry *obd_svc_procroot; + struct lprocfs_stats *obd_svc_stats; + struct lprocfs_seq_vars *obd_vars; +diff --git a/lustre/lmv/lmv_obd.c b/lustre/lmv/lmv_obd.c +index e0941c9..7e1738e 100644 +--- a/lustre/lmv/lmv_obd.c ++++ b/lustre/lmv/lmv_obd.c +@@ -242,9 +242,6 @@ static int lmv_connect(const struct lu_env *env, + struct obd_uuid *cluuid, struct obd_connect_data *data, + void *localdata) + { +-#ifdef __KERNEL__ +- struct proc_dir_entry *lmv_proc_dir; +-#endif + struct lmv_obd *lmv = &obd->u.lmv; + struct lustre_handle conn = { 0 }; + int rc = 0; +@@ -277,18 +274,15 @@ static int lmv_connect(const struct lu_env *env, + lmv->conn_data = *data; + + #ifdef __KERNEL__ +- if (obd->obd_proc_private != NULL) { +- lmv_proc_dir = obd->obd_proc_private; +- } else { +- lmv_proc_dir = lprocfs_seq_register("target_obds", +- obd->obd_proc_entry, +- NULL, NULL); +- if (IS_ERR(lmv_proc_dir)) { ++ if (obd->obd_type->typ_procsym == NULL) { ++ obd->obd_type->typ_procsym = lprocfs_seq_register("target_obds", ++ obd->obd_proc_entry, ++ NULL, NULL); ++ if (IS_ERR(obd->obd_type->typ_procsym)) { + CERROR("could not register /proc/fs/lustre/%s/%s/target_obds.", + obd->obd_type->typ_name, obd->obd_name); +- lmv_proc_dir = NULL; ++ obd->obd_type->typ_procsym = NULL; + } +- obd->obd_proc_private = lmv_proc_dir; + } + #endif + +@@ -302,9 +296,9 @@ static int lmv_connect(const struct lu_env *env, + rc = lmv_check_connect(obd); + + #ifdef __KERNEL__ +- if (rc && lmv_proc_dir) { +- lprocfs_remove(&lmv_proc_dir); +- obd->obd_proc_private = NULL; ++ if (rc && obd->obd_type->typ_procsym != NULL) { ++ lprocfs_remove(&obd->obd_type->typ_procsym); ++ obd->obd_type->typ_procsym = NULL; + } + #endif + RETURN(rc); +@@ -384,9 +378,6 @@ static int lmv_init_ea_size(struct obd_export *exp, int easize, + + int lmv_connect_mdc(struct obd_device *obd, struct lmv_tgt_desc *tgt) + { +-#ifdef __KERNEL__ +- struct proc_dir_entry *lmv_proc_dir; +-#endif + struct lmv_obd *lmv = &obd->u.lmv; + struct obd_uuid *cluuid = &lmv->cluuid; + struct obd_uuid lmv_mdc_uuid = { "LMV_MDC_UUID" }; +@@ -466,14 +457,13 @@ int lmv_connect_mdc(struct obd_device *obd, struct lmv_tgt_desc *tgt) + cfs_atomic_read(&obd->obd_refcount)); + + #ifdef __KERNEL__ +- lmv_proc_dir = obd->obd_proc_private; +- if (lmv_proc_dir) { ++ if (obd->obd_type->typ_procsym != NULL) { + struct proc_dir_entry *mdc_symlink; + + LASSERT(mdc_obd->obd_type != NULL); + LASSERT(mdc_obd->obd_type->typ_name != NULL); + mdc_symlink = lprocfs_add_symlink(mdc_obd->obd_name, +- lmv_proc_dir, ++ obd->obd_type->typ_procsym, + "../../../%s/%s", + mdc_obd->obd_type->typ_name, + mdc_obd->obd_name); +@@ -482,8 +472,8 @@ int lmv_connect_mdc(struct obd_device *obd, struct lmv_tgt_desc *tgt) + "/proc/fs/lustre/%s/%s/target_obds/%s.", + obd->obd_type->typ_name, obd->obd_name, + mdc_obd->obd_name); +- lprocfs_remove(&lmv_proc_dir); +- obd->obd_proc_private = NULL; ++ lprocfs_remove(&obd->obd_type->typ_procsym); ++ obd->obd_type->typ_procsym = NULL; + } + } + #endif +@@ -675,9 +665,6 @@ int lmv_check_connect(struct obd_device *obd) + + static int lmv_disconnect_mdc(struct obd_device *obd, struct lmv_tgt_desc *tgt) + { +-#ifdef __KERNEL__ +- struct proc_dir_entry *lmv_proc_dir; +-#endif + struct lmv_obd *lmv = &obd->u.lmv; + struct obd_device *mdc_obd; + int rc; +@@ -695,9 +682,9 @@ static int lmv_disconnect_mdc(struct obd_device *obd, struct lmv_tgt_desc *tgt) + } + + #ifdef __KERNEL__ +- lmv_proc_dir = obd->obd_proc_private; +- if (lmv_proc_dir) +- lprocfs_remove_proc_entry(mdc_obd->obd_name, lmv_proc_dir); ++ if (obd->obd_type->typ_procsym != NULL) ++ lprocfs_remove_proc_entry(mdc_obd->obd_name, ++ obd->obd_type->typ_procsym); + #endif + rc = obd_fid_fini(tgt->ltd_exp->exp_obd); + if (rc) +@@ -747,8 +734,8 @@ static int lmv_disconnect(struct obd_export *exp) + } + + #ifdef __KERNEL__ +- if (obd->obd_proc_private) +- lprocfs_remove((struct proc_dir_entry **)&obd->obd_proc_private); ++ if (obd->obd_type->typ_procsym != NULL) ++ lprocfs_remove(&obd->obd_type->typ_procsym); + else + CERROR("/proc/fs/lustre/%s/%s/target_obds missing\n", + obd->obd_type->typ_name, obd->obd_name); +diff --git a/lustre/lov/lov_obd.c b/lustre/lov/lov_obd.c +index 286cd15..b52a263 100644 +--- a/lustre/lov/lov_obd.c ++++ b/lustre/lov/lov_obd.c +@@ -127,19 +127,16 @@ static int lov_notify(struct obd_device *obd, struct obd_device *watched, + 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; +- struct obd_device *tgt_obd; +- static struct obd_uuid lov_osc_uuid = { "LOV_OSC_UUID" }; +- struct obd_import *imp; +-#ifdef __KERNEL__ +- struct proc_dir_entry *lov_proc_dir; +-#endif +- int rc; +- ENTRY; ++ struct lov_obd *lov = &obd->u.lov; ++ struct obd_uuid *tgt_uuid; ++ struct obd_device *tgt_obd; ++ static struct obd_uuid lov_osc_uuid = { "LOV_OSC_UUID" }; ++ struct obd_import *imp; ++ int rc; ++ ENTRY; + +- if (!lov->lov_tgts[index]) +- RETURN(-EINVAL); ++ if (lov->lov_tgts[index] == NULL) ++ RETURN(-EINVAL); + + tgt_uuid = &lov->lov_tgts[index]->ltd_uuid; + tgt_obd = lov->lov_tgts[index]->ltd_obd; +@@ -195,27 +192,26 @@ int lov_connect_obd(struct obd_device *obd, __u32 index, int activate, + obd_uuid2str(tgt_uuid), tgt_obd->obd_name, activate ? "":"in"); + + #ifdef __KERNEL__ +- lov_proc_dir = obd->obd_proc_private; +- if (lov_proc_dir) { +- struct obd_device *osc_obd = lov->lov_tgts[index]->ltd_exp->exp_obd; ++ if (obd->obd_type->typ_procsym != NULL) { ++ struct obd_device *osc_obd = lov->lov_tgts[index]->ltd_exp->exp_obd; + struct proc_dir_entry *osc_symlink; + +- LASSERT(osc_obd != NULL); +- LASSERT(osc_obd->obd_magic == OBD_DEVICE_MAGIC); +- LASSERT(osc_obd->obd_type->typ_name != NULL); +- +- osc_symlink = lprocfs_add_symlink(osc_obd->obd_name, +- lov_proc_dir, +- "../../../%s/%s", +- osc_obd->obd_type->typ_name, +- osc_obd->obd_name); +- if (osc_symlink == NULL) { +- CERROR("could not register LOV target " +- "/proc/fs/lustre/%s/%s/target_obds/%s.", +- obd->obd_type->typ_name, obd->obd_name, +- osc_obd->obd_name); +- lprocfs_remove(&lov_proc_dir); +- obd->obd_proc_private = NULL; ++ LASSERT(osc_obd != NULL); ++ LASSERT(osc_obd->obd_magic == OBD_DEVICE_MAGIC); ++ LASSERT(osc_obd->obd_type->typ_name != NULL); ++ ++ osc_symlink = lprocfs_add_symlink(osc_obd->obd_name, ++ obd->obd_type->typ_procsym, ++ "../../../%s/%s", ++ osc_obd->obd_type->typ_name, ++ osc_obd->obd_name); ++ if (osc_symlink == NULL) { ++ CERROR("could not register LOV target " ++ "/proc/fs/lustre/%s/%s/target_obds/%s.", ++ obd->obd_type->typ_name, obd->obd_name, ++ osc_obd->obd_name); ++ lprocfs_remove(&obd->obd_type->typ_procsym); ++ obd->obd_type->typ_procsym = NULL; + } + } + #endif +@@ -250,6 +246,17 @@ static int lov_connect(const struct lu_env *env, + if (data) + lov->lov_ocd = *data; + ++#ifdef __KERNEL__ ++ obd->obd_type->typ_procsym = lprocfs_seq_register("target_obds", ++ obd->obd_proc_entry, ++ NULL, NULL); ++ if (IS_ERR(obd->obd_type->typ_procsym)) { ++ CERROR("could not register /proc/fs/lustre/%s/%s/target_obds.", ++ obd->obd_type->typ_name, obd->obd_name); ++ obd->obd_type->typ_procsym = NULL; ++ } ++#endif ++ + obd_getref(obd); + for (i = 0; i < lov->desc.ld_tgt_count; i++) { + tgt = lov->lov_tgts[i]; +@@ -280,7 +287,6 @@ static int lov_connect(const struct lu_env *env, + + static int lov_disconnect_obd(struct obd_device *obd, struct lov_tgt_desc *tgt) + { +- struct proc_dir_entry *lov_proc_dir; + struct lov_obd *lov = &obd->u.lov; + struct obd_device *osc_obd; + int rc; +@@ -296,18 +302,18 @@ static int lov_disconnect_obd(struct obd_device *obd, struct lov_tgt_desc *tgt) + tgt->ltd_exp->exp_obd->obd_inactive = 1; + } + +- lov_proc_dir = obd->obd_proc_private; +- if (lov_proc_dir) +- lprocfs_remove_proc_entry(osc_obd->obd_name, lov_proc_dir); ++ if (obd->obd_type->typ_procsym) ++ lprocfs_remove_proc_entry(osc_obd->obd_name, ++ obd->obd_type->typ_procsym); + +- if (osc_obd) { +- /* Pass it on to our clients. +- * XXX This should be an argument to disconnect, +- * XXX not a back-door flag on the OBD. Ah well. +- */ +- osc_obd->obd_force = obd->obd_force; +- osc_obd->obd_fail = obd->obd_fail; +- osc_obd->obd_no_recov = obd->obd_no_recov; ++ if (osc_obd) { ++ /* Pass it on to our clients. ++ * XXX This should be an argument to disconnect, ++ * XXX not a back-door flag on the OBD. Ah well. ++ */ ++ osc_obd->obd_force = obd->obd_force; ++ osc_obd->obd_fail = obd->obd_fail; ++ osc_obd->obd_no_recov = obd->obd_no_recov; + } + + obd_register_observer(osc_obd, NULL); +@@ -353,6 +359,14 @@ static int lov_disconnect(struct obd_export *exp) + } + obd_putref(obd); + ++#ifdef __KERNEL__ ++ if (obd->obd_type->typ_procsym) ++ lprocfs_remove(&obd->obd_type->typ_procsym); ++ else ++ CERROR("/proc/fs/lustre/%s/%s/target_obds missing\n", ++ obd->obd_type->typ_name, obd->obd_name); ++#endif ++ + out: + rc = class_disconnect(exp); /* bz 9811 */ + RETURN(rc); +diff --git a/lustre/obdclass/genops.c b/lustre/obdclass/genops.c +index c9d8a4e..b9606bb 100644 +--- a/lustre/obdclass/genops.c ++++ b/lustre/obdclass/genops.c +@@ -220,6 +220,7 @@ int class_register_type(struct obd_ops *dt_ops, struct md_ops *md_ops, + type->typ_procroot = NULL; + GOTO (failed, rc); + } ++ type->typ_procsym = NULL; + #endif + if (ldt != NULL) { + type->typ_lu = ldt; +@@ -242,6 +243,8 @@ int class_register_type(struct obd_ops *dt_ops, struct md_ops *md_ops, + if (type->typ_dt_ops != NULL) + OBD_FREE_PTR(type->typ_dt_ops); + #ifdef LPROCFS ++ if (type->typ_procsym != NULL) ++ lprocfs_remove(&type->typ_procsym); + #ifndef HAVE_ONLY_PROCFS_SEQ + lprocfs_try_remove_proc_entry(type->typ_name, proc_lustre_root); + #else +-- +1.8.5.3 + diff --git a/sys-cluster/lustre/files/0003-LU-3974-llite-dentry-d_compare-changes-in-3.11.patch b/sys-cluster/lustre/files/0003-LU-3974-llite-dentry-d_compare-changes-in-3.11.patch deleted file mode 100644 index 6873a226a..000000000 --- a/sys-cluster/lustre/files/0003-LU-3974-llite-dentry-d_compare-changes-in-3.11.patch +++ /dev/null @@ -1,132 +0,0 @@ -From 18cfd561fae3b2eac663b51f8e5147b59c711af7 Mon Sep 17 00:00:00 2001 -From: James Simmons <uja.ornl@gmail.com> -Date: Wed, 11 Dec 2013 10:29:41 -0500 -Subject: [PATCH 03/18] LU-3974 llite: dentry d_compare changes in 3.11 - -In the linux 3.11 kernel the d_compare function has -removed passing in any struct inode arguments. This -patch provides support to handle this case. - -Signed-off-by: James Simmons <uja.ornl@gmail.com> -Change-Id: I363057e4d0a119ad43a9907ec26e7e0079f7c305 ---- - lustre/autoconf/lustre-core.m4 | 19 +++++++++++++++++++ - lustre/llite/dcache.c | 27 +++++++++++---------------- - lustre/llite/llite_internal.h | 7 ------- - 3 files changed, 30 insertions(+), 23 deletions(-) - -diff --git a/lustre/autoconf/lustre-core.m4 b/lustre/autoconf/lustre-core.m4 -index f47bc5f..7f9bb45 100644 ---- a/lustre/autoconf/lustre-core.m4 -+++ b/lustre/autoconf/lustre-core.m4 -@@ -1287,6 +1287,24 @@ LB_LINUX_TRY_COMPILE([ - ]) - - # -+# 3.11 dentry_operations.d_compare() taken 5 arguments. -+# -+AC_DEFUN([LC_D_COMPARE_5ARGS], -+[AC_MSG_CHECKING([if d_compare taken 5 arguments]) -+LB_LINUX_TRY_COMPILE([ -+ #include <linux/dcache.h> -+],[ -+ ((struct dentry_operations*)0)->d_compare(NULL,NULL,0,NULL,NULL); -+],[ -+ AC_DEFINE(HAVE_D_COMPARE_5ARGS, 1, -+ [d_compare need 5 arguments]) -+ AC_MSG_RESULT([yes]) -+],[ -+ AC_MSG_RESULT([no]) -+]) -+]) -+ -+# - # 3.11 need to access d_count to get dentry reference count - # - AC_DEFUN([LC_HAVE_DCOUNT], -@@ -1405,6 +1423,7 @@ AC_DEFUN([LC_PROG_LINUX], - LC_BLKDEV_RELEASE_RETURN_INT - - # 3.11 -+ LC_D_COMPARE_5ARGS - LC_HAVE_DCOUNT - - # -diff --git a/lustre/llite/dcache.c b/lustre/llite/dcache.c -index 6fca4cb..8a8c100 100644 ---- a/lustre/llite/dcache.c -+++ b/lustre/llite/dcache.c -@@ -89,11 +89,19 @@ static void ll_release(struct dentry *de) - int ll_dcompare(const struct dentry *parent, const struct inode *pinode, - const struct dentry *dentry, const struct inode *inode, - unsigned int len, const char *str, const struct qstr *name) -+#elif defined(HAVE_D_COMPARE_5ARGS) -+int ll_dcompare(const struct dentry *parent, const struct dentry *dentry, -+ unsigned int len, const char *str, const struct qstr *name) - #else - int ll_dcompare(struct dentry *parent, struct qstr *d_name, struct qstr *name) - #endif - { --#ifdef HAVE_D_COMPARE_7ARGS -+#if !defined(HAVE_D_COMPARE_7ARGS) && !defined(HAVE_D_COMPARE_5ARGS) -+ /* XXX: (ugh !) d_name must be in-dentry structure */ -+ struct dentry *dentry = container_of(d_name, struct dentry, d_name); -+ unsigned int len = d_name->len; -+ const char *str = d_name->name; -+#endif - ENTRY; - - if (len != name->len) -@@ -101,19 +109,6 @@ int ll_dcompare(struct dentry *parent, struct qstr *d_name, struct qstr *name) - - if (memcmp(str, name->name, len)) - RETURN(1); --#else -- struct dentry *dentry; -- ENTRY; -- -- if (d_name->len != name->len) -- RETURN(1); -- -- if (memcmp(d_name->name, name->name, name->len)) -- RETURN(1); -- -- /* XXX: d_name must be in-dentry structure */ -- dentry = container_of(d_name, struct dentry, d_name); /* ugh */ --#endif - - CDEBUG(D_DENTRY, "found name %.*s(%p) flags %#x refc %d\n", - name->len, name->name, dentry, dentry->d_flags, -@@ -124,9 +119,9 @@ int ll_dcompare(struct dentry *parent, struct qstr *d_name, struct qstr *name) - RETURN(0); - - if (d_lustre_invalid(dentry)) -- RETURN(1); -+ RETURN(1); - -- RETURN(0); -+ RETURN(0); - } - - static inline int return_if_equal(struct ldlm_lock *lock, void *data) -diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h -index daeac51..9da81ca 100644 ---- a/lustre/llite/llite_internal.h -+++ b/lustre/llite/llite_internal.h -@@ -857,13 +857,6 @@ void ll_intent_release(struct lookup_intent *); - void ll_invalidate_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); --#ifdef HAVE_D_COMPARE_7ARGS --int ll_dcompare(const struct dentry *parent, const struct inode *pinode, -- const struct dentry *dentry, const struct inode *inode, -- unsigned int len, const char *str, const struct qstr *d_name); --#else --int ll_dcompare(struct dentry *parent, struct qstr *d_name, struct qstr *name); --#endif - int ll_revalidate_it_finish(struct ptlrpc_request *request, - struct lookup_intent *it, struct dentry *de); - --- -1.8.5.1 - diff --git a/sys-cluster/lustre/files/0012-LU-3319-procfs-move-mgs-proc-handling-to-seq_files.patch b/sys-cluster/lustre/files/0004-LU-3319-procfs-move-mgs-proc-handling-to-seq_files.patch index bc0b2238f..dd5e37782 100644 --- a/sys-cluster/lustre/files/0012-LU-3319-procfs-move-mgs-proc-handling-to-seq_files.patch +++ b/sys-cluster/lustre/files/0004-LU-3319-procfs-move-mgs-proc-handling-to-seq_files.patch @@ -1,7 +1,7 @@ -From fa5fde4522b64dfc2e5695d88dca0ae99910cb1f Mon Sep 17 00:00:00 2001 +From 223f07785cbb8d28ef563bfba382b101a064a928 Mon Sep 17 00:00:00 2001 From: James Simmons <uja.ornl@gmail.com> -Date: Tue, 17 Dec 2013 12:24:40 -0500 -Subject: [PATCH 12/18] LU-3319 procfs: move mgs proc handling to seq_files +Date: Fri, 3 Jan 2014 09:58:53 -0500 +Subject: [PATCH 04/13] LU-3319 procfs: move mgs proc handling to seq_files With 3.10 linux kernel and above proc handling now only uses struct seq_files. This patch migrates the mgs @@ -10,17 +10,17 @@ layer proc entries over to using seq_files. Signed-off-by: James Simmons <uja.ornl@gmail.com> Change-Id: I1a12dd9b1fc8f139116a8f3a684956a5ba88f055 --- - lustre/mgs/lproc_mgs.c | 197 ++++++++++++++++++++++------------------------ + lustre/mgs/lproc_mgs.c | 202 +++++++++++++++++++++++----------------------- lustre/mgs/mgs_handler.c | 5 +- lustre/mgs/mgs_internal.h | 13 +-- lustre/mgs/mgs_nids.c | 11 ++- - 4 files changed, 105 insertions(+), 121 deletions(-) + 4 files changed, 110 insertions(+), 121 deletions(-) diff --git a/lustre/mgs/lproc_mgs.c b/lustre/mgs/lproc_mgs.c -index ffa2d0d..746d1c1 100644 +index ffa2d0d..f0ea956 100644 --- a/lustre/mgs/lproc_mgs.c +++ b/lustre/mgs/lproc_mgs.c -@@ -126,19 +126,105 @@ static int mgsself_srpc_seq_show(struct seq_file *seq, void *v) +@@ -126,19 +126,110 @@ static int mgsself_srpc_seq_show(struct seq_file *seq, void *v) return 0; } @@ -107,11 +107,16 @@ index ffa2d0d..746d1c1 100644 +LPROC_SEQ_FOPS_RW_TYPE(mgs, ir_timeout); + +struct lprocfs_seq_vars lprocfs_mgs_obd_vars[] = { -+ { "uuid", &mgs_uuid_fops }, -+ { "num_exports", &mgs_num_exports_fops }, -+ { "hash_stats", &mgs_hash_fops }, -+ { "evict_client", &mgs_evict_client_fops }, -+ { "ir_timeout", &mgs_ir_timeout_fops }, ++ { .name = "uuid", ++ .fops = &mgs_uuid_fops }, ++ { .name = "num_exports", ++ .fops = &mgs_num_exports_fops }, ++ { .name = "hash_stats", ++ .fops = &mgs_hash_fops }, ++ { .name = "evict_client", ++ .fops = &mgs_evict_client_fops }, ++ { .name = "ir_timeout", ++ .fops = &mgs_ir_timeout_fops }, + { 0 } +}; + @@ -130,7 +135,7 @@ index ffa2d0d..746d1c1 100644 if (rc != 0) GOTO(out, rc); -@@ -152,17 +238,17 @@ int lproc_mgs_setup(struct mgs_device *mgs, const char *osd_name) +@@ -152,17 +243,17 @@ int lproc_mgs_setup(struct mgs_device *mgs, const char *osd_name) if (rc != 0) GOTO(out, rc); @@ -153,7 +158,7 @@ index ffa2d0d..746d1c1 100644 if (IS_ERR(obd->obd_proc_exports_entry)) { rc = PTR_ERR(obd->obd_proc_exports_entry); obd->obd_proc_exports_entry = NULL; -@@ -215,7 +301,6 @@ void lproc_mgs_cleanup(struct mgs_device *mgs) +@@ -215,7 +306,6 @@ void lproc_mgs_cleanup(struct mgs_device *mgs) if (mgs->mgs_proc_live != NULL) { /* Should be no live entries */ @@ -161,7 +166,7 @@ index ffa2d0d..746d1c1 100644 lprocfs_remove(&mgs->mgs_proc_live); mgs->mgs_proc_live = NULL; } -@@ -226,92 +311,6 @@ void lproc_mgs_cleanup(struct mgs_device *mgs) +@@ -226,92 +316,6 @@ void lproc_mgs_cleanup(struct mgs_device *mgs) lprocfs_free_md_stats(obd); } @@ -254,7 +259,7 @@ index ffa2d0d..746d1c1 100644 void mgs_counter_incr(struct obd_export *exp, int opcode) { lprocfs_counter_incr(exp->exp_obd->obd_stats, opcode); -@@ -329,10 +328,4 @@ void mgs_stats_counter_init(struct lprocfs_stats *stats) +@@ -329,10 +333,4 @@ void mgs_stats_counter_init(struct lprocfs_stats *stats) lprocfs_counter_init(stats, LPROC_MGS_TARGET_REG, 0, "tgtreg", "reqs"); lprocfs_counter_init(stats, LPROC_MGS_TARGET_DEL, 0, "tgtdel", "reqs"); } @@ -266,10 +271,10 @@ index ffa2d0d..746d1c1 100644 -} #endif diff --git a/lustre/mgs/mgs_handler.c b/lustre/mgs/mgs_handler.c -index 560dd19..a294237 100644 +index 5be9040..4bb842c 100644 --- a/lustre/mgs/mgs_handler.c +++ b/lustre/mgs/mgs_handler.c -@@ -1376,12 +1376,9 @@ static struct obd_ops mgs_obd_device_ops = { +@@ -1434,12 +1434,9 @@ static struct obd_ops mgs_obd_device_ops = { static int __init mgs_init(void) { @@ -284,10 +289,10 @@ index 560dd19..a294237 100644 LUSTRE_MGS_NAME, &mgs_device_type); } diff --git a/lustre/mgs/mgs_internal.h b/lustre/mgs/mgs_internal.h -index 514dc23..497ad9d 100644 +index ca2846e..d3baacd 100644 --- a/lustre/mgs/mgs_internal.h +++ b/lustre/mgs/mgs_internal.h -@@ -225,10 +225,10 @@ int mgs_get_ir_logs(struct ptlrpc_request *req); +@@ -229,10 +229,10 @@ int mgs_get_ir_logs(struct ptlrpc_request *req); int lprocfs_wr_ir_state(struct file *file, const char *buffer, unsigned long count, void *data); int lprocfs_rd_ir_state(struct seq_file *seq, void *data); @@ -302,7 +307,7 @@ index 514dc23..497ad9d 100644 void mgs_fsc_cleanup(struct obd_export *exp); void mgs_fsc_cleanup_by_fsdb(struct fs_db *fsdb); int mgs_fsc_attach(const struct lu_env *env, struct obd_export *exp, -@@ -246,7 +246,6 @@ int lproc_mgs_setup(struct mgs_device *mgs, const char *osd_name); +@@ -250,7 +250,6 @@ int lproc_mgs_setup(struct mgs_device *mgs, const char *osd_name); void lproc_mgs_cleanup(struct mgs_device *mgs); int lproc_mgs_add_live(struct mgs_device *mgs, struct fs_db *fsdb); int lproc_mgs_del_live(struct mgs_device *mgs, struct fs_db *fsdb); @@ -310,7 +315,7 @@ index 514dc23..497ad9d 100644 #else static inline int lproc_mgs_setup(struct mgs_device *mgs, const char *osd_name) {return 0;} -@@ -256,10 +255,6 @@ static inline int lproc_mgs_add_live(struct mgs_device *mgs, struct fs_db *fsdb) +@@ -260,10 +259,6 @@ static inline int lproc_mgs_add_live(struct mgs_device *mgs, struct fs_db *fsdb) {return 0;} static inline int lproc_mgs_del_live(struct mgs_device *mgs, struct fs_db *fsdb) {return 0;} @@ -322,7 +327,7 @@ index 514dc23..497ad9d 100644 /* mgs/lproc_mgs.c */ diff --git a/lustre/mgs/mgs_nids.c b/lustre/mgs/mgs_nids.c -index 4d53969..73a4576 100644 +index a2bae59..3248387 100644 --- a/lustre/mgs/mgs_nids.c +++ b/lustre/mgs/mgs_nids.c @@ -838,15 +838,14 @@ int lprocfs_rd_ir_state(struct seq_file *seq, void *data) @@ -347,5 +352,5 @@ index 4d53969..73a4576 100644 return lprocfs_wr_uint(file, buffer, count, &ir_timeout); } -- -1.8.5.1 +1.8.5.3 diff --git a/sys-cluster/lustre/files/0004-LU-3974-llite-use-new-struct-dir_context.patch b/sys-cluster/lustre/files/0004-LU-3974-llite-use-new-struct-dir_context.patch deleted file mode 100644 index f79a30e16..000000000 --- a/sys-cluster/lustre/files/0004-LU-3974-llite-use-new-struct-dir_context.patch +++ /dev/null @@ -1,276 +0,0 @@ -From 82f692de87cb6c7db8f050b3201d23f4852a404c Mon Sep 17 00:00:00 2001 -From: James Simmons <uja.ornl@gmail.com> -Date: Mon, 2 Dec 2013 12:05:14 -0500 -Subject: [PATCH 04/18] LU-3974 llite: use new struct dir_context - -The readdir and nfs code over time has added more -parameters to be passed to be processed. For the 3.11 -kernel a new struct dir_context was introduced to -minimize the impact of future expansion. This patch -addresses this change. - -Signed-off-by: James Simmons <uja.ornl@gmail.com> -Change-Id: Ib42bf8cb06635a2a64e63b294d79e66ac82a1a5b ---- - lustre/autoconf/lustre-core.m4 | 20 ++++++++++ - lustre/llite/dir.c | 86 +++++++++++++++++++++++++++++------------- - lustre/llite/llite_internal.h | 7 ++++ - lustre/llite/llite_nfs.c | 33 ++++++++++------ - 4 files changed, 107 insertions(+), 39 deletions(-) - -diff --git a/lustre/autoconf/lustre-core.m4 b/lustre/autoconf/lustre-core.m4 -index 7f9bb45..3ac55d6 100644 ---- a/lustre/autoconf/lustre-core.m4 -+++ b/lustre/autoconf/lustre-core.m4 -@@ -1287,6 +1287,25 @@ LB_LINUX_TRY_COMPILE([ - ]) - - # -+# 3.11 readdir now takes the new struct dir_context -+# -+AC_DEFUN([LC_HAVE_DIR_CONTEXT], -+[AC_MSG_CHECKING([if dir_context exist]) -+LB_LINUX_TRY_COMPILE([ -+ #include <linux/fs.h> -+],[ -+ struct dir_context ctx; -+ -+ ctx.pos = 0; -+],[ -+ AC_DEFINE(HAVE_DIR_CONTEXT, 1, [dir_context exist]) -+ AC_MSG_RESULT([yes]) -+],[ -+ AC_MSG_RESULT([no]) -+]) -+]) -+ -+# - # 3.11 dentry_operations.d_compare() taken 5 arguments. - # - AC_DEFUN([LC_D_COMPARE_5ARGS], -@@ -1423,6 +1442,7 @@ AC_DEFUN([LC_PROG_LINUX], - LC_BLKDEV_RELEASE_RETURN_INT - - # 3.11 -+ LC_HAVE_DIR_CONTEXT - LC_D_COMPARE_5ARGS - LC_HAVE_DCOUNT - -diff --git a/lustre/llite/dir.c b/lustre/llite/dir.c -index 2021897..e2546cc 100644 ---- a/lustre/llite/dir.c -+++ b/lustre/llite/dir.c -@@ -477,19 +477,25 @@ fail: - goto out_unlock; - } - -+#ifdef HAVE_DIR_CONTEXT -+int ll_dir_read(struct inode *inode, struct dir_context *ctx) -+{ -+ __u64 pos = ctx->pos; -+#else - int ll_dir_read(struct inode *inode, __u64 *_pos, void *cookie, - filldir_t filldir) - { -- struct ll_inode_info *info = ll_i2info(inode); -- struct ll_sb_info *sbi = ll_i2sbi(inode); -- __u64 pos = *_pos; -- int api32 = ll_need_32bit_api(sbi); -- int hash64 = sbi->ll_flags & LL_SBI_64BIT_HASH; -- struct page *page; -- struct ll_dir_chain chain; -- int done = 0; -- int rc = 0; -- ENTRY; -+ __u64 pos = *_pos; -+#endif -+ struct ll_inode_info *info = ll_i2info(inode); -+ struct ll_sb_info *sbi = ll_i2sbi(inode); -+ int api32 = ll_need_32bit_api(sbi); -+ int hash64 = sbi->ll_flags & LL_SBI_64BIT_HASH; -+ struct page *page; -+ struct ll_dir_chain chain; -+ int done = 0; -+ int rc = 0; -+ ENTRY; - - ll_dir_chain_init(&chain); - -@@ -542,12 +548,18 @@ int ll_dir_read(struct inode *inode, __u64 *_pos, void *cookie, - fid_le_to_cpu(&fid, &ent->lde_fid); - ino = cl_fid_build_ino(&fid, api32); - type = ll_dirent_type_get(ent); -- /* For 'll_nfs_get_name_filldir()', it will try -- * to access the 'ent' through its 'lde_name', -- * so the parameter 'name' for 'filldir()' must -- * be part of the 'ent'. */ -- done = filldir(cookie, ent->lde_name, namelen, -- lhash, ino, type); -+#ifdef HAVE_DIR_CONTEXT -+ ctx->pos = lhash; -+ /* For 'll_nfs_get_name_filldir()', it will try -+ * to access the 'ent' through its 'lde_name', -+ * so the parameter 'name' for 'filldir()' must -+ * be part of the 'ent'. */ -+ done = !dir_emit(ctx, ent->lde_name, -+ namelen, ino, type); -+#else -+ done = filldir(cookie, ent->lde_name, namelen, -+ lhash, ino, type); -+#endif - } - next = le64_to_cpu(dp->ldp_hash_end); - if (!done) { -@@ -588,12 +600,20 @@ int ll_dir_read(struct inode *inode, __u64 *_pos, void *cookie, - } - } - -+#ifdef HAVE_DIR_CONTEXT -+ ctx->pos = pos; -+#else - *_pos = pos; -+#endif - ll_dir_chain_fini(&chain); - RETURN(rc); - } - -+#ifdef HAVE_DIR_CONTEXT -+static int ll_iterate(struct file *filp, struct dir_context *ctx) -+#else - static int ll_readdir(struct file *filp, void *cookie, filldir_t filldir) -+#endif - { - struct inode *inode = filp->f_dentry->d_inode; - struct ll_file_data *lfd = LUSTRE_FPRIVATE(filp); -@@ -622,20 +642,28 @@ static int ll_readdir(struct file *filp, void *cookie, filldir_t filldir) - */ - GOTO(out, rc = 0); - -+#ifdef HAVE_DIR_CONTEXT -+ ctx->pos = pos; -+ rc = ll_dir_read(inode, ctx); -+ pos = ctx->pos; -+#else - rc = ll_dir_read(inode, &pos, cookie, filldir); -+#endif - if (lfd != NULL) - lfd->lfd_pos = pos; -- if (pos == MDS_DIR_END_OFF) { -- if (api32) -- filp->f_pos = LL_DIR_END_OFF_32BIT; -- else -- filp->f_pos = LL_DIR_END_OFF; -- } else { -- if (api32 && hash64) -- filp->f_pos = pos >> 32; -- else -- filp->f_pos = pos; -+ if (pos == MDS_DIR_END_OFF) { -+ if (api32) -+ pos = LL_DIR_END_OFF_32BIT; -+ else -+ pos = LL_DIR_END_OFF; -+ } else if (api32 && hash64) { -+ pos >>= 32; - } -+#ifdef HAVE_DIR_CONTEXT -+ ctx->pos = pos; -+#else -+ filp->f_pos = pos; -+#endif - filp->f_version = inode->i_version; - #ifdef HAVE_TOUCH_ATIME_1ARG - #ifdef HAVE_F_PATH_MNT -@@ -2020,7 +2048,11 @@ struct file_operations ll_dir_operations = { - .open = ll_dir_open, - .release = ll_dir_release, - .read = generic_read_dir, -- .readdir = ll_readdir, -+#ifdef HAVE_DIR_CONTEXT -+ .iterate = ll_iterate, -+#else -+ .readdir = ll_readdir, -+#endif - .unlocked_ioctl = ll_dir_ioctl, - .fsync = ll_fsync, - }; -diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h -index 9da81ca..283e106 100644 ---- a/lustre/llite/llite_internal.h -+++ b/lustre/llite/llite_internal.h -@@ -91,6 +91,9 @@ extern struct file_operations ll_pgcache_seq_fops; - #define REMOTE_PERM_HASHSIZE 16 - - struct ll_getname_data { -+#ifdef HAVE_DIR_CONTEXT -+ struct dir_context ctx; -+#endif - char *lgd_name; /* points to a buffer with NAME_MAX+1 size */ - struct lu_fid lgd_fid; /* target fid we are looking for */ - int lgd_found; /* inode matched? */ -@@ -722,8 +725,12 @@ extern struct file_operations ll_dir_operations; - extern struct inode_operations ll_dir_inode_operations; - struct page *ll_get_dir_page(struct inode *dir, __u64 hash, - struct ll_dir_chain *chain); -+#ifdef HAVE_DIR_CONTEXT -+int ll_dir_read(struct inode *inode, struct dir_context *ctx); -+#else - int ll_dir_read(struct inode *inode, __u64 *_pos, void *cookie, - filldir_t filldir); -+#endif - - int ll_get_mdt_idx(struct inode *inode); - /* llite/namei.c */ -diff --git a/lustre/llite/llite_nfs.c b/lustre/llite/llite_nfs.c -index 2926caf..25b16e8 100644 ---- a/lustre/llite/llite_nfs.c -+++ b/lustre/llite/llite_nfs.c -@@ -235,24 +235,33 @@ static int ll_nfs_get_name_filldir(void *cookie, const char *name, int namelen, - static int ll_get_name(struct dentry *dentry, char *name, - struct dentry *child) - { -- struct inode *dir = dentry->d_inode; -- struct ll_getname_data lgd; -+ struct inode *dir = dentry->d_inode; -+ struct ll_getname_data lgd = { -+ .lgd_name = name, -+ .lgd_fid = ll_i2info(child->d_inode)->lli_fid, -+#ifdef HAVE_DIR_CONTEXT -+ .ctx.actor = ll_nfs_get_name_filldir, -+ }; -+#else -+ .lgd_found = 0, -+ }; - __u64 offset = 0; -- int rc; -- ENTRY; -- -- if (!dir || !S_ISDIR(dir->i_mode)) -- GOTO(out, rc = -ENOTDIR); -+#endif -+ int rc; -+ ENTRY; - -- if (!dir->i_fop) -- GOTO(out, rc = -EINVAL); -+ if (!dir || !S_ISDIR(dir->i_mode)) -+ GOTO(out, rc = -ENOTDIR); - -- lgd.lgd_name = name; -- lgd.lgd_fid = ll_i2info(child->d_inode)->lli_fid; -- lgd.lgd_found = 0; -+ if (!dir->i_fop) -+ GOTO(out, rc = -EINVAL); - - mutex_lock(&dir->i_mutex); -+#ifdef HAVE_DIR_CONTEXT -+ rc = ll_dir_read(dir, &lgd.ctx); -+#else - rc = ll_dir_read(dir, &offset, &lgd, ll_nfs_get_name_filldir); -+#endif - mutex_unlock(&dir->i_mutex); - if (!rc && !lgd.lgd_found) - rc = -ENOENT; --- -1.8.5.1 - diff --git a/sys-cluster/lustre/files/0011-LU-3319-procfs-update-zfs-proc-handling-to-seq_files.patch b/sys-cluster/lustre/files/0005-LU-3319-procfs-update-zfs-proc-handling-to-seq_files.patch index b3964cc06..4d11be880 100644 --- a/sys-cluster/lustre/files/0011-LU-3319-procfs-update-zfs-proc-handling-to-seq_files.patch +++ b/sys-cluster/lustre/files/0005-LU-3319-procfs-update-zfs-proc-handling-to-seq_files.patch @@ -1,23 +1,49 @@ -From 45e9fffb84c0c272992232ed229586003ab99e5e Mon Sep 17 00:00:00 2001 +From 3c08f9d074a2f89f71f41c8a99272706ad4450ea Mon Sep 17 00:00:00 2001 From: James Simmons <uja.ornl@gmail.com> -Date: Thu, 14 Nov 2013 19:11:20 -0500 -Subject: [PATCH 11/18] LU-3319 procfs: update zfs proc handling to seq_files +Date: Fri, 3 Jan 2014 09:55:26 -0500 +Subject: [PATCH 05/13] LU-3319 procfs: update zfs proc handling to seq_files Migrate all zfs proc handling to using strictly seq_files. Signed-off-by: James Simmons <uja.ornl@gmail.com> Change-Id: I6dc7e65c3e74e7934a17939815ec3c334fac58c7 --- - lustre/osd-zfs/osd_handler.c | 2 +- + lustre/osd-zfs/osd_handler.c | 13 ++++--- lustre/osd-zfs/osd_internal.h | 3 -- - lustre/osd-zfs/osd_lproc.c | 78 ++++++++++++++++++++++--------------------- - 3 files changed, 41 insertions(+), 42 deletions(-) + lustre/osd-zfs/osd_lproc.c | 88 ++++++++++++++++++++++++------------------- + 3 files changed, 57 insertions(+), 47 deletions(-) diff --git a/lustre/osd-zfs/osd_handler.c b/lustre/osd-zfs/osd_handler.c -index 77f4799..b40d03d 100644 +index d4193cd..36bf6a4 100644 --- a/lustre/osd-zfs/osd_handler.c +++ b/lustre/osd-zfs/osd_handler.c -@@ -900,7 +900,7 @@ int __init osd_init(void) +@@ -745,6 +745,7 @@ static int osd_device_init(const struct lu_env *env, struct lu_device *d, + static int osd_process_config(const struct lu_env *env, + struct lu_device *d, struct lustre_cfg *cfg) + { ++ struct obd_device *obd = d->ld_obd; + struct osd_device *o = osd_dev(d); + int rc; + ENTRY; +@@ -758,12 +759,12 @@ static int osd_process_config(const struct lu_env *env, + break; + case LCFG_PARAM: { + LASSERT(&o->od_dt_dev); +- rc = class_process_proc_param(PARAM_OSD, lprocfs_osd_obd_vars, +- cfg, &o->od_dt_dev); ++ rc = class_process_proc_seq_param(PARAM_OSD, obd->obd_vars, ++ cfg, &o->od_dt_dev); + if (rc > 0 || rc == -ENOSYS) +- rc = class_process_proc_param(PARAM_OST, +- lprocfs_osd_obd_vars, +- cfg, &o->od_dt_dev); ++ rc = class_process_proc_seq_param(PARAM_OST, ++ obd->obd_vars, cfg, ++ &o->od_dt_dev); + break; + } + default: +@@ -911,7 +912,7 @@ int __init osd_init(void) rc = class_register_type(&osd_obd_device_ops, NULL, NULL, #ifndef HAVE_ONLY_PROCFS_SEQ @@ -27,7 +53,7 @@ index 77f4799..b40d03d 100644 LUSTRE_OSD_ZFS_NAME, &osd_device_type); if (rc) diff --git a/lustre/osd-zfs/osd_internal.h b/lustre/osd-zfs/osd_internal.h -index 0e202d2..fbad073 100644 +index bc51cb1..77b118f 100644 --- a/lustre/osd-zfs/osd_internal.h +++ b/lustre/osd-zfs/osd_internal.h @@ -402,9 +402,6 @@ enum { @@ -41,7 +67,7 @@ index 0e202d2..fbad073 100644 int osd_procfs_fini(struct osd_device *osd); diff --git a/lustre/osd-zfs/osd_lproc.c b/lustre/osd-zfs/osd_lproc.c -index 0854ce6..5a2bbac 100644 +index 0854ce6..a7ce60d 100644 --- a/lustre/osd-zfs/osd_lproc.c +++ b/lustre/osd-zfs/osd_lproc.c @@ -107,27 +107,26 @@ out: @@ -112,7 +138,7 @@ index 0854ce6..5a2bbac 100644 int rc, val; LASSERT(osd != NULL); -@@ -165,24 +165,26 @@ static int lprocfs_osd_wr_iused_est(struct file *file, const char *buffer, +@@ -165,24 +165,36 @@ static int lprocfs_osd_wr_iused_est(struct file *file, const char *buffer, return count; } @@ -144,20 +170,30 @@ index 0854ce6..5a2bbac 100644 +LPROC_SEQ_FOPS_RO_TYPE(zfs, dt_filesfree); + +struct lprocfs_seq_vars lprocfs_osd_obd_vars[] = { -+ { "blocksize", &zfs_dt_blksize_fops }, -+ { "kbytestotal", &zfs_dt_kbytestotal_fops }, -+ { "kbytesfree", &zfs_dt_kbytesfree_fops }, -+ { "kbytesavail", &zfs_dt_kbytesavail_fops }, -+ { "filestotal", &zfs_dt_filestotal_fops }, -+ { "filesfree", &zfs_dt_filesfree_fops }, -+ { "fstype", &zfs_osd_fstype_fops }, -+ { "mntdev", &zfs_osd_mntdev_fops }, -+ { "force_sync", &zfs_osd_force_sync_fops }, -+ { "quota_iused_estimate",&zfs_osd_iused_est_fops }, ++ { .name = "blocksize", ++ .fops = &zfs_dt_blksize_fops }, ++ { .name = "kbytestotal", ++ .fops = &zfs_dt_kbytestotal_fops }, ++ { .name = "kbytesfree", ++ .fops = &zfs_dt_kbytesfree_fops }, ++ { .name = "kbytesavail", ++ .fops = &zfs_dt_kbytesavail_fops }, ++ { .name = "filestotal", ++ .fops = &zfs_dt_filestotal_fops }, ++ { .name = "filesfree", ++ .fops = &zfs_dt_filesfree_fops }, ++ { .name = "fstype", ++ .fops = &zfs_osd_fstype_fops }, ++ { .name = "mntdev", ++ .fops = &zfs_osd_mntdev_fops }, ++ { .name = "force_sync", ++ .fops = &zfs_osd_force_sync_fops }, ++ { .name = "quota_iused_estimate", ++ .fops = &zfs_osd_iused_est_fops }, { 0 } }; -@@ -202,7 +204,7 @@ int osd_procfs_init(struct osd_device *osd, const char *name) +@@ -202,7 +214,7 @@ int osd_procfs_init(struct osd_device *osd, const char *name) LASSERT(name != NULL); LASSERT(type != NULL); @@ -167,5 +203,5 @@ index 0854ce6..5a2bbac 100644 if (IS_ERR(osd->od_proc_entry)) { rc = PTR_ERR(osd->od_proc_entry); -- -1.8.5.1 +1.8.5.3 diff --git a/sys-cluster/lustre/files/0006-LU-3319-procfs-move-llite-proc-handling-over-to-seq_.patch b/sys-cluster/lustre/files/0006-LU-3319-procfs-move-llite-proc-handling-over-to-seq_.patch deleted file mode 100644 index e56376aab..000000000 --- a/sys-cluster/lustre/files/0006-LU-3319-procfs-move-llite-proc-handling-over-to-seq_.patch +++ /dev/null @@ -1,1334 +0,0 @@ -From 01ce737ef8bba37c904d79f3aabe88a4ead20b74 Mon Sep 17 00:00:00 2001 -From: James Simmons <uja.ornl@gmail.com> -Date: Thu, 5 Dec 2013 13:53:37 -0500 -Subject: [PATCH 06/18] LU-3319 procfs: move llite proc handling over to - seq_file - -For lustre clients a special abstract layer so a lustre -client can be mounted. In order to support 3.10+ kernels -this client code being the llite,vvp,and clio layers proc -proc handling has been ported to using seq_files only. - -Signed-off-by: James Simmons <uja.ornl@gmail.com> -Change-Id: Id2ac0956dbdf586ab1200e2edb00d489c15c5d50 ---- - lustre/include/cl_object.h | 4 +- - lustre/include/lu_object.h | 1 + - lustre/llite/llite_internal.h | 7 +- - lustre/llite/llite_lib.c | 40 ++- - lustre/llite/lproc_llite.c | 611 +++++++++++++++++++++--------------------- - lustre/llite/super25.c | 2 +- - lustre/llite/vvp_dev.c | 7 +- - lustre/obdclass/cl_object.c | 93 +++---- - lustre/obdclass/lu_object.c | 22 ++ - 9 files changed, 402 insertions(+), 385 deletions(-) - -diff --git a/lustre/include/cl_object.h b/lustre/include/cl_object.h -index 0aedd62..9735671 100644 ---- a/lustre/include/cl_object.h -+++ b/lustre/include/cl_object.h -@@ -2553,8 +2553,6 @@ struct cache_stats { - - /** These are not exported so far */ - void cache_stats_init (struct cache_stats *cs, const char *name); --int cache_stats_print(const struct cache_stats *cs, -- char *page, int count, int header); - - /** - * Client-side site. This represents particular client stack. "Global" -@@ -2586,7 +2584,7 @@ void cl_stack_fini(const struct lu_env *env, struct cl_device *cl); - * Output client site statistical counters into a buffer. Suitable for - * ll_rd_*()-style functions. - */ --int cl_site_stats_print(const struct cl_site *s, char *page, int count); -+int cl_site_stats_print(const struct cl_site *site, struct seq_file *m); - - /** - * \name helpers -diff --git a/lustre/include/lu_object.h b/lustre/include/lu_object.h -index 94c0b47..103debd 100644 ---- a/lustre/include/lu_object.h -+++ b/lustre/include/lu_object.h -@@ -1279,6 +1279,7 @@ int lu_env_refill_by_tags(struct lu_env *env, __u32 ctags, __u32 stags); - * Output site statistical counters into a buffer. Suitable for - * ll_rd_*()-style functions. - */ -+int lu_site_stats_seq_print(const struct lu_site *s, struct seq_file *m); - int lu_site_stats_print(const struct lu_site *s, char *page, int count); - - /** -diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h -index 283e106..44f6522 100644 ---- a/lustre/llite/llite_internal.h -+++ b/lustre/llite/llite_internal.h -@@ -706,15 +706,16 @@ int lprocfs_register_mountpoint(struct proc_dir_entry *parent, - struct super_block *sb, char *osc, char *mdc); - void lprocfs_unregister_mountpoint(struct ll_sb_info *sbi); - void ll_stats_ops_tally(struct ll_sb_info *sbi, int op, int count); --void lprocfs_llite_init_vars(struct lprocfs_static_vars *lvars); -+int ll_process_proc_param(struct lustre_cfg *lcfg, unsigned long *sb); - #else - static inline int lprocfs_register_mountpoint(struct proc_dir_entry *parent, - struct super_block *sb, char *osc, char *mdc){return 0;} - static inline void lprocfs_unregister_mountpoint(struct ll_sb_info *sbi) {} - static void ll_stats_ops_tally(struct ll_sb_info *sbi, int op, int count) {} --static void lprocfs_llite_init_vars(struct lprocfs_static_vars *lvars) -+ -+static int ll_process_proc_param(struct lustre_cfg *lcfg, unsigned long *sb) - { -- memset(lvars, 0, sizeof(*lvars)); -+ return 0; - } - #endif - -diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c -index 9d9e432..86f07c9 100644 ---- a/lustre/llite/llite_lib.c -+++ b/lustre/llite/llite_lib.c -@@ -2277,31 +2277,23 @@ out_statfs: - - int ll_process_config(struct lustre_cfg *lcfg) - { -- char *ptr; -- void *sb; -- struct lprocfs_static_vars lvars; -- unsigned long x; -- int rc = 0; -+ struct super_block *sb; -+ unsigned long x; -+ char *ptr; - -- lprocfs_llite_init_vars(&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); -- if (rc > 0) -- rc = 0; -- return(rc); -+ /* 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 = (struct super_block *)x; -+ /* This better be a real Lustre superblock! */ -+ LASSERT(s2lsi(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! */ -+ return ll_process_proc_param(lcfg, &x); - } - - /* this function prepares md_op_data hint for passing ot down to MD stack. */ -diff --git a/lustre/llite/lproc_llite.c b/lustre/llite/lproc_llite.c -index 2686924..7793a63 100644 ---- a/lustre/llite/lproc_llite.c -+++ b/lustre/llite/lproc_llite.c -@@ -37,8 +37,8 @@ - - #include <linux/version.h> - #include <lustre_lite.h> -+#include <lustre_param.h> - #include <lprocfs_status.h> --#include <linux/seq_file.h> - #include <obd_support.h> - - #include "llite_internal.h" -@@ -52,10 +52,9 @@ struct file_operations ll_rw_extents_stats_fops; - struct file_operations ll_rw_extents_stats_pp_fops; - struct file_operations ll_rw_offset_stats_fops; - --static int ll_rd_blksize(char *page, char **start, off_t off, int count, -- int *eof, void *data) -+static int ll_blksize_seq_show(struct seq_file *m, void *v) - { -- struct super_block *sb = (struct super_block *)data; -+ struct super_block *sb = m->private; - struct obd_statfs osfs; - int rc; - -@@ -63,18 +62,15 @@ static int ll_rd_blksize(char *page, char **start, off_t off, int count, - rc = ll_statfs_internal(sb, &osfs, - cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS), - OBD_STATFS_NODELAY); -- if (!rc) { -- *eof = 1; -- rc = snprintf(page, count, "%u\n", osfs.os_bsize); -- } -- -+ if (!rc) -+ rc = seq_printf(m, "%u\n", osfs.os_bsize); - return rc; - } -+LPROC_SEQ_FOPS_RO(ll_blksize); - --static int ll_rd_kbytestotal(char *page, char **start, off_t off, int count, -- int *eof, void *data) -+static int ll_kbytestotal_seq_show(struct seq_file *m, void *v) - { -- struct super_block *sb = (struct super_block *)data; -+ struct super_block *sb = m->private; - struct obd_statfs osfs; - int rc; - -@@ -89,17 +85,15 @@ static int ll_rd_kbytestotal(char *page, char **start, off_t off, int count, - while (blk_size >>= 1) - result <<= 1; - -- *eof = 1; -- rc = snprintf(page, count, LPU64"\n", result); -+ rc = seq_printf(m, LPU64"\n", result); - } - return rc; -- - } -+LPROC_SEQ_FOPS_RO(ll_kbytestotal); - --static int ll_rd_kbytesfree(char *page, char **start, off_t off, int count, -- int *eof, void *data) -+static int ll_kbytesfree_seq_show(struct seq_file *m, void *v) - { -- struct super_block *sb = (struct super_block *)data; -+ struct super_block *sb = m->private; - struct obd_statfs osfs; - int rc; - -@@ -114,16 +108,15 @@ static int ll_rd_kbytesfree(char *page, char **start, off_t off, int count, - while (blk_size >>= 1) - result <<= 1; - -- *eof = 1; -- rc = snprintf(page, count, LPU64"\n", result); -+ rc = seq_printf(m, LPU64"\n", result); - } - return rc; - } -+LPROC_SEQ_FOPS_RO(ll_kbytesfree); - --static int ll_rd_kbytesavail(char *page, char **start, off_t off, int count, -- int *eof, void *data) -+static int ll_kbytesavail_seq_show(struct seq_file *m, void *v) - { -- struct super_block *sb = (struct super_block *)data; -+ struct super_block *sb = m->private; - struct obd_statfs osfs; - int rc; - -@@ -138,16 +131,15 @@ static int ll_rd_kbytesavail(char *page, char **start, off_t off, int count, - while (blk_size >>= 1) - result <<= 1; - -- *eof = 1; -- rc = snprintf(page, count, LPU64"\n", result); -+ rc = seq_printf(m, LPU64"\n", result); - } - return rc; - } -+LPROC_SEQ_FOPS_RO(ll_kbytesavail); - --static int ll_rd_filestotal(char *page, char **start, off_t off, int count, -- int *eof, void *data) -+static int ll_filestotal_seq_show(struct seq_file *m, void *v) - { -- struct super_block *sb = (struct super_block *)data; -+ struct super_block *sb = m->private; - struct obd_statfs osfs; - int rc; - -@@ -155,86 +147,73 @@ static int ll_rd_filestotal(char *page, char **start, off_t off, int count, - rc = ll_statfs_internal(sb, &osfs, - cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS), - OBD_STATFS_NODELAY); -- if (!rc) { -- *eof = 1; -- rc = snprintf(page, count, LPU64"\n", osfs.os_files); -- } -- return rc; -+ if (!rc) -+ rc = seq_printf(m, LPU64"\n", osfs.os_files); -+ return rc; - } -+LPROC_SEQ_FOPS_RO(ll_filestotal); - --static int ll_rd_filesfree(char *page, char **start, off_t off, int count, -- int *eof, void *data) -+static int ll_filesfree_seq_show(struct seq_file *m, void *v) - { -- struct super_block *sb = (struct super_block *)data; -- struct obd_statfs osfs; -- int rc; -- -- LASSERT(sb != NULL); -- rc = ll_statfs_internal(sb, &osfs, -- cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS), -- OBD_STATFS_NODELAY); -- if (!rc) { -- *eof = 1; -- rc = snprintf(page, count, LPU64"\n", osfs.os_ffree); -- } -- return rc; -+ struct super_block *sb = m->private; -+ struct obd_statfs osfs; -+ int rc; - -+ LASSERT(sb != NULL); -+ rc = ll_statfs_internal(sb, &osfs, -+ cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS), -+ OBD_STATFS_NODELAY); -+ if (!rc) -+ rc = seq_printf(m, LPU64"\n", osfs.os_ffree); -+ return rc; - } -+LPROC_SEQ_FOPS_RO(ll_filesfree); - --static int ll_rd_client_type(char *page, char **start, off_t off, int count, -- int *eof, void *data) -+static int ll_client_type_seq_show(struct seq_file *m, void *v) - { -- struct ll_sb_info *sbi = ll_s2sbi((struct super_block *)data); -- int rc; -- -- LASSERT(sbi != NULL); -+ struct ll_sb_info *sbi = ll_s2sbi((struct super_block *)m->private); -+ int rc; - -- *eof = 1; -- if (sbi->ll_flags & LL_SBI_RMT_CLIENT) -- rc = snprintf(page, count, "remote client\n"); -- else -- rc = snprintf(page, count, "local client\n"); -+ LASSERT(sbi != NULL); - -- return rc; -+ if (sbi->ll_flags & LL_SBI_RMT_CLIENT) -+ rc = seq_printf(m, "remote client\n"); -+ else -+ rc = seq_printf(m, "local client\n"); -+ return rc; - } -+LPROC_SEQ_FOPS_RO(ll_client_type); - --static int ll_rd_fstype(char *page, char **start, off_t off, int count, -- int *eof, void *data) -+static int ll_fstype_seq_show(struct seq_file *m, void *v) - { -- struct super_block *sb = (struct super_block*)data; -+ struct super_block *sb = m->private; - -- LASSERT(sb != NULL); -- *eof = 1; -- return snprintf(page, count, "%s\n", sb->s_type->name); -+ LASSERT(sb != NULL); -+ return seq_printf(m, "%s\n", sb->s_type->name); - } -+LPROC_SEQ_FOPS_RO(ll_fstype); - --static int ll_rd_sb_uuid(char *page, char **start, off_t off, int count, -- int *eof, void *data) -+static int ll_sb_uuid_seq_show(struct seq_file *m, void *v) - { -- struct super_block *sb = (struct super_block *)data; -+ struct super_block *sb = m->private; - -- LASSERT(sb != NULL); -- *eof = 1; -- return snprintf(page, count, "%s\n", ll_s2sbi(sb)->ll_sb_uuid.uuid); -+ LASSERT(sb != NULL); -+ return seq_printf(m, "%s\n", ll_s2sbi(sb)->ll_sb_uuid.uuid); - } -+LPROC_SEQ_FOPS_RO(ll_sb_uuid); - --static int ll_rd_xattr_cache(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int ll_xattr_cache_seq_show(struct seq_file *m, void *v) - { -- struct super_block *sb = (struct super_block *)data; -- struct ll_sb_info *sbi = ll_s2sbi(sb); -- int rc; -- -- rc = snprintf(page, count, "%u\n", sbi->ll_xattr_cache_enabled); -+ struct ll_sb_info *sbi = ll_s2sbi((struct super_block *)m->private); - -- return rc; -+ return seq_printf(m, "%u\n", sbi->ll_xattr_cache_enabled); - } - --static int ll_wr_xattr_cache(struct file *file, const char *buffer, -- unsigned long count, void *data) -+static ssize_t ll_xattr_cache_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) - { -- struct super_block *sb = (struct super_block *)data; -- struct ll_sb_info *sbi = ll_s2sbi(sb); -+ struct seq_file *m = file->private_data; -+ struct ll_sb_info *sbi = ll_s2sbi((struct super_block *)m->private); - int val, rc; - - rc = lprocfs_write_helper(buffer, count, &val); -@@ -251,24 +230,23 @@ static int ll_wr_xattr_cache(struct file *file, const char *buffer, - - return count; - } -+LPROC_SEQ_FOPS(ll_xattr_cache); - --static int ll_rd_site_stats(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int ll_site_stats_seq_show(struct seq_file *m, void *v) - { -- struct super_block *sb = data; -- -- /* -- * See description of statistical counters in struct cl_site, and -- * struct lu_site. -- */ -- return cl_site_stats_print(lu2cl_site(ll_s2sbi(sb)->ll_site), -- page, count); -+ struct super_block *sb = m->private; -+ -+ /* -+ * See description of statistical counters in struct cl_site, and -+ * struct lu_site. -+ */ -+ return cl_site_stats_print(lu2cl_site(ll_s2sbi(sb)->ll_site), m); - } -+LPROC_SEQ_FOPS_RO(ll_site_stats); - --static int ll_rd_max_readahead_mb(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int ll_max_readahead_mb_seq_show(struct seq_file *m, void *v) - { -- struct super_block *sb = data; -+ struct super_block *sb = m->private; - struct ll_sb_info *sbi = ll_s2sbi(sb); - long pages_number; - int mult; -@@ -278,14 +256,15 @@ static int ll_rd_max_readahead_mb(char *page, char **start, off_t off, - spin_unlock(&sbi->ll_lock); - - mult = 1 << (20 - PAGE_CACHE_SHIFT); -- return lprocfs_read_frac_helper(page, count, pages_number, mult); -+ return lprocfs_seq_read_frac_helper(m, pages_number, mult); - } - --static int ll_wr_max_readahead_mb(struct file *file, const char *buffer, -- unsigned long count, void *data) -+static ssize_t -+ll_max_readahead_mb_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) - { -- struct super_block *sb = data; -- struct ll_sb_info *sbi = ll_s2sbi(sb); -+ struct seq_file *m = file->private_data; -+ struct ll_sb_info *sbi = ll_s2sbi((struct super_block *)m->private); - int mult, rc, pages_number; - - mult = 1 << (20 - PAGE_CACHE_SHIFT); -@@ -303,14 +282,13 @@ static int ll_wr_max_readahead_mb(struct file *file, const char *buffer, - spin_lock(&sbi->ll_lock); - sbi->ll_ra_info.ra_max_pages = pages_number; - spin_unlock(&sbi->ll_lock); -- - return count; - } -+LPROC_SEQ_FOPS(ll_max_readahead_mb); - --static int ll_rd_max_readahead_per_file_mb(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int ll_max_readahead_per_file_mb_seq_show(struct seq_file *m, void *v) - { -- struct super_block *sb = data; -+ struct super_block *sb = m->private; - struct ll_sb_info *sbi = ll_s2sbi(sb); - long pages_number; - int mult; -@@ -320,15 +298,16 @@ static int ll_rd_max_readahead_per_file_mb(char *page, char **start, off_t off, - spin_unlock(&sbi->ll_lock); - - mult = 1 << (20 - PAGE_CACHE_SHIFT); -- return lprocfs_read_frac_helper(page, count, pages_number, mult); -+ return lprocfs_seq_read_frac_helper(m, pages_number, mult); - } - --static int ll_wr_max_readahead_per_file_mb(struct file *file, const char *buffer, -- unsigned long count, void *data) -+static ssize_t -+ll_max_readahead_per_file_mb_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) - { -- struct super_block *sb = data; -- struct ll_sb_info *sbi = ll_s2sbi(sb); -- int mult, rc, pages_number; -+ struct seq_file *m = file->private_data; -+ struct ll_sb_info *sbi = ll_s2sbi((struct super_block *)m->private); -+ int mult, rc, pages_number; - - mult = 1 << (20 - PAGE_CACHE_SHIFT); - rc = lprocfs_write_frac_helper(buffer, count, &pages_number, mult); -@@ -346,14 +325,13 @@ static int ll_wr_max_readahead_per_file_mb(struct file *file, const char *buffer - spin_lock(&sbi->ll_lock); - sbi->ll_ra_info.ra_max_pages_per_file = pages_number; - spin_unlock(&sbi->ll_lock); -- - return count; - } -+LPROC_SEQ_FOPS(ll_max_readahead_per_file_mb); - --static int ll_rd_max_read_ahead_whole_mb(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int ll_max_read_ahead_whole_mb_seq_show(struct seq_file *m, void *v) - { -- struct super_block *sb = data; -+ struct super_block *sb = m->private; - struct ll_sb_info *sbi = ll_s2sbi(sb); - long pages_number; - int mult; -@@ -363,14 +341,15 @@ static int ll_rd_max_read_ahead_whole_mb(char *page, char **start, off_t off, - spin_unlock(&sbi->ll_lock); - - mult = 1 << (20 - PAGE_CACHE_SHIFT); -- return lprocfs_read_frac_helper(page, count, pages_number, mult); -+ return lprocfs_seq_read_frac_helper(m, pages_number, mult); - } - --static int ll_wr_max_read_ahead_whole_mb(struct file *file, const char *buffer, -- unsigned long count, void *data) -+static ssize_t -+ll_max_read_ahead_whole_mb_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) - { -- struct super_block *sb = data; -- struct ll_sb_info *sbi = ll_s2sbi(sb); -+ struct seq_file *m = file->private_data; -+ struct ll_sb_info *sbi = ll_s2sbi((struct super_block *)m->private); - int mult, rc, pages_number; - - mult = 1 << (20 - PAGE_CACHE_SHIFT); -@@ -392,24 +371,22 @@ 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 = pages_number; - spin_unlock(&sbi->ll_lock); -- - return count; - } -+LPROC_SEQ_FOPS(ll_max_read_ahead_whole_mb); - --static int ll_rd_max_cached_mb(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int ll_max_cached_mb_seq_show(struct seq_file *m, void *v) - { -- struct super_block *sb = data; -+ struct super_block *sb = m->private; - struct ll_sb_info *sbi = ll_s2sbi(sb); - struct cl_client_cache *cache = &sbi->ll_cache; - int shift = 20 - PAGE_CACHE_SHIFT; - int max_cached_mb; - int unused_mb; - -- *eof = 1; - max_cached_mb = cache->ccc_lru_max >> shift; - unused_mb = cfs_atomic_read(&cache->ccc_lru_left) >> shift; -- return snprintf(page, count, -+ return seq_printf(m, - "users: %d\n" - "max_cached_mb: %d\n" - "used_mb: %d\n" -@@ -422,16 +399,17 @@ static int ll_rd_max_cached_mb(char *page, char **start, off_t off, - cache->ccc_lru_shrinkers); - } - --static int ll_wr_max_cached_mb(struct file *file, const char *buffer, -- unsigned long nob, void *data) -+static ssize_t -+ll_max_cached_mb_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) - { -- struct super_block *sb = data; -+ struct seq_file *m = file->private_data; -+ struct super_block *sb = m->private; - struct ll_sb_info *sbi = ll_s2sbi(sb); - struct cl_client_cache *cache = &sbi->ll_cache; - struct lu_env *env; - int refcheck; - int mult, rc, pages_number; -- size_t count = nob; - int diff = 0; - int nrpages = 0; - ENTRY; -@@ -512,22 +490,21 @@ out: - } - return rc; - } -+LPROC_SEQ_FOPS(ll_max_cached_mb); - --static int ll_rd_checksum(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int ll_checksum_seq_show(struct seq_file *m, void *v) - { -- struct super_block *sb = data; -- struct ll_sb_info *sbi = ll_s2sbi(sb); -+ struct super_block *sb = m->private; -+ struct ll_sb_info *sbi = ll_s2sbi(sb); - -- return snprintf(page, count, "%u\n", -- (sbi->ll_flags & LL_SBI_CHECKSUM) ? 1 : 0); -+ return seq_printf(m, "%u\n", (sbi->ll_flags & LL_SBI_CHECKSUM) ? 1 : 0); - } - --static int ll_wr_checksum(struct file *file, const char *buffer, -- unsigned long count, void *data) -+static ssize_t ll_checksum_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) - { -- struct super_block *sb = data; -- struct ll_sb_info *sbi = ll_s2sbi(sb); -+ struct seq_file *m = file->private_data; -+ struct ll_sb_info *sbi = ll_s2sbi((struct super_block *)m->private); - int val, rc; - - if (!sbi->ll_dt_exp) -@@ -549,19 +526,20 @@ static int ll_wr_checksum(struct file *file, const char *buffer, - - return count; - } -+LPROC_SEQ_FOPS(ll_checksum); - --static int ll_rd_max_rw_chunk(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int ll_max_rw_chunk_seq_show(struct seq_file *m, void *v) - { -- struct super_block *sb = data; -+ struct super_block *sb = m->private; - -- return snprintf(page, count, "%lu\n", ll_s2sbi(sb)->ll_max_rw_chunk); -+ return seq_printf(m, "%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) -+static ssize_t ll_max_rw_chunk_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) - { -- struct super_block *sb = data; -+ struct seq_file *m = file->private_data; -+ struct super_block *sb = m->private; - int rc, val; - - rc = lprocfs_write_helper(buffer, count, &val); -@@ -570,27 +548,26 @@ static int ll_wr_max_rw_chunk(struct file *file, const char *buffer, - ll_s2sbi(sb)->ll_max_rw_chunk = val; - return count; - } -+LPROC_SEQ_FOPS(ll_max_rw_chunk); - --static int ll_rd_track_id(char *page, int count, void *data, -- enum stats_track_type type) -+static int ll_rd_track_id(struct seq_file *m, enum stats_track_type type) - { -- struct super_block *sb = data; -- -- if (ll_s2sbi(sb)->ll_stats_track_type == type) { -- return snprintf(page, count, "%d\n", -- ll_s2sbi(sb)->ll_stats_track_id); -+ struct super_block *sb = m->private; - -- } else if (ll_s2sbi(sb)->ll_stats_track_type == STATS_TRACK_ALL) { -- return snprintf(page, count, "0 (all)\n"); -- } else { -- return snprintf(page, count, "untracked\n"); -- } -+ if (ll_s2sbi(sb)->ll_stats_track_type == type) { -+ return seq_printf(m, "%d\n", -+ ll_s2sbi(sb)->ll_stats_track_id); -+ } else if (ll_s2sbi(sb)->ll_stats_track_type == STATS_TRACK_ALL) { -+ return seq_printf(m, "0 (all)\n"); -+ } else { -+ return seq_printf(m, "untracked\n"); -+ } - } - - static int ll_wr_track_id(const char *buffer, unsigned long count, void *data, -- enum stats_track_type type) -+ enum stats_track_type type) - { -- struct super_block *sb = data; -+ struct super_block *sb = data; - int rc, pid; - - rc = lprocfs_write_helper(buffer, count, &pid); -@@ -605,57 +582,59 @@ static int ll_wr_track_id(const char *buffer, unsigned long count, void *data, - return count; - } - --static int ll_rd_track_pid(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int ll_track_pid_seq_show(struct seq_file *m, void *v) - { -- return (ll_rd_track_id(page, count, data, STATS_TRACK_PID)); -+ return ll_rd_track_id(m, STATS_TRACK_PID); - } - --static int ll_wr_track_pid(struct file *file, const char *buffer, -- unsigned long count, void *data) -+static ssize_t ll_track_pid_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) - { -- return (ll_wr_track_id(buffer, count, data, STATS_TRACK_PID)); -+ struct seq_file *seq = file->private_data; -+ return ll_wr_track_id(buffer, count, seq->private, STATS_TRACK_PID); - } -+LPROC_SEQ_FOPS(ll_track_pid); - --static int ll_rd_track_ppid(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int ll_track_ppid_seq_show(struct seq_file *m, void *v) - { -- return (ll_rd_track_id(page, count, data, STATS_TRACK_PPID)); -+ return ll_rd_track_id(m, STATS_TRACK_PPID); - } - --static int ll_wr_track_ppid(struct file *file, const char *buffer, -- unsigned long count, void *data) -+static ssize_t ll_track_ppid_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) - { -- return (ll_wr_track_id(buffer, count, data, STATS_TRACK_PPID)); -+ struct seq_file *seq = file->private_data; -+ return ll_wr_track_id(buffer, count, seq->private, STATS_TRACK_PPID); - } -+LPROC_SEQ_FOPS(ll_track_ppid); - --static int ll_rd_track_gid(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int ll_track_gid_seq_show(struct seq_file *m, void *v) - { -- return (ll_rd_track_id(page, count, data, STATS_TRACK_GID)); -+ return ll_rd_track_id(m, STATS_TRACK_GID); - } - --static int ll_wr_track_gid(struct file *file, const char *buffer, -- unsigned long count, void *data) -+static ssize_t ll_track_gid_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) - { -- return (ll_wr_track_id(buffer, count, data, STATS_TRACK_GID)); -+ struct seq_file *seq = file->private_data; -+ return ll_wr_track_id(buffer, count, seq->private, STATS_TRACK_GID); - } -+LPROC_SEQ_FOPS(ll_track_gid); - --static int ll_rd_statahead_max(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int ll_statahead_max_seq_show(struct seq_file *m, void *v) - { -- struct super_block *sb = data; -- struct ll_sb_info *sbi = ll_s2sbi(sb); -+ struct super_block *sb = m->private; -+ struct ll_sb_info *sbi = ll_s2sbi(sb); - -- return snprintf(page, count, "%u\n", sbi->ll_sa_max); -+ return seq_printf(m, "%u\n", sbi->ll_sa_max); - } - --static int ll_wr_statahead_max(struct file *file, const char *buffer, -- unsigned long count, void *data) -+static ssize_t ll_statahead_max_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) - { -- struct super_block *sb = data; -- struct ll_sb_info *sbi = ll_s2sbi(sb); -- int val, rc; -+ struct seq_file *m = file->private_data; -+ struct ll_sb_info *sbi = ll_s2sbi((struct super_block *)m->private); -+ int val, rc; - - rc = lprocfs_write_helper(buffer, count, &val); - if (rc) -@@ -669,23 +648,23 @@ static int ll_wr_statahead_max(struct file *file, const char *buffer, - - return count; - } -+LPROC_SEQ_FOPS(ll_statahead_max); - --static int ll_rd_statahead_agl(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int ll_statahead_agl_seq_show(struct seq_file *m, void *v) - { -- struct super_block *sb = data; -- struct ll_sb_info *sbi = ll_s2sbi(sb); -+ struct super_block *sb = m->private; -+ struct ll_sb_info *sbi = ll_s2sbi(sb); - -- return snprintf(page, count, "%u\n", -- sbi->ll_flags & LL_SBI_AGL_ENABLED ? 1 : 0); -+ return seq_printf(m, "%u\n", -+ sbi->ll_flags & LL_SBI_AGL_ENABLED ? 1 : 0); - } - --static int ll_wr_statahead_agl(struct file *file, const char *buffer, -- unsigned long count, void *data) -+static ssize_t ll_statahead_agl_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) - { -- struct super_block *sb = data; -- struct ll_sb_info *sbi = ll_s2sbi(sb); -- int val, rc; -+ struct seq_file *m = file->private_data; -+ struct ll_sb_info *sbi = ll_s2sbi((struct super_block *)m->private); -+ int val, rc; - - rc = lprocfs_write_helper(buffer, count, &val); - if (rc) -@@ -698,14 +677,14 @@ static int ll_wr_statahead_agl(struct file *file, const char *buffer, - - return count; - } -+LPROC_SEQ_FOPS(ll_statahead_agl); - --static int ll_rd_statahead_stats(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int ll_statahead_stats_seq_show(struct seq_file *m, void *v) - { -- struct super_block *sb = data; -- struct ll_sb_info *sbi = ll_s2sbi(sb); -+ struct super_block *sb = m->private; -+ struct ll_sb_info *sbi = ll_s2sbi(sb); - -- return snprintf(page, count, -+ return seq_printf(m, - "statahead total: %u\n" - "statahead wrong: %u\n" - "agl total: %u\n", -@@ -713,23 +692,23 @@ static int ll_rd_statahead_stats(char *page, char **start, off_t off, - atomic_read(&sbi->ll_sa_wrong), - atomic_read(&sbi->ll_agl_total)); - } -+LPROC_SEQ_FOPS_RO(ll_statahead_stats); - --static int ll_rd_lazystatfs(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int ll_lazystatfs_seq_show(struct seq_file *m, void *v) - { -- struct super_block *sb = data; -- struct ll_sb_info *sbi = ll_s2sbi(sb); -+ struct super_block *sb = m->private; -+ struct ll_sb_info *sbi = ll_s2sbi(sb); - -- return snprintf(page, count, "%u\n", -- (sbi->ll_flags & LL_SBI_LAZYSTATFS) ? 1 : 0); -+ return seq_printf(m, "%u\n", -+ (sbi->ll_flags & LL_SBI_LAZYSTATFS) ? 1 : 0); - } - --static int ll_wr_lazystatfs(struct file *file, const char *buffer, -- unsigned long count, void *data) -+static ssize_t ll_lazystatfs_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) - { -- struct super_block *sb = data; -- struct ll_sb_info *sbi = ll_s2sbi(sb); -- int val, rc; -+ struct seq_file *m = file->private_data; -+ struct ll_sb_info *sbi = ll_s2sbi((struct super_block *)m->private); -+ int val, rc; - - rc = lprocfs_write_helper(buffer, count, &val); - if (rc) -@@ -742,30 +721,29 @@ static int ll_wr_lazystatfs(struct file *file, const char *buffer, - - return count; - } -+LPROC_SEQ_FOPS(ll_lazystatfs); - --static int ll_rd_maxea_size(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int ll_maxea_size_seq_show(struct seq_file *m, void *v) - { -- struct super_block *sb = data; -- struct ll_sb_info *sbi = ll_s2sbi(sb); -- unsigned int ealen; -- int rc; -+ struct super_block *sb = m->private; -+ struct ll_sb_info *sbi = ll_s2sbi(sb); -+ unsigned int ealen; -+ int rc; - - rc = ll_get_max_mdsize(sbi, &ealen); - if (rc) - return rc; - -- return snprintf(page, count, "%u\n", ealen); -+ return seq_printf(m, "%u\n", ealen); - } -+LPROC_SEQ_FOPS_RO(ll_maxea_size); - --static int ll_rd_sbi_flags(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int ll_sbi_flags_seq_show(struct seq_file *m, void *v) - { - const char *str[] = LL_SBI_FLAGS; -- struct super_block *sb = data; -+ struct super_block *sb = m->private; - int flags = ll_s2sbi(sb)->ll_flags; - int i = 0; -- int rc = 0; - - while (flags != 0) { - if (ARRAY_SIZE(str) <= i) { -@@ -775,66 +753,86 @@ static int ll_rd_sbi_flags(char *page, char **start, off_t off, - } - - if (flags & 0x1) -- rc += snprintf(page + rc, count - rc, "%s ", str[i]); -+ seq_printf(m, "%s ", str[i]); - flags >>= 1; - ++i; - } -- if (rc > 0) -- rc += snprintf(page + rc, count - rc, "\b\n"); -- return rc; -+ seq_printf(m, "\b\n"); -+ return 0; - } -+LPROC_SEQ_FOPS_RO(ll_sbi_flags); - --static int ll_rd_unstable_stats(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int ll_unstable_stats_seq_show(struct seq_file *m, void *v) - { -- struct super_block *sb = data; -+ struct super_block *sb = m->private; - struct ll_sb_info *sbi = ll_s2sbi(sb); - struct cl_client_cache *cache = &sbi->ll_cache; -- int pages, mb, rc; -+ int pages, mb; - - pages = cfs_atomic_read(&cache->ccc_unstable_nr); - mb = (pages * PAGE_CACHE_SIZE) >> 20; - -- rc = snprintf(page, count, "unstable_pages: %8d\n" -- "unstable_mb: %8d\n", pages, mb); -- -- return rc; -+ return seq_printf(m, "unstable_pages: %8d\n" -+ "unstable_mb: %8d\n", pages, mb); - } -- --static struct lprocfs_vars lprocfs_llite_obd_vars[] = { -- { "uuid", ll_rd_sb_uuid, 0, 0 }, -- //{ "mntpt_path", ll_rd_path, 0, 0 }, -- { "fstype", ll_rd_fstype, 0, 0 }, -- { "site", ll_rd_site_stats, 0, 0 }, -- { "blocksize", ll_rd_blksize, 0, 0 }, -- { "kbytestotal", ll_rd_kbytestotal, 0, 0 }, -- { "kbytesfree", ll_rd_kbytesfree, 0, 0 }, -- { "kbytesavail", ll_rd_kbytesavail, 0, 0 }, -- { "filestotal", ll_rd_filestotal, 0, 0 }, -- { "filesfree", ll_rd_filesfree, 0, 0 }, -- { "client_type", ll_rd_client_type, 0, 0 }, -- //{ "filegroups", lprocfs_rd_filegroups, 0, 0 }, -- { "max_read_ahead_mb", ll_rd_max_readahead_mb, -- ll_wr_max_readahead_mb, 0 }, -- { "max_read_ahead_per_file_mb", ll_rd_max_readahead_per_file_mb, -- ll_wr_max_readahead_per_file_mb, 0 }, -- { "max_read_ahead_whole_mb", ll_rd_max_read_ahead_whole_mb, -- 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 }, -- { "stats_track_pid", ll_rd_track_pid, ll_wr_track_pid, 0 }, -- { "stats_track_ppid", ll_rd_track_ppid, ll_wr_track_ppid, 0 }, -- { "stats_track_gid", ll_rd_track_gid, ll_wr_track_gid, 0 }, -- { "statahead_max", ll_rd_statahead_max, ll_wr_statahead_max, 0 }, -- { "statahead_agl", ll_rd_statahead_agl, ll_wr_statahead_agl, 0 }, -- { "statahead_stats", ll_rd_statahead_stats, 0, 0 }, -- { "lazystatfs", ll_rd_lazystatfs, ll_wr_lazystatfs, 0 }, -- { "max_easize", ll_rd_maxea_size, 0, 0 }, -- { "sbi_flags", ll_rd_sbi_flags, 0, 0 }, -- { "xattr_cache", ll_rd_xattr_cache, ll_wr_xattr_cache, 0 }, -- { "unstable_stats", ll_rd_unstable_stats, 0, 0}, -- { 0 } -+LPROC_SEQ_FOPS_RO(ll_unstable_stats); -+ -+static struct lprocfs_seq_vars lprocfs_llite_obd_vars[] = { -+ { .name = "uuid", -+ .fops = &ll_sb_uuid_fops }, -+ { .name = "fstype", -+ .fops = &ll_fstype_fops }, -+ { .name = "site", -+ .fops = &ll_site_stats_fops }, -+ { .name = "blocksize", -+ .fops = &ll_blksize_fops }, -+ { .name = "kbytestotal", -+ .fops = &ll_kbytestotal_fops }, -+ { .name = "kbytesfree", -+ .fops = &ll_kbytesfree_fops }, -+ { .name = "kbytesavail", -+ .fops = &ll_kbytesavail_fops }, -+ { .name = "filestotal", -+ .fops = &ll_filestotal_fops }, -+ { .name = "filesfree", -+ .fops = &ll_filesfree_fops }, -+ { .name = "client_type", -+ .fops = &ll_client_type_fops }, -+ { .name = "max_read_ahead_mb", -+ .fops = &ll_max_readahead_mb_fops }, -+ { .name = "max_read_ahead_per_file_mb", -+ .fops = &ll_max_readahead_per_file_mb_fops }, -+ { .name = "max_read_ahead_whole_mb", -+ .fops = &ll_max_read_ahead_whole_mb_fops }, -+ { .name = "max_cached_mb", -+ .fops = &ll_max_cached_mb_fops }, -+ { .name = "checksum_pages", -+ .fops = &ll_checksum_fops }, -+ { .name = "max_rw_chunk", -+ .fops = &ll_max_rw_chunk_fops }, -+ { .name = "stats_track_pid", -+ .fops = &ll_track_pid_fops }, -+ { .name = "stats_track_ppid", -+ .fops = &ll_track_ppid_fops }, -+ { .name = "stats_track_gid", -+ .fops = &ll_track_gid_fops }, -+ { .name = "statahead_max", -+ .fops = &ll_statahead_max_fops }, -+ { .name = "statahead_agl", -+ .fops = &ll_statahead_agl_fops }, -+ { .name = "statahead_stats", -+ .fops = &ll_statahead_stats_fops }, -+ { .name = "lazystatfs", -+ .fops = &ll_lazystatfs_fops }, -+ { .name = "max_easize", -+ .fops = &ll_maxea_size_fops }, -+ { .name = "sbi_flags", -+ .fops = &ll_sbi_flags_fops }, -+ { .name = "xattr_cache", -+ .fops = &ll_xattr_cache_fops }, -+ { .name = "unstable_stats", -+ .fops = &ll_unstable_stats_fops }, -+ { 0 } - }; - - #define MAX_STRING_SIZE 128 -@@ -924,14 +922,17 @@ static const char *ra_stat_string[] = { - [RA_STAT_WRONG_GRAB_PAGE] = "wrong page from grab_cache_page", - }; - -+LPROC_SEQ_FOPS_RO_TYPE(llite, name); -+LPROC_SEQ_FOPS_RO_TYPE(llite, uuid); - - int lprocfs_register_mountpoint(struct proc_dir_entry *parent, - struct super_block *sb, char *osc, char *mdc) - { -- struct lprocfs_vars lvars[2]; -+ struct lprocfs_seq_vars lvars[2]; - struct lustre_sb_info *lsi = s2lsi(sb); - struct ll_sb_info *sbi = ll_s2sbi(sb); - struct obd_device *obd; -+ struct proc_dir_entry *dir; - char name[MAX_STRING_SIZE + 1], *ptr; - int err, id, len, rc; - ENTRY; -@@ -955,7 +956,7 @@ int lprocfs_register_mountpoint(struct proc_dir_entry *parent, - snprintf(name, MAX_STRING_SIZE, "%.*s-%p", len, - lsi->lsi_lmd->lmd_profile, sb); - -- sbi->ll_proc_root = lprocfs_register(name, parent, NULL, NULL); -+ sbi->ll_proc_root = lprocfs_seq_register(name, parent, NULL, NULL); - if (IS_ERR(sbi->ll_proc_root)) { - err = PTR_ERR(sbi->ll_proc_root); - sbi->ll_proc_root = NULL; -@@ -1020,7 +1021,7 @@ int lprocfs_register_mountpoint(struct proc_dir_entry *parent, - GOTO(out, err); - - -- err = lprocfs_add_vars(sbi->ll_proc_root, lprocfs_llite_obd_vars, sb); -+ err = lprocfs_seq_add_vars(sbi->ll_proc_root, lprocfs_llite_obd_vars, sb); - if (err) - GOTO(out, err); - -@@ -1031,18 +1032,21 @@ int lprocfs_register_mountpoint(struct proc_dir_entry *parent, - LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC); - LASSERT(obd->obd_type->typ_name != NULL); - -- snprintf(name, MAX_STRING_SIZE, "%s/common_name", -- obd->obd_type->typ_name); -- lvars[0].read_fptr = lprocfs_rd_name; -- err = lprocfs_add_vars(sbi->ll_proc_root, lvars, obd); -- if (err) -- GOTO(out, err); -+ dir = proc_mkdir(obd->obd_type->typ_name, sbi->ll_proc_root); -+ if (dir == NULL) -+ GOTO(out, err = -ENOMEM); - -- snprintf(name, MAX_STRING_SIZE, "%s/uuid", obd->obd_type->typ_name); -- lvars[0].read_fptr = lprocfs_rd_uuid; -- err = lprocfs_add_vars(sbi->ll_proc_root, lvars, obd); -- if (err) -- GOTO(out, err); -+ snprintf(name, MAX_STRING_SIZE, "common_name"); -+ lvars[0].fops = &llite_name_fops; -+ err = lprocfs_seq_add_vars(dir, lvars, obd); -+ if (err) -+ GOTO(out, err); -+ -+ snprintf(name, MAX_STRING_SIZE, "uuid"); -+ lvars[0].fops = &llite_uuid_fops; -+ err = lprocfs_seq_add_vars(dir, lvars, obd); -+ if (err) -+ GOTO(out, err); - - /* OSC */ - obd = class_name2obd(osc); -@@ -1051,16 +1055,19 @@ int lprocfs_register_mountpoint(struct proc_dir_entry *parent, - LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC); - LASSERT(obd->obd_type->typ_name != NULL); - -- snprintf(name, MAX_STRING_SIZE, "%s/common_name", -- obd->obd_type->typ_name); -- lvars[0].read_fptr = lprocfs_rd_name; -- err = lprocfs_add_vars(sbi->ll_proc_root, lvars, obd); -- if (err) -- GOTO(out, err); -+ dir = proc_mkdir(obd->obd_type->typ_name, sbi->ll_proc_root); -+ if (dir == NULL) -+ GOTO(out, err = -ENOMEM); -+ -+ snprintf(name, MAX_STRING_SIZE, "common_name"); -+ lvars[0].fops = &llite_name_fops; -+ err = lprocfs_seq_add_vars(dir, lvars, obd); -+ if (err) -+ GOTO(out, err); - -- snprintf(name, MAX_STRING_SIZE, "%s/uuid", obd->obd_type->typ_name); -- lvars[0].read_fptr = lprocfs_rd_uuid; -- err = lprocfs_add_vars(sbi->ll_proc_root, lvars, obd); -+ snprintf(name, MAX_STRING_SIZE, "uuid"); -+ lvars[0].fops = &llite_uuid_fops; -+ err = lprocfs_seq_add_vars(dir, lvars, obd); - out: - if (err) { - lprocfs_remove(&sbi->ll_proc_root); -@@ -1439,9 +1446,11 @@ static ssize_t ll_rw_offset_stats_seq_write(struct file *file, const char *buf, - - LPROC_SEQ_FOPS(ll_rw_offset_stats); - --void lprocfs_llite_init_vars(struct lprocfs_static_vars *lvars) -+int ll_process_proc_param(struct lustre_cfg *lcfg, unsigned long *sb) - { -- lvars->module_vars = NULL; -- lvars->obd_vars = lprocfs_llite_obd_vars; -+ int rc = class_process_proc_seq_param(PARAM_LLITE, -+ lprocfs_llite_obd_vars, -+ lcfg, (void *)sb); -+ return (rc > 0 ? 0 : rc); - } - #endif /* LPROCFS */ -diff --git a/lustre/llite/super25.c b/lustre/llite/super25.c -index 06b55fe..4692f6e 100644 ---- a/lustre/llite/super25.c -+++ b/lustre/llite/super25.c -@@ -169,7 +169,7 @@ static int __init init_lustre_lite(void) - } - - proc_lustre_fs_root = proc_lustre_root ? -- lprocfs_register("llite", proc_lustre_root, NULL, NULL) : NULL; -+ lprocfs_seq_register("llite", proc_lustre_root, NULL, NULL) : NULL; - - lustre_register_client_fill_super(ll_fill_super); - lustre_register_kill_super_cb(ll_kill_super); -diff --git a/lustre/llite/vvp_dev.c b/lustre/llite/vvp_dev.c -index 2fdb613..fa124e2 100644 ---- a/lustre/llite/vvp_dev.c -+++ b/lustre/llite/vvp_dev.c -@@ -530,10 +530,9 @@ static struct seq_operations vvp_pgcache_ops = { - - static int vvp_dump_pgcache_seq_open(struct inode *inode, struct file *filp) - { -- struct proc_dir_entry *dp = PDE(inode); -- struct ll_sb_info *sbi = dp->data; -- struct seq_file *seq; -- int result; -+ struct ll_sb_info *sbi = PDE_DATA(inode); -+ struct seq_file *seq; -+ int result; - - result = seq_open(filp, &vvp_pgcache_ops); - if (result == 0) { -diff --git a/lustre/obdclass/cl_object.c b/lustre/obdclass/cl_object.c -index 1984836..985cf0b 100644 ---- a/lustre/obdclass/cl_object.c -+++ b/lustre/obdclass/cl_object.c -@@ -400,11 +400,10 @@ void cache_stats_init(struct cache_stats *cs, const char *name) - cfs_atomic_set(&cs->cs_stats[i], 0); - } - --int cache_stats_print(const struct cache_stats *cs, -- char *page, int count, int h) -+int cache_stats_print(const struct cache_stats *cs, struct seq_file *m, int h) - { -- int nob = 0; - int i; -+ - /* - * lookup hit total cached create - * env: ...... ...... ...... ...... ...... -@@ -412,18 +411,16 @@ int cache_stats_print(const struct cache_stats *cs, - if (h) { - const char *names[CS_NR] = CS_NAMES; - -- nob += snprintf(page + nob, count - nob, "%6s", " "); -+ seq_printf(m, "%6s", " "); - for (i = 0; i < CS_NR; i++) -- nob += snprintf(page + nob, count - nob, -- "%8s", names[i]); -- nob += snprintf(page + nob, count - nob, "\n"); -+ seq_printf(m, "%8s", names[i]); -+ seq_printf(m, "\n"); - } - -- nob += snprintf(page + nob, count - nob, "%5.5s:", cs->cs_name); -+ seq_printf(m, "%5.5s:", cs->cs_name); - for (i = 0; i < CS_NR; i++) -- nob += snprintf(page + nob, count - nob, "%8u", -- cfs_atomic_read(&cs->cs_stats[i])); -- return nob; -+ seq_printf(m, "%8u", cfs_atomic_read(&cs->cs_stats[i])); -+ return 0; - } - - static void cl_env_percpu_refill(void); -@@ -471,50 +468,48 @@ static struct cache_stats cl_env_stats = { - * Outputs client site statistical counters into a buffer. Suitable for - * ll_rd_*()-style functions. - */ --int cl_site_stats_print(const struct cl_site *site, char *page, int count) --{ -- int nob; -- int i; -- static const char *pstate[] = { -- [CPS_CACHED] = "c", -- [CPS_OWNED] = "o", -- [CPS_PAGEOUT] = "w", -- [CPS_PAGEIN] = "r", -- [CPS_FREEING] = "f" -- }; -- static const char *lstate[] = { -- [CLS_NEW] = "n", -- [CLS_QUEUING] = "q", -- [CLS_ENQUEUED] = "e", -- [CLS_HELD] = "h", -- [CLS_INTRANSIT] = "t", -- [CLS_CACHED] = "c", -- [CLS_FREEING] = "f" -- }; -+int cl_site_stats_print(const struct cl_site *site, struct seq_file *m) -+{ -+ static const char *pstate[] = { -+ [CPS_CACHED] = "c", -+ [CPS_OWNED] = "o", -+ [CPS_PAGEOUT] = "w", -+ [CPS_PAGEIN] = "r", -+ [CPS_FREEING] = "f" -+ }; -+ static const char *lstate[] = { -+ [CLS_NEW] = "n", -+ [CLS_QUEUING] = "q", -+ [CLS_ENQUEUED] = "e", -+ [CLS_HELD] = "h", -+ [CLS_INTRANSIT] = "t", -+ [CLS_CACHED] = "c", -+ [CLS_FREEING] = "f" -+ }; -+ int i; -+ - /* - lookup hit total busy create - pages: ...... ...... ...... ...... ...... [...... ...... ...... ......] - locks: ...... ...... ...... ...... ...... [...... ...... ...... ...... ......] - env: ...... ...... ...... ...... ...... - */ -- nob = lu_site_stats_print(&site->cs_lu, page, count); -- nob += cache_stats_print(&site->cs_pages, page + nob, count - nob, 1); -- nob += snprintf(page + nob, count - nob, " ["); -- for (i = 0; i < ARRAY_SIZE(site->cs_pages_state); ++i) -- nob += snprintf(page + nob, count - nob, "%s: %u ", -- pstate[i], -- cfs_atomic_read(&site->cs_pages_state[i])); -- nob += snprintf(page + nob, count - nob, "]\n"); -- nob += cache_stats_print(&site->cs_locks, page + nob, count - nob, 0); -- nob += snprintf(page + nob, count - nob, " ["); -- for (i = 0; i < ARRAY_SIZE(site->cs_locks_state); ++i) -- nob += snprintf(page + nob, count - nob, "%s: %u ", -- lstate[i], -- cfs_atomic_read(&site->cs_locks_state[i])); -- nob += snprintf(page + nob, count - nob, "]\n"); -- nob += cache_stats_print(&cl_env_stats, page + nob, count - nob, 0); -- nob += snprintf(page + nob, count - nob, "\n"); -- return nob; -+ lu_site_stats_seq_print(&site->cs_lu, m); -+ cache_stats_print(&site->cs_pages, m, 1); -+ seq_printf(m, " ["); -+ for (i = 0; i < ARRAY_SIZE(site->cs_pages_state); ++i) -+ seq_printf(m, "%s: %u ", pstate[i], -+ cfs_atomic_read(&site->cs_pages_state[i])); -+ seq_printf(m, "]\n"); -+ cache_stats_print(&site->cs_locks, m, 0); -+ seq_printf(m, " ["); -+ for (i = 0; i < ARRAY_SIZE(site->cs_locks_state); ++i) -+ seq_printf(m, "%s: %u ", lstate[i], -+ cfs_atomic_read(&site->cs_locks_state[i])); -+ seq_printf(m, "]\n"); -+ cache_stats_print(&cl_env_stats, m, 0); -+ seq_printf(m, "\n"); -+ return 0; - } - EXPORT_SYMBOL(cl_site_stats_print); - -diff --git a/lustre/obdclass/lu_object.c b/lustre/obdclass/lu_object.c -index 28a18ef..cca2ec0 100644 ---- a/lustre/obdclass/lu_object.c -+++ b/lustre/obdclass/lu_object.c -@@ -2090,6 +2090,28 @@ static __u32 ls_stats_read(struct lprocfs_stats *stats, int idx) - * Output site statistical counters into a buffer. Suitable for - * lprocfs_rd_*()-style functions. - */ -+int lu_site_stats_seq_print(const struct lu_site *s, struct seq_file *m) -+{ -+ lu_site_stats_t stats; -+ -+ memset(&stats, 0, sizeof(stats)); -+ lu_site_stats_get(s->ls_obj_hash, &stats, 1); -+ -+ return seq_printf(m, "%d/%d %d/%d %d %d %d %d %d %d %d\n", -+ stats.lss_busy, -+ stats.lss_total, -+ stats.lss_populated, -+ CFS_HASH_NHLIST(s->ls_obj_hash), -+ stats.lss_max_search, -+ ls_stats_read(s->ls_stats, LU_SS_CREATED), -+ ls_stats_read(s->ls_stats, LU_SS_CACHE_HIT), -+ ls_stats_read(s->ls_stats, LU_SS_CACHE_MISS), -+ ls_stats_read(s->ls_stats, LU_SS_CACHE_RACE), -+ ls_stats_read(s->ls_stats, LU_SS_CACHE_DEATH_RACE), -+ ls_stats_read(s->ls_stats, LU_SS_LRU_PURGED)); -+} -+EXPORT_SYMBOL(lu_site_stats_seq_print); -+ - int lu_site_stats_print(const struct lu_site *s, char *page, int count) - { - lu_site_stats_t stats; --- -1.8.5.1 - diff --git a/sys-cluster/lustre/files/0015-LU-3319-procfs-move-osp-proc-handling-to-seq_files.patch b/sys-cluster/lustre/files/0006-LU-3319-procfs-move-osp-proc-handling-to-seq_files.patch index 8d2547696..4189564a8 100644 --- a/sys-cluster/lustre/files/0015-LU-3319-procfs-move-osp-proc-handling-to-seq_files.patch +++ b/sys-cluster/lustre/files/0006-LU-3319-procfs-move-osp-proc-handling-to-seq_files.patch @@ -1,23 +1,23 @@ -From 1537f22b9b2bc9250006805774fc300e5240c2bc Mon Sep 17 00:00:00 2001 +From 0af5f0dce053b1623b18bec48731d20c0a80b7b5 Mon Sep 17 00:00:00 2001 From: James Simmons <uja.ornl@gmail.com> -Date: Thu, 14 Nov 2013 19:23:09 -0500 -Subject: [PATCH 15/18] LU-3319 procfs: move osp proc handling to seq_files +Date: Fri, 31 Jan 2014 12:50:59 -0500 +Subject: [PATCH 06/13] LU-3319 procfs: move osp proc handling to seq_files With 3.10 linux kernel and above proc handling now only uses struct seq_files. This patch migrates the osp layer proc entries over to using seq_files. Signed-off-by: James Simmons <uja.ornl@gmail.com> -Change-Id: If58826e11524a5fffd2e491c1386e3795015bc7e +Change-Id: Id8f77d72fd35755f1b7b1c17fcf27e0731bd5ac1 --- - lustre/osp/lproc_osp.c | 363 ++++++++++++++++++++++++---------------------- + lustre/osp/lproc_osp.c | 374 ++++++++++++++++++++++++---------------------- lustre/osp/lwp_dev.c | 18 +-- - lustre/osp/osp_dev.c | 38 ++--- + lustre/osp/osp_dev.c | 48 +++--- lustre/osp/osp_internal.h | 2 - - 4 files changed, 203 insertions(+), 218 deletions(-) + 4 files changed, 223 insertions(+), 219 deletions(-) diff --git a/lustre/osp/lproc_osp.c b/lustre/osp/lproc_osp.c -index 22e3372..24f2f4c 100644 +index 75ebeb1..3dc5ec7 100644 --- a/lustre/osp/lproc_osp.c +++ b/lustre/osp/lproc_osp.c @@ -45,24 +45,23 @@ @@ -189,7 +189,7 @@ index 22e3372..24f2f4c 100644 + struct obd_device *obd = m->private; struct osp_device *osp = lu2osp_dev(obd->obd_lu_dev); - if (osp == NULL) + if (osp == NULL || osp->opd_pre == NULL) return 0; - return snprintf(page, count, "%d\n", osp->opd_pre_grow_count); @@ -221,7 +221,7 @@ index 22e3372..24f2f4c 100644 + struct obd_device *obd = m->private; struct osp_device *osp = lu2osp_dev(obd->obd_lu_dev); - if (osp == NULL) + if (osp == NULL || osp->opd_pre == NULL) return 0; - return snprintf(page, count, "%d\n", osp->opd_pre_max_grow_count); @@ -253,7 +253,7 @@ index 22e3372..24f2f4c 100644 + struct obd_device *obd = m->private; struct osp_device *osp = lu2osp_dev(obd->obd_lu_dev); - if (osp == NULL) + if (osp == NULL || osp->opd_pre == NULL) return 0; - return snprintf(page, count, "%u\n", @@ -270,7 +270,7 @@ index 22e3372..24f2f4c 100644 + struct obd_device *obd = m->private; struct osp_device *osp = lu2osp_dev(obd->obd_lu_dev); - if (osp == NULL) + if (osp == NULL || osp->opd_pre == NULL) return 0; - return snprintf(page, count, "%u\n", @@ -287,7 +287,7 @@ index 22e3372..24f2f4c 100644 + struct obd_device *obd = m->private; struct osp_device *osp = lu2osp_dev(obd->obd_lu_dev); - if (osp == NULL) + if (osp == NULL || osp->opd_pre == NULL) return 0; - return snprintf(page, count, LPX64"\n", @@ -304,7 +304,7 @@ index 22e3372..24f2f4c 100644 + struct obd_device *obd = m->private; struct osp_device *osp = lu2osp_dev(obd->obd_lu_dev); - if (osp == NULL) + if (osp == NULL || osp->opd_pre == NULL) return 0; - return snprintf(page, count, LPX64"\n", @@ -321,7 +321,7 @@ index 22e3372..24f2f4c 100644 + struct obd_device *obd = m->private; struct osp_device *osp = lu2osp_dev(obd->obd_lu_dev); - if (osp == NULL) + if (osp == NULL || osp->opd_pre == NULL) return 0; - return snprintf(page, count, LPU64"\n", osp->opd_pre_reserved); @@ -372,7 +372,7 @@ index 22e3372..24f2f4c 100644 struct osp_device *osp = lu2osp_dev(dev->obd_lu_dev); - int rc; - if (osp == NULL) + if (osp == NULL || osp->opd_pre == NULL) return -EINVAL; - rc = snprintf(page, count, "%d\n", osp->opd_pre_status); @@ -390,7 +390,7 @@ index 22e3372..24f2f4c 100644 struct osp_device *osp = lu2osp_dev(dev->obd_lu_dev); if (osp == NULL) -@@ -411,87 +398,94 @@ static int osp_rd_destroys_in_flight(char *page, char **start, off_t off, +@@ -411,87 +398,126 @@ static int osp_rd_destroys_in_flight(char *page, char **start, off_t off, * - sync changes are zero - no llog records * - sync in progress are zero - no RPCs in flight */ @@ -468,30 +468,55 @@ index 22e3372..24f2f4c 100644 +LPROC_SEQ_FOPS_RO_TYPE(osp, state); + +static struct lprocfs_seq_vars lprocfs_osp_obd_vars[] = { -+ { "uuid", &osp_uuid_fops }, -+ { "ping", &osp_ping_fops, 0, 0222 }, -+ { "connect_flags", &osp_connect_flags_fops }, -+ { "ost_server_uuid", &osp_server_uuid_fops }, -+ { "ost_conn_uuid", &osp_conn_uuid_fops }, -+ { "active", &osp_active_fops }, -+ { "max_rpcs_in_flight", &osp_max_rpcs_in_flight_fops }, -+ { "max_rpcs_in_progress", &osp_max_rpcs_in_prog_fops }, -+ { "create_count", &osp_create_count_fops }, -+ { "max_create_count", &osp_max_create_count_fops }, -+ { "prealloc_next_id", &osp_prealloc_next_id_fops }, -+ { "prealloc_next_seq", &osp_prealloc_next_seq_fops }, -+ { "prealloc_last_id", &osp_prealloc_last_id_fops }, -+ { "prealloc_last_seq", &osp_prealloc_last_seq_fops }, -+ { "prealloc_reserved", &osp_prealloc_reserved_fops }, -+ { "timeouts", &osp_timeouts_fops }, -+ { "import", &osp_import_fops }, -+ { "state", &osp_state_fops }, -+ { "maxage", &osp_maxage_fops }, -+ { "prealloc_status", &osp_pre_status_fops }, -+ { "sync_changes", &osp_syn_changes_fops }, -+ { "sync_in_flight", &osp_syn_in_flight_fops }, -+ { "sync_in_progress", &osp_syn_in_prog_fops }, -+ { "old_sync_processed", &osp_old_sync_processed_fops }, ++ { .name = "uuid", ++ .fops = &osp_uuid_fops }, ++ { .name = "ping", ++ .fops = &osp_ping_fops, ++ .proc_mode = 0222 }, ++ { .name = "connect_flags", ++ .fops = &osp_connect_flags_fops }, ++ { .name = "ost_server_uuid", ++ .fops = &osp_server_uuid_fops }, ++ { .name = "ost_conn_uuid", ++ .fops = &osp_conn_uuid_fops }, ++ { .name = "active", ++ .fops = &osp_active_fops }, ++ { .name = "max_rpcs_in_flight", ++ .fops = &osp_max_rpcs_in_flight_fops }, ++ { .name = "max_rpcs_in_progress", ++ .fops = &osp_max_rpcs_in_prog_fops }, ++ { .name = "create_count", ++ .fops = &osp_create_count_fops }, ++ { .name = "max_create_count", ++ .fops = &osp_max_create_count_fops }, ++ { .name = "prealloc_next_id", ++ .fops = &osp_prealloc_next_id_fops }, ++ { .name = "prealloc_next_seq", ++ .fops = &osp_prealloc_next_seq_fops }, ++ { .name = "prealloc_last_id", ++ .fops = &osp_prealloc_last_id_fops }, ++ { .name = "prealloc_last_seq", ++ .fops = &osp_prealloc_last_seq_fops }, ++ { .name = "prealloc_reserved", ++ .fops = &osp_prealloc_reserved_fops }, ++ { .name = "timeouts", ++ .fops = &osp_timeouts_fops }, ++ { .name = "import", ++ .fops = &osp_import_fops }, ++ { .name = "state", ++ .fops = &osp_state_fops }, ++ { .name = "maxage", ++ .fops = &osp_maxage_fops }, ++ { .name = "prealloc_status", ++ .fops = &osp_pre_status_fops }, ++ { .name = "sync_changes", ++ .fops = &osp_syn_changes_fops }, ++ { .name = "sync_in_flight", ++ .fops = &osp_syn_in_flight_fops }, ++ { .name = "sync_in_progress", ++ .fops = &osp_syn_in_prog_fops }, ++ { .name = "old_sync_processed", ++ .fops = &osp_old_sync_processed_fops }, -static struct lprocfs_vars lprocfs_osp_osd_vars[] = { - { "blocksize", lprocfs_dt_rd_blksize, 0, 0 }, @@ -501,7 +526,8 @@ index 22e3372..24f2f4c 100644 - { "filestotal", lprocfs_dt_rd_filestotal, 0, 0 }, - { "filesfree", lprocfs_dt_rd_filesfree, 0, 0 }, + /* for compatibility reasons */ -+ { "destroys_in_flight", &osp_destroys_in_flight_fops }, ++ { .name = "destroys_in_flight", ++ .fops = &osp_destroys_in_flight_fops }, { 0 } }; @@ -515,12 +541,18 @@ index 22e3372..24f2f4c 100644 +LPROC_SEQ_FOPS_RO_TYPE(osp, dt_filesfree); + +static struct lprocfs_seq_vars lprocfs_osp_osd_vars[] = { -+ { "blocksize", &osp_dt_blksize_fops }, -+ { "kbytestotal", &osp_dt_kbytestotal_fops }, -+ { "kbytesfree", &osp_dt_kbytesfree_fops }, -+ { "kbytesavail", &osp_dt_kbytesavail_fops }, -+ { "filestotal", &osp_dt_filestotal_fops }, -+ { "filesfree", &osp_dt_filesfree_fops }, ++ { .name = "blocksize", ++ .fops = &osp_dt_blksize_fops }, ++ { .name = "kbytestotal", ++ .fops = &osp_dt_kbytestotal_fops }, ++ { .name = "kbytesfree", ++ .fops = &osp_dt_kbytesfree_fops }, ++ { .name = "kbytesavail", ++ .fops = &osp_dt_kbytesavail_fops }, ++ { .name = "filestotal", ++ .fops = &osp_dt_filestotal_fops }, ++ { .name = "filesfree", ++ .fops = &osp_dt_filesfree_fops }, { 0 } }; @@ -533,7 +565,8 @@ index 22e3372..24f2f4c 100644 void osp_lprocfs_init(struct osp_device *osp) { struct obd_device *obd = osp->opd_obd; - struct proc_dir_entry *osc_proc_dir; +- struct proc_dir_entry *osc_proc_dir; ++ struct proc_dir_entry *symlink = NULL; int rc; - obd->obd_proc_entry = lprocfs_register(obd->obd_name, @@ -541,7 +574,7 @@ index 22e3372..24f2f4c 100644 obd->obd_type->typ_procroot, lprocfs_osp_osd_vars, &osp->opd_dt_dev); -@@ -502,7 +496,7 @@ void osp_lprocfs_init(struct osp_device *osp) +@@ -502,34 +528,30 @@ void osp_lprocfs_init(struct osp_device *osp) return; } @@ -550,11 +583,14 @@ index 22e3372..24f2f4c 100644 if (rc) { CERROR("%s: can't register in lprocfs: %ld\n", obd->obd_name, PTR_ERR(obd->obd_proc_entry)); -@@ -511,24 +505,47 @@ void osp_lprocfs_init(struct osp_device *osp) + return; + } ++ obd->obd_vars = lprocfs_osp_obd_vars; ptlrpc_lprocfs_register_obd(obd); -+ if (osp->opd_connect_mdt) ++ if (osp->opd_connect_mdt || obd->obd_type->typ_procsym == NULL || ++ !strstr(obd->obd_name, "osc")) + return; + /* for compatibility we link old procfs's OSC entries to osp ones */ @@ -573,52 +609,26 @@ index 22e3372..24f2f4c 100644 - symlink = lprocfs_add_symlink(name, - osc_proc_dir, "../osp/%s", - obd->obd_name); -+ osc_proc_dir = obd->obd_proc_private; -+ if (osc_proc_dir == NULL) { -+ cfs_proc_dir_entry_t *symlink = NULL; -+ struct obd_type *type; -+ char *name; -+ -+ type = class_search_type(LUSTRE_OSC_NAME); -+ if (type == NULL) { -+ osc_proc_dir = lprocfs_seq_register("osc", -+ proc_lustre_root, -+ NULL, NULL); -+ if (IS_ERR(osc_proc_dir)) -+ CERROR("osp: can't create compat entry \"osc\": %d\n", -+ (int) PTR_ERR(osc_proc_dir)); -+ } else { -+ osc_proc_dir = type->typ_procroot; -+ } -+ -+ OBD_ALLOC(name, strlen(obd->obd_name) + 1); -+ if (name == NULL) -+ return; -+ -+ strcpy(name, obd->obd_name); -+ if (strstr(name, "osc")) { -+ symlink = lprocfs_add_symlink(name, osc_proc_dir, -+ "../osp/%s", -+ obd->obd_name); - OBD_FREE(name, strlen(obd->obd_name) + 1); +- OBD_FREE(name, strlen(obd->obd_name) + 1); - osp->opd_symlink = symlink; -+ if (symlink == NULL) { -+ CERROR("could not register OSC symlink for " -+ "/proc/fs/lustre/osp/%s.", -+ obd->obd_name); -+ lprocfs_remove(&osc_proc_dir); -+ } else { -+ osp->opd_symlink = symlink; -+ obd->obd_proc_private = osc_proc_dir; -+ } - } +- } ++ symlink = lprocfs_add_symlink(obd->obd_name, obd->obd_type->typ_procsym, ++ "../osp/%s", obd->obd_name); ++ if (symlink == NULL) { ++ CERROR("could not register OSC symlink for " ++ "/proc/fs/lustre/osp/%s.", obd->obd_name); ++ lprocfs_remove(&obd->obd_type->typ_procsym); ++ obd->obd_type->typ_procsym = NULL; ++ } else { ++ osp->opd_symlink = symlink; } } + diff --git a/lustre/osp/lwp_dev.c b/lustre/osp/lwp_dev.c -index fce82a2..755c096 100644 +index 9560504..d6ae965 100644 --- a/lustre/osp/lwp_dev.c +++ b/lustre/osp/lwp_dev.c -@@ -210,25 +210,13 @@ const struct lu_device_operations lwp_lu_ops = { +@@ -186,25 +186,13 @@ const struct lu_device_operations lwp_lu_ops = { .ldo_process_config = lwp_process_config, }; @@ -645,7 +655,7 @@ index fce82a2..755c096 100644 int rc; ENTRY; -@@ -257,8 +245,8 @@ int lwp_init0(const struct lu_env *env, struct lwp_device *lwp, +@@ -233,8 +221,8 @@ int lwp_init0(const struct lu_env *env, struct lwp_device *lwp, RETURN(rc); } @@ -657,7 +667,7 @@ index fce82a2..755c096 100644 RETURN(0); diff --git a/lustre/osp/osp_dev.c b/lustre/osp/osp_dev.c -index 096de6a..780276d 100644 +index 5828d88..7d45fa1 100644 --- a/lustre/osp/osp_dev.c +++ b/lustre/osp/osp_dev.c @@ -371,7 +371,7 @@ static int osp_process_config(const struct lu_env *env, @@ -684,23 +694,24 @@ index 096de6a..780276d 100644 if (rc > 0) rc = 0; if (rc == -ENOSYS) { -@@ -837,6 +835,9 @@ static struct lu_device *osp_device_fini(const struct lu_env *env, +@@ -842,6 +840,9 @@ static struct lu_device *osp_device_fini(const struct lu_env *env, OBD_FREE_PTR(cli->cl_rpc_lock); cli->cl_rpc_lock = NULL; } + } else { -+ if (m->opd_obd->obd_proc_private != NULL) -+ lprocfs_remove((struct proc_dir_entry **)&m->opd_obd->obd_proc_private); ++ if (m->opd_obd->obd_type->typ_procsym != NULL) ++ lprocfs_remove(&m->opd_obd->obd_type->typ_procsym); } rc = client_obd_cleanup(m->opd_obd); -@@ -1188,33 +1189,25 @@ struct llog_operations osp_mds_ost_orig_logops; +@@ -1220,33 +1221,26 @@ struct llog_operations osp_mds_ost_orig_logops; static int __init osp_mod_init(void) { - struct lprocfs_static_vars lvars; - cfs_proc_dir_entry_t *osc_proc_dir; - int rc; ++ struct obd_type *type; + int rc; rc = lu_kmem_init(osp_caches); @@ -731,11 +742,10 @@ index 096de6a..780276d 100644 #endif LUSTRE_LWP_NAME, &lwp_device_type); if (rc != 0) { -@@ -1227,22 +1220,11 @@ static int __init osp_mod_init(void) - osp_mds_ost_orig_logops = llog_osd_ops; +@@ -1260,21 +1254,23 @@ static int __init osp_mod_init(void) osp_mds_ost_orig_logops.lop_add = llog_cat_add_rec; osp_mds_ost_orig_logops.lop_declare_add = llog_cat_declare_add_rec; -- + - osc_proc_dir = lprocfs_srch(proc_lustre_root, "osc"); - if (osc_proc_dir == NULL) { - osc_proc_dir = lprocfs_register("osc", proc_lustre_root, NULL, @@ -743,7 +753,18 @@ index 096de6a..780276d 100644 - if (IS_ERR(osc_proc_dir)) - CERROR("osp: can't create compat entry \"osc\": %d\n", - (int) PTR_ERR(osc_proc_dir)); -- } ++ type = class_search_type(LUSTRE_OSC_NAME); ++ if (type) ++ return rc; ++ ++ type = class_search_type(LUSTRE_OSP_NAME); ++ type->typ_procsym = lprocfs_seq_register("osc", proc_lustre_root, ++ NULL, NULL); ++ if (IS_ERR(type->typ_procsym)) { ++ CERROR("osp: can't create compat entry \"osc\": %d\n", ++ (int) PTR_ERR(type->typ_procsym)); ++ type->typ_procsym = NULL; + } return rc; } @@ -755,18 +776,18 @@ index 096de6a..780276d 100644 class_unregister_type(LUSTRE_OSP_NAME); lu_kmem_fini(osp_caches); diff --git a/lustre/osp/osp_internal.h b/lustre/osp/osp_internal.h -index 92c7b72..fe8b57e 100644 +index 0871d8d..0cc608b 100644 --- a/lustre/osp/osp_internal.h +++ b/lustre/osp/osp_internal.h -@@ -415,7 +415,6 @@ int osp_write_last_oid_seq_files(struct lu_env *env, struct osp_device *osp, - struct lu_fid *fid, int sync); +@@ -433,7 +433,6 @@ int osp_write_last_oid_seq_files(struct lu_env *env, struct osp_device *osp, + int osp_init_pre_fid(struct osp_device *osp); /* lproc_osp.c */ -void lprocfs_osp_init_vars(struct lprocfs_static_vars *lvars); void osp_lprocfs_init(struct osp_device *osp); /* osp_sync.c */ -@@ -429,7 +428,6 @@ int osp_sync_fini(struct osp_device *d); +@@ -447,7 +446,6 @@ int osp_sync_fini(struct osp_device *d); void __osp_sync_check_for_work(struct osp_device *d); /* lwp_dev.c */ @@ -775,5 +796,5 @@ index 92c7b72..fe8b57e 100644 extern struct lu_device_type lwp_device_type; -- -1.8.5.1 +1.8.5.3 diff --git a/sys-cluster/lustre/files/0007-LU-3319-procfs-move-lmv-proc-handling-over-to-seq_fi.patch b/sys-cluster/lustre/files/0007-LU-3319-procfs-move-lmv-proc-handling-over-to-seq_fi.patch deleted file mode 100644 index 0fee4ee7b..000000000 --- a/sys-cluster/lustre/files/0007-LU-3319-procfs-move-lmv-proc-handling-over-to-seq_fi.patch +++ /dev/null @@ -1,409 +0,0 @@ -From 4169735b41f2452d884e24c92581af0c4fbf6121 Mon Sep 17 00:00:00 2001 -From: James Simmons <uja.ornl@gmail.com> -Date: Thu, 14 Nov 2013 09:32:29 -0500 -Subject: [PATCH 07/18] LU-3319 procfs: move lmv proc handling over to seq_file - -In order to support 3.10+ kernels for clients we adapt -the lmv proc handling to using seq_files. - -Signed-off-by: James Simmons <uja.ornl@gmail.com> -Change-Id: I34f58c3a484ee79b41b59d4a60f6a21726373152 ---- - lustre/lmv/lmv_internal.h | 7 +-- - lustre/lmv/lmv_obd.c | 138 ++++++++++++++++++++-------------------------- - lustre/lmv/lproc_lmv.c | 78 ++++++++++---------------- - 3 files changed, 91 insertions(+), 132 deletions(-) - -diff --git a/lustre/lmv/lmv_internal.h b/lustre/lmv/lmv_internal.h -index 15692c5..1d027d7 100644 ---- a/lustre/lmv/lmv_internal.h -+++ b/lustre/lmv/lmv_internal.h -@@ -147,12 +147,7 @@ struct lmv_tgt_desc - struct lu_fid *fid); - /* lproc_lmv.c */ - #ifdef LPROCFS --void lprocfs_lmv_init_vars(struct lprocfs_static_vars *lvars); --#else --static inline void lprocfs_lmv_init_vars(struct lprocfs_static_vars *lvars) --{ -- memset(lvars, 0, sizeof(*lvars)); --} -+extern struct lprocfs_seq_vars lprocfs_lmv_obd_vars[]; - #endif - extern struct file_operations lmv_proc_target_fops; - -diff --git a/lustre/lmv/lmv_obd.c b/lustre/lmv/lmv_obd.c -index 56d6e20..888a86f 100644 ---- a/lustre/lmv/lmv_obd.c -+++ b/lustre/lmv/lmv_obd.c -@@ -239,13 +239,19 @@ static int lmv_connect(const struct lu_env *env, - lmv->conn_data = *data; - - #ifdef __KERNEL__ -- lmv_proc_dir = lprocfs_register("target_obds", obd->obd_proc_entry, -- NULL, NULL); -- if (IS_ERR(lmv_proc_dir)) { -- CERROR("could not register /proc/fs/lustre/%s/%s/target_obds.", -- obd->obd_type->typ_name, obd->obd_name); -- lmv_proc_dir = NULL; -- } -+ if (obd->obd_proc_private != NULL) { -+ lmv_proc_dir = obd->obd_proc_private; -+ } else { -+ lmv_proc_dir = lprocfs_seq_register("target_obds", -+ obd->obd_proc_entry, -+ NULL, NULL); -+ if (IS_ERR(lmv_proc_dir)) { -+ CERROR("could not register /proc/fs/lustre/%s/%s/target_obds.", -+ obd->obd_type->typ_name, obd->obd_name); -+ lmv_proc_dir = NULL; -+ } -+ obd->obd_proc_private = lmv_proc_dir; -+ } - #endif - - /* -@@ -258,12 +264,11 @@ static int lmv_connect(const struct lu_env *env, - rc = lmv_check_connect(obd); - - #ifdef __KERNEL__ -- if (rc) { -- if (lmv_proc_dir) -- lprocfs_remove(&lmv_proc_dir); -- } -+ if (rc && lmv_proc_dir) { -+ lprocfs_remove(&lmv_proc_dir); -+ obd->obd_proc_private = NULL; -+ } - #endif -- - RETURN(rc); - } - -@@ -423,28 +428,28 @@ int lmv_connect_mdc(struct obd_device *obd, struct lmv_tgt_desc *tgt) - cfs_atomic_read(&obd->obd_refcount)); - - #ifdef __KERNEL__ -- lmv_proc_dir = lprocfs_srch(obd->obd_proc_entry, "target_obds"); -- if (lmv_proc_dir) { -- struct proc_dir_entry *mdc_symlink; -- -- LASSERT(mdc_obd->obd_type != NULL); -- LASSERT(mdc_obd->obd_type->typ_name != NULL); -- mdc_symlink = lprocfs_add_symlink(mdc_obd->obd_name, -- lmv_proc_dir, -- "../../../%s/%s", -- mdc_obd->obd_type->typ_name, -- mdc_obd->obd_name); -- if (mdc_symlink == NULL) { -- CERROR("Could not register LMV target " -- "/proc/fs/lustre/%s/%s/target_obds/%s.", -- obd->obd_type->typ_name, obd->obd_name, -- mdc_obd->obd_name); -- lprocfs_remove(&lmv_proc_dir); -- lmv_proc_dir = NULL; -- } -- } -+ lmv_proc_dir = obd->obd_proc_private; -+ if (lmv_proc_dir) { -+ struct proc_dir_entry *mdc_symlink; -+ -+ LASSERT(mdc_obd->obd_type != NULL); -+ LASSERT(mdc_obd->obd_type->typ_name != NULL); -+ mdc_symlink = lprocfs_add_symlink(mdc_obd->obd_name, -+ lmv_proc_dir, -+ "../../../%s/%s", -+ mdc_obd->obd_type->typ_name, -+ mdc_obd->obd_name); -+ if (mdc_symlink == NULL) { -+ CERROR("Could not register LMV target " -+ "/proc/fs/lustre/%s/%s/target_obds/%s.", -+ obd->obd_type->typ_name, obd->obd_name, -+ mdc_obd->obd_name); -+ lprocfs_remove(&lmv_proc_dir); -+ obd->obd_proc_private = NULL; -+ } -+ } - #endif -- RETURN(0); -+ RETURN(0); - } - - static void lmv_del_target(struct lmv_obd *lmv, int index) -@@ -652,19 +657,9 @@ static int lmv_disconnect_mdc(struct obd_device *obd, struct lmv_tgt_desc *tgt) - } - - #ifdef __KERNEL__ -- lmv_proc_dir = lprocfs_srch(obd->obd_proc_entry, "target_obds"); -- if (lmv_proc_dir) { -- struct proc_dir_entry *mdc_symlink; -- -- mdc_symlink = lprocfs_srch(lmv_proc_dir, mdc_obd->obd_name); -- if (mdc_symlink) { -- lprocfs_remove(&mdc_symlink); -- } else { -- CERROR("/proc/fs/lustre/%s/%s/target_obds/%s missing\n", -- obd->obd_type->typ_name, obd->obd_name, -- mdc_obd->obd_name); -- } -- } -+ lmv_proc_dir = obd->obd_proc_private; -+ if (lmv_proc_dir) -+ lprocfs_remove_proc_entry(mdc_obd->obd_name, lmv_proc_dir); - #endif - rc = obd_fid_fini(tgt->ltd_exp->exp_obd); - if (rc) -@@ -691,9 +686,6 @@ static int lmv_disconnect_mdc(struct obd_device *obd, struct lmv_tgt_desc *tgt) - static int lmv_disconnect(struct obd_export *exp) - { - struct obd_device *obd = class_exp2obd(exp); --#ifdef __KERNEL__ -- struct proc_dir_entry *lmv_proc_dir; --#endif - struct lmv_obd *lmv = &obd->u.lmv; - int rc; - __u32 i; -@@ -717,13 +709,11 @@ static int lmv_disconnect(struct obd_export *exp) - } - - #ifdef __KERNEL__ -- lmv_proc_dir = lprocfs_srch(obd->obd_proc_entry, "target_obds"); -- if (lmv_proc_dir) { -- lprocfs_remove(&lmv_proc_dir); -- } else { -- CERROR("/proc/fs/lustre/%s/%s/target_obds missing\n", -- obd->obd_type->typ_name, obd->obd_name); -- } -+ if (obd->obd_proc_private) -+ lprocfs_remove((struct proc_dir_entry **)&obd->obd_proc_private); -+ else -+ CERROR("/proc/fs/lustre/%s/%s/target_obds missing\n", -+ obd->obd_type->typ_name, obd->obd_name); - #endif - - out_local: -@@ -1383,11 +1373,10 @@ int lmv_fid_alloc(struct obd_export *exp, struct lu_fid *fid, - - static int lmv_setup(struct obd_device *obd, struct lustre_cfg *lcfg) - { -- struct lmv_obd *lmv = &obd->u.lmv; -- struct lprocfs_static_vars lvars; -- struct lmv_desc *desc; -- int rc; -- ENTRY; -+ struct lmv_obd *lmv = &obd->u.lmv; -+ struct lmv_desc *desc; -+ int rc; -+ ENTRY; - - if (LUSTRE_CFG_BUFLEN(lcfg, 1) < 1) { - CERROR("LMV setup requires a descriptor\n"); -@@ -1417,18 +1406,15 @@ static int lmv_setup(struct obd_device *obd, struct lustre_cfg *lcfg) - spin_lock_init(&lmv->lmv_lock); - mutex_init(&lmv->init_mutex); - -- lprocfs_lmv_init_vars(&lvars); -- -- lprocfs_obd_setup(obd, lvars.obd_vars); -- lprocfs_alloc_md_stats(obd, 0); - #ifdef LPROCFS -- { -- rc = lprocfs_seq_create(obd->obd_proc_entry, "target_obd", -- 0444, &lmv_proc_target_fops, obd); -- if (rc) -- CWARN("%s: error adding LMV target_obd file: rc = %d\n", -- obd->obd_name, rc); -- } -+ obd->obd_vars = lprocfs_lmv_obd_vars; -+ lprocfs_seq_obd_setup(obd); -+ lprocfs_alloc_md_stats(obd, 0); -+ rc = lprocfs_seq_create(obd->obd_proc_entry, "target_obd", -+ 0444, &lmv_proc_target_fops, obd); -+ if (rc) -+ CWARN("%s: error adding LMV target_obd file: rc = %d\n", -+ obd->obd_name, rc); - #endif - rc = fld_client_init(&lmv->lmv_fld, obd->obd_name, - LUSTRE_CLI_FLD_HASH_DHT); -@@ -2477,7 +2463,7 @@ int lmv_set_info_async(const struct lu_env *env, struct obd_export *exp, - obd_count keylen, void *key, obd_count vallen, - void *val, struct ptlrpc_request_set *set) - { -- struct lmv_tgt_desc *tgt; -+ struct lmv_tgt_desc *tgt = NULL; - struct obd_device *obd; - struct lmv_obd *lmv; - int rc = 0; -@@ -2982,13 +2968,9 @@ struct md_ops lmv_md_ops = { - - int __init lmv_init(void) - { -- struct lprocfs_static_vars lvars; -- -- lprocfs_lmv_init_vars(&lvars); -- - return class_register_type(&lmv_obd_ops, &lmv_md_ops, NULL, - #ifndef HAVE_ONLY_PROCFS_SEQ -- lvars.module_vars, -+ NULL, - #endif - LUSTRE_LMV_NAME, NULL); - } -diff --git a/lustre/lmv/lproc_lmv.c b/lustre/lmv/lproc_lmv.c -index 6a3b128..eea5927 100644 ---- a/lustre/lmv/lproc_lmv.c -+++ b/lustre/lmv/lproc_lmv.c -@@ -46,18 +46,16 @@ - static struct lprocfs_vars lprocfs_module_vars[] = { {0} }; - static struct lprocfs_vars lprocfs_obd_vars[] = { {0} }; - #else --static int lmv_rd_numobd(char *page, char **start, off_t off, int count, -- int *eof, void *data) -+static int lmv_numobd_seq_show(struct seq_file *m, void *v) - { -- struct obd_device *dev = (struct obd_device*)data; -+ struct obd_device *dev = (struct obd_device *)m->private; - struct lmv_desc *desc; - - LASSERT(dev != NULL); - desc = &dev->u.lmv.desc; -- *eof = 1; -- return snprintf(page, count, "%u\n", desc->ld_tgt_count); -- -+ return seq_printf(m, "%u\n", desc->ld_tgt_count); - } -+LPROC_SEQ_FOPS_RO(lmv_numobd); - - static const char *placement_name[] = { - [PLACEMENT_CHAR_POLICY] = "CHAR", -@@ -82,26 +80,22 @@ static const char *placement_policy2name(placement_policy_t placement) - return placement_name[placement]; - } - --static int lmv_rd_placement(char *page, char **start, off_t off, int count, -- int *eof, void *data) -+static int lmv_placement_seq_show(struct seq_file *m, void *v) - { -- struct obd_device *dev = (struct obd_device*)data; -+ struct obd_device *dev = (struct obd_device *)m->private; - struct lmv_obd *lmv; - - LASSERT(dev != NULL); - lmv = &dev->u.lmv; -- *eof = 1; -- return snprintf(page, count, "%s\n", -- placement_policy2name(lmv->lmv_placement)); -- -+ return seq_printf(m, "%s\n", placement_policy2name(lmv->lmv_placement)); - } - - #define MAX_POLICY_STRING_SIZE 64 - --static int lmv_wr_placement(struct file *file, const char *buffer, -- unsigned long count, void *data) -+static ssize_t lmv_placement_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) - { -- struct obd_device *dev = (struct obd_device *)data; -+ struct obd_device *dev = ((struct seq_file *)file->private_data)->private; - char dummy[MAX_POLICY_STRING_SIZE + 1]; - int len = count; - placement_policy_t policy; -@@ -131,30 +125,29 @@ static int lmv_wr_placement(struct file *file, const char *buffer, - } - return count; - } -+LPROC_SEQ_FOPS(lmv_placement); - --static int lmv_rd_activeobd(char *page, char **start, off_t off, int count, -- int *eof, void *data) -+static int lmv_activeobd_seq_show(struct seq_file *m, void *v) - { -- struct obd_device *dev = (struct obd_device*)data; -+ struct obd_device *dev = (struct obd_device *)m->private; - struct lmv_desc *desc; - - LASSERT(dev != NULL); - desc = &dev->u.lmv.desc; -- *eof = 1; -- return snprintf(page, count, "%u\n", desc->ld_active_tgt_count); -+ return seq_printf(m, "%u\n", desc->ld_active_tgt_count); - } -+LPROC_SEQ_FOPS_RO(lmv_activeobd); - --static int lmv_rd_desc_uuid(char *page, char **start, off_t off, int count, -- int *eof, void *data) -+static int lmv_desc_uuid_seq_show(struct seq_file *m, void *v) - { -- struct obd_device *dev = (struct obd_device*) data; -+ struct obd_device *dev = (struct obd_device*)m->private; - struct lmv_obd *lmv; - - LASSERT(dev != NULL); - lmv = &dev->u.lmv; -- *eof = 1; -- return snprintf(page, count, "%s\n", lmv->desc.ld_uuid.uuid); -+ return seq_printf(m, "%s\n", lmv->desc.ld_uuid.uuid); - } -+LPROC_SEQ_FOPS_RO(lmv_desc_uuid); - - static void *lmv_tgt_seq_start(struct seq_file *p, loff_t *pos) - { -@@ -195,7 +188,6 @@ struct seq_operations lmv_tgt_sops = { - - static int lmv_target_seq_open(struct inode *inode, struct file *file) - { -- struct proc_dir_entry *dp = PDE(inode); - struct seq_file *seq; - int rc; - -@@ -203,24 +195,20 @@ static int lmv_target_seq_open(struct inode *inode, struct file *file) - if (rc) - return rc; - -- seq = file->private_data; -- seq->private = dp->data; -- -- return 0; -+ seq = file->private_data; -+ seq->private = PDE_DATA(inode); -+ return 0; - } - --struct lprocfs_vars lprocfs_lmv_obd_vars[] = { -- { "numobd", lmv_rd_numobd, 0, 0 }, -- { "placement", lmv_rd_placement, lmv_wr_placement, 0 }, -- { "activeobd", lmv_rd_activeobd, 0, 0 }, -- { "uuid", lprocfs_rd_uuid, 0, 0 }, -- { "desc_uuid", lmv_rd_desc_uuid, 0, 0 }, -- { 0 } --}; -+LPROC_SEQ_FOPS_RO_TYPE(lmv, uuid); - --static struct lprocfs_vars lprocfs_lmv_module_vars[] = { -- { "num_refs", lprocfs_rd_numrefs, 0, 0 }, -- { 0 } -+struct lprocfs_seq_vars lprocfs_lmv_obd_vars[] = { -+ { "numobd", &lmv_numobd_fops }, -+ { "placement", &lmv_placement_fops }, -+ { "activeobd", &lmv_activeobd_fops }, -+ { "uuid", &lmv_uuid_fops }, -+ { "desc_uuid", &lmv_desc_uuid_fops }, -+ { 0 } - }; - - struct file_operations lmv_proc_target_fops = { -@@ -230,10 +218,4 @@ struct file_operations lmv_proc_target_fops = { - .llseek = seq_lseek, - .release = seq_release, - }; -- - #endif /* LPROCFS */ --void lprocfs_lmv_init_vars(struct lprocfs_static_vars *lvars) --{ -- lvars->module_vars = lprocfs_lmv_module_vars; -- lvars->obd_vars = lprocfs_lmv_obd_vars; --} --- -1.8.5.1 - diff --git a/sys-cluster/lustre/files/0014-LU-3319-procfs-move-lod-proc-handling-to-seq_files.patch b/sys-cluster/lustre/files/0007-LU-3319-procfs-move-lod-proc-handling-to-seq_files.patch index 4bbea0353..3aad32c41 100644 --- a/sys-cluster/lustre/files/0014-LU-3319-procfs-move-lod-proc-handling-to-seq_files.patch +++ b/sys-cluster/lustre/files/0007-LU-3319-procfs-move-lod-proc-handling-to-seq_files.patch @@ -1,7 +1,7 @@ -From eb1406399522d52e51c3dd7e8a73813c0179d12a Mon Sep 17 00:00:00 2001 +From 9260e5e777af25ebc1a94113ede31667c5f10e97 Mon Sep 17 00:00:00 2001 From: James Simmons <uja.ornl@gmail.com> -Date: Thu, 14 Nov 2013 19:20:50 -0500 -Subject: [PATCH 14/18] LU-3319 procfs: move lod proc handling to seq_files +Date: Fri, 31 Jan 2014 12:46:28 -0500 +Subject: [PATCH 07/13] LU-3319 procfs: move lod proc handling to seq_files With 3.10 linux kernel and above proc handling now only uses struct seq_files. This patch migrates the lod @@ -10,14 +10,14 @@ layer proc entries over to using seq_files. Signed-off-by: James Simmons <uja.ornl@gmail.com> Change-Id: Iaa0f617fcd430e91f12afbc0faf6906fd275a7a5 --- - lustre/lod/lod_dev.c | 28 +---- + lustre/lod/lod_dev.c | 39 ++++--- lustre/lod/lod_internal.h | 1 - lustre/lod/lod_pool.c | 7 +- - lustre/lod/lproc_lod.c | 255 ++++++++++++++++++++++++---------------------- - 4 files changed, 143 insertions(+), 148 deletions(-) + lustre/lod/lproc_lod.c | 252 ++++++++++++++++++++++++---------------------- + 4 files changed, 153 insertions(+), 146 deletions(-) diff --git a/lustre/lod/lod_dev.c b/lustre/lod/lod_dev.c -index e36aee1..8a0be26 100644 +index 02a1e1e..b0ad1fd 100644 --- a/lustre/lod/lod_dev.c +++ b/lustre/lod/lod_dev.c @@ -297,12 +297,10 @@ static int lod_process_config(const struct lu_env *env, @@ -36,13 +36,15 @@ index e36aee1..8a0be26 100644 if (rc > 0) rc = 0; GOTO(out, rc); -@@ -916,44 +914,26 @@ static struct obd_ops lod_obd_device_ops = { +@@ -916,19 +914,16 @@ static struct obd_ops lod_obd_device_ops = { static int __init lod_mod_init(void) { - struct lprocfs_static_vars lvars = { 0 }; - cfs_proc_dir_entry_t *lov_proc_dir; - int rc; +- int rc; ++ struct obd_type *lod, *lov; ++ int rc; rc = lu_kmem_init(lod_caches); if (rc) @@ -57,19 +59,30 @@ index e36aee1..8a0be26 100644 #endif LUSTRE_LOD_NAME, &lod_device_type); if (rc) { - lu_kmem_fini(lod_caches); - return rc; +@@ -937,23 +932,25 @@ static int __init lod_mod_init(void) } -- -- /* create "lov" entry in procfs for compatibility purposes */ + + /* create "lov" entry in procfs for compatibility purposes */ - lov_proc_dir = lprocfs_srch(proc_lustre_root, "lov"); - if (lov_proc_dir == NULL) { - lov_proc_dir = lprocfs_register("lov", proc_lustre_root, - NULL, NULL); - if (IS_ERR(lov_proc_dir)) -- CERROR("lod: can't create compat entry \"lov\": %d\n", ++ lod = class_search_type(LUSTRE_LOD_NAME); ++ lov = class_search_type(LUSTRE_LOV_NAME); ++ if (lov == NULL) { ++ lod->typ_procsym = lprocfs_seq_register("lov", proc_lustre_root, ++ NULL, NULL); ++ if (IS_ERR(lod->typ_procsym)) { + CERROR("lod: can't create compat entry \"lov\": %d\n", - (int)PTR_ERR(lov_proc_dir)); -- } ++ (int)PTR_ERR(lod->typ_procsym)); ++ lod->typ_procsym = NULL; ++ } ++ } else { ++ /* Map lov proc root to lod symlink */ ++ lod->typ_procsym = lov->typ_procroot; + } - return rc; } @@ -83,10 +96,10 @@ index e36aee1..8a0be26 100644 lu_kmem_fini(lod_caches); } diff --git a/lustre/lod/lod_internal.h b/lustre/lod/lod_internal.h -index 0dd077b..bb6fbfb 100644 +index 6d99ad5..9299a91 100644 --- a/lustre/lod/lod_internal.h +++ b/lustre/lod/lod_internal.h -@@ -317,7 +317,6 @@ int qos_add_tgt(struct lod_device*, struct lod_tgt_desc *); +@@ -376,7 +376,6 @@ int qos_add_tgt(struct lod_device*, struct lod_tgt_desc *); int qos_del_tgt(struct lod_device *, struct lod_tgt_desc *); /* lproc_lod.c */ @@ -95,7 +108,7 @@ index 0dd077b..bb6fbfb 100644 void lod_procfs_fini(struct lod_device *lod); diff --git a/lustre/lod/lod_pool.c b/lustre/lod/lod_pool.c -index e33ae4d..77d04a7 100644 +index 98b2416..1849e5d 100644 --- a/lustre/lod/lod_pool.c +++ b/lustre/lod/lod_pool.c @@ -283,7 +283,7 @@ static int pool_proc_open(struct inode *inode, struct file *file) @@ -120,7 +133,7 @@ index e33ae4d..77d04a7 100644 &pool_proc_operations); if (IS_ERR(new_pool->pool_proc_entry)) { diff --git a/lustre/lod/lproc_lod.c b/lustre/lod/lproc_lod.c -index e976063..b0d4e17 100644 +index e976063..6e20b36 100644 --- a/lustre/lod/lproc_lod.c +++ b/lustre/lod/lproc_lod.c @@ -42,23 +42,22 @@ @@ -408,7 +421,7 @@ index e976063..b0d4e17 100644 static void *lod_osts_seq_start(struct seq_file *p, loff_t *pos) { -@@ -414,56 +409,52 @@ static const struct seq_operations lod_osts_sops = { +@@ -414,56 +409,63 @@ static const struct seq_operations lod_osts_sops = { static int lod_osts_seq_open(struct inode *inode, struct file *file) { @@ -439,16 +452,6 @@ index e976063..b0d4e17 100644 - { "qos_prio_free",lod_rd_qos_priofree, lod_wr_qos_priofree, 0 }, - { "qos_threshold_rr", lod_rd_qos_thresholdrr, lod_wr_qos_thresholdrr, 0 }, - { "qos_maxage", lod_rd_qos_maxage, lod_wr_qos_maxage, 0 }, -- { 0 } --}; -- --static struct lprocfs_vars lprocfs_lod_osd_vars[] = { -- { "blocksize", lprocfs_dt_rd_blksize, 0, 0 }, -- { "kbytestotal", lprocfs_dt_rd_kbytestotal, 0, 0 }, -- { "kbytesfree", lprocfs_dt_rd_kbytesfree, 0, 0 }, -- { "kbytesavail", lprocfs_dt_rd_kbytesavail, 0, 0 }, -- { "filestotal", lprocfs_dt_rd_filestotal, 0, 0 }, -- { "filesfree", lprocfs_dt_rd_filesfree, 0, 0 }, +LPROC_SEQ_FOPS_RO_TYPE(lod, uuid); + +LPROC_SEQ_FOPS_RO_TYPE(lod, dt_blksize); @@ -459,22 +462,38 @@ index e976063..b0d4e17 100644 +LPROC_SEQ_FOPS_RO_TYPE(lod, dt_filesfree); + +static struct lprocfs_seq_vars lprocfs_lod_obd_vars[] = { -+ { "uuid", &lod_uuid_fops }, -+ { "stripesize", &lod_stripesize_fops }, -+ { "stripeoffset", &lod_stripeoffset_fops }, -+ { "stripecount", &lod_stripecount_fops }, -+ { "stripetype", &lod_stripetype_fops }, -+ { "numobd", &lod_numobd_fops }, -+ { "activeobd", &lod_activeobd_fops }, -+ { "desc_uuid", &lod_desc_uuid_fops }, -+ { "qos_prio_free", &lod_qos_priofree_fops }, -+ { "qos_threshold_rr", &lod_qos_thresholdrr_fops }, -+ { "qos_maxage", &lod_qos_maxage_fops }, ++ { .name = "uuid", ++ .fops = &lod_uuid_fops }, ++ { .name = "stripesize", ++ .fops = &lod_stripesize_fops }, ++ { .name = "stripeoffset", ++ .fops = &lod_stripeoffset_fops }, ++ { .name = "stripecount", ++ .fops = &lod_stripecount_fops }, ++ { .name = "stripetype", ++ .fops = &lod_stripetype_fops }, ++ { .name = "numobd", ++ .fops = &lod_numobd_fops }, ++ { .name = "activeobd", ++ .fops = &lod_activeobd_fops }, ++ { .name = "desc_uuid", ++ .fops = &lod_desc_uuid_fops }, ++ { .name = "qos_prio_free", ++ .fops = &lod_qos_priofree_fops }, ++ { .name = "qos_threshold_rr", ++ .fops = &lod_qos_thresholdrr_fops }, ++ { .name = "qos_maxage", ++ .fops = &lod_qos_maxage_fops }, { 0 } }; --static struct lprocfs_vars lprocfs_lod_module_vars[] = { -- { "num_refs", lprocfs_rd_numrefs, 0, 0 }, +-static struct lprocfs_vars lprocfs_lod_osd_vars[] = { +- { "blocksize", lprocfs_dt_rd_blksize, 0, 0 }, +- { "kbytestotal", lprocfs_dt_rd_kbytestotal, 0, 0 }, +- { "kbytesfree", lprocfs_dt_rd_kbytesfree, 0, 0 }, +- { "kbytesavail", lprocfs_dt_rd_kbytesavail, 0, 0 }, +- { "filestotal", lprocfs_dt_rd_filestotal, 0, 0 }, +- { "filesfree", lprocfs_dt_rd_filesfree, 0, 0 }, +static struct lprocfs_seq_vars lprocfs_lod_osd_vars[] = { + { "blocksize", &lod_dt_blksize_fops }, + { "kbytestotal", &lod_dt_kbytestotal_fops }, @@ -485,6 +504,11 @@ index e976063..b0d4e17 100644 { 0 } }; +-static struct lprocfs_vars lprocfs_lod_module_vars[] = { +- { "num_refs", lprocfs_rd_numrefs, 0, 0 }, +- { 0 } +-}; +- -void lprocfs_lod_init_vars(struct lprocfs_static_vars *lvars) -{ - lvars->module_vars = lprocfs_lod_module_vars; @@ -494,12 +518,12 @@ index e976063..b0d4e17 100644 static const struct file_operations lod_proc_target_fops = { .owner = THIS_MODULE, .open = lod_osts_seq_open, -@@ -475,20 +466,19 @@ static const struct file_operations lod_proc_target_fops = { +@@ -475,20 +477,18 @@ static const struct file_operations lod_proc_target_fops = { int lod_procfs_init(struct lod_device *lod) { struct obd_device *obd = lod2obd(lod); - struct lprocfs_static_vars lvars; - cfs_proc_dir_entry_t *lov_proc_dir; +- cfs_proc_dir_entry_t *lov_proc_dir; int rc; - lprocfs_lod_init_vars(&lvars); @@ -519,7 +543,7 @@ index e976063..b0d4e17 100644 if (rc) { CERROR("%s: cannot setup procfs entry: %d\n", obd->obd_name, rc); -@@ -503,9 +493,9 @@ int lod_procfs_init(struct lod_device *lod) +@@ -503,9 +503,9 @@ int lod_procfs_init(struct lod_device *lod) GOTO(out, rc); } @@ -532,58 +556,43 @@ index e976063..b0d4e17 100644 if (IS_ERR(lod->lod_pool_proc_entry)) { rc = PTR_ERR(lod->lod_pool_proc_entry); lod->lod_pool_proc_entry = NULL; -@@ -514,14 +504,34 @@ int lod_procfs_init(struct lod_device *lod) +@@ -514,14 +514,19 @@ int lod_procfs_init(struct lod_device *lod) GOTO(out, rc); } - /* for compatibility we link old procfs's OSC entries to osp ones */ - lov_proc_dir = lprocfs_srch(proc_lustre_root, "lov"); - if (lov_proc_dir != NULL && strstr(obd->obd_name, "lov") != NULL) -- lod->lod_symlink = lprocfs_add_symlink(obd->obd_name, ++ /* for compatibility we link old procfs's LOV entries to lod ones */ ++ if (obd->obd_type->typ_procsym != NULL) { + lod->lod_symlink = lprocfs_add_symlink(obd->obd_name, - lov_proc_dir, - "../lod/%s", - obd->obd_name); -+ /* for compatibility we link old procfs's LOV entries to lod ones */ -+ lov_proc_dir = obd->obd_proc_private; -+ if (lov_proc_dir == NULL) { -+ struct obd_type *type = class_search_type(LUSTRE_LOV_NAME); -+ -+ /* create "lov" entry in procfs for compatibility purposes */ -+ if (type == NULL) { -+ lov_proc_dir = lprocfs_seq_register("lov", -+ proc_lustre_root, -+ NULL, NULL); -+ if (IS_ERR(lov_proc_dir)) -+ CERROR("lod: can't create compat entry \"lov\"" -+ ": %d\n",(int)PTR_ERR(lov_proc_dir)); -+ } else { -+ lov_proc_dir = type->typ_procroot; -+ } - -+ lod->lod_symlink = lprocfs_add_symlink(obd->obd_name, -+ lov_proc_dir, +- ++ obd->obd_type->typ_procsym, + "../lod/%s", + obd->obd_name); + if (lod->lod_symlink == NULL) { + CERROR("could not register LOV symlink for " + "/proc/fs/lustre/lod/%s.", obd->obd_name); -+ lprocfs_remove(&lov_proc_dir); -+ } else -+ obd->obd_proc_private = lov_proc_dir; ++ lprocfs_remove(&obd->obd_type->typ_procsym); ++ obd->obd_type->typ_procsym = NULL; ++ } + } RETURN(0); out: -@@ -542,6 +552,9 @@ void lod_procfs_fini(struct lod_device *lod) +@@ -542,6 +547,9 @@ void lod_procfs_fini(struct lod_device *lod) lod->lod_pool_proc_entry = NULL; } -+ if (obd->obd_proc_private != NULL) -+ lprocfs_remove((struct proc_dir_entry **)&obd->obd_proc_private); ++ if (obd->obd_type->typ_procsym != NULL) ++ lprocfs_remove(&obd->obd_type->typ_procsym); + lprocfs_obd_cleanup(obd); } -- -1.8.5.1 +1.8.5.3 diff --git a/sys-cluster/lustre/files/0008-LU-3319-procfs-move-ldlm-proc-handling-over-to-seq_f.patch b/sys-cluster/lustre/files/0008-LU-3319-procfs-move-ldlm-proc-handling-over-to-seq_f.patch deleted file mode 100644 index d3768d583..000000000 --- a/sys-cluster/lustre/files/0008-LU-3319-procfs-move-ldlm-proc-handling-over-to-seq_f.patch +++ /dev/null @@ -1,789 +0,0 @@ -From a464fd862a7876e1c4f679b32956904eee88d45e Mon Sep 17 00:00:00 2001 -From: James Simmons <uja.ornl@gmail.com> -Date: Tue, 17 Dec 2013 19:11:15 -0500 -Subject: [PATCH 08/18] LU-3319 procfs: move ldlm proc handling over to - seq_file - -In order to support 3.10+ kernels for clients we adapt -the ldlm proc handling to using seq_files. - -Signed-off-by: James Simmons <uja.ornl@gmail.com> -Change-Id: Iaedae5fe1e1cd2985a6240314810db9bba3cd747 ---- - lustre/include/lustre_dlm.h | 5 +- - lustre/ldlm/ldlm_internal.h | 85 ++++++------ - lustre/ldlm/ldlm_pool.c | 197 +++++++++++++--------------- - lustre/ldlm/ldlm_resource.c | 306 +++++++++++++++++++------------------------- - 4 files changed, 270 insertions(+), 323 deletions(-) - -diff --git a/lustre/include/lustre_dlm.h b/lustre/include/lustre_dlm.h -index 30b70b5..d01b7e9 100644 ---- a/lustre/include/lustre_dlm.h -+++ b/lustre/include/lustre_dlm.h -@@ -243,7 +243,7 @@ struct ldlm_pool_ops { - */ - struct ldlm_pool { - /** Pool proc directory. */ -- cfs_proc_dir_entry_t *pl_proc_dir; -+ struct proc_dir_entry *pl_proc_dir; - /** Pool name, must be long enough to hold compound proc entry name. */ - char pl_name[100]; - /** Lock for protecting SLV/CLV updates. */ -@@ -400,6 +400,9 @@ struct ldlm_namespace { - /** Client side original connect flags supported by server. */ - __u64 ns_orig_connect_flags; - -+ /* namespace proc dir entry */ -+ struct proc_dir_entry *ns_proc_dir_entry; -+ - /** - * Position in global namespace list linking all namespaces on - * the node. -diff --git a/lustre/ldlm/ldlm_internal.h b/lustre/ldlm/ldlm_internal.h -index 5077072..ffc528b 100644 ---- a/lustre/ldlm/ldlm_internal.h -+++ b/lustre/ldlm/ldlm_internal.h -@@ -212,8 +212,8 @@ void ldlm_destroy_flock_export(struct obd_export *exp); - void l_check_ns_lock(struct ldlm_namespace *ns); - void l_check_no_ns_lock(struct ldlm_namespace *ns); - --extern cfs_proc_dir_entry_t *ldlm_svc_proc_dir; --extern cfs_proc_dir_entry_t *ldlm_type_proc_dir; -+extern struct proc_dir_entry *ldlm_svc_proc_dir; -+extern struct proc_dir_entry *ldlm_type_proc_dir; - - struct ldlm_state { - struct ptlrpc_service *ldlm_cb_service; -@@ -252,42 +252,51 @@ enum ldlm_policy_res { - - typedef enum ldlm_policy_res ldlm_policy_res_t; - --#define LDLM_POOL_PROC_READER(var, type) \ -- static int lprocfs_rd_##var(char *page, char **start, off_t off, \ -- int count, int *eof, void *data) \ -- { \ -- struct ldlm_pool *pl = data; \ -- type tmp; \ -- \ -- spin_lock(&pl->pl_lock); \ -- tmp = pl->pl_##var; \ -- spin_unlock(&pl->pl_lock); \ -- \ -- return lprocfs_rd_uint(page, start, off, count, eof, &tmp); \ -- } \ -- struct __##var##__dummy_read {;} /* semicolon catcher */ -- --#define LDLM_POOL_PROC_WRITER(var, type) \ -- int lprocfs_wr_##var(struct file *file, const char *buffer, \ -- unsigned long count, void *data) \ -- { \ -- struct ldlm_pool *pl = data; \ -- type tmp; \ -- int rc; \ -- \ -- rc = lprocfs_wr_uint(file, buffer, count, &tmp); \ -- if (rc < 0) { \ -- CERROR("Can't parse user input, rc = %d\n", rc); \ -- return rc; \ -- } \ -- \ -- spin_lock(&pl->pl_lock); \ -- pl->pl_##var = tmp; \ -- spin_unlock(&pl->pl_lock); \ -- \ -- return rc; \ -- } \ -- struct __##var##__dummy_write {;} /* semicolon catcher */ -+#define LDLM_POOL_PROC_READER_SEQ_SHOW(var, type) \ -+ static int lprocfs_##var##_seq_show(struct seq_file *m, void *v)\ -+ { \ -+ struct ldlm_pool *pl = m->private; \ -+ type tmp; \ -+ \ -+ spin_lock(&pl->pl_lock); \ -+ tmp = pl->pl_##var; \ -+ spin_unlock(&pl->pl_lock); \ -+ \ -+ return lprocfs_uint_seq_show(m, &tmp); \ -+ } \ -+ struct __##var##__dummy_read {;} /* semicolon catcher */ -+ -+#define LDLM_POOL_PROC_WRITER(var, type) \ -+ int lprocfs_wr_##var(struct file *file, const char *buffer, \ -+ unsigned long count, void *data) \ -+ { \ -+ struct ldlm_pool *pl = data; \ -+ type tmp; \ -+ int rc; \ -+ \ -+ rc = lprocfs_wr_uint(file, buffer, count, &tmp); \ -+ if (rc < 0) { \ -+ CERROR("Can't parse user input, rc = %d\n", rc);\ -+ return rc; \ -+ } \ -+ \ -+ spin_lock(&pl->pl_lock); \ -+ pl->pl_##var = tmp; \ -+ spin_unlock(&pl->pl_lock); \ -+ \ -+ return rc; \ -+ } \ -+ struct __##var##__dummy_write {;} /* semicolon catcher */ -+ -+static inline void -+ldlm_add_var(struct lprocfs_seq_vars *vars, struct proc_dir_entry *proc_dir, -+ const char *name, void *data, const struct file_operations *ops) -+{ -+ snprintf((char *)vars->name, MAX_STRING_SIZE, "%s", name); -+ vars->data = data; -+ vars->fops = ops; -+ lprocfs_seq_add_vars(proc_dir, vars, 0); -+} - - static inline int is_granted_or_cancelled(struct ldlm_lock *lock) - { -diff --git a/lustre/ldlm/ldlm_pool.c b/lustre/ldlm/ldlm_pool.c -index 734b330..c1b7ac6 100644 ---- a/lustre/ldlm/ldlm_pool.c -+++ b/lustre/ldlm/ldlm_pool.c -@@ -148,7 +148,7 @@ - #define LDLM_POOL_SLV_SHIFT (10) - - #ifdef __KERNEL__ --extern cfs_proc_dir_entry_t *ldlm_ns_proc_dir; -+extern struct proc_dir_entry *ldlm_ns_proc_dir; - #endif - - static inline __u64 dru(__u64 val, __u32 shift, int round_up) -@@ -656,14 +656,13 @@ int ldlm_pool_setup(struct ldlm_pool *pl, int limit) - EXPORT_SYMBOL(ldlm_pool_setup); - - #ifdef __KERNEL__ --static int lprocfs_rd_pool_state(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int lprocfs_pool_state_seq_show(struct seq_file *m, void *unused) - { -- int granted, grant_rate, cancel_rate, grant_step; -- int nr = 0, grant_speed, grant_plan, lvf; -- struct ldlm_pool *pl = data; -- __u64 slv, clv; -- __u32 limit; -+ int granted, grant_rate, cancel_rate, grant_step; -+ int grant_speed, grant_plan, lvf; -+ struct ldlm_pool *pl = m->private; -+ __u64 slv, clv; -+ __u32 limit; - - spin_lock(&pl->pl_lock); - slv = pl->pl_server_lock_volume; -@@ -678,35 +677,28 @@ static int lprocfs_rd_pool_state(char *page, char **start, off_t off, - grant_step = ldlm_pool_t2gsp(pl->pl_recalc_period); - spin_unlock(&pl->pl_lock); - -- nr += snprintf(page + nr, count - nr, "LDLM pool state (%s):\n", -- pl->pl_name); -- nr += snprintf(page + nr, count - nr, " SLV: "LPU64"\n", slv); -- nr += snprintf(page + nr, count - nr, " CLV: "LPU64"\n", clv); -- nr += snprintf(page + nr, count - nr, " LVF: %d\n", lvf); -- -- if (ns_is_server(ldlm_pl2ns(pl))) { -- nr += snprintf(page + nr, count - nr, " GSP: %d%%\n", -- grant_step); -- nr += snprintf(page + nr, count - nr, " GP: %d\n", -- grant_plan); -- } -- nr += snprintf(page + nr, count - nr, " GR: %d\n", -- grant_rate); -- nr += snprintf(page + nr, count - nr, " CR: %d\n", -- cancel_rate); -- nr += snprintf(page + nr, count - nr, " GS: %d\n", -- grant_speed); -- nr += snprintf(page + nr, count - nr, " G: %d\n", -- granted); -- nr += snprintf(page + nr, count - nr, " L: %d\n", -- limit); -- return nr; -+ seq_printf(m, "LDLM pool state (%s):\n" -+ " SLV: "LPU64"\n" -+ " CLV: "LPU64"\n" -+ " LVF: %d\n", -+ pl->pl_name, slv, clv, lvf); -+ -+ if (ns_is_server(ldlm_pl2ns(pl))) { -+ seq_printf(m, " GSP: %d%%\n" -+ " GP: %d\n", -+ grant_step, grant_plan); -+ } -+ seq_printf(m, " GR: %d\n" " CR: %d\n" " GS: %d\n" -+ " G: %d\n" " L: %d\n", -+ grant_rate, cancel_rate, grant_speed, -+ granted, limit); -+ return 0; - } -+LPROC_SEQ_FOPS_RO(lprocfs_pool_state); - --static int lprocfs_rd_grant_speed(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int lprocfs_grant_speed_seq_show(struct seq_file *m, void *unused) - { -- struct ldlm_pool *pl = data; -+ struct ldlm_pool *pl = m->private; - int grant_speed; - - spin_lock(&pl->pl_lock); -@@ -714,35 +706,50 @@ static int lprocfs_rd_grant_speed(char *page, char **start, off_t off, - grant_speed = cfs_atomic_read(&pl->pl_grant_rate) - - cfs_atomic_read(&pl->pl_cancel_rate); - spin_unlock(&pl->pl_lock); -- return lprocfs_rd_uint(page, start, off, count, eof, &grant_speed); -+ return lprocfs_uint_seq_show(m, &grant_speed); - } - --LDLM_POOL_PROC_READER(grant_plan, int); --LDLM_POOL_PROC_READER(recalc_period, int); -+LDLM_POOL_PROC_READER_SEQ_SHOW(grant_plan, int); -+LPROC_SEQ_FOPS_RO(lprocfs_grant_plan); -+ -+LDLM_POOL_PROC_READER_SEQ_SHOW(recalc_period, int); - LDLM_POOL_PROC_WRITER(recalc_period, int); -+static ssize_t lprocfs_recalc_period_seq_write(struct file *file, const char *buf, -+ size_t len, loff_t *off) -+{ -+ struct seq_file *seq = file->private_data; -+ -+ return lprocfs_wr_recalc_period(file, buf, len, seq->private); -+} -+LPROC_SEQ_FOPS(lprocfs_recalc_period); -+ -+LPROC_SEQ_FOPS_RO_TYPE(ldlm_pool, u64); -+LPROC_SEQ_FOPS_RO_TYPE(ldlm_pool, atomic); -+LPROC_SEQ_FOPS_RW_TYPE(ldlm_pool_rw, atomic); -+ -+LPROC_SEQ_FOPS_RO(lprocfs_grant_speed); - - static int ldlm_pool_proc_init(struct ldlm_pool *pl) - { -- struct ldlm_namespace *ns = ldlm_pl2ns(pl); -- struct proc_dir_entry *parent_ns_proc; -- struct lprocfs_vars pool_vars[2]; -- char *var_name = NULL; -- int rc = 0; -- ENTRY; -+ struct ldlm_namespace *ns = ldlm_pl2ns(pl); -+ struct proc_dir_entry *parent_ns_proc; -+ struct lprocfs_seq_vars pool_vars[2]; -+ char *var_name = NULL; -+ int rc = 0; -+ ENTRY; - -- OBD_ALLOC(var_name, MAX_STRING_SIZE + 1); -- if (!var_name) -- RETURN(-ENOMEM); -+ OBD_ALLOC(var_name, MAX_STRING_SIZE + 1); -+ if (!var_name) -+ RETURN(-ENOMEM); - -- parent_ns_proc = lprocfs_srch(ldlm_ns_proc_dir, -- ldlm_ns_name(ns)); -- if (parent_ns_proc == NULL) { -- CERROR("%s: proc entry is not initialized\n", -- ldlm_ns_name(ns)); -- GOTO(out_free_name, rc = -EINVAL); -- } -- pl->pl_proc_dir = lprocfs_register("pool", parent_ns_proc, -- NULL, NULL); -+ parent_ns_proc = ns->ns_proc_dir_entry; -+ if (parent_ns_proc == NULL) { -+ CERROR("%s: proc entry is not initialized\n", -+ ldlm_ns_name(ns)); -+ GOTO(out_free_name, rc = -EINVAL); -+ } -+ pl->pl_proc_dir = lprocfs_seq_register("pool", parent_ns_proc, -+ NULL, NULL); - if (IS_ERR(pl->pl_proc_dir)) { - rc = PTR_ERR(pl->pl_proc_dir); - pl->pl_proc_dir = NULL; -@@ -751,62 +758,30 @@ static int ldlm_pool_proc_init(struct ldlm_pool *pl) - GOTO(out_free_name, rc); - } - -- var_name[MAX_STRING_SIZE] = '\0'; -- memset(pool_vars, 0, sizeof(pool_vars)); -- pool_vars[0].name = var_name; -- -- snprintf(var_name, MAX_STRING_SIZE, "server_lock_volume"); -- pool_vars[0].data = &pl->pl_server_lock_volume; -- pool_vars[0].read_fptr = lprocfs_rd_u64; -- lprocfs_add_vars(pl->pl_proc_dir, pool_vars, 0); -- -- snprintf(var_name, MAX_STRING_SIZE, "limit"); -- pool_vars[0].data = &pl->pl_limit; -- pool_vars[0].read_fptr = lprocfs_rd_atomic; -- pool_vars[0].write_fptr = lprocfs_wr_atomic; -- lprocfs_add_vars(pl->pl_proc_dir, pool_vars, 0); -- -- snprintf(var_name, MAX_STRING_SIZE, "granted"); -- pool_vars[0].data = &pl->pl_granted; -- pool_vars[0].read_fptr = lprocfs_rd_atomic; -- lprocfs_add_vars(pl->pl_proc_dir, pool_vars, 0); -- -- snprintf(var_name, MAX_STRING_SIZE, "grant_speed"); -- pool_vars[0].data = pl; -- pool_vars[0].read_fptr = lprocfs_rd_grant_speed; -- lprocfs_add_vars(pl->pl_proc_dir, pool_vars, 0); -- -- snprintf(var_name, MAX_STRING_SIZE, "cancel_rate"); -- pool_vars[0].data = &pl->pl_cancel_rate; -- pool_vars[0].read_fptr = lprocfs_rd_atomic; -- lprocfs_add_vars(pl->pl_proc_dir, pool_vars, 0); -- -- snprintf(var_name, MAX_STRING_SIZE, "grant_rate"); -- pool_vars[0].data = &pl->pl_grant_rate; -- pool_vars[0].read_fptr = lprocfs_rd_atomic; -- lprocfs_add_vars(pl->pl_proc_dir, pool_vars, 0); -- -- snprintf(var_name, MAX_STRING_SIZE, "grant_plan"); -- pool_vars[0].data = pl; -- pool_vars[0].read_fptr = lprocfs_rd_grant_plan; -- lprocfs_add_vars(pl->pl_proc_dir, pool_vars, 0); -- -- snprintf(var_name, MAX_STRING_SIZE, "recalc_period"); -- pool_vars[0].data = pl; -- pool_vars[0].read_fptr = lprocfs_rd_recalc_period; -- pool_vars[0].write_fptr = lprocfs_wr_recalc_period; -- lprocfs_add_vars(pl->pl_proc_dir, pool_vars, 0); -- -- snprintf(var_name, MAX_STRING_SIZE, "lock_volume_factor"); -- pool_vars[0].data = &pl->pl_lock_volume_factor; -- pool_vars[0].read_fptr = lprocfs_rd_atomic; -- pool_vars[0].write_fptr = lprocfs_wr_atomic; -- lprocfs_add_vars(pl->pl_proc_dir, pool_vars, 0); -- -- snprintf(var_name, MAX_STRING_SIZE, "state"); -- pool_vars[0].data = pl; -- pool_vars[0].read_fptr = lprocfs_rd_pool_state; -- lprocfs_add_vars(pl->pl_proc_dir, pool_vars, 0); -+ var_name[MAX_STRING_SIZE] = '\0'; -+ memset(pool_vars, 0, sizeof(pool_vars)); -+ pool_vars[0].name = var_name; -+ -+ ldlm_add_var(&pool_vars[0], pl->pl_proc_dir, "server_lock_volume", -+ &pl->pl_server_lock_volume, &ldlm_pool_u64_fops); -+ ldlm_add_var(&pool_vars[0], pl->pl_proc_dir, "limit", &pl->pl_limit, -+ &ldlm_pool_rw_atomic_fops); -+ ldlm_add_var(&pool_vars[0], pl->pl_proc_dir, "granted", -+ &pl->pl_granted, &ldlm_pool_atomic_fops); -+ ldlm_add_var(&pool_vars[0], pl->pl_proc_dir, "grant_speed", pl, -+ &lprocfs_grant_speed_fops); -+ ldlm_add_var(&pool_vars[0], pl->pl_proc_dir, "cancel_rate", -+ &pl->pl_cancel_rate, &ldlm_pool_atomic_fops); -+ ldlm_add_var(&pool_vars[0], pl->pl_proc_dir, "grant_rate", -+ &pl->pl_grant_rate, &ldlm_pool_atomic_fops); -+ ldlm_add_var(&pool_vars[0], pl->pl_proc_dir, "grant_plan", pl, -+ &lprocfs_grant_plan_fops); -+ ldlm_add_var(&pool_vars[0], pl->pl_proc_dir, "recalc_period", -+ pl, &lprocfs_recalc_period_fops); -+ ldlm_add_var(&pool_vars[0], pl->pl_proc_dir, "lock_volume_factor", -+ &pl->pl_lock_volume_factor, &ldlm_pool_rw_atomic_fops); -+ ldlm_add_var(&pool_vars[0], pl->pl_proc_dir, "state", pl, -+ &lprocfs_pool_state_fops); - - pl->pl_stats = lprocfs_alloc_stats(LDLM_POOL_LAST_STAT - - LDLM_POOL_FIRST_STAT, 0); -diff --git a/lustre/ldlm/ldlm_resource.c b/lustre/ldlm/ldlm_resource.c -index e1b8787..e504cff 100644 ---- a/lustre/ldlm/ldlm_resource.c -+++ b/lustre/ldlm/ldlm_resource.c -@@ -66,9 +66,9 @@ CFS_LIST_HEAD(ldlm_cli_active_namespace_list); - /* Client namespaces that don't have any locks in them */ - CFS_LIST_HEAD(ldlm_cli_inactive_namespace_list); - --cfs_proc_dir_entry_t *ldlm_type_proc_dir = NULL; --cfs_proc_dir_entry_t *ldlm_ns_proc_dir = NULL; --cfs_proc_dir_entry_t *ldlm_svc_proc_dir = NULL; -+struct proc_dir_entry *ldlm_type_proc_dir = NULL; -+struct proc_dir_entry *ldlm_ns_proc_dir = NULL; -+struct proc_dir_entry *ldlm_svc_proc_dir = NULL; - - extern unsigned int ldlm_cancel_unused_locks_before_replay; - -@@ -77,57 +77,64 @@ extern unsigned int ldlm_cancel_unused_locks_before_replay; - unsigned int ldlm_dump_granted_max = 256; - - #ifdef LPROCFS --static int ldlm_proc_dump_ns(struct file *file, const char *buffer, -- unsigned long count, void *data) -+static ssize_t -+lprocfs_dump_ns_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) - { -- ldlm_dump_all_namespaces(LDLM_NAMESPACE_SERVER, D_DLMTRACE); -- ldlm_dump_all_namespaces(LDLM_NAMESPACE_CLIENT, D_DLMTRACE); -- RETURN(count); -+ ldlm_dump_all_namespaces(LDLM_NAMESPACE_SERVER, D_DLMTRACE); -+ ldlm_dump_all_namespaces(LDLM_NAMESPACE_CLIENT, D_DLMTRACE); -+ RETURN(count); - } -+LPROC_SEQ_FOPS_WO_TYPE(ldlm, dump_ns); -+ -+LPROC_SEQ_FOPS_RW_TYPE(ldlm_rw, uint); -+LPROC_SEQ_FOPS_RO_TYPE(ldlm, uint); - - int ldlm_proc_setup(void) - { -- int rc; -- struct lprocfs_vars list[] = { -- { "dump_namespaces", NULL, ldlm_proc_dump_ns, NULL }, -- { "dump_granted_max", -- lprocfs_rd_uint, lprocfs_wr_uint, -- &ldlm_dump_granted_max, NULL }, -- { "cancel_unused_locks_before_replay", -- lprocfs_rd_uint, lprocfs_wr_uint, -- &ldlm_cancel_unused_locks_before_replay, NULL }, -- { NULL }}; -- ENTRY; -- LASSERT(ldlm_ns_proc_dir == NULL); -- -- ldlm_type_proc_dir = lprocfs_register(OBD_LDLM_DEVICENAME, -- proc_lustre_root, -- NULL, NULL); -- if (IS_ERR(ldlm_type_proc_dir)) { -- CERROR("LProcFS failed in ldlm-init\n"); -- rc = PTR_ERR(ldlm_type_proc_dir); -- GOTO(err, rc); -- } -+ int rc; -+ struct lprocfs_seq_vars list[] = { -+ { .name = "dump_namespaces", -+ .fops = &ldlm_dump_ns_fops, -+ .proc_mode = 0222 }, -+ { .name = "dump_granted_max", -+ .fops = &ldlm_rw_uint_fops, -+ .data = &ldlm_dump_granted_max }, -+ { .name = "cancel_unused_locks_before_replay", -+ .fops = &ldlm_rw_uint_fops, -+ .data = &ldlm_cancel_unused_locks_before_replay }, -+ { NULL }}; -+ ENTRY; -+ LASSERT(ldlm_ns_proc_dir == NULL); -+ -+ ldlm_type_proc_dir = lprocfs_seq_register(OBD_LDLM_DEVICENAME, -+ proc_lustre_root, -+ NULL, NULL); -+ if (IS_ERR(ldlm_type_proc_dir)) { -+ CERROR("LProcFS failed in ldlm-init\n"); -+ rc = PTR_ERR(ldlm_type_proc_dir); -+ GOTO(err, rc); -+ } - -- ldlm_ns_proc_dir = lprocfs_register("namespaces", -- ldlm_type_proc_dir, -- NULL, NULL); -- if (IS_ERR(ldlm_ns_proc_dir)) { -- CERROR("LProcFS failed in ldlm-init\n"); -- rc = PTR_ERR(ldlm_ns_proc_dir); -- GOTO(err_type, rc); -- } -+ ldlm_ns_proc_dir = lprocfs_seq_register("namespaces", -+ ldlm_type_proc_dir, -+ NULL, NULL); -+ if (IS_ERR(ldlm_ns_proc_dir)) { -+ CERROR("LProcFS failed in ldlm-init\n"); -+ rc = PTR_ERR(ldlm_ns_proc_dir); -+ GOTO(err_type, rc); -+ } - -- ldlm_svc_proc_dir = lprocfs_register("services", -- ldlm_type_proc_dir, -- NULL, NULL); -- if (IS_ERR(ldlm_svc_proc_dir)) { -- CERROR("LProcFS failed in ldlm-init\n"); -- rc = PTR_ERR(ldlm_svc_proc_dir); -- GOTO(err_ns, rc); -- } -+ ldlm_svc_proc_dir = lprocfs_seq_register("services", -+ ldlm_type_proc_dir, -+ NULL, NULL); -+ if (IS_ERR(ldlm_svc_proc_dir)) { -+ CERROR("LProcFS failed in ldlm-init\n"); -+ rc = PTR_ERR(ldlm_svc_proc_dir); -+ GOTO(err_ns, rc); -+ } - -- rc = lprocfs_add_vars(ldlm_type_proc_dir, list, NULL); -+ rc = lprocfs_seq_add_vars(ldlm_type_proc_dir, list, NULL); - if (rc != 0) { - CERROR("LProcFS failed in ldlm-init\n"); - GOTO(err_svc, rc); -@@ -158,46 +165,45 @@ void ldlm_proc_cleanup(void) - lprocfs_remove(&ldlm_type_proc_dir); - } - --static int lprocfs_rd_ns_resources(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int lprocfs_ns_resources_seq_show(struct seq_file *m, void *v) - { -- struct ldlm_namespace *ns = data; -- __u64 res = 0; -- cfs_hash_bd_t bd; -- int i; -- -- /* result is not strictly consistant */ -- cfs_hash_for_each_bucket(ns->ns_rs_hash, &bd, i) -- res += cfs_hash_bd_count_get(&bd); -- return lprocfs_rd_u64(page, start, off, count, eof, &res); -+ struct ldlm_namespace *ns = m->private; -+ __u64 res = 0; -+ cfs_hash_bd_t bd; -+ int i; -+ -+ /* result is not strictly consistant */ -+ cfs_hash_for_each_bucket(ns->ns_rs_hash, &bd, i) -+ res += cfs_hash_bd_count_get(&bd); -+ return lprocfs_u64_seq_show(m, &res); - } -+LPROC_SEQ_FOPS_RO(lprocfs_ns_resources); - --static int lprocfs_rd_ns_locks(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int lprocfs_ns_locks_seq_show(struct seq_file *m, void *v) - { -- struct ldlm_namespace *ns = data; -- __u64 locks; -+ struct ldlm_namespace *ns = m->private; -+ __u64 locks; - -- locks = lprocfs_stats_collector(ns->ns_stats, LDLM_NSS_LOCKS, -- LPROCFS_FIELDS_FLAGS_SUM); -- return lprocfs_rd_u64(page, start, off, count, eof, &locks); -+ locks = lprocfs_stats_collector(ns->ns_stats, LDLM_NSS_LOCKS, -+ LPROCFS_FIELDS_FLAGS_SUM); -+ return lprocfs_u64_seq_show(m, &locks); - } -+LPROC_SEQ_FOPS_RO(lprocfs_ns_locks); - --static int lprocfs_rd_lru_size(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int lprocfs_lru_size_seq_show(struct seq_file *m, void *v) - { -- struct ldlm_namespace *ns = data; -- __u32 *nr = &ns->ns_max_unused; -+ struct ldlm_namespace *ns = m->private; -+ __u32 *nr = &ns->ns_max_unused; - -- if (ns_connect_lru_resize(ns)) -- nr = &ns->ns_nr_unused; -- return lprocfs_rd_uint(page, start, off, count, eof, nr); -+ if (ns_connect_lru_resize(ns)) -+ nr = &ns->ns_nr_unused; -+ return lprocfs_uint_seq_show(m, nr); - } - --static int lprocfs_wr_lru_size(struct file *file, const char *buffer, -- unsigned long count, void *data) -+static ssize_t lprocfs_lru_size_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) - { -- struct ldlm_namespace *ns = data; -+ struct ldlm_namespace *ns = ((struct seq_file *)file->private_data)->private; - char dummy[MAX_STRING_SIZE + 1], *end; - unsigned long tmp; - int lru_resize; -@@ -280,20 +286,20 @@ static int lprocfs_wr_lru_size(struct file *file, const char *buffer, - - return count; - } -+LPROC_SEQ_FOPS(lprocfs_lru_size); - --static int lprocfs_rd_elc(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int lprocfs_elc_seq_show(struct seq_file *m, void *v) - { -- struct ldlm_namespace *ns = data; -+ struct ldlm_namespace *ns = m->private; - unsigned int supp = ns_connect_cancelset(ns); - -- return lprocfs_rd_uint(page, start, off, count, eof, &supp); -+ return lprocfs_uint_seq_show(m, &supp); - } - --static int lprocfs_wr_elc(struct file *file, const char *buffer, -- unsigned long count, void *data) -+static ssize_t lprocfs_elc_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) - { -- struct ldlm_namespace *ns = data; -+ struct ldlm_namespace *ns = ((struct seq_file *)file->private_data)->private; - unsigned int supp = -1; - int rc; - -@@ -307,31 +313,38 @@ static int lprocfs_wr_elc(struct file *file, const char *buffer, - ns->ns_connect_flags |= OBD_CONNECT_CANCELSET; - return count; - } -+LPROC_SEQ_FOPS(lprocfs_elc); - - void ldlm_namespace_proc_unregister(struct ldlm_namespace *ns) - { -- struct proc_dir_entry *dir; -- -- dir = lprocfs_srch(ldlm_ns_proc_dir, ldlm_ns_name(ns)); -- if (dir == NULL) { -+ if (ns->ns_proc_dir_entry == NULL) - CERROR("dlm namespace %s has no procfs dir?\n", - ldlm_ns_name(ns)); -- } else { -- lprocfs_remove(&dir); -- } -+ else -+ lprocfs_remove(&ns->ns_proc_dir_entry); - -- if (ns->ns_stats != NULL) -- lprocfs_free_stats(&ns->ns_stats); -+ if (ns->ns_stats != NULL) -+ lprocfs_free_stats(&ns->ns_stats); - } - - int ldlm_namespace_proc_register(struct ldlm_namespace *ns) - { -- struct lprocfs_vars lock_vars[2]; -+ struct lprocfs_seq_vars lock_vars[2]; - char lock_name[MAX_STRING_SIZE + 1]; -+ struct proc_dir_entry *ns_pde; - - LASSERT(ns != NULL); - LASSERT(ns->ns_rs_hash != NULL); - -+ if (ns->ns_proc_dir_entry != NULL) { -+ ns_pde = ns->ns_proc_dir_entry; -+ } else { -+ ns_pde = proc_mkdir(ldlm_ns_name(ns), ldlm_ns_proc_dir); -+ if (ns_pde == NULL) -+ return -ENOMEM; -+ ns->ns_proc_dir_entry = ns_pde; -+ } -+ - ns->ns_stats = lprocfs_alloc_stats(LDLM_NSS_LAST, 0); - if (ns->ns_stats == NULL) - return -ENOMEM; -@@ -344,88 +357,35 @@ int ldlm_namespace_proc_register(struct ldlm_namespace *ns) - memset(lock_vars, 0, sizeof(lock_vars)); - lock_vars[0].name = lock_name; - -- snprintf(lock_name, MAX_STRING_SIZE, "%s/resource_count", -- ldlm_ns_name(ns)); -- lock_vars[0].data = ns; -- lock_vars[0].read_fptr = lprocfs_rd_ns_resources; -- lprocfs_add_vars(ldlm_ns_proc_dir, lock_vars, 0); -- -- snprintf(lock_name, MAX_STRING_SIZE, "%s/lock_count", -- ldlm_ns_name(ns)); -- lock_vars[0].data = ns; -- lock_vars[0].read_fptr = lprocfs_rd_ns_locks; -- lprocfs_add_vars(ldlm_ns_proc_dir, lock_vars, 0); -- -- if (ns_is_client(ns)) { -- snprintf(lock_name, MAX_STRING_SIZE, "%s/lock_unused_count", -- ldlm_ns_name(ns)); -- lock_vars[0].data = &ns->ns_nr_unused; -- lock_vars[0].read_fptr = lprocfs_rd_uint; -- lprocfs_add_vars(ldlm_ns_proc_dir, lock_vars, 0); -- -- snprintf(lock_name, MAX_STRING_SIZE, "%s/lru_size", -- ldlm_ns_name(ns)); -- lock_vars[0].data = ns; -- lock_vars[0].read_fptr = lprocfs_rd_lru_size; -- lock_vars[0].write_fptr = lprocfs_wr_lru_size; -- lprocfs_add_vars(ldlm_ns_proc_dir, lock_vars, 0); -- -- snprintf(lock_name, MAX_STRING_SIZE, "%s/lru_max_age", -- ldlm_ns_name(ns)); -- lock_vars[0].data = &ns->ns_max_age; -- lock_vars[0].read_fptr = lprocfs_rd_uint; -- lock_vars[0].write_fptr = lprocfs_wr_uint; -- lprocfs_add_vars(ldlm_ns_proc_dir, lock_vars, 0); -- -- snprintf(lock_name, MAX_STRING_SIZE, "%s/early_lock_cancel", -- ldlm_ns_name(ns)); -- lock_vars[0].data = ns; -- lock_vars[0].read_fptr = lprocfs_rd_elc; -- lock_vars[0].write_fptr = lprocfs_wr_elc; -- lprocfs_add_vars(ldlm_ns_proc_dir, lock_vars, 0); -- } else { -- snprintf(lock_name, MAX_STRING_SIZE, "%s/ctime_age_limit", -- ldlm_ns_name(ns)); -- lock_vars[0].data = &ns->ns_ctime_age_limit; -- lock_vars[0].read_fptr = lprocfs_rd_uint; -- lock_vars[0].write_fptr = lprocfs_wr_uint; -- lprocfs_add_vars(ldlm_ns_proc_dir, lock_vars, 0); -- -- snprintf(lock_name, MAX_STRING_SIZE, "%s/lock_timeouts", -- ldlm_ns_name(ns)); -- lock_vars[0].data = &ns->ns_timeouts; -- lock_vars[0].read_fptr = lprocfs_rd_uint; -- lprocfs_add_vars(ldlm_ns_proc_dir, lock_vars, 0); -- -- snprintf(lock_name, MAX_STRING_SIZE, "%s/max_nolock_bytes", -- ldlm_ns_name(ns)); -- lock_vars[0].data = &ns->ns_max_nolock_size; -- lock_vars[0].read_fptr = lprocfs_rd_uint; -- lock_vars[0].write_fptr = lprocfs_wr_uint; -- lprocfs_add_vars(ldlm_ns_proc_dir, lock_vars, 0); -- -- snprintf(lock_name, MAX_STRING_SIZE, "%s/contention_seconds", -- ldlm_ns_name(ns)); -- lock_vars[0].data = &ns->ns_contention_time; -- lock_vars[0].read_fptr = lprocfs_rd_uint; -- lock_vars[0].write_fptr = lprocfs_wr_uint; -- lprocfs_add_vars(ldlm_ns_proc_dir, lock_vars, 0); -- -- snprintf(lock_name, MAX_STRING_SIZE, "%s/contended_locks", -- ldlm_ns_name(ns)); -- lock_vars[0].data = &ns->ns_contended_locks; -- lock_vars[0].read_fptr = lprocfs_rd_uint; -- lock_vars[0].write_fptr = lprocfs_wr_uint; -- lprocfs_add_vars(ldlm_ns_proc_dir, lock_vars, 0); -- -- snprintf(lock_name, MAX_STRING_SIZE, "%s/max_parallel_ast", -- ldlm_ns_name(ns)); -- lock_vars[0].data = &ns->ns_max_parallel_ast; -- lock_vars[0].read_fptr = lprocfs_rd_uint; -- lock_vars[0].write_fptr = lprocfs_wr_uint; -- lprocfs_add_vars(ldlm_ns_proc_dir, lock_vars, 0); -- } -- return 0; -+ ldlm_add_var(&lock_vars[0], ns_pde, "resource_count", ns, -+ &lprocfs_ns_resources_fops); -+ ldlm_add_var(&lock_vars[0], ns_pde, "lock_count", ns, -+ &lprocfs_ns_locks_fops); -+ -+ if (ns_is_client(ns)) { -+ ldlm_add_var(&lock_vars[0], ns_pde, "lock_unused_count", -+ &ns->ns_nr_unused, &ldlm_uint_fops); -+ ldlm_add_var(&lock_vars[0], ns_pde, "lru_size", ns, -+ &lprocfs_lru_size_fops); -+ ldlm_add_var(&lock_vars[0], ns_pde, "lru_max_age", -+ &ns->ns_max_age, &ldlm_rw_uint_fops); -+ ldlm_add_var(&lock_vars[0], ns_pde, "early_lock_cancel", -+ ns, &lprocfs_elc_fops); -+ } else { -+ ldlm_add_var(&lock_vars[0], ns_pde, "ctime_age_limit", -+ &ns->ns_ctime_age_limit, &ldlm_rw_uint_fops); -+ ldlm_add_var(&lock_vars[0], ns_pde, "lock_timeouts", -+ &ns->ns_timeouts, &ldlm_uint_fops); -+ ldlm_add_var(&lock_vars[0], ns_pde, "max_nolock_bytes", -+ &ns->ns_max_nolock_size, &ldlm_rw_uint_fops); -+ ldlm_add_var(&lock_vars[0], ns_pde, "contention_seconds", -+ &ns->ns_contention_time, &ldlm_rw_uint_fops); -+ ldlm_add_var(&lock_vars[0], ns_pde, "contended_locks", -+ &ns->ns_contended_locks, &ldlm_rw_uint_fops); -+ ldlm_add_var(&lock_vars[0], ns_pde, "max_parallel_ast", -+ &ns->ns_max_parallel_ast, &ldlm_rw_uint_fops); -+ } -+ return 0; - } - #undef MAX_STRING_SIZE - #else /* LPROCFS */ --- -1.8.5.1 - diff --git a/sys-cluster/lustre/files/0016-LU-3319-procfs-move-mdt-mds-proc-handling-to-seq_fil.patch b/sys-cluster/lustre/files/0008-LU-3319-procfs-move-mdt-mds-proc-handling-to-seq_fil.patch index 3bc1eb5a9..efaca78f9 100644 --- a/sys-cluster/lustre/files/0016-LU-3319-procfs-move-mdt-mds-proc-handling-to-seq_fil.patch +++ b/sys-cluster/lustre/files/0008-LU-3319-procfs-move-mdt-mds-proc-handling-to-seq_fil.patch @@ -1,7 +1,7 @@ -From 2110d1028da0bab44e1b3494ba4642155195a735 Mon Sep 17 00:00:00 2001 +From 44996aad332f6a30634b651c6e5fe92c01923090 Mon Sep 17 00:00:00 2001 From: James Simmons <uja.ornl@gmail.com> -Date: Mon, 2 Dec 2013 12:36:06 -0500 -Subject: [PATCH 16/18] LU-3319 procfs: move mdt/mds proc handling to seq_files +Date: Fri, 31 Jan 2014 10:47:37 -0500 +Subject: [PATCH 08/13] LU-3319 procfs: move mdt/mds proc handling to seq_files With 3.10 linux kernel and above proc handling now only uses struct seq_files. This patch migrates the mdt/mds @@ -9,20 +9,19 @@ layer proc entries over to using seq_files. Signed-off-by: James Simmons <uja.ornl@gmail.com> Change-Id: Icbafdcd2c2fe3959a51dda3f9c715b0ff8d95742 -Signed-off-by: Alexey Shvetsov <alexxy@gentoo.org> --- - lustre/mdt/mdt_coordinator.c | 246 +++++++--------- + lustre/mdt/mdt_coordinator.c | 259 +++++++-------- lustre/mdt/mdt_handler.c | 16 +- lustre/mdt/mdt_hsm_cdt_actions.c | 5 +- lustre/mdt/mdt_hsm_cdt_agent.c | 5 +- lustre/mdt/mdt_hsm_cdt_requests.c | 5 +- lustre/mdt/mdt_internal.h | 14 +- - lustre/mdt/mdt_lproc.c | 603 ++++++++++++++++++-------------------- + lustre/mdt/mdt_lproc.c | 639 ++++++++++++++++++-------------------- lustre/mdt/mdt_mds.c | 12 +- - 8 files changed, 401 insertions(+), 505 deletions(-) + 8 files changed, 442 insertions(+), 513 deletions(-) diff --git a/lustre/mdt/mdt_coordinator.c b/lustre/mdt/mdt_coordinator.c -index 3915e21..eb05bdf 100644 +index 037bcbd..9bbcbd4 100644 --- a/lustre/mdt/mdt_coordinator.c +++ b/lustre/mdt/mdt_coordinator.c @@ -46,7 +46,7 @@ @@ -52,7 +51,7 @@ index 3915e21..eb05bdf 100644 { return lprocfs_mdt_hsm_vars; } -@@ -1769,22 +1769,17 @@ static __u64 hsm_policy_str2bit(const char *name) +@@ -1786,22 +1786,17 @@ static __u64 hsm_policy_str2bit(const char *name) * \param hexa [IN] print mask before bit names * \param buffer [OUT] string * \param count [IN] size of buffer @@ -81,7 +80,7 @@ index 3915e21..eb05bdf 100644 for (i = 0; i < CDT_POLICY_SHIFT_COUNT; i++) { bit = (1ULL << i); -@@ -1793,48 +1788,34 @@ static int hsm_policy_bit2str(const __u64 mask, const bool hexa, char *buffer, +@@ -1810,48 +1805,34 @@ static int hsm_policy_bit2str(const __u64 mask, const bool hexa, char *buffer, break; } if (bit & mask) @@ -141,7 +140,7 @@ index 3915e21..eb05bdf 100644 int rc; ENTRY; -@@ -1867,18 +1848,10 @@ static int lprocfs_wr_hsm_policy(struct file *file, const char *buffer, +@@ -1884,18 +1865,10 @@ static int lprocfs_wr_hsm_policy(struct file *file, const char *buffer, policy = hsm_policy_str2bit(token); if (policy == 0) { @@ -163,7 +162,7 @@ index 3915e21..eb05bdf 100644 GOTO(out, rc = -EINVAL); } switch (sign) { -@@ -1917,25 +1890,24 @@ out: +@@ -1934,25 +1907,24 @@ out: OBD_FREE(buf, count + 1); RETURN(rc); } @@ -198,7 +197,7 @@ index 3915e21..eb05bdf 100644 struct coordinator *cdt = &mdt->mdt_coordinator; \ int val; \ int rc; \ -@@ -1949,7 +1921,7 @@ static int lprocfs_wr_hsm_##VAR(struct file *file, const char *buffer, \ +@@ -1966,7 +1938,7 @@ static int lprocfs_wr_hsm_##VAR(struct file *file, const char *buffer, \ RETURN(count); \ } \ RETURN(-EINVAL); \ @@ -207,7 +206,7 @@ index 3915e21..eb05bdf 100644 GENERATE_PROC_METHOD(cdt_loop_period) GENERATE_PROC_METHOD(cdt_grace_delay) -@@ -1967,10 +1939,11 @@ GENERATE_PROC_METHOD(cdt_default_archive_id) +@@ -1984,10 +1956,11 @@ GENERATE_PROC_METHOD(cdt_default_archive_id) #define CDT_PURGE_CMD "purge" #define CDT_HELP_CMD "help" @@ -222,7 +221,7 @@ index 3915e21..eb05bdf 100644 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev); struct coordinator *cdt = &(mdt->mdt_coordinator); int rc, usage = 0; -@@ -2024,83 +1997,71 @@ int lprocfs_wr_hsm_cdt_control(struct file *file, const char *buffer, +@@ -2041,83 +2014,71 @@ int lprocfs_wr_hsm_cdt_control(struct file *file, const char *buffer, RETURN(count); } @@ -328,7 +327,7 @@ index 3915e21..eb05bdf 100644 } static inline enum hsm_copytool_action -@@ -2120,9 +2081,9 @@ hsm_copytool_name2action(const char *name) +@@ -2137,9 +2098,9 @@ hsm_copytool_name2action(const char *name) return -1; } @@ -341,7 +340,7 @@ index 3915e21..eb05bdf 100644 { char *buf, *pos, *name; size_t buf_size; -@@ -2166,69 +2127,60 @@ out: +@@ -2183,69 +2144,73 @@ out: RETURN(rc); } @@ -434,25 +433,38 @@ index 3915e21..eb05bdf 100644 +LPROC_SEQ_FOPS(mdt_hsm_other_request_mask); + +static struct lprocfs_seq_vars lprocfs_mdt_hsm_vars[] = { -+ { "agents", &mdt_hsm_agent_fops }, -+ { "actions", &mdt_hsm_actions_fops, NULL, 0444 }, -+ { "default_archive_id", &mdt_hsm_cdt_default_archive_id_fops }, -+ { "grace_delay", &mdt_hsm_cdt_grace_delay_fops }, -+ { "loop_period", &mdt_hsm_cdt_loop_period_fops }, -+ { "max_requests", &mdt_hsm_cdt_max_requests_fops }, -+ { "policy", &mdt_hsm_policy_fops }, -+ { "active_request_timeout",&mdt_hsm_cdt_active_req_timeout_fops }, -+ { "active_requests", &mdt_hsm_active_requests_fops }, -+ { "user_request_mask", &mdt_hsm_user_request_mask_fops, }, -+ { "group_request_mask", &mdt_hsm_group_request_mask_fops, }, -+ { "other_request_mask", &mdt_hsm_other_request_mask_fops, }, ++ { .name = "agents", ++ .fops = &mdt_hsm_agent_fops }, ++ { .name = "actions", ++ .fops = &mdt_hsm_actions_fops, ++ .proc_mode = 0444 }, ++ { .name = "default_archive_id", ++ .fops = &mdt_hsm_cdt_default_archive_id_fops }, ++ { .name = "grace_delay", ++ .fops = &mdt_hsm_cdt_grace_delay_fops }, ++ { .name = "loop_period", ++ .fops = &mdt_hsm_cdt_loop_period_fops }, ++ { .name = "max_requests", ++ .fops = &mdt_hsm_cdt_max_requests_fops }, ++ { .name = "policy", ++ .fops = &mdt_hsm_policy_fops }, ++ { .name = "active_request_timeout", ++ .fops = &mdt_hsm_cdt_active_req_timeout_fops }, ++ { .name = "active_requests", ++ .fops = &mdt_hsm_active_requests_fops }, ++ { .name = "user_request_mask", ++ .fops = &mdt_hsm_user_request_mask_fops, }, ++ { .name = "group_request_mask", ++ .fops = &mdt_hsm_group_request_mask_fops, }, ++ { .name = "other_request_mask", ++ .fops = &mdt_hsm_other_request_mask_fops, }, { 0 } }; diff --git a/lustre/mdt/mdt_handler.c b/lustre/mdt/mdt_handler.c -index 8daf7e1..9f7d4ba 100644 +index 4c386b1..273cb80 100644 --- a/lustre/mdt/mdt_handler.c +++ b/lustre/mdt/mdt_handler.c -@@ -4508,7 +4508,6 @@ static int mdt_process_config(const struct lu_env *env, +@@ -4538,7 +4538,6 @@ static int mdt_process_config(const struct lu_env *env, switch (cfg->lcfg_command) { case LCFG_PARAM: { @@ -460,7 +472,7 @@ index 8daf7e1..9f7d4ba 100644 struct obd_device *obd = d->ld_obd; /* For interoperability */ -@@ -4543,14 +4542,13 @@ static int mdt_process_config(const struct lu_env *env, +@@ -4573,14 +4572,13 @@ static int mdt_process_config(const struct lu_env *env, } } @@ -480,7 +492,7 @@ index 8daf7e1..9f7d4ba 100644 if (rc > 0 || rc == -ENOSYS) /* we don't understand; pass it on */ rc = next->ld_ops->ldo_process_config(env, next, -@@ -5725,7 +5723,6 @@ static struct lu_device_type mdt_device_type = { +@@ -5759,7 +5757,6 @@ static struct lu_device_type mdt_device_type = { static int __init mdt_mod_init(void) { @@ -488,7 +500,7 @@ index 8daf7e1..9f7d4ba 100644 int rc; CLASSERT(sizeof("0x0123456789ABCDEF:0x01234567:0x01234567") == -@@ -5740,10 +5737,9 @@ static int __init mdt_mod_init(void) +@@ -5774,10 +5771,9 @@ static int __init mdt_mod_init(void) if (rc) GOTO(lu_fini, rc); @@ -566,10 +578,10 @@ index 796cbea..7bbc771 100644 RETURN(rc); } diff --git a/lustre/mdt/mdt_internal.h b/lustre/mdt/mdt_internal.h -index dd36201..43cf9eb 100644 +index d548988..e30d78d 100644 --- a/lustre/mdt/mdt_internal.h +++ b/lustre/mdt/mdt_internal.h -@@ -778,9 +778,6 @@ void mdt_thread_info_init(struct ptlrpc_request *req, +@@ -784,9 +784,6 @@ void mdt_thread_info_init(struct ptlrpc_request *req, void mdt_thread_info_fini(struct mdt_thread_info *mti); struct mdt_thread_info *tsi2mdt_info(struct tgt_session_info *tsi); @@ -579,7 +591,7 @@ index dd36201..43cf9eb 100644 int mdt_hsm_attr_set(struct mdt_thread_info *info, struct mdt_object *obj, const struct md_hsm *mh); -@@ -913,13 +910,12 @@ int mdt_hsm_cdt_fini(struct mdt_device *mdt); +@@ -919,13 +916,12 @@ int mdt_hsm_cdt_fini(struct mdt_device *mdt); int mdt_hsm_cdt_wakeup(struct mdt_device *mdt); /* coordinator control /proc interface */ @@ -597,7 +609,7 @@ index dd36201..43cf9eb 100644 /* md_hsm helpers */ struct mdt_object *mdt_hsm_get_md_hsm(struct mdt_thread_info *mti, const struct lu_fid *fid, -@@ -1087,8 +1083,6 @@ enum { +@@ -1065,8 +1061,6 @@ enum { }; void mdt_counter_incr(struct ptlrpc_request *req, int opcode); void mdt_stats_counter_init(struct lprocfs_stats *stats); @@ -605,9 +617,9 @@ index dd36201..43cf9eb 100644 -void lprocfs_mds_init_vars(struct lprocfs_static_vars *lvars); int mdt_procfs_init(struct mdt_device *mdt, const char *name); void mdt_procfs_fini(struct mdt_device *mdt); - void mdt_rename_counter_tally(struct mdt_thread_info *info, + diff --git a/lustre/mdt/mdt_lproc.c b/lustre/mdt/mdt_lproc.c -index 4abb532..236b6c2 100644 +index 0ee5148..658f00d 100644 --- a/lustre/mdt/mdt_lproc.c +++ b/lustre/mdt/mdt_lproc.c @@ -156,7 +156,6 @@ static ssize_t mdt_rename_stats_seq_write(struct file *file, const char *buf, @@ -623,7 +635,8 @@ index 4abb532..236b6c2 100644 } -int mdt_procfs_init(struct mdt_device *mdt, const char *name) --{ ++static int mdt_identity_expire_seq_show(struct seq_file *m, void *data) + { - struct obd_device *obd = mdt2obd_dev(mdt); - struct lprocfs_static_vars lvars; - int rc; @@ -687,8 +700,7 @@ index 4abb532..236b6c2 100644 - -static int lprocfs_rd_identity_expire(char *page, char **start, off_t off, - int count, int *eof, void *data) -+static int mdt_identity_expire_seq_show(struct seq_file *m, void *data) - { +-{ - struct obd_device *obd = data; - struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev); + struct obd_device *obd = m->private; @@ -838,6 +850,15 @@ index 4abb532..236b6c2 100644 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev); struct identity_downcall_data *param; int size = sizeof(*param), rc, checked = 0; +@@ -415,7 +348,7 @@ static int lprocfs_wr_identity_info(struct file *file, const char *buffer, + again: + if (count < size) { + CERROR("%s: invalid data count = %lu, size = %d\n", +- mdt_obd_name(mdt), count, size); ++ mdt_obd_name(mdt), (unsigned long) count, size); + return -EINVAL; + } + @@ -468,23 +401,24 @@ out: return rc ? rc : count; @@ -1235,7 +1256,7 @@ index 4abb532..236b6c2 100644 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev); __u32 val; int rc; -@@ -957,97 +899,46 @@ static int lprocfs_wr_enable_remote_dir_gid(struct file *file, +@@ -957,97 +899,72 @@ static int lprocfs_wr_enable_remote_dir_gid(struct file *file, mdt->mdt_enable_remote_dir_gid = val; return count; } @@ -1344,36 +1365,85 @@ index 4abb532..236b6c2 100644 +LPROC_SEQ_FOPS(mdt_hsm_cdt_control); + +static struct lprocfs_seq_vars lprocfs_mdt_obd_vars[] = { -+ { "uuid", &mdt_uuid_fops }, -+ { "recovery_status", &mdt_recovery_status_fops }, -+ { "num_exports", &mdt_num_exports_fops }, -+ { "identity_expire", &mdt_identity_expire_fops }, -+ { "identity_acquire_expire", &mdt_identity_acquire_expire_fops }, -+ { "identity_upcall", &mdt_identity_upcall_fops }, -+ { "identity_flush", &mdt_identity_flush_fops }, -+ { "identity_info", &mdt_identity_info_fops }, -+ { "capa", &mdt_capa_fops }, -+ { "capa_timeout", &mdt_capa_timeout_fops }, -+ { "capa_key_timeout", &mdt_ck_timeout_fops }, -+ { "capa_count", &mdt_capa_count_fops }, -+ { "site_stats", &mdt_site_stats_fops }, -+ { "evict_client", &mdt_mds_evict_client_fops }, -+ { "hash_stats", &mdt_hash_fops }, -+ { "sec_level", &mdt_sec_level_fops }, -+ { "commit_on_sharing", &mdt_cos_fops }, -+ { "root_squash", &mdt_root_squash_fops }, -+ { "nosquash_nids", &mdt_nosquash_nids_fops }, -+ { "som", &mdt_som_fops }, -+ { "instance", &mdt_target_instance_fops }, -+ { "ir_factor", &mdt_ir_factor_fops }, -+ { "job_cleanup_interval", &mdt_job_interval_fops }, -+ { "enable_remote_dir", &mdt_enable_remote_dir_fops }, -+ { "enable_remote_dir_gid", &mdt_enable_remote_dir_gid_fops }, -+ { "hsm_control", &mdt_hsm_cdt_control_fops }, ++ { .name = "uuid", ++ .fops = &mdt_uuid_fops }, ++ { .name = "recovery_status", ++ .fops = &mdt_recovery_status_fops }, ++ { .name = "num_exports", ++ .fops = &mdt_num_exports_fops }, ++ { .name = "identity_expire", ++ .fops = &mdt_identity_expire_fops }, ++ { .name = "identity_acquire_expire", ++ .fops = &mdt_identity_acquire_expire_fops }, ++ { .name = "identity_upcall", ++ .fops = &mdt_identity_upcall_fops }, ++ { .name = "identity_flush", ++ .fops = &mdt_identity_flush_fops }, ++ { .name = "identity_info", ++ .fops = &mdt_identity_info_fops }, ++ { .name = "capa", ++ .fops = &mdt_capa_fops }, ++ { .name = "capa_timeout", ++ .fops = &mdt_capa_timeout_fops }, ++ { .name = "capa_key_timeout", ++ .fops = &mdt_ck_timeout_fops }, ++ { .name = "capa_count", ++ .fops = &mdt_capa_count_fops }, ++ { .name = "site_stats", ++ .fops = &mdt_site_stats_fops }, ++ { .name = "evict_client", ++ .fops = &mdt_mds_evict_client_fops }, ++ { .name = "hash_stats", ++ .fops = &mdt_hash_fops }, ++ { .name = "sec_level", ++ .fops = &mdt_sec_level_fops }, ++ { .name = "commit_on_sharing", ++ .fops = &mdt_cos_fops }, ++ { .name = "root_squash", ++ .fops = &mdt_root_squash_fops }, ++ { .name = "nosquash_nids", ++ .fops = &mdt_nosquash_nids_fops }, ++ { .name = "som", ++ .fops = &mdt_som_fops }, ++ { .name = "instance", ++ .fops = &mdt_target_instance_fops }, ++ { .name = "ir_factor", ++ .fops = &mdt_ir_factor_fops }, ++ { .name = "job_cleanup_interval", ++ .fops = &mdt_job_interval_fops }, ++ { .name = "enable_remote_dir", ++ .fops = &mdt_enable_remote_dir_fops }, ++ { .name = "enable_remote_dir_gid", ++ .fops = &mdt_enable_remote_dir_gid_fops }, ++ { .name = "hsm_control", ++ .fops = &mdt_hsm_cdt_control_fops }, { 0 } }; -@@ -1087,3 +978,67 @@ void mdt_stats_counter_init(struct lprocfs_stats *stats) +@@ -1085,21 +1002,15 @@ int lprocfs_mdt_open_files_seq_show(struct seq_file *seq, void *v) + + int lprocfs_mdt_open_files_seq_open(struct inode *inode, struct file *file) + { +- struct proc_dir_entry *dp = PDE(inode); + struct seq_file *seq; +- struct nid_stat *tmp; + int rc; + +- if (LPROCFS_ENTRY_CHECK(dp)) +- return -ENOENT; +- +- tmp = dp->data; + rc = single_open(file, &lprocfs_mdt_open_files_seq_show, NULL); + if (rc != 0) + return rc; + + seq = file->private_data; +- seq->private = tmp; ++ seq->private = PDE_DATA(inode); + + return 0; + } +@@ -1140,3 +1051,67 @@ void mdt_stats_counter_init(struct lprocfs_stats *stats) lprocfs_counter_init(stats, LPROC_MDT_CROSSDIR_RENAME, 0, "crossdir_rename", "reqs"); } @@ -1479,5 +1549,5 @@ index 367f659..4fa66c3 100644 LUSTRE_MDS_NAME, &mds_device_type); } -- -1.8.5.1 +1.8.5.3 diff --git a/sys-cluster/lustre/files/0009-LU-3319-procfs-move-mdd-ofd-proc-handling-to-seq_fil.patch b/sys-cluster/lustre/files/0009-LU-3319-procfs-move-mdd-ofd-proc-handling-to-seq_fil.patch new file mode 100644 index 000000000..e2891347a --- /dev/null +++ b/sys-cluster/lustre/files/0009-LU-3319-procfs-move-mdd-ofd-proc-handling-to-seq_fil.patch @@ -0,0 +1,1928 @@ +From 075cf04c212e2bf0f38c94433a80bca2e5bb051e Mon Sep 17 00:00:00 2001 +From: James Simmons <uja.ornl@gmail.com> +Date: Fri, 31 Jan 2014 14:00:32 -0500 +Subject: [PATCH 09/13] LU-3319 procfs: move mdd/ofd proc handling to seq_files + +With 3.10 linux kernel and above proc handling now only +uses struct seq_files. This patch migrates the mdd/ofd +layer proc entries over to using seq_files. + +Signed-off-by: James Simmons <uja.ornl@gmail.com> +Change-Id: I61b7df6bfd5efd0f12e3ca1a1813b7b62d493168 +--- + lustre/include/lustre_lfsck.h | 6 +- + lustre/lfsck/lfsck_internal.h | 9 +- + lustre/lfsck/lfsck_layout.c | 66 ++---- + lustre/lfsck/lfsck_lib.c | 77 +++---- + lustre/lfsck/lfsck_namespace.c | 75 ++----- + lustre/mdd/mdd_device.c | 25 +-- + lustre/mdd/mdd_internal.h | 1 - + lustre/mdd/mdd_lproc.c | 293 ++++++++++++-------------- + lustre/obdclass/lprocfs_status.c | 9 +- + lustre/ofd/lproc_ofd.c | 436 ++++++++++++++++++++------------------- + lustre/ofd/ofd_dev.c | 48 ++--- + lustre/ofd/ofd_internal.h | 6 +- + lustre/osd-ldiskfs/osd_handler.c | 1 + + lustre/osd-zfs/osd_handler.c | 1 + + 14 files changed, 463 insertions(+), 590 deletions(-) + +diff --git a/lustre/include/lustre_lfsck.h b/lustre/include/lustre_lfsck.h +index 2e93420..0e578ac 100644 +--- a/lustre/include/lustre_lfsck.h ++++ b/lustre/include/lustre_lfsck.h +@@ -156,11 +156,11 @@ int lfsck_in_notify(const struct lu_env *env, struct dt_device *key, + int lfsck_query(const struct lu_env *env, struct dt_device *key, + struct lfsck_request *lr); + +-int lfsck_get_speed(struct dt_device *key, void *buf, int len); ++int lfsck_get_speed(struct seq_file *m, struct dt_device *key); + int lfsck_set_speed(struct dt_device *key, int val); +-int lfsck_get_windows(struct dt_device *key, void *buf, int len); ++int lfsck_get_windows(struct seq_file *m, struct dt_device *key); + int lfsck_set_windows(struct dt_device *key, int val); + +-int lfsck_dump(struct dt_device *key, void *buf, int len, enum lfsck_type type); ++int lfsck_dump(struct seq_file *m, struct dt_device *key, enum lfsck_type type); + + #endif /* _LUSTRE_LFSCK_H */ +diff --git a/lustre/lfsck/lfsck_internal.h b/lustre/lfsck/lfsck_internal.h +index 698fb5f..1893ccc 100644 +--- a/lustre/lfsck/lfsck_internal.h ++++ b/lustre/lfsck/lfsck_internal.h +@@ -288,8 +288,7 @@ struct lfsck_operations { + + int (*lfsck_dump)(const struct lu_env *env, + struct lfsck_component *com, +- char *buf, +- int len); ++ struct seq_file *m); + + int (*lfsck_double_scan)(const struct lu_env *env, + struct lfsck_component *com); +@@ -539,10 +538,10 @@ void lfsck_component_cleanup(const struct lu_env *env, + struct lfsck_component *com); + void lfsck_instance_cleanup(const struct lu_env *env, + struct lfsck_instance *lfsck); +-int lfsck_bits_dump(char **buf, int *len, int bits, const char *names[], ++int lfsck_bits_dump(struct seq_file *m, int bits, const char *names[], + const char *prefix); +-int lfsck_time_dump(char **buf, int *len, __u64 time, const char *prefix); +-int lfsck_pos_dump(char **buf, int *len, struct lfsck_position *pos, ++int lfsck_time_dump(struct seq_file *m, __u64 time, const char *prefix); ++int lfsck_pos_dump(struct seq_file *m, struct lfsck_position *pos, + const char *prefix); + void lfsck_pos_fill(const struct lu_env *env, struct lfsck_instance *lfsck, + struct lfsck_position *pos, bool init); +diff --git a/lustre/lfsck/lfsck_layout.c b/lustre/lfsck/lfsck_layout.c +index e7c12d2..8b9c43e 100644 +--- a/lustre/lfsck/lfsck_layout.c ++++ b/lustre/lfsck/lfsck_layout.c +@@ -2024,69 +2024,53 @@ static int lfsck_layout_slave_post(const struct lu_env *env, + } + + static int lfsck_layout_dump(const struct lu_env *env, +- struct lfsck_component *com, char *buf, int len) ++ struct lfsck_component *com, struct seq_file *m) + { + struct lfsck_instance *lfsck = com->lc_lfsck; + struct lfsck_bookmark *bk = &lfsck->li_bookmark_ram; + struct lfsck_layout *lo = com->lc_file_ram; +- int save = len; +- int ret = -ENOSPC; + int rc; + + down_read(&com->lc_sem); +- rc = snprintf(buf, len, +- "name: lfsck_layout\n" ++ seq_printf(m, "name: lfsck_layout\n" + "magic: %#x\n" + "version: %d\n" + "status: %s\n", + lo->ll_magic, + bk->lb_version, + lfsck_status2names(lo->ll_status)); +- if (rc <= 0) +- goto out; + +- buf += rc; +- len -= rc; +- rc = lfsck_bits_dump(&buf, &len, lo->ll_flags, lfsck_flags_names, +- "flags"); ++ rc = lfsck_bits_dump(m, lo->ll_flags, lfsck_flags_names, "flags"); + if (rc < 0) + goto out; + +- rc = lfsck_bits_dump(&buf, &len, bk->lb_param, lfsck_param_names, +- "param"); ++ rc = lfsck_bits_dump(m, bk->lb_param, lfsck_param_names, "param"); + if (rc < 0) + goto out; + +- rc = lfsck_time_dump(&buf, &len, lo->ll_time_last_complete, ++ rc = lfsck_time_dump(m, lo->ll_time_last_complete, + "time_since_last_completed"); + if (rc < 0) + goto out; + +- rc = lfsck_time_dump(&buf, &len, lo->ll_time_latest_start, ++ rc = lfsck_time_dump(m, lo->ll_time_latest_start, + "time_since_latest_start"); + if (rc < 0) + goto out; + +- rc = lfsck_time_dump(&buf, &len, lo->ll_time_last_checkpoint, ++ rc = lfsck_time_dump(m, lo->ll_time_last_checkpoint, + "time_since_last_checkpoint"); + if (rc < 0) + goto out; + +- rc = snprintf(buf, len, +- "latest_start_position: "LPU64"\n" ++ seq_printf(m, "latest_start_position: "LPU64"\n" + "last_checkpoint_position: "LPU64"\n" + "first_failure_position: "LPU64"\n", + lo->ll_pos_latest_start, + lo->ll_pos_last_checkpoint, + lo->ll_pos_first_inconsistent); +- if (rc <= 0) +- goto out; +- +- buf += rc; +- len -= rc; + +- rc = snprintf(buf, len, +- "success_count: %u\n" ++ seq_printf(m, "success_count: %u\n" + "repaired_dangling: "LPU64"\n" + "repaired_unmatched_pair: "LPU64"\n" + "repaired_multiple_referenced: "LPU64"\n" +@@ -2106,11 +2090,6 @@ static int lfsck_layout_dump(const struct lu_env *env, + lo->ll_objs_skipped, + lo->ll_objs_failed_phase1, + lo->ll_objs_failed_phase2); +- if (rc <= 0) +- goto out; +- +- buf += rc; +- len -= rc; + + if (lo->ll_status == LS_SCANNING_PHASE1) { + __u64 pos; +@@ -2127,8 +2106,7 @@ static int lfsck_layout_dump(const struct lu_env *env, + do_div(new_checked, duration); + if (rtime != 0) + do_div(speed, rtime); +- rc = snprintf(buf, len, +- "checked_phase1: "LPU64"\n" ++ seq_printf(m, "checked_phase1: "LPU64"\n" + "checked_phase2: "LPU64"\n" + "run_time_phase1: %u seconds\n" + "run_time_phase2: %u seconds\n" +@@ -2142,11 +2120,6 @@ static int lfsck_layout_dump(const struct lu_env *env, + lo->ll_run_time_phase2, + speed, + new_checked); +- if (rc <= 0) +- goto out; +- +- buf += rc; +- len -= rc; + + LASSERT(lfsck->li_di_oit != NULL); + +@@ -2159,12 +2132,7 @@ static int lfsck_layout_dump(const struct lu_env *env, + pos = iops->store(env, lfsck->li_di_oit); + if (!lfsck->li_current_oit_processed) + pos--; +- rc = snprintf(buf, len, "current_position: "LPU64"\n", pos); +- if (rc <= 0) +- goto out; +- +- buf += rc; +- len -= rc; ++ seq_printf(m, "current_position: "LPU64"\n", pos); + } else { + /* XXX: LS_SCANNING_PHASE2 will be handled in the future. */ + __u64 speed1 = lo->ll_objs_checked_phase1; +@@ -2174,8 +2142,7 @@ static int lfsck_layout_dump(const struct lu_env *env, + do_div(speed1, lo->ll_run_time_phase1); + if (lo->ll_run_time_phase2 != 0) + do_div(speed2, lo->ll_run_time_phase2); +- rc = snprintf(buf, len, +- "checked_phase1: "LPU64"\n" ++ seq_printf(m, "checked_phase1: "LPU64"\n" + "checked_phase2: "LPU64"\n" + "run_time_phase1: %u seconds\n" + "run_time_phase2: %u seconds\n" +@@ -2190,18 +2157,11 @@ static int lfsck_layout_dump(const struct lu_env *env, + lo->ll_run_time_phase2, + speed1, + speed2); +- if (rc <= 0) +- goto out; +- +- buf += rc; +- len -= rc; + } +- ret = save - len; +- + out: + up_read(&com->lc_sem); + +- return ret; ++ return rc; + } + + static int lfsck_layout_master_double_scan(const struct lu_env *env, +diff --git a/lustre/lfsck/lfsck_lib.c b/lustre/lfsck/lfsck_lib.c +index ad92e32..747e376 100644 +--- a/lustre/lfsck/lfsck_lib.c ++++ b/lustre/lfsck/lfsck_lib.c +@@ -424,77 +424,52 @@ static inline int lfsck_instance_add(struct lfsck_instance *lfsck) + return 0; + } + +-int lfsck_bits_dump(char **buf, int *len, int bits, const char *names[], ++int lfsck_bits_dump(struct seq_file *m, int bits, const char *names[], + const char *prefix) + { +- int save = *len; + int flag; +- int rc; + int i; + +- rc = snprintf(*buf, *len, "%s:%c", prefix, bits != 0 ? ' ' : '\n'); +- if (rc <= 0) +- return -ENOSPC; ++ seq_printf(m, "%s:%c", prefix, bits != 0 ? ' ' : '\n'); + +- *buf += rc; +- *len -= rc; + for (i = 0, flag = 1; bits != 0; i++, flag = 1 << i) { + if (flag & bits) { + bits &= ~flag; + if (names[i] != NULL) { +- rc = snprintf(*buf, *len, "%s%c", names[i], +- bits != 0 ? ',' : '\n'); +- if (rc <= 0) +- return -ENOSPC; +- +- *buf += rc; +- *len -= rc; ++ seq_printf(m, "%s%c", names[i], ++ bits != 0 ? ',' : '\n'); + } + } + } +- return save - *len; ++ return 0; + } + +-int lfsck_time_dump(char **buf, int *len, __u64 time, const char *prefix) ++int lfsck_time_dump(struct seq_file *m, __u64 time, const char *prefix) + { +- int rc; +- + if (time != 0) +- rc = snprintf(*buf, *len, "%s: "LPU64" seconds\n", prefix, +- cfs_time_current_sec() - time); ++ seq_printf(m, "%s: "LPU64" seconds\n", prefix, ++ cfs_time_current_sec() - time); + else +- rc = snprintf(*buf, *len, "%s: N/A\n", prefix); +- if (rc <= 0) +- return -ENOSPC; +- +- *buf += rc; +- *len -= rc; +- return rc; ++ seq_printf(m, "%s: N/A\n", prefix); ++ return 0; + } + +-int lfsck_pos_dump(char **buf, int *len, struct lfsck_position *pos, ++int lfsck_pos_dump(struct seq_file *m, struct lfsck_position *pos, + const char *prefix) + { +- int rc; +- + if (fid_is_zero(&pos->lp_dir_parent)) { + if (pos->lp_oit_cookie == 0) +- rc = snprintf(*buf, *len, "%s: N/A, N/A, N/A\n", +- prefix); ++ seq_printf(m, "%s: N/A, N/A, N/A\n", ++ prefix); + else +- rc = snprintf(*buf, *len, "%s: "LPU64", N/A, N/A\n", +- prefix, pos->lp_oit_cookie); ++ seq_printf(m, "%s: "LPU64", N/A, N/A\n", ++ prefix, pos->lp_oit_cookie); + } else { +- rc = snprintf(*buf, *len, "%s: "LPU64", "DFID", "LPU64"\n", +- prefix, pos->lp_oit_cookie, +- PFID(&pos->lp_dir_parent), pos->lp_dir_cookie); ++ seq_printf(m, "%s: "LPU64", "DFID", "LPU64"\n", ++ prefix, pos->lp_oit_cookie, ++ PFID(&pos->lp_dir_parent), pos->lp_dir_cookie); + } +- if (rc <= 0) +- return -ENOSPC; +- +- *buf += rc; +- *len -= rc; +- return rc; ++ return 0; + } + + void lfsck_pos_fill(const struct lu_env *env, struct lfsck_instance *lfsck, +@@ -1102,7 +1077,7 @@ int lfsck_async_request(const struct lu_env *env, struct obd_export *exp, + + /* external interfaces */ + +-int lfsck_get_speed(struct dt_device *key, void *buf, int len) ++int lfsck_get_speed(struct seq_file *m, struct dt_device *key) + { + struct lu_env env; + struct lfsck_instance *lfsck; +@@ -1115,8 +1090,7 @@ int lfsck_get_speed(struct dt_device *key, void *buf, int len) + + lfsck = lfsck_instance_find(key, true, false); + if (likely(lfsck != NULL)) { +- rc = snprintf(buf, len, "%u\n", +- lfsck->li_bookmark_ram.lb_speed_limit); ++ seq_printf(m, "%u\n", lfsck->li_bookmark_ram.lb_speed_limit); + lfsck_instance_put(&env, lfsck); + } else { + rc = -ENODEV; +@@ -1156,7 +1130,7 @@ int lfsck_set_speed(struct dt_device *key, int val) + } + EXPORT_SYMBOL(lfsck_set_speed); + +-int lfsck_get_windows(struct dt_device *key, void *buf, int len) ++int lfsck_get_windows(struct seq_file *m, struct dt_device *key) + { + struct lu_env env; + struct lfsck_instance *lfsck; +@@ -1169,8 +1143,7 @@ int lfsck_get_windows(struct dt_device *key, void *buf, int len) + + lfsck = lfsck_instance_find(key, true, false); + if (likely(lfsck != NULL)) { +- rc = snprintf(buf, len, "%u\n", +- lfsck->li_bookmark_ram.lb_async_windows); ++ seq_printf(m, "%u\n", lfsck->li_bookmark_ram.lb_async_windows); + lfsck_instance_put(&env, lfsck); + } else { + rc = -ENODEV; +@@ -1220,7 +1193,7 @@ int lfsck_set_windows(struct dt_device *key, int val) + } + EXPORT_SYMBOL(lfsck_set_windows); + +-int lfsck_dump(struct dt_device *key, void *buf, int len, enum lfsck_type type) ++int lfsck_dump(struct seq_file *m, struct dt_device *key, enum lfsck_type type) + { + struct lu_env env; + struct lfsck_instance *lfsck; +@@ -1236,7 +1209,7 @@ int lfsck_dump(struct dt_device *key, void *buf, int len, enum lfsck_type type) + if (likely(lfsck != NULL)) { + com = lfsck_component_find(lfsck, type); + if (likely(com != NULL)) { +- rc = com->lc_ops->lfsck_dump(&env, com, buf, len); ++ rc = com->lc_ops->lfsck_dump(&env, com, m); + lfsck_component_put(&env, com); + } else { + rc = -ENOTSUPP; +diff --git a/lustre/lfsck/lfsck_namespace.c b/lustre/lfsck/lfsck_namespace.c +index 6fc08fb..2abad67 100644 +--- a/lustre/lfsck/lfsck_namespace.c ++++ b/lustre/lfsck/lfsck_namespace.c +@@ -1088,65 +1088,56 @@ static int lfsck_namespace_post(const struct lu_env *env, + + static int + lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com, +- char *buf, int len) ++ struct seq_file *m) + { + struct lfsck_instance *lfsck = com->lc_lfsck; + struct lfsck_bookmark *bk = &lfsck->li_bookmark_ram; + struct lfsck_namespace *ns = com->lc_file_ram; +- int save = len; +- int ret = -ENOSPC; + int rc; + + down_read(&com->lc_sem); +- rc = snprintf(buf, len, +- "name: lfsck_namespace\n" +- "magic: %#x\n" +- "version: %d\n" +- "status: %s\n", +- ns->ln_magic, +- bk->lb_version, +- lfsck_status2names(ns->ln_status)); +- if (rc <= 0) +- goto out; +- +- buf += rc; +- len -= rc; +- rc = lfsck_bits_dump(&buf, &len, ns->ln_flags, lfsck_flags_names, +- "flags"); ++ seq_printf(m, "name: lfsck_namespace\n" ++ "magic: %#x\n" ++ "version: %d\n" ++ "status: %s\n", ++ ns->ln_magic, ++ bk->lb_version, ++ lfsck_status2names(ns->ln_status)); ++ ++ rc = lfsck_bits_dump(m, ns->ln_flags, lfsck_flags_names, "flags"); + if (rc < 0) + goto out; + +- rc = lfsck_bits_dump(&buf, &len, bk->lb_param, lfsck_param_names, +- "param"); ++ rc = lfsck_bits_dump(m, bk->lb_param, lfsck_param_names, "param"); + if (rc < 0) + goto out; + +- rc = lfsck_time_dump(&buf, &len, ns->ln_time_last_complete, ++ rc = lfsck_time_dump(m, ns->ln_time_last_complete, + "time_since_last_completed"); + if (rc < 0) + goto out; + +- rc = lfsck_time_dump(&buf, &len, ns->ln_time_latest_start, ++ rc = lfsck_time_dump(m, ns->ln_time_latest_start, + "time_since_latest_start"); + if (rc < 0) + goto out; + +- rc = lfsck_time_dump(&buf, &len, ns->ln_time_last_checkpoint, ++ rc = lfsck_time_dump(m, ns->ln_time_last_checkpoint, + "time_since_last_checkpoint"); + if (rc < 0) + goto out; + +- rc = lfsck_pos_dump(&buf, &len, &ns->ln_pos_latest_start, ++ rc = lfsck_pos_dump(m, &ns->ln_pos_latest_start, + "latest_start_position"); + if (rc < 0) + goto out; + +- rc = lfsck_pos_dump(&buf, &len, &ns->ln_pos_last_checkpoint, ++ rc = lfsck_pos_dump(m, &ns->ln_pos_last_checkpoint, + "last_checkpoint_position"); + if (rc < 0) + goto out; + +- rc = lfsck_pos_dump(&buf, &len, &ns->ln_pos_first_inconsistent, ++ rc = lfsck_pos_dump(m, &ns->ln_pos_first_inconsistent, + "first_failure_position"); + if (rc < 0) + goto out; +@@ -1166,8 +1157,7 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com, + do_div(new_checked, duration); + if (rtime != 0) + do_div(speed, rtime); +- rc = snprintf(buf, len, +- "checked_phase1: "LPU64"\n" ++ seq_printf(m, "checked_phase1: "LPU64"\n" + "checked_phase2: "LPU64"\n" + "updated_phase1: "LPU64"\n" + "updated_phase2: "LPU64"\n" +@@ -1199,11 +1189,6 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com, + ns->ln_run_time_phase2, + speed, + new_checked); +- if (rc <= 0) +- goto out; +- +- buf += rc; +- len -= rc; + + LASSERT(lfsck->li_di_oit != NULL); + +@@ -1232,9 +1217,7 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com, + pos.lp_dir_cookie = 0; + } + spin_unlock(&lfsck->li_lock); +- rc = lfsck_pos_dump(&buf, &len, &pos, "current_position"); +- if (rc <= 0) +- goto out; ++ lfsck_pos_dump(m, &pos, "current_position"); + } else if (ns->ln_status == LS_SCANNING_PHASE2) { + cfs_duration_t duration = cfs_time_current() - + lfsck->li_time_last_checkpoint; +@@ -1252,8 +1235,7 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com, + do_div(speed1, ns->ln_run_time_phase1); + if (rtime != 0) + do_div(speed2, rtime); +- rc = snprintf(buf, len, +- "checked_phase1: "LPU64"\n" ++ seq_printf(m, "checked_phase1: "LPU64"\n" + "checked_phase2: "LPU64"\n" + "updated_phase1: "LPU64"\n" + "updated_phase2: "LPU64"\n" +@@ -1288,11 +1270,6 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com, + speed2, + new_checked, + PFID(&ns->ln_fid_latest_scanned_phase2)); +- if (rc <= 0) +- goto out; +- +- buf += rc; +- len -= rc; + } else { + __u64 speed1 = ns->ln_items_checked; + __u64 speed2 = ns->ln_objs_checked_phase2; +@@ -1301,8 +1278,7 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com, + do_div(speed1, ns->ln_run_time_phase1); + if (ns->ln_run_time_phase2 != 0) + do_div(speed2, ns->ln_run_time_phase2); +- rc = snprintf(buf, len, +- "checked_phase1: "LPU64"\n" ++ seq_printf(m, "checked_phase1: "LPU64"\n" + "checked_phase2: "LPU64"\n" + "updated_phase1: "LPU64"\n" + "updated_phase2: "LPU64"\n" +@@ -1335,17 +1311,10 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com, + ns->ln_run_time_phase2, + speed1, + speed2); +- if (rc <= 0) +- goto out; +- +- buf += rc; +- len -= rc; + } +- ret = save - len; +- + out: + up_read(&com->lc_sem); +- return ret; ++ return 0; + } + + static int lfsck_namespace_double_scan_main(void *args) +diff --git a/lustre/mdd/mdd_device.c b/lustre/mdd/mdd_device.c +index 40a4ee3..b0acecb 100644 +--- a/lustre/mdd/mdd_device.c ++++ b/lustre/mdd/mdd_device.c +@@ -812,16 +812,16 @@ static int mdd_process_config(const struct lu_env *env, + ENTRY; + + switch (cfg->lcfg_command) { +- case LCFG_PARAM: { +- struct lprocfs_static_vars lvars; +- +- lprocfs_mdd_init_vars(&lvars); +- rc = class_process_proc_param(PARAM_MDD, lvars.obd_vars, cfg,m); +- if (rc > 0 || rc == -ENOSYS) +- /* we don't understand; pass it on */ +- rc = next->ld_ops->ldo_process_config(env, next, cfg); +- break; +- } ++ case LCFG_PARAM: { ++ struct obd_device *obd = mdd2obd_dev(m); ++ ++ rc = class_process_proc_seq_param(PARAM_MDD, obd->obd_vars, ++ cfg, m); ++ if (rc > 0 || rc == -ENOSYS) ++ /* we don't understand; pass it on */ ++ rc = next->ld_ops->ldo_process_config(env, next, cfg); ++ break; ++ } + case LCFG_SETUP: + rc = next->ld_ops->ldo_process_config(env, next, cfg); + if (rc) +@@ -1497,11 +1497,8 @@ LU_CONTEXT_KEY_DEFINE(mdd, LCT_MD_THREAD); + + static int __init mdd_mod_init(void) + { +- struct lprocfs_static_vars lvars; + int rc; + +- lprocfs_mdd_init_vars(&lvars); +- + rc = lu_kmem_init(mdd_caches); + if (rc) + return rc; +@@ -1517,7 +1514,7 @@ static int __init mdd_mod_init(void) + + rc = class_register_type(&mdd_obd_device_ops, NULL, NULL, + #ifndef HAVE_ONLY_PROCFS_SEQ +- lvars.module_vars, ++ NULL, + #endif + LUSTRE_MDD_NAME, &mdd_device_type); + if (rc) +diff --git a/lustre/mdd/mdd_internal.h b/lustre/mdd/mdd_internal.h +index daa1dcb..5332b2c 100644 +--- a/lustre/mdd/mdd_internal.h ++++ b/lustre/mdd/mdd_internal.h +@@ -340,7 +340,6 @@ int orph_declare_index_delete(const struct lu_env *, struct mdd_object *, + struct thandle *); + + /* mdd_lproc.c */ +-void lprocfs_mdd_init_vars(struct lprocfs_static_vars *lvars); + int mdd_procfs_init(struct mdd_device *mdd, const char *name); + int mdd_procfs_fini(struct mdd_device *mdd); + +diff --git a/lustre/mdd/mdd_lproc.c b/lustre/mdd/mdd_lproc.c +index 2573e33..e20324c 100644 +--- a/lustre/mdd/mdd_lproc.c ++++ b/lustre/mdd/mdd_lproc.c +@@ -49,56 +49,14 @@ + #include <libcfs/libcfs_string.h> + #include "mdd_internal.h" + +-int mdd_procfs_init(struct mdd_device *mdd, const char *name) ++static ssize_t ++mdd_atime_diff_seq_write(struct file *file, const char *buffer, ++ size_t count, loff_t *off) + { +- struct lprocfs_static_vars lvars; +- struct obd_type *type; +- int rc; +- ENTRY; +- +- /* at the moment there is no linkage between lu_type +- * and obd_type, so we lookup obd_type this way */ +- type = class_search_type(LUSTRE_MDD_NAME); +- +- LASSERT(name != NULL); +- LASSERT(type != NULL); +- +- /* Find the type procroot and add the proc entry for this device */ +- lprocfs_mdd_init_vars(&lvars); +- mdd->mdd_proc_entry = lprocfs_register(name, type->typ_procroot, +- lvars.obd_vars, mdd); +- if (IS_ERR(mdd->mdd_proc_entry)) { +- rc = PTR_ERR(mdd->mdd_proc_entry); +- CERROR("Error %d setting up lprocfs for %s\n", +- rc, name); +- mdd->mdd_proc_entry = NULL; +- GOTO(out, rc); +- } +- +- rc = 0; +- +- EXIT; +-out: +- if (rc) +- mdd_procfs_fini(mdd); +- return rc; +-} +- +-int mdd_procfs_fini(struct mdd_device *mdd) +-{ +- if (mdd->mdd_proc_entry) { +- lprocfs_remove(&mdd->mdd_proc_entry); +- mdd->mdd_proc_entry = NULL; +- } +- RETURN(0); +-} +- +-static int lprocfs_wr_atime_diff(struct file *file, const char *buffer, +- unsigned long count, void *data) +-{ +- struct mdd_device *mdd = data; +- char kernbuf[20], *end; +- unsigned long diff = 0; ++ struct seq_file *m = file->private_data; ++ struct mdd_device *mdd = m->private; ++ char kernbuf[20], *end; ++ unsigned long diff = 0; + + if (count > (sizeof(kernbuf) - 1)) + return -EINVAL; +@@ -116,37 +74,35 @@ static int lprocfs_wr_atime_diff(struct file *file, const char *buffer, + return count; + } + +-static int lprocfs_rd_atime_diff(char *page, char **start, off_t off, +- int count, int *eof, void *data) ++static int mdd_atime_diff_seq_show(struct seq_file *m, void *data) + { +- struct mdd_device *mdd = data; ++ struct mdd_device *mdd = m->private; + +- *eof = 1; +- return snprintf(page, count, "%lu\n", mdd->mdd_atime_diff); ++ return seq_printf(m, "%lu\n", mdd->mdd_atime_diff); + } +- ++LPROC_SEQ_FOPS(mdd_atime_diff); + + /**** changelogs ****/ +-static int lprocfs_rd_changelog_mask(char *page, char **start, off_t off, +- int count, int *eof, void *data) ++static int mdd_changelog_mask_seq_show(struct seq_file *m, void *data) + { +- struct mdd_device *mdd = data; +- int i = 0, rc = 0; +- +- *eof = 1; +- while (i < CL_LAST) { +- if (mdd->mdd_cl.mc_mask & (1 << i)) +- rc += snprintf(page + rc, count - rc, "%s ", +- changelog_type2str(i)); +- i++; +- } +- return rc; ++ struct mdd_device *mdd = m->private; ++ int i = 0; ++ ++ while (i < CL_LAST) { ++ if (mdd->mdd_cl.mc_mask & (1 << i)) ++ seq_printf(m, "%s ", changelog_type2str(i)); ++ i++; ++ } ++ seq_printf(m, "\n"); ++ return 0; + } + +-static int lprocfs_wr_changelog_mask(struct file *file, const char *buffer, +- unsigned long count, void *data) ++static ssize_t ++mdd_changelog_mask_seq_write(struct file *file, const char *buffer, ++ size_t count, loff_t *off) + { +- struct mdd_device *mdd = data; ++ struct seq_file *m = file->private_data; ++ struct mdd_device *mdd = m->private; + char *kernbuf; + int rc; + ENTRY; +@@ -168,45 +124,32 @@ out: + OBD_FREE(kernbuf, PAGE_CACHE_SIZE); + return rc; + } +- +-struct cucb_data { +- char *page; +- int count; +- int idx; +-}; ++LPROC_SEQ_FOPS(mdd_changelog_mask); + + static int lprocfs_changelog_users_cb(const struct lu_env *env, + struct llog_handle *llh, + struct llog_rec_hdr *hdr, void *data) + { +- struct llog_changelog_user_rec *rec; +- struct cucb_data *cucb = (struct cucb_data *)data; +- +- LASSERT(llh->lgh_hdr->llh_flags & LLOG_F_IS_PLAIN); ++ struct llog_changelog_user_rec *rec; ++ struct seq_file *m = data; + +- rec = (struct llog_changelog_user_rec *)hdr; ++ LASSERT(llh->lgh_hdr->llh_flags & LLOG_F_IS_PLAIN); + +- cucb->idx += snprintf(cucb->page + cucb->idx, cucb->count - cucb->idx, +- CHANGELOG_USER_PREFIX"%-3d "LPU64"\n", +- rec->cur_id, rec->cur_endrec); +- if (cucb->idx >= cucb->count) +- return -ENOSPC; ++ rec = (struct llog_changelog_user_rec *)hdr; + +- return 0; ++ seq_printf(m, CHANGELOG_USER_PREFIX"%-3d "LPU64"\n", ++ rec->cur_id, rec->cur_endrec); ++ return 0; + } + +-static int lprocfs_rd_changelog_users(char *page, char **start, off_t off, +- int count, int *eof, void *data) ++static int mdd_changelog_users_seq_show(struct seq_file *m, void *data) + { + struct lu_env env; +- struct mdd_device *mdd = data; ++ struct mdd_device *mdd = m->private; + struct llog_ctxt *ctxt; +- struct cucb_data cucb; + __u64 cur; + int rc; + +- *eof = 1; +- + ctxt = llog_get_context(mdd2obd_dev(mdd), + LLOG_CHANGELOG_USER_ORIG_CTXT); + if (ctxt == NULL) +@@ -223,37 +166,32 @@ static int lprocfs_rd_changelog_users(char *page, char **start, off_t off, + cur = mdd->mdd_cl.mc_index; + spin_unlock(&mdd->mdd_cl.mc_lock); + +- cucb.count = count; +- cucb.page = page; +- cucb.idx = 0; +- +- cucb.idx += snprintf(cucb.page + cucb.idx, cucb.count - cucb.idx, +- "current index: "LPU64"\n", cur); +- +- cucb.idx += snprintf(cucb.page + cucb.idx, cucb.count - cucb.idx, +- "%-5s %s\n", "ID", "index"); ++ seq_printf(m, "current index: "LPU64"\n", cur); ++ seq_printf(m, "%-5s %s\n", "ID", "index"); + + llog_cat_process(&env, ctxt->loc_handle, lprocfs_changelog_users_cb, +- &cucb, 0, 0); ++ &m, 0, 0); + + lu_env_fini(&env); + llog_ctxt_put(ctxt); +- return cucb.idx; ++ return 0; + } ++LPROC_SEQ_FOPS_RO(mdd_changelog_users); + +-static int lprocfs_rd_sync_perm(char *page, char **start, off_t off, +- int count, int *eof, void *data) ++static int mdd_sync_perm_seq_show(struct seq_file *m, void *data) + { +- struct mdd_device *mdd = data; ++ struct mdd_device *mdd = m->private; + +- LASSERT(mdd != NULL); +- return snprintf(page, count, "%d\n", mdd->mdd_sync_permission); ++ LASSERT(mdd != NULL); ++ return seq_printf(m, "%d\n", mdd->mdd_sync_permission); + } + +-static int lprocfs_wr_sync_perm(struct file *file, const char *buffer, +- unsigned long count, void *data) ++static ssize_t ++mdd_sync_perm_seq_write(struct file *file, const char *buffer, ++ size_t count, loff_t *off) + { +- struct mdd_device *mdd = data; ++ struct seq_file *m = file->private_data; ++ struct mdd_device *mdd = m->private; + int val, rc; + + LASSERT(mdd != NULL); +@@ -264,24 +202,22 @@ static int lprocfs_wr_sync_perm(struct file *file, const char *buffer, + mdd->mdd_sync_permission = !!val; + return count; + } ++LPROC_SEQ_FOPS(mdd_sync_perm); + +-static int lprocfs_rd_lfsck_speed_limit(char *page, char **start, off_t off, +- int count, int *eof, void *data) ++static int mdd_lfsck_speed_limit_seq_show(struct seq_file *m, void *data) + { +- struct mdd_device *mdd = data; +- int rc; ++ struct mdd_device *mdd = m->private; + + LASSERT(mdd != NULL); +- *eof = 1; +- +- rc = lfsck_get_speed(mdd->mdd_bottom, page, count); +- return rc != 0 ? rc : count; ++ return lfsck_get_speed(m, mdd->mdd_bottom); + } + +-static int lprocfs_wr_lfsck_speed_limit(struct file *file, const char *buffer, +- unsigned long count, void *data) ++static ssize_t ++mdd_lfsck_speed_limit_seq_write(struct file *file, const char *buffer, ++ size_t count, loff_t *off) + { +- struct mdd_device *mdd = data; ++ struct seq_file *m = file->private_data; ++ struct mdd_device *mdd = m->private; + __u32 val; + int rc; + +@@ -293,25 +229,22 @@ static int lprocfs_wr_lfsck_speed_limit(struct file *file, const char *buffer, + rc = lfsck_set_speed(mdd->mdd_bottom, val); + return rc != 0 ? rc : count; + } ++LPROC_SEQ_FOPS(mdd_lfsck_speed_limit); + +-static int lprocfs_rd_lfsck_async_windows(char *page, char **start, off_t off, +- int count, int *eof, void *data) ++static int mdd_lfsck_async_windows_seq_show(struct seq_file *m, void *data) + { +- struct mdd_device *mdd = data; +- int rc; ++ struct mdd_device *mdd = m->private; + + LASSERT(mdd != NULL); +- *eof = 1; +- +- rc = lfsck_get_windows(mdd->mdd_bottom, page, count); +- +- return rc != 0 ? rc : count; ++ return lfsck_get_windows(m, mdd->mdd_bottom); + } + +-static int lprocfs_wr_lfsck_async_windows(struct file *file, const char *buffer, +- unsigned long count, void *data) ++static ssize_t ++mdd_lfsck_async_windows_seq_write(struct file *file, const char *buffer, ++ size_t count, loff_t *off) + { +- struct mdd_device *mdd = data; ++ struct seq_file *m = file->private_data; ++ struct mdd_device *mdd = m->private; + __u32 val; + int rc; + +@@ -322,42 +255,76 @@ static int lprocfs_wr_lfsck_async_windows(struct file *file, const char *buffer, + + return rc != 0 ? rc : count; + } ++LPROC_SEQ_FOPS(mdd_lfsck_async_windows); + +-static int lprocfs_rd_lfsck_namespace(char *page, char **start, off_t off, +- int count, int *eof, void *data) ++static int mdd_lfsck_namespace_seq_show(struct seq_file *m, void *data) + { +- struct mdd_device *mdd = data; +- int rc; ++ struct mdd_device *mdd = m->private; + + LASSERT(mdd != NULL); +- *eof = 1; + +- rc = lfsck_dump(mdd->mdd_bottom, page, count, LT_NAMESPACE); +- return rc; ++ return lfsck_dump(m, mdd->mdd_bottom, LT_NAMESPACE); + } +- +-static struct lprocfs_vars lprocfs_mdd_obd_vars[] = { +- { "atime_diff", lprocfs_rd_atime_diff, lprocfs_wr_atime_diff, 0 }, +- { "changelog_mask", lprocfs_rd_changelog_mask, +- lprocfs_wr_changelog_mask, 0 }, +- { "changelog_users", lprocfs_rd_changelog_users, 0, 0}, +- { "sync_permission", lprocfs_rd_sync_perm, lprocfs_wr_sync_perm, 0 }, +- { "lfsck_speed_limit", lprocfs_rd_lfsck_speed_limit, +- lprocfs_wr_lfsck_speed_limit, 0 }, +- { "lfsck_async_windows", lprocfs_rd_lfsck_async_windows, +- lprocfs_wr_lfsck_async_windows, 0 }, +- { "lfsck_namespace", lprocfs_rd_lfsck_namespace, 0, 0 }, ++LPROC_SEQ_FOPS_RO(mdd_lfsck_namespace); ++ ++static struct lprocfs_seq_vars lprocfs_mdd_obd_vars[] = { ++ { .name = "atime_diff", ++ .fops = &mdd_atime_diff_fops }, ++ { .name = "changelog_mask", ++ .fops = &mdd_changelog_mask_fops }, ++ { .name = "changelog_users", ++ .fops = &mdd_changelog_users_fops }, ++ { .name = "sync_permission", ++ .fops = &mdd_sync_perm_fops }, ++ { .name = "lfsck_speed_limit", ++ .fops = &mdd_lfsck_speed_limit_fops }, ++ { .name = "lfsck_async_windows", ++ .fops = &mdd_lfsck_async_windows_fops }, ++ { .name = "lfsck_namespace", ++ .fops = &mdd_lfsck_namespace_fops }, + { 0 } + }; + +-static struct lprocfs_vars lprocfs_mdd_module_vars[] = { +- { "num_refs", lprocfs_rd_numrefs, 0, 0 }, +- { 0 } +-}; +- +-void lprocfs_mdd_init_vars(struct lprocfs_static_vars *lvars) ++int mdd_procfs_init(struct mdd_device *mdd, const char *name) + { +- lvars->module_vars = lprocfs_mdd_module_vars; +- lvars->obd_vars = lprocfs_mdd_obd_vars; ++ struct obd_device *obd = class_name2obd(name); ++ struct obd_type *type; ++ int rc; ++ ENTRY; ++ ++ /* at the moment there is no linkage between lu_type ++ * and obd_type, so we lookup obd_type this way */ ++ type = class_search_type(LUSTRE_MDD_NAME); ++ ++ LASSERT(name != NULL); ++ LASSERT(type != NULL); ++ LASSERT(obd != NULL); ++ ++ /* Find the type procroot and add the proc entry for this device */ ++ obd->obd_vars = lprocfs_mdd_obd_vars; ++ mdd->mdd_proc_entry = lprocfs_seq_register(name, type->typ_procroot, ++ obd->obd_vars, mdd); ++ if (IS_ERR(mdd->mdd_proc_entry)) { ++ rc = PTR_ERR(mdd->mdd_proc_entry); ++ CERROR("Error %d setting up lprocfs for %s\n", ++ rc, name); ++ mdd->mdd_proc_entry = NULL; ++ GOTO(out, rc); ++ } ++ rc = 0; ++ ++ EXIT; ++out: ++ if (rc) ++ mdd_procfs_fini(mdd); ++ return rc; + } + ++int mdd_procfs_fini(struct mdd_device *mdd) ++{ ++ if (mdd->mdd_proc_entry) { ++ lprocfs_remove(&mdd->mdd_proc_entry); ++ mdd->mdd_proc_entry = NULL; ++ } ++ RETURN(0); ++} +diff --git a/lustre/obdclass/lprocfs_status.c b/lustre/obdclass/lprocfs_status.c +index 63d01cc..abe5d71 100644 +--- a/lustre/obdclass/lprocfs_status.c ++++ b/lustre/obdclass/lprocfs_status.c +@@ -388,11 +388,10 @@ EXPORT_SYMBOL(lprocfs_evict_client_seq_write); + #undef BUFLEN + + struct file_operations lprocfs_evict_client_fops = { +- .owner = THIS_MODULE, +- .read = lprocfs_fops_read, +- .write = lprocfs_fops_write, +- .open = lprocfs_evict_client_open, +- .release = lprocfs_evict_client_release, ++ .owner = THIS_MODULE, ++ .open = lprocfs_evict_client_open, ++ .release = lprocfs_evict_client_release, ++ .write = lprocfs_evict_client_seq_write, + }; + EXPORT_SYMBOL(lprocfs_evict_client_fops); + #endif +diff --git a/lustre/ofd/lproc_ofd.c b/lustre/ofd/lproc_ofd.c +index e303fd6..1759a7d 100644 +--- a/lustre/ofd/lproc_ofd.c ++++ b/lustre/ofd/lproc_ofd.c +@@ -47,80 +47,75 @@ + + #ifdef LPROCFS + +-static int lprocfs_ofd_rd_seqs(char *page, char **start, off_t off, +- int count, int *eof, void *data) ++static int ofd_seqs_seq_show(struct seq_file *m, void *data) + { +- struct obd_device *obd = (struct obd_device *)data; ++ struct obd_device *obd = m->private; + struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); + +- *eof = 1; +- return snprintf(page, count, "%u\n", ofd->ofd_seq_count); ++ return seq_printf(m, "%u\n", ofd->ofd_seq_count); + } ++LPROC_SEQ_FOPS_RO(ofd_seqs); + +-static int lprocfs_ofd_rd_tot_dirty(char *page, char **start, off_t off, +- int count, int *eof, void *data) ++static int ofd_tot_dirty_seq_show(struct seq_file *m, void *data) + { +- struct obd_device *obd = (struct obd_device *)data; ++ struct obd_device *obd = m->private; + struct ofd_device *ofd; + + LASSERT(obd != NULL); + ofd = ofd_dev(obd->obd_lu_dev); +- *eof = 1; +- return snprintf(page, count, LPU64"\n", ofd->ofd_tot_dirty); ++ return seq_printf(m, LPU64"\n", ofd->ofd_tot_dirty); + } ++LPROC_SEQ_FOPS_RO(ofd_tot_dirty); + +-static int lprocfs_ofd_rd_tot_granted(char *page, char **start, off_t off, +- int count, int *eof, void *data) ++static int ofd_tot_granted_seq_show(struct seq_file *m, void *data) + { +- struct obd_device *obd = (struct obd_device *)data; ++ struct obd_device *obd = m->private; + struct ofd_device *ofd; + + LASSERT(obd != NULL); + ofd = ofd_dev(obd->obd_lu_dev); +- *eof = 1; +- return snprintf(page, count, LPU64"\n", ofd->ofd_tot_granted); ++ return seq_printf(m, LPU64"\n", ofd->ofd_tot_granted); + } ++LPROC_SEQ_FOPS_RO(ofd_tot_granted); + +-static int lprocfs_ofd_rd_tot_pending(char *page, char **start, off_t off, +- int count, int *eof, void *data) ++static int ofd_tot_pending_seq_show(struct seq_file *m, void *data) + { +- struct obd_device *obd = (struct obd_device *)data; ++ struct obd_device *obd = m->private; + struct ofd_device *ofd; + + LASSERT(obd != NULL); + ofd = ofd_dev(obd->obd_lu_dev); +- *eof = 1; +- return snprintf(page, count, LPU64"\n", ofd->ofd_tot_pending); ++ return seq_printf(m, LPU64"\n", ofd->ofd_tot_pending); + } ++LPROC_SEQ_FOPS_RO(ofd_tot_pending); + +-static int lprocfs_ofd_rd_grant_precreate(char *page, char **start, off_t off, +- int count, int *eof, void *data) ++static int ofd_grant_precreate_seq_show(struct seq_file *m, void *data) + { +- struct obd_device *obd = (struct obd_device *)data; ++ struct obd_device *obd = m->private; + + LASSERT(obd != NULL); +- *eof = 1; +- return snprintf(page, count, "%ld\n", ++ return seq_printf(m, "%ld\n", + obd->obd_self_export->exp_filter_data.fed_grant); + } ++LPROC_SEQ_FOPS_RO(ofd_grant_precreate); + +-static int lprocfs_ofd_rd_grant_ratio(char *page, char **start, off_t off, +- int count, int *eof, void *data) ++static int ofd_grant_ratio_seq_show(struct seq_file *m, void *data) + { +- struct obd_device *obd = (struct obd_device *)data; ++ struct obd_device *obd = m->private; + struct ofd_device *ofd; + + LASSERT(obd != NULL); + ofd = ofd_dev(obd->obd_lu_dev); +- *eof = 1; +- return snprintf(page, count, "%d%%\n", ++ return seq_printf(m, "%d%%\n", + (int) ofd_grant_reserved(ofd, 100)); + } + +-static int lprocfs_ofd_wr_grant_ratio(struct file *file, const char *buffer, +- unsigned long count, void *data) ++static ssize_t ++ofd_grant_ratio_seq_write(struct file *file, const char *buffer, ++ size_t count, loff_t *off) + { +- struct obd_device *obd = (struct obd_device *)data; ++ struct seq_file *m = file->private_data; ++ struct obd_device *obd = m->private; + struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); + int val; + int rc; +@@ -144,23 +139,24 @@ static int lprocfs_ofd_wr_grant_ratio(struct file *file, const char *buffer, + spin_unlock(&ofd->ofd_grant_lock); + return count; + } ++LPROC_SEQ_FOPS(ofd_grant_ratio); + +-static int lprocfs_ofd_rd_precreate_batch(char *page, char **start, off_t off, +- int count, int *eof, void *data) ++static int ofd_precreate_batch_seq_show(struct seq_file *m, void *data) + { +- struct obd_device *obd = (struct obd_device *)data; ++ struct obd_device *obd = m->private; + struct ofd_device *ofd; + + LASSERT(obd != NULL); + ofd = ofd_dev(obd->obd_lu_dev); +- *eof = 1; +- return snprintf(page, count, "%d\n", ofd->ofd_precreate_batch); ++ return seq_printf(m, "%d\n", ofd->ofd_precreate_batch); + } + +-static int lprocfs_ofd_wr_precreate_batch(struct file *file, const char *buffer, +- unsigned long count, void *data) ++static ssize_t ++ofd_precreate_batch_seq_write(struct file *file, const char *buffer, ++ size_t count, loff_t *off) + { +- struct obd_device *obd = (struct obd_device *)data; ++ struct seq_file *m = file->private_data; ++ struct obd_device *obd = m->private; + struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); + int val; + int rc; +@@ -177,11 +173,11 @@ static int lprocfs_ofd_wr_precreate_batch(struct file *file, const char *buffer, + spin_unlock(&ofd->ofd_batch_lock); + return count; + } ++LPROC_SEQ_FOPS(ofd_precreate_batch); + +-static int lprocfs_ofd_rd_last_id(char *page, char **start, off_t off, +- int count, int *eof, void *data) ++static int ofd_last_id_seq_show(struct seq_file *m, void *data) + { +- struct obd_device *obd = data; ++ struct obd_device *obd = m->private; + struct ofd_device *ofd; + struct ofd_seq *oseq = NULL; + int retval = 0, rc; +@@ -199,35 +195,32 @@ static int lprocfs_ofd_rd_last_id(char *page, char **start, off_t off, + fid_idif_seq(ostid_id(&oseq->os_oi), + ofd->ofd_lut.lut_lsd.lsd_osd_index) : + ostid_seq(&oseq->os_oi); +- rc = snprintf(page, count, DOSTID"\n", seq, +- ostid_id(&oseq->os_oi)); ++ rc = seq_printf(m, DOSTID"\n", seq, ostid_id(&oseq->os_oi)); + if (rc < 0) { + retval = rc; + break; + } +- page += rc; +- count -= rc; + retval += rc; + } + read_unlock(&ofd->ofd_seq_list_lock); + return retval; + } ++LPROC_SEQ_FOPS_RO(ofd_last_id); + +-int lprocfs_ofd_rd_fmd_max_num(char *page, char **start, off_t off, +- int count, int *eof, void *data) ++static int ofd_fmd_max_num_seq_show(struct seq_file *m, void *data) + { +- struct obd_device *obd = data; ++ struct obd_device *obd = m->private; + struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); +- int rc; + +- rc = snprintf(page, count, "%u\n", ofd->ofd_fmd_max_num); +- return rc; ++ return seq_printf(m, "%u\n", ofd->ofd_fmd_max_num); + } + +-int lprocfs_ofd_wr_fmd_max_num(struct file *file, const char *buffer, +- unsigned long count, void *data) ++static ssize_t ++ofd_fmd_max_num_seq_write(struct file *file, const char *buffer, ++ size_t count, loff_t *off) + { +- struct obd_device *obd = data; ++ struct seq_file *m = file->private_data; ++ struct obd_device *obd = m->private; + struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); + int val; + int rc; +@@ -242,22 +235,22 @@ int lprocfs_ofd_wr_fmd_max_num(struct file *file, const char *buffer, + ofd->ofd_fmd_max_num = val; + return count; + } ++LPROC_SEQ_FOPS(ofd_fmd_max_num); + +-int lprocfs_ofd_rd_fmd_max_age(char *page, char **start, off_t off, +- int count, int *eof, void *data) ++static int ofd_fmd_max_age_seq_show(struct seq_file *m, void *data) + { +- struct obd_device *obd = data; ++ struct obd_device *obd = m->private; + struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); +- int rc; + +- rc = snprintf(page, count, "%ld\n", ofd->ofd_fmd_max_age / HZ); +- return rc; ++ return seq_printf(m, "%ld\n", ofd->ofd_fmd_max_age / HZ); + } + +-int lprocfs_ofd_wr_fmd_max_age(struct file *file, const char *buffer, +- unsigned long count, void *data) ++static ssize_t ++ofd_fmd_max_age_seq_write(struct file *file, const char *buffer, ++ size_t count, loff_t *off) + { +- struct obd_device *obd = data; ++ struct seq_file *m = file->private_data; ++ struct obd_device *obd = m->private; + struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); + int val; + int rc; +@@ -272,22 +265,22 @@ int lprocfs_ofd_wr_fmd_max_age(struct file *file, const char *buffer, + ofd->ofd_fmd_max_age = val * HZ; + return count; + } ++LPROC_SEQ_FOPS(ofd_fmd_max_age); + +-static int lprocfs_ofd_rd_capa(char *page, char **start, off_t off, +- int count, int *eof, void *data) ++static int ofd_capa_seq_show(struct seq_file *m, void *data) + { +- struct obd_device *obd = data; +- int rc; ++ struct obd_device *obd = m->private; + +- rc = snprintf(page, count, "capability on: %s\n", +- obd->u.filter.fo_fl_oss_capa ? "oss" : ""); +- return rc; ++ return seq_printf(m, "capability on: %s\n", ++ obd->u.filter.fo_fl_oss_capa ? "oss" : ""); + } + +-static int lprocfs_ofd_wr_capa(struct file *file, const char *buffer, +- unsigned long count, void *data) ++static ssize_t ++ofd_capa_seq_write(struct file *file, const char *buffer, size_t count, ++ loff_t *off) + { +- struct obd_device *obd = data; ++ struct seq_file *m = file->private_data; ++ struct obd_device *obd = m->private; + int val, rc; + + rc = lprocfs_write_helper(buffer, count, &val); +@@ -306,28 +299,30 @@ static int lprocfs_ofd_wr_capa(struct file *file, const char *buffer, + val ? "enabled" : "disabled"); + return count; + } ++LPROC_SEQ_FOPS(ofd_capa); + +-static int lprocfs_ofd_rd_capa_count(char *page, char **start, off_t off, +- int count, int *eof, void *data) ++static int ofd_capa_count_seq_show(struct seq_file *m, void *data) + { +- return snprintf(page, count, "%d %d\n", ++ return seq_printf(m, "%d %d\n", + capa_count[CAPA_SITE_CLIENT], + capa_count[CAPA_SITE_SERVER]); + } ++LPROC_SEQ_FOPS_RO(ofd_capa_count); + +-int lprocfs_ofd_rd_degraded(char *page, char **start, off_t off, +- int count, int *eof, void *data) ++static int ofd_degraded_seq_show(struct seq_file *m, void *data) + { +- struct obd_device *obd = data; ++ struct obd_device *obd = m->private; + struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); + +- return snprintf(page, count, "%u\n", ofd->ofd_raid_degraded); ++ return seq_printf(m, "%u\n", ofd->ofd_raid_degraded); + } + +-int lprocfs_ofd_wr_degraded(struct file *file, const char *buffer, +- unsigned long count, void *data) ++static ssize_t ++ofd_degraded_seq_write(struct file *file, const char *buffer, ++ size_t count, loff_t *off) + { +- struct obd_device *obd = data; ++ struct seq_file *m = file->private_data; ++ struct obd_device *obd = m->private; + struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); + int val, rc; + +@@ -338,38 +333,37 @@ int lprocfs_ofd_wr_degraded(struct file *file, const char *buffer, + spin_lock(&ofd->ofd_flags_lock); + ofd->ofd_raid_degraded = !!val; + spin_unlock(&ofd->ofd_flags_lock); +- + return count; + } ++LPROC_SEQ_FOPS(ofd_degraded); + +-int lprocfs_ofd_rd_fstype(char *page, char **start, off_t off, int count, +- int *eof, void *data) ++static int ofd_fstype_seq_show(struct seq_file *m, void *data) + { +- struct obd_device *obd = data; ++ struct obd_device *obd = m->private; + struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); + struct lu_device *d; + + LASSERT(ofd->ofd_osd); + d = &ofd->ofd_osd->dd_lu_dev; + LASSERT(d->ld_type); +- return snprintf(page, count, "%s\n", d->ld_type->ldt_name); ++ return seq_printf(m, "%s\n", d->ld_type->ldt_name); + } ++LPROC_SEQ_FOPS_RO(ofd_fstype); + +-int lprocfs_ofd_rd_syncjournal(char *page, char **start, off_t off, +- int count, int *eof, void *data) ++static int ofd_syncjournal_seq_show(struct seq_file *m, void *data) + { +- struct obd_device *obd = data; ++ struct obd_device *obd = m->private; + struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); +- int rc; + +- rc = snprintf(page, count, "%u\n", ofd->ofd_syncjournal); +- return rc; ++ return seq_printf(m, "%u\n", ofd->ofd_syncjournal); + } + +-int lprocfs_ofd_wr_syncjournal(struct file *file, const char *buffer, +- unsigned long count, void *data) ++static ssize_t ++ofd_syncjournal_seq_write(struct file *file, const char *buffer, ++ size_t count, loff_t *off) + { +- struct obd_device *obd = data; ++ struct seq_file *m = file->private_data; ++ struct obd_device *obd = m->private; + struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); + int val; + int rc; +@@ -388,27 +382,27 @@ int lprocfs_ofd_wr_syncjournal(struct file *file, const char *buffer, + + return count; + } ++LPROC_SEQ_FOPS(ofd_syncjournal); + + static char *sync_on_cancel_states[] = {"never", + "blocking", + "always" }; + +-int lprocfs_ofd_rd_sync_lock_cancel(char *page, char **start, off_t off, +- int count, int *eof, void *data) ++static int ofd_sync_lock_cancel_seq_show(struct seq_file *m, void *data) + { +- struct obd_device *obd = data; ++ struct obd_device *obd = m->private; + struct lu_target *tgt = obd->u.obt.obt_lut; +- int rc; + +- rc = snprintf(page, count, "%s\n", +- sync_on_cancel_states[tgt->lut_sync_lock_cancel]); +- return rc; ++ return seq_printf(m, "%s\n", ++ sync_on_cancel_states[tgt->lut_sync_lock_cancel]); + } + +-int lprocfs_ofd_wr_sync_lock_cancel(struct file *file, const char *buffer, +- unsigned long count, void *data) ++static ssize_t ++ofd_sync_lock_cancel_seq_write(struct file *file, const char *buffer, ++ size_t count, loff_t *off) + { +- struct obd_device *obd = data; ++ struct seq_file *m = file->private_data; ++ struct obd_device *obd = m->private; + struct lu_target *tgt = obd->u.obt.obt_lut; + int val = -1; + int i; +@@ -436,22 +430,22 @@ int lprocfs_ofd_wr_sync_lock_cancel(struct file *file, const char *buffer, + spin_unlock(&tgt->lut_flags_lock); + return count; + } ++LPROC_SEQ_FOPS(ofd_sync_lock_cancel); + +-int lprocfs_ofd_rd_grant_compat_disable(char *page, char **start, off_t off, +- int count, int *eof, void *data) ++static int ofd_grant_compat_disable_seq_show(struct seq_file *m, void *data) + { +- struct obd_device *obd = data; ++ struct obd_device *obd = m->private; + struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); +- int rc; + +- rc = snprintf(page, count, "%u\n", ofd->ofd_grant_compat_disable); +- return rc; ++ return seq_printf(m, "%u\n", ofd->ofd_grant_compat_disable); + } + +-int lprocfs_ofd_wr_grant_compat_disable(struct file *file, const char *buffer, +- unsigned long count, void *data) ++static ssize_t ++ofd_grant_compat_disable_seq_write(struct file *file, const char *buffer, ++ size_t count, loff_t *off) + { +- struct obd_device *obd = data; ++ struct seq_file *m = file->private_data; ++ struct obd_device *obd = m->private; + struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); + int val; + int rc; +@@ -469,41 +463,43 @@ int lprocfs_ofd_wr_grant_compat_disable(struct file *file, const char *buffer, + + return count; + } ++LPROC_SEQ_FOPS(ofd_grant_compat_disable); + +-int lprocfs_ofd_rd_soft_sync_limit(char *page, char **start, off_t off, +- int count, int *eof, void *data) ++static int ofd_soft_sync_limit_seq_show(struct seq_file *m, void *data) + { +- struct obd_device *obd = data; ++ struct obd_device *obd = m->private; + struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); + +- return lprocfs_rd_uint(page, start, off, count, eof, +- &ofd->ofd_soft_sync_limit); ++ return lprocfs_uint_seq_show(m, &ofd->ofd_soft_sync_limit); + } + +-int lprocfs_ofd_wr_soft_sync_limit(struct file *file, const char *buffer, +- unsigned long count, void *data) ++static ssize_t ++ofd_soft_sync_limit_seq_write(struct file *file, const char *buffer, ++ size_t count, loff_t *off) + { +- struct obd_device *obd = data; ++ struct seq_file *m = file->private_data; ++ struct obd_device *obd = m->private; + struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); + +- return lprocfs_wr_uint(file, buffer, count, &ofd->ofd_soft_sync_limit); ++ return lprocfs_uint_seq_write(file, buffer, count, ++ (loff_t *) &ofd->ofd_soft_sync_limit); + } ++LPROC_SEQ_FOPS(ofd_soft_sync_limit); + +-static int lprocfs_rd_lfsck_speed_limit(char *page, char **start, off_t off, +- int count, int *eof, void *data) ++static int ofd_lfsck_speed_limit_seq_show(struct seq_file *m, void *data) + { +- struct obd_device *obd = data; ++ struct obd_device *obd = m->private; + struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); + +- *eof = 1; +- +- return lfsck_get_speed(ofd->ofd_osd, page, count); ++ return lfsck_get_speed(m, ofd->ofd_osd); + } + +-static int lprocfs_wr_lfsck_speed_limit(struct file *file, const char *buffer, +- unsigned long count, void *data) ++static ssize_t ++ofd_lfsck_speed_limit_seq_write(struct file *file, const char *buffer, ++ size_t count, loff_t *off) + { +- struct obd_device *obd = data; ++ struct seq_file *m = file->private_data; ++ struct obd_device *obd = m->private; + struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); + __u32 val; + int rc; +@@ -516,84 +512,108 @@ static int lprocfs_wr_lfsck_speed_limit(struct file *file, const char *buffer, + + return rc != 0 ? rc : count; + } ++LPROC_SEQ_FOPS(ofd_lfsck_speed_limit); + +-static int lprocfs_rd_lfsck_layout(char *page, char **start, off_t off, +- int count, int *eof, void *data) ++static int ofd_lfsck_layout_seq_show(struct seq_file *m, void *data) + { +- struct obd_device *obd = data; ++ struct obd_device *obd = m->private; + struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); + +- *eof = 1; +- +- return lfsck_dump(ofd->ofd_osd, page, count, LT_LAYOUT); +-} +- +-static struct lprocfs_vars lprocfs_ofd_obd_vars[] = { +- { "uuid", lprocfs_rd_uuid, 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 }, +- { "filestotal", lprocfs_rd_filestotal, 0, 0 }, +- { "filesfree", lprocfs_rd_filesfree, 0, 0 }, +- { "seqs_allocated", lprocfs_ofd_rd_seqs, 0, 0 }, +- { "fstype", lprocfs_ofd_rd_fstype, 0, 0 }, +- { "last_id", lprocfs_ofd_rd_last_id, 0, 0 }, +- { "tot_dirty", lprocfs_ofd_rd_tot_dirty, 0, 0 }, +- { "tot_pending", lprocfs_ofd_rd_tot_pending, 0, 0 }, +- { "tot_granted", lprocfs_ofd_rd_tot_granted, 0, 0 }, +- { "grant_precreate", lprocfs_ofd_rd_grant_precreate, 0, 0 }, +- { "grant_ratio", lprocfs_ofd_rd_grant_ratio, +- lprocfs_ofd_wr_grant_ratio, 0, 0 }, +- { "precreate_batch", lprocfs_ofd_rd_precreate_batch, +- lprocfs_ofd_wr_precreate_batch, 0 }, +- { "recovery_status", lprocfs_obd_rd_recovery_status, 0, 0 }, +- { "recovery_time_soft", lprocfs_obd_rd_recovery_time_soft, +- lprocfs_obd_wr_recovery_time_soft, 0}, +- { "recovery_time_hard", lprocfs_obd_rd_recovery_time_hard, +- lprocfs_obd_wr_recovery_time_hard, 0}, +- { "evict_client", 0, lprocfs_wr_evict_client, 0, +- &lprocfs_evict_client_fops}, +- { "num_exports", lprocfs_rd_num_exports, 0, 0 }, +- { "degraded", lprocfs_ofd_rd_degraded, +- lprocfs_ofd_wr_degraded, 0}, +- { "sync_journal", lprocfs_ofd_rd_syncjournal, +- lprocfs_ofd_wr_syncjournal, 0 }, +- { "sync_on_lock_cancel", lprocfs_ofd_rd_sync_lock_cancel, +- lprocfs_ofd_wr_sync_lock_cancel, 0 }, +- { "instance", lprocfs_target_rd_instance, 0 }, +- { "ir_factor", lprocfs_obd_rd_ir_factor, +- lprocfs_obd_wr_ir_factor, 0}, +- { "grant_compat_disable", lprocfs_ofd_rd_grant_compat_disable, +- lprocfs_ofd_wr_grant_compat_disable, 0 }, +- { "client_cache_count", lprocfs_ofd_rd_fmd_max_num, +- lprocfs_ofd_wr_fmd_max_num, 0 }, +- { "client_cache_seconds", lprocfs_ofd_rd_fmd_max_age, +- lprocfs_ofd_wr_fmd_max_age, 0 }, +- { "capa", lprocfs_ofd_rd_capa, +- lprocfs_ofd_wr_capa, 0 }, +- { "capa_count", lprocfs_ofd_rd_capa_count, 0, 0 }, +- { "job_cleanup_interval", lprocfs_rd_job_interval, +- lprocfs_wr_job_interval, 0}, +- { "soft_sync_limit", lprocfs_ofd_rd_soft_sync_limit, +- lprocfs_ofd_wr_soft_sync_limit, 0}, +- { "lfsck_speed_limit", lprocfs_rd_lfsck_speed_limit, +- lprocfs_wr_lfsck_speed_limit, 0 }, +- { "lfsck_layout", lprocfs_rd_lfsck_layout, 0, 0 }, +- { 0 } +-}; +- +-static struct lprocfs_vars lprocfs_ofd_module_vars[] = { +- { "num_refs", lprocfs_rd_numrefs, 0, 0 }, ++ return lfsck_dump(m, ofd->ofd_osd, LT_LAYOUT); ++} ++LPROC_SEQ_FOPS_RO(ofd_lfsck_layout); ++ ++LPROC_SEQ_FOPS_RO_TYPE(ofd, uuid); ++LPROC_SEQ_FOPS_RO_TYPE(ofd, blksize); ++LPROC_SEQ_FOPS_RO_TYPE(ofd, kbytestotal); ++LPROC_SEQ_FOPS_RO_TYPE(ofd, kbytesfree); ++LPROC_SEQ_FOPS_RO_TYPE(ofd, kbytesavail); ++LPROC_SEQ_FOPS_RO_TYPE(ofd, filestotal); ++LPROC_SEQ_FOPS_RO_TYPE(ofd, filesfree); ++ ++LPROC_SEQ_FOPS_RO_TYPE(ofd, recovery_status); ++LPROC_SEQ_FOPS_RW_TYPE(ofd, recovery_time_soft); ++LPROC_SEQ_FOPS_RW_TYPE(ofd, recovery_time_hard); ++LPROC_SEQ_FOPS_WO_TYPE(ofd, evict_client); ++LPROC_SEQ_FOPS_RO_TYPE(ofd, num_exports); ++LPROC_SEQ_FOPS_RO_TYPE(ofd, target_instance); ++LPROC_SEQ_FOPS_RW_TYPE(ofd, ir_factor); ++LPROC_SEQ_FOPS_RW_TYPE(ofd, job_interval); ++ ++struct lprocfs_seq_vars lprocfs_ofd_obd_vars[] = { ++ { .name = "uuid", ++ .fops = &ofd_uuid_fops }, ++ { .name = "blocksize", ++ .fops = &ofd_blksize_fops }, ++ { .name = "kbytestotal", ++ .fops = &ofd_kbytestotal_fops }, ++ { .name = "kbytesfree", ++ .fops = &ofd_kbytesfree_fops }, ++ { .name = "kbytesavail", ++ .fops = &ofd_kbytesavail_fops }, ++ { .name = "filestotal", ++ .fops = &ofd_filestotal_fops }, ++ { .name = "filesfree", ++ .fops = &ofd_filesfree_fops }, ++ { .name = "seqs_allocated", ++ .fops = &ofd_seqs_fops }, ++ { .name = "fstype", ++ .fops = &ofd_fstype_fops }, ++ { .name = "last_id", ++ .fops = &ofd_last_id_fops }, ++ { .name = "tot_dirty", ++ .fops = &ofd_tot_dirty_fops }, ++ { .name = "tot_pending", ++ .fops = &ofd_tot_pending_fops }, ++ { .name = "tot_granted", ++ .fops = &ofd_tot_granted_fops }, ++ { .name = "grant_precreate", ++ .fops = &ofd_grant_precreate_fops }, ++ { .name = "grant_ratio", ++ .fops = &ofd_grant_ratio_fops }, ++ { .name = "precreate_batch", ++ .fops = &ofd_precreate_batch_fops }, ++ { .name = "recovery_status", ++ .fops = &ofd_recovery_status_fops }, ++ { .name = "recovery_time_soft", ++ .fops = &ofd_recovery_time_soft_fops }, ++ { .name = "recovery_time_hard", ++ .fops = &ofd_recovery_time_hard_fops }, ++ { .name = "evict_client", ++ .fops = &ofd_evict_client_fops }, ++ { .name = "num_exports", ++ .fops = &ofd_num_exports_fops }, ++ { .name = "degraded", ++ .fops = &ofd_degraded_fops }, ++ { .name = "sync_journal", ++ .fops = &ofd_syncjournal_fops }, ++ { .name = "sync_on_lock_cancel", ++ .fops = &ofd_sync_lock_cancel_fops }, ++ { .name = "instance", ++ .fops = &ofd_target_instance_fops }, ++ { .name = "ir_factor", ++ .fops = &ofd_ir_factor_fops }, ++ { .name = "grant_compat_disable", ++ .fops = &ofd_grant_compat_disable_fops }, ++ { .name = "client_cache_count", ++ .fops = &ofd_fmd_max_num_fops }, ++ { .name = "client_cache_seconds", ++ .fops = &ofd_fmd_max_age_fops }, ++ { .name = "capa", ++ .fops = &ofd_capa_fops }, ++ { .name = "capa_count", ++ .fops = &ofd_capa_count_fops }, ++ { .name = "job_cleanup_interval", ++ .fops = &ofd_job_interval_fops }, ++ { .name = "soft_sync_limit", ++ .fops = &ofd_soft_sync_limit_fops }, ++ { .name = "lfsck_speed_limit", ++ .fops = &ofd_lfsck_speed_limit_fops }, ++ { .name = "lfsck_layout", ++ .fops = &ofd_lfsck_layout_fops }, + { 0 } + }; + +-void lprocfs_ofd_init_vars(struct lprocfs_static_vars *lvars) +-{ +- lvars->module_vars = lprocfs_ofd_module_vars; +- lvars->obd_vars = lprocfs_ofd_obd_vars; +-} +- + void ofd_stats_counter_init(struct lprocfs_stats *stats) + { + LASSERT(stats && stats->ls_num >= LPROC_OFD_STATS_LAST); +diff --git a/lustre/ofd/ofd_dev.c b/lustre/ofd/ofd_dev.c +index 3559991..f59f843 100644 +--- a/lustre/ofd/ofd_dev.c ++++ b/lustre/ofd/ofd_dev.c +@@ -240,8 +240,7 @@ static int ofd_process_config(const struct lu_env *env, struct lu_device *d, + + switch (cfg->lcfg_command) { + case LCFG_PARAM: { +- struct lprocfs_static_vars lvars; +- ++ struct obd_device *obd = ofd_obd(m); + /* For interoperability */ + struct cfg_interop_param *ptr = NULL; + struct lustre_cfg *old_cfg = NULL; +@@ -279,8 +278,7 @@ static int ofd_process_config(const struct lu_env *env, struct lu_device *d, + break; + } + +- lprocfs_ofd_init_vars(&lvars); +- rc = class_process_proc_param(PARAM_OST, lvars.obd_vars, cfg, ++ rc = class_process_proc_seq_param(PARAM_OST, obd->obd_vars, cfg, + d->ld_obd); + if (rc > 0 || rc == -ENOSYS) { + CDEBUG(D_CONFIG, "pass param %s down the stack.\n", +@@ -492,9 +490,10 @@ static struct lu_device_operations ofd_lu_ops = { + .ldo_prepare = ofd_prepare, + }; + ++LPROC_SEQ_FOPS(lprocfs_nid_stats_clear); ++ + static int ofd_procfs_init(struct ofd_device *ofd) + { +- struct lprocfs_static_vars lvars; + struct obd_device *obd = ofd_obd(ofd); + cfs_proc_dir_entry_t *entry; + int rc = 0; +@@ -503,8 +502,8 @@ static int ofd_procfs_init(struct ofd_device *ofd) + + /* lprocfs must be setup before the ofd so state can be safely added + * to /proc incrementally as the ofd is setup */ +- lprocfs_ofd_init_vars(&lvars); +- rc = lprocfs_obd_setup(obd, lvars.obd_vars); ++ obd->obd_vars = lprocfs_ofd_obd_vars; ++ rc = lprocfs_seq_obd_setup(obd); + if (rc) { + CERROR("%s: lprocfs_obd_setup failed: %d.\n", + obd->obd_name, rc); +@@ -520,7 +519,7 @@ static int ofd_procfs_init(struct ofd_device *ofd) + + obd->obd_uses_nid_stats = 1; + +- entry = lprocfs_register("exports", obd->obd_proc_entry, NULL, NULL); ++ entry = lprocfs_seq_register("exports", obd->obd_proc_entry, NULL, NULL); + if (IS_ERR(entry)) { + rc = PTR_ERR(entry); + CERROR("%s: error %d setting up lprocfs for %s\n", +@@ -530,8 +529,10 @@ static int ofd_procfs_init(struct ofd_device *ofd) + obd->obd_proc_exports_entry = entry; + + entry = lprocfs_add_simple(obd->obd_proc_exports_entry, "clear", +- lprocfs_nid_stats_clear_read, +- lprocfs_nid_stats_clear_write, obd, NULL); ++#ifndef HAVE_ONLY_PROCFS_SEQ ++ NULL, NULL, ++#endif ++ obd, &lprocfs_nid_stats_clear_fops); + if (IS_ERR(entry)) { + rc = PTR_ERR(entry); + CERROR("%s: add proc entry 'clear' failed: %d.\n", +@@ -547,7 +548,7 @@ static int ofd_procfs_init(struct ofd_device *ofd) + GOTO(remove_entry_clear, rc); + RETURN(0); + remove_entry_clear: +- lprocfs_remove_proc_entry("clear", obd->obd_proc_exports_entry); ++ lprocfs_remove(&obd->obd_proc_exports_entry); + obd_cleanup: + lprocfs_obd_cleanup(obd); + lprocfs_free_obd_stats(obd); +@@ -560,29 +561,28 @@ static void ofd_procfs_add_brw_stats_symlink(struct ofd_device *ofd) + struct obd_device *obd = ofd_obd(ofd); + struct obd_device *osd_obd = ofd->ofd_osd_exp->exp_obd; + cfs_proc_dir_entry_t *osd_root = osd_obd->obd_type->typ_procroot; +- cfs_proc_dir_entry_t *osd_dir; ++ cfs_proc_dir_entry_t *osd_dir = osd_obd->obd_type->typ_procsym; + +- osd_dir = lprocfs_srch(osd_root, obd->obd_name); + if (osd_dir == NULL) + return; + +- if (lprocfs_srch(osd_dir, "brw_stats") != NULL) ++ //if (lprocfs_srch(osd_dir, "brw_stats") != NULL) + lprocfs_add_symlink("brw_stats", obd->obd_proc_entry, + "../../%s/%s/brw_stats", + osd_root->name, osd_dir->name); + +- if (lprocfs_srch(osd_dir, "read_cache_enable") != NULL) ++ //if (lprocfs_srch(osd_dir, "read_cache_enable") != NULL) + lprocfs_add_symlink("read_cache_enable", obd->obd_proc_entry, + "../../%s/%s/read_cache_enable", + osd_root->name, osd_dir->name); + +- if (lprocfs_srch(osd_dir, "readcache_max_filesize") != NULL) ++ //if (lprocfs_srch(osd_dir, "readcache_max_filesize") != NULL) + lprocfs_add_symlink("readcache_max_filesize", + obd->obd_proc_entry, + "../../%s/%s/readcache_max_filesize", + osd_root->name, osd_dir->name); + +- if (lprocfs_srch(osd_dir, "writethrough_cache_enable") != NULL) ++ //if (lprocfs_srch(osd_dir, "writethrough_cache_enable") != NULL) + lprocfs_add_symlink("writethrough_cache_enable", + obd->obd_proc_entry, + "../../%s/%s/writethrough_cache_enable", +@@ -593,13 +593,8 @@ static void ofd_procfs_fini(struct ofd_device *ofd) + { + struct obd_device *obd = ofd_obd(ofd); + +- lprocfs_remove_proc_entry("writethrough_cache_enable", +- obd->obd_proc_entry); +- lprocfs_remove_proc_entry("readcache_max_filesize", +- obd->obd_proc_entry); +- lprocfs_remove_proc_entry("read_cache_enable", obd->obd_proc_entry); +- lprocfs_remove_proc_entry("brw_stats", obd->obd_proc_entry); +- lprocfs_remove_proc_entry("clear", obd->obd_proc_exports_entry); ++ lprocfs_remove(&obd->obd_proc_exports_entry); ++ lprocfs_remove(&obd->obd_proc_entry); + lprocfs_free_per_client_stats(obd); + lprocfs_obd_cleanup(obd); + lprocfs_free_obd_stats(obd); +@@ -2363,7 +2358,6 @@ static struct lu_device_type ofd_device_type = { + + int __init ofd_init(void) + { +- struct lprocfs_static_vars lvars; + int rc; + + rc = lu_kmem_init(ofd_caches); +@@ -2376,11 +2370,9 @@ int __init ofd_init(void) + return(rc); + } + +- lprocfs_ofd_init_vars(&lvars); +- + rc = class_register_type(&ofd_obd_ops, NULL, NULL, + #ifndef HAVE_ONLY_PROCFS_SEQ +- lvars.module_vars, ++ NULL, + #endif + LUSTRE_OST_NAME, &ofd_device_type); + return rc; +diff --git a/lustre/ofd/ofd_internal.h b/lustre/ofd/ofd_internal.h +index b22ceec..79dfaa9 100644 +--- a/lustre/ofd/ofd_internal.h ++++ b/lustre/ofd/ofd_internal.h +@@ -390,13 +390,9 @@ int ofd_txn_stop_cb(const struct lu_env *env, struct thandle *txn, + + /* lproc_ofd.c */ + #ifdef LPROCFS +-void lprocfs_ofd_init_vars(struct lprocfs_static_vars *lvars); ++extern struct lprocfs_seq_vars lprocfs_ofd_obd_vars[]; + void ofd_stats_counter_init(struct lprocfs_stats *stats); + #else +-static void lprocfs_ofd_init_vars(struct lprocfs_static_vars *lvars) +-{ +- memset(lvars, 0, sizeof(*lvars)); +-} + static inline void ofd_stats_counter_init(struct lprocfs_stats *stats) {} + #endif + +diff --git a/lustre/osd-ldiskfs/osd_handler.c b/lustre/osd-ldiskfs/osd_handler.c +index 6f369d0..9027533 100644 +--- a/lustre/osd-ldiskfs/osd_handler.c ++++ b/lustre/osd-ldiskfs/osd_handler.c +@@ -5882,6 +5882,7 @@ static int osd_obd_connect(const struct lu_env *env, struct obd_export **exp, + osd->od_connects++; + spin_unlock(&osd->od_osfs_lock); + ++ obd->obd_type->typ_procsym = osd->od_proc_entry; + RETURN(0); + } + +diff --git a/lustre/osd-zfs/osd_handler.c b/lustre/osd-zfs/osd_handler.c +index 36bf6a4..40d2c67 100644 +--- a/lustre/osd-zfs/osd_handler.c ++++ b/lustre/osd-zfs/osd_handler.c +@@ -813,6 +813,7 @@ static int osd_obd_connect(const struct lu_env *env, struct obd_export **exp, + osd->od_connects++; + spin_unlock(&osd->od_objset.lock); + ++ obd->obd_type->typ_procsym = osd->od_proc_entry; + RETURN(0); + } + +-- +1.8.5.3 + diff --git a/sys-cluster/lustre/files/0009-LU-3319-procfs-move-ost-proc-handling-over-to-seq_fi.patch b/sys-cluster/lustre/files/0009-LU-3319-procfs-move-ost-proc-handling-over-to-seq_fi.patch deleted file mode 100644 index 59eeb06e6..000000000 --- a/sys-cluster/lustre/files/0009-LU-3319-procfs-move-ost-proc-handling-over-to-seq_fi.patch +++ /dev/null @@ -1,174 +0,0 @@ -From 917c26236db7d3684733f693ccc579c3dd41f26c Mon Sep 17 00:00:00 2001 -From: James Simmons <uja.ornl@gmail.com> -Date: Thu, 14 Nov 2013 09:48:08 -0500 -Subject: [PATCH 09/18] LU-3319 procfs: move ost proc handling over to seq_file - -Most of the current proc handling of the OST is already -based on seq_file handling except for the reporting of -the UUID of the OST. This patch moves this last piece -so that the OST layer will use strictly proc files with -seq_files. - -Signed-off-by: James Simmons <uja.ornl@gmail.com> -Change-Id: Idf2bc014ada9292d545f761aa27c777412a66671 ---- - lustre/ost/Makefile.in | 2 +- - lustre/ost/lproc_ost.c | 58 ----------------------------------------------- - lustre/ost/ost_handler.c | 21 +++++++++++------ - lustre/ost/ost_internal.h | 9 -------- - 4 files changed, 15 insertions(+), 75 deletions(-) - delete mode 100644 lustre/ost/lproc_ost.c - -diff --git a/lustre/ost/Makefile.in b/lustre/ost/Makefile.in -index 6bd8be3..bae023e 100644 ---- a/lustre/ost/Makefile.in -+++ b/lustre/ost/Makefile.in -@@ -1,5 +1,5 @@ - MODULES := ost --ost-objs := ost_handler.o lproc_ost.o -+ost-objs := ost_handler.o - - EXTRA_DIST = $(ost-objs:%.o=%.c) ost_internal.h - -diff --git a/lustre/ost/lproc_ost.c b/lustre/ost/lproc_ost.c -deleted file mode 100644 -index a978c51..0000000 ---- a/lustre/ost/lproc_ost.c -+++ /dev/null -@@ -1,58 +0,0 @@ --/* -- * GPL HEADER START -- * -- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 only, -- * 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 version 2 for more details (a copy is included -- * in the LICENSE file that accompanied this code). -- * -- * You should have received a copy of the GNU General Public License -- * version 2 along with this program; If not, see -- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf -- * -- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, -- * CA 95054 USA or visit www.sun.com if you need additional information or -- * have any questions. -- * -- * GPL HEADER END -- */ --/* -- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. -- * Use is subject to license terms. -- */ --/* -- * This file is part of Lustre, http://www.lustre.org/ -- * Lustre is a trademark of Sun Microsystems, Inc. -- */ --#define DEBUG_SUBSYSTEM S_OST -- --#include <obd_class.h> --#include <lprocfs_status.h> --#include <linux/seq_file.h> --#include "ost_internal.h" -- --#ifdef LPROCFS --static struct lprocfs_vars lprocfs_ost_obd_vars[] = { -- { "uuid", lprocfs_rd_uuid, 0, 0 }, -- { 0 } --}; -- --static struct lprocfs_vars lprocfs_ost_module_vars[] = { -- { "num_refs", lprocfs_rd_numrefs, 0, 0 }, -- { 0 } --}; -- --void lprocfs_ost_init_vars(struct lprocfs_static_vars *lvars) --{ -- lvars->module_vars = lprocfs_ost_module_vars; -- lvars->obd_vars = lprocfs_ost_obd_vars; --} -- --#endif /* LPROCFS */ -diff --git a/lustre/ost/ost_handler.c b/lustre/ost/ost_handler.c -index 662a489..7567acf 100644 ---- a/lustre/ost/ost_handler.c -+++ b/lustre/ost/ost_handler.c -@@ -538,12 +538,20 @@ static int ost_io_hpreq_handler(struct ptlrpc_request *req) - - static struct cfs_cpt_table *ost_io_cptable; - -+#ifdef LPROCFS -+LPROC_SEQ_FOPS_RO_TYPE(ost, uuid); -+ -+static struct lprocfs_seq_vars lprocfs_ost_obd_vars[] = { -+ { "uuid", &ost_uuid_fops }, -+ { 0 } -+}; -+#endif /* LPROCFS */ -+ - /* Sigh - really, this is an OSS, the _server_, not the _target_ */ - static int ost_setup(struct obd_device *obd, struct lustre_cfg* lcfg) - { - static struct ptlrpc_service_conf svc_conf; - struct ost_obd *ost = &obd->u.ost; -- struct lprocfs_static_vars lvars; - nodemask_t *mask; - int rc; - ENTRY; -@@ -552,9 +560,10 @@ static int ost_setup(struct obd_device *obd, struct lustre_cfg* lcfg) - if (rc) - RETURN(rc); - -- lprocfs_ost_init_vars(&lvars); -- lprocfs_obd_setup(obd, lvars.obd_vars); -- -+#ifdef LPROCFS -+ obd->obd_vars = lprocfs_ost_obd_vars; -+ lprocfs_seq_obd_setup(obd); -+#endif - mutex_init(&ost->ost_health_mutex); - - svc_conf = (typeof(svc_conf)) { -@@ -877,15 +886,13 @@ static struct obd_ops ost_obd_ops = { - - static int __init ost_init(void) - { -- struct lprocfs_static_vars lvars; - int rc; - - ENTRY; - -- lprocfs_ost_init_vars(&lvars); - rc = class_register_type(&ost_obd_ops, NULL, NULL, - #ifndef HAVE_ONLY_PROCFS_SEQ -- lvars.module_vars, -+ NULL, - #endif - LUSTRE_OSS_NAME, NULL); - -diff --git a/lustre/ost/ost_internal.h b/lustre/ost/ost_internal.h -index 8b475a1..63c8415 100644 ---- a/lustre/ost/ost_internal.h -+++ b/lustre/ost/ost_internal.h -@@ -39,13 +39,4 @@ - - #define OSS_SERVICE_WATCHDOG_FACTOR 2 - --#ifdef LPROCFS --void lprocfs_ost_init_vars(struct lprocfs_static_vars *lvars); --#else --static void lprocfs_ost_init_vars(struct lprocfs_static_vars *lvars) --{ -- memset(lvars, 0, sizeof(*lvars)); --} --#endif -- - #endif /* OST_INTERNAL_H */ --- -1.8.5.1 - diff --git a/sys-cluster/lustre/files/0018-LU-3319-procfs-update-ldiskfs-proc-handling-to-seq_f.patch b/sys-cluster/lustre/files/0010-LU-3319-procfs-update-ldiskfs-proc-handling-to-seq_f.patch index c74a18b36..acfa04f0f 100644 --- a/sys-cluster/lustre/files/0018-LU-3319-procfs-update-ldiskfs-proc-handling-to-seq_f.patch +++ b/sys-cluster/lustre/files/0010-LU-3319-procfs-update-ldiskfs-proc-handling-to-seq_f.patch @@ -1,7 +1,7 @@ -From 40b657155058d824c3ef8e4f22955eacca5eeb79 Mon Sep 17 00:00:00 2001 +From 5a0b800373ce5e05f6ac64686e6381f7d2706044 Mon Sep 17 00:00:00 2001 From: James Simmons <uja.ornl@gmail.com> -Date: Thu, 14 Nov 2013 19:41:12 -0500 -Subject: [PATCH 18/18] LU-3319 procfs: update ldiskfs proc handling to +Date: Fri, 31 Jan 2014 10:38:14 -0500 +Subject: [PATCH 10/13] LU-3319 procfs: update ldiskfs proc handling to seq_files Migrate all ldiskfs proc handling to using strictly @@ -10,58 +10,103 @@ seq_files. Signed-off-by: James Simmons <uja.ornl@gmail.com> Change-Id: Ia296a4682e2feda02bcfbe0100de8a89404cd731 --- - lustre/osd-ldiskfs/osd_handler.c | 7 +- + lustre/osd-ldiskfs/osd_compat.c | 6 +- + lustre/osd-ldiskfs/osd_handler.c | 16 +- lustre/osd-ldiskfs/osd_internal.h | 6 +- - lustre/osd-ldiskfs/osd_lproc.c | 321 +++++++++++++++++++------------------- - lustre/osd-ldiskfs/osd_scrub.c | 73 +++------ - 4 files changed, 192 insertions(+), 215 deletions(-) + lustre/osd-ldiskfs/osd_lproc.c | 338 ++++++++++++++++++++------------------ + lustre/osd-ldiskfs/osd_scrub.c | 73 +++----- + 5 files changed, 222 insertions(+), 217 deletions(-) +diff --git a/lustre/osd-ldiskfs/osd_compat.c b/lustre/osd-ldiskfs/osd_compat.c +index b4a018c..6ca1304 100644 +--- a/lustre/osd-ldiskfs/osd_compat.c ++++ b/lustre/osd-ldiskfs/osd_compat.c +@@ -1168,7 +1168,7 @@ int osd_obj_spec_update(struct osd_thread_info *info, struct osd_device *osd, + handle_t *th) + { + struct dentry *root; +- char *name; ++ char *name = NULL; + int rc; + ENTRY; + +@@ -1189,7 +1189,7 @@ int osd_obj_spec_insert(struct osd_thread_info *info, struct osd_device *osd, + handle_t *th) + { + struct dentry *root; +- char *name; ++ char *name = NULL; + int rc; + ENTRY; + +@@ -1211,7 +1211,7 @@ int osd_obj_spec_lookup(struct osd_thread_info *info, struct osd_device *osd, + struct dentry *root; + struct dentry *dentry; + struct inode *inode; +- char *name; ++ char *name = NULL; + int rc = -ENOENT; + ENTRY; + diff --git a/lustre/osd-ldiskfs/osd_handler.c b/lustre/osd-ldiskfs/osd_handler.c -index c13c682..7f8748d 100644 +index 9027533..dfaa542 100644 --- a/lustre/osd-ldiskfs/osd_handler.c +++ b/lustre/osd-ldiskfs/osd_handler.c -@@ -5820,19 +5820,18 @@ static struct obd_ops osd_obd_device_ops = { - - static int __init osd_mod_init(void) +@@ -5814,6 +5814,7 @@ static struct lu_device *osd_device_free(const struct lu_env *env, + static int osd_process_config(const struct lu_env *env, + struct lu_device *d, struct lustre_cfg *cfg) { -- struct lprocfs_static_vars lvars; - int rc; - - osd_oi_mod_init(); -- lprocfs_osd_init_vars(&lvars); - - rc = lu_kmem_init(ldiskfs_caches); ++ struct obd_device *obd = d->ld_obd; + struct osd_device *o = osd_dev(d); + int rc; + ENTRY; +@@ -5828,12 +5829,12 @@ static int osd_process_config(const struct lu_env *env, + break; + case LCFG_PARAM: + LASSERT(&o->od_dt_dev); +- rc = class_process_proc_param(PARAM_OSD, lprocfs_osd_obd_vars, +- cfg, &o->od_dt_dev); ++ rc = class_process_proc_seq_param(PARAM_OSD, obd->obd_vars, ++ cfg, &o->od_dt_dev); + if (rc > 0 || rc == -ENOSYS) +- rc = class_process_proc_param(PARAM_OST, +- lprocfs_osd_obd_vars, +- cfg, &o->od_dt_dev); ++ rc = class_process_proc_seq_param(PARAM_OST, ++ obd->obd_vars, cfg, ++ &o->od_dt_dev); + break; + default: + rc = -ENOSYS; +@@ -5981,9 +5982,10 @@ static int __init osd_mod_init(void) if (rc) return rc; - rc = class_register_type(&osd_obd_device_ops, NULL, NULL, +-#ifndef HAVE_ONLY_PROCFS_SEQ + rc = class_register_type(&osd_obd_device_ops, NULL, -+ lprocfs_osd_module_vars, - #ifndef HAVE_ONLY_PROCFS_SEQ -- lvars.module_vars, + lprocfs_osd_module_vars, ++#ifndef HAVE_ONLY_PROCFS_SEQ + NULL, #endif LUSTRE_OSD_LDISKFS_NAME, &osd_device_type); if (rc) diff --git a/lustre/osd-ldiskfs/osd_internal.h b/lustre/osd-ldiskfs/osd_internal.h -index 8d5ca40..35d1b10 100644 +index 8436d1f..c90147f 100644 --- a/lustre/osd-ldiskfs/osd_internal.h +++ b/lustre/osd-ldiskfs/osd_internal.h -@@ -623,11 +623,11 @@ static inline int __osd_xattr_set(struct osd_thread_info *info, +@@ -623,8 +623,8 @@ static inline int __osd_xattr_set(struct osd_thread_info *info, #ifdef LPROCFS /* osd_lproc.c */ --void lprocfs_osd_init_vars(struct lprocfs_static_vars *lvars); +-extern struct lprocfs_vars lprocfs_osd_obd_vars[]; +-extern struct lprocfs_vars lprocfs_osd_module_vars[]; ++extern struct lprocfs_seq_vars lprocfs_osd_obd_vars[]; +extern struct lprocfs_seq_vars lprocfs_osd_module_vars[]; -+ int osd_procfs_init(struct osd_device *osd, const char *name); int osd_procfs_fini(struct osd_device *osd); void osd_brw_stats_update(struct osd_device *osd, struct osd_iobuf *iobuf); -- - #endif - int osd_statfs(const struct lu_env *env, struct dt_device *dev, - struct obd_statfs *sfs); -@@ -678,7 +678,7 @@ int osd_oii_insert(struct osd_device *dev, struct osd_idmap_cache *oic, +@@ -679,7 +679,7 @@ int osd_oii_insert(struct osd_device *dev, struct osd_idmap_cache *oic, int insert); int osd_oii_lookup(struct osd_device *dev, const struct lu_fid *fid, struct osd_inode_id *id); @@ -71,16 +116,15 @@ index 8d5ca40..35d1b10 100644 int osd_fld_lookup(const struct lu_env *env, struct osd_device *osd, obd_seq seq, struct lu_seq_range *range); diff --git a/lustre/osd-ldiskfs/osd_lproc.c b/lustre/osd-ldiskfs/osd_lproc.c -index 83bb586..528f60e 100644 +index b9b4e3d..67f3423 100644 --- a/lustre/osd-ldiskfs/osd_lproc.c +++ b/lustre/osd-ldiskfs/osd_lproc.c -@@ -237,93 +237,45 @@ out: +@@ -237,92 +237,46 @@ out: RETURN(result); } -int osd_procfs_init(struct osd_device *osd, const char *name) -{ -- struct lprocfs_static_vars lvars; - struct obd_type *type; - int rc; - ENTRY; @@ -93,9 +137,9 @@ index 83bb586..528f60e 100644 - LASSERT(type != NULL); - - /* Find the type procroot and add the proc entry for this device */ -- lprocfs_osd_init_vars(&lvars); - osd->od_proc_entry = lprocfs_register(name, type->typ_procroot, -- lvars.obd_vars, &osd->od_dt_dev); +- lprocfs_osd_obd_vars, +- &osd->od_dt_dev); - if (IS_ERR(osd->od_proc_entry)) { - rc = PTR_ERR(osd->od_proc_entry); - CERROR("Error %d setting up lprocfs for %s\n", @@ -155,7 +199,7 @@ index 83bb586..528f60e 100644 + return -EINPROGRESS; - return snprintf(page, count, "%s\n", osd->od_mntdev); -+ return seq_printf(m, "%s\n", osd->od_mntdev); ++ return seq_printf(m, "%u\n", osd->od_read_cache); } +LPROC_SEQ_FOPS_RO(ldiskfs_osd_mntdev); @@ -178,17 +222,18 @@ index 83bb586..528f60e 100644 - unsigned long count, void *data) +static ssize_t +ldiskfs_osd_cache_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) ++ size_t count, loff_t *off) { - struct osd_device *osd = osd_dt_dev(data); - int val, rc; -+ struct dt_device *dt = ((struct seq_file *)file->private_data)->private; ++ struct seq_file *m = file->private_data; ++ struct dt_device *dt = m->private; + struct osd_device *osd = osd_dt_dev(dt); + int val, rc; LASSERT(osd != NULL); if (unlikely(osd->od_mnt == NULL)) -@@ -336,24 +288,26 @@ static int lprocfs_osd_wr_cache(struct file *file, const char *buffer, +@@ -335,24 +289,26 @@ static int lprocfs_osd_wr_cache(struct file *file, const char *buffer, osd->od_read_cache = !!val; return count; } @@ -223,7 +268,7 @@ index 83bb586..528f60e 100644 LASSERT(osd != NULL); if (unlikely(osd->od_mnt == NULL)) -@@ -366,14 +320,16 @@ static int lprocfs_osd_wr_wcache(struct file *file, const char *buffer, +@@ -365,14 +321,16 @@ static int lprocfs_osd_wr_wcache(struct file *file, const char *buffer, osd->od_writethrough_cache = !!val; return count; } @@ -246,7 +291,7 @@ index 83bb586..528f60e 100644 LASSERT(osd != NULL); if (unlikely(osd->od_mnt == NULL)) -@@ -387,20 +343,18 @@ static int lprocfs_osd_wr_force_sync(struct file *file, const char *buffer, +@@ -386,20 +344,18 @@ static int lprocfs_osd_wr_force_sync(struct file *file, const char *buffer, return rc == 0 ? count : rc; } @@ -274,7 +319,7 @@ index 83bb586..528f60e 100644 rc = lprocfs_write_helper(buffer, count, &pdo); if (rc != 0) -@@ -410,24 +364,25 @@ static int lprocfs_osd_wr_pdo(struct file *file, const char *buffer, +@@ -409,24 +365,25 @@ static int lprocfs_osd_wr_pdo(struct file *file, const char *buffer, return count; } @@ -308,7 +353,7 @@ index 83bb586..528f60e 100644 int val, rc; LASSERT(dev != NULL); -@@ -441,19 +396,18 @@ static int lprocfs_osd_wr_auto_scrub(struct file *file, const char *buffer, +@@ -440,19 +397,18 @@ static int lprocfs_osd_wr_auto_scrub(struct file *file, const char *buffer, dev->od_noscrub = !val; return count; } @@ -335,7 +380,7 @@ index 83bb586..528f60e 100644 { int track_declares_assert; int rc; -@@ -466,38 +420,39 @@ static int lprocfs_osd_wr_track_declares_assert(struct file *file, +@@ -465,38 +421,39 @@ static int lprocfs_osd_wr_track_declares_assert(struct file *file, return count; } @@ -389,7 +434,7 @@ index 83bb586..528f60e 100644 __u64 val; int rc; -@@ -513,24 +468,25 @@ int lprocfs_osd_wr_readcache(struct file *file, const char *buffer, +@@ -512,24 +469,25 @@ int lprocfs_osd_wr_readcache(struct file *file, const char *buffer, OSD_MAX_CACHE_SIZE : val; return count; } @@ -423,7 +468,7 @@ index 83bb586..528f60e 100644 int val; int rc; -@@ -545,43 +501,86 @@ static int lprocfs_osd_wr_lma_self_repair(struct file *file, const char *buffer, +@@ -544,38 +502,104 @@ static int lprocfs_osd_wr_lma_self_repair(struct file *file, const char *buffer, dev->od_lma_self_repair = !!val; return count; } @@ -459,23 +504,39 @@ index 83bb586..528f60e 100644 +LPROC_SEQ_FOPS_RO_TYPE(ldiskfs, dt_filestotal); +LPROC_SEQ_FOPS_RO_TYPE(ldiskfs, dt_filesfree); + -+static struct lprocfs_seq_vars lprocfs_osd_obd_vars[] = { -+ { "blocksize", &ldiskfs_dt_blksize_fops }, -+ { "kbytestotal", &ldiskfs_dt_kbytestotal_fops }, -+ { "kbytesfree", &ldiskfs_dt_kbytesfree_fops }, -+ { "kbytesavail", &ldiskfs_dt_kbytesavail_fops }, -+ { "filestotal", &ldiskfs_dt_filestotal_fops }, -+ { "filesfree", &ldiskfs_dt_filesfree_fops }, -+ { "fstype", &ldiskfs_osd_fstype_fops }, -+ { "mntdev", &ldiskfs_osd_mntdev_fops }, -+ { "force_sync", &ldiskfs_osd_force_sync_fops }, -+ { "pdo", &ldiskfs_osd_pdo_fops }, -+ { "auto_scrub", &ldiskfs_osd_auto_scrub_fops }, -+ { "oi_scrub", &ldiskfs_osd_oi_scrub_fops }, -+ { "read_cache_enable", &ldiskfs_osd_cache_fops }, -+ { "writethrough_cache_enable", &ldiskfs_osd_wcache_fops }, -+ { "readcache_max_filesize", &ldiskfs_osd_readcache_fops }, -+ { "lma_self_repair", &ldiskfs_osd_lma_self_repair_fops }, ++struct lprocfs_seq_vars lprocfs_osd_obd_vars[] = { ++ { .name = "blocksize", ++ .fops = &ldiskfs_dt_blksize_fops }, ++ { .name = "kbytestotal", ++ .fops = &ldiskfs_dt_kbytestotal_fops }, ++ { .name = "kbytesfree", ++ .fops = &ldiskfs_dt_kbytesfree_fops }, ++ { .name = "kbytesavail", ++ .fops = &ldiskfs_dt_kbytesavail_fops }, ++ { .name = "filestotal", ++ .fops = &ldiskfs_dt_filestotal_fops }, ++ { .name = "filesfree", ++ .fops = &ldiskfs_dt_filesfree_fops }, ++ { .name = "fstype", ++ .fops = &ldiskfs_osd_fstype_fops }, ++ { .name = "mntdev", ++ .fops = &ldiskfs_osd_mntdev_fops }, ++ { .name = "force_sync", ++ .fops = &ldiskfs_osd_force_sync_fops }, ++ { .name = "pdo", ++ .fops = &ldiskfs_osd_pdo_fops }, ++ { .name = "auto_scrub", ++ .fops = &ldiskfs_osd_auto_scrub_fops }, ++ { .name = "oi_scrub", ++ .fops = &ldiskfs_osd_oi_scrub_fops }, ++ { .name = "read_cache_enable", ++ .fops = &ldiskfs_osd_cache_fops }, ++ { .name = "writethrough_cache_enable", ++ .fops = &ldiskfs_osd_wcache_fops }, ++ { .name = "readcache_max_filesize", ++ .fops = &ldiskfs_osd_readcache_fops }, ++ { .name = "lma_self_repair", ++ .fops = &ldiskfs_osd_lma_self_repair_fops }, { 0 } }; @@ -486,11 +547,12 @@ index 83bb586..528f60e 100644 - 0 }, - { 0 } +struct lprocfs_seq_vars lprocfs_osd_module_vars[] = { -+ { "track_declares_assert", &ldiskfs_osd_track_declares_assert_fops }, ++ { .name = "track_declares_assert", ++ .fops = &ldiskfs_osd_track_declares_assert_fops }, + { 0 } }; --void lprocfs_osd_init_vars(struct lprocfs_static_vars *lvars) ++ +int osd_procfs_init(struct osd_device *osd, const char *name) +{ + struct obd_type *type; @@ -509,12 +571,12 @@ index 83bb586..528f60e 100644 + + /* Find the type procroot and add the proc entry for this device */ + osd->od_proc_entry = lprocfs_seq_register(name, type->typ_procroot, -+ lprocfs_osd_obd_vars, -+ &osd->od_dt_dev); ++ lprocfs_osd_obd_vars, ++ &osd->od_dt_dev); + if (IS_ERR(osd->od_proc_entry)) { + rc = PTR_ERR(osd->od_proc_entry); + CERROR("Error %d setting up lprocfs for %s\n", -+ rc, name); ++ rc, name); + osd->od_proc_entry = NULL; + GOTO(out, rc); + } @@ -529,9 +591,7 @@ index 83bb586..528f60e 100644 +} + +int osd_procfs_fini(struct osd_device *osd) - { -- lvars->module_vars = lprocfs_osd_module_vars; -- lvars->obd_vars = lprocfs_osd_obd_vars; ++{ + if (osd->od_stats) + lprocfs_free_stats(&osd->od_stats); + @@ -540,13 +600,13 @@ index 83bb586..528f60e 100644 + osd->od_proc_entry = NULL; + } + RETURN(0); - } ++} #endif diff --git a/lustre/osd-ldiskfs/osd_scrub.c b/lustre/osd-ldiskfs/osd_scrub.c -index 18a0a2a..38f5d29 100644 +index cce33af..1002913 100644 --- a/lustre/osd-ldiskfs/osd_scrub.c +++ b/lustre/osd-ldiskfs/osd_scrub.c -@@ -2508,80 +2508,69 @@ static const char *scrub_param_names[] = { +@@ -2578,80 +2578,69 @@ static const char *scrub_param_names[] = { NULL }; @@ -641,7 +701,7 @@ index 18a0a2a..38f5d29 100644 "name: OI_scrub\n" "magic: 0x%x\n" "oi_files: %d\n" -@@ -2591,51 +2580,48 @@ int osd_scrub_dump(struct osd_device *dev, char *buf, int len) +@@ -2661,51 +2650,48 @@ int osd_scrub_dump(struct osd_device *dev, char *buf, int len) if (rc <= 0) goto out; @@ -702,7 +762,7 @@ index 18a0a2a..38f5d29 100644 "updated: "LPU64"\n" "failed: "LPU64"\n" "prior_updated: "LPU64"\n" -@@ -2648,8 +2634,6 @@ int osd_scrub_dump(struct osd_device *dev, char *buf, int len) +@@ -2718,8 +2704,6 @@ int osd_scrub_dump(struct osd_device *dev, char *buf, int len) if (rc <= 0) goto out; @@ -711,7 +771,7 @@ index 18a0a2a..38f5d29 100644 speed = checked; if (thread_is_running(&scrub->os_thread)) { cfs_duration_t duration = cfs_time_current() - -@@ -2662,8 +2646,7 @@ int osd_scrub_dump(struct osd_device *dev, char *buf, int len) +@@ -2732,8 +2716,7 @@ int osd_scrub_dump(struct osd_device *dev, char *buf, int len) do_div(new_checked, duration); if (rtime != 0) do_div(speed, rtime); @@ -721,7 +781,7 @@ index 18a0a2a..38f5d29 100644 "average_speed: "LPU64" objects/sec\n" "real-time_speed: "LPU64" objects/sec\n" "current_position: %u\n" -@@ -2676,8 +2659,7 @@ int osd_scrub_dump(struct osd_device *dev, char *buf, int len) +@@ -2746,8 +2729,7 @@ int osd_scrub_dump(struct osd_device *dev, char *buf, int len) } else { if (sf->sf_run_time != 0) do_div(speed, sf->sf_run_time); @@ -731,7 +791,7 @@ index 18a0a2a..38f5d29 100644 "average_speed: "LPU64" objects/sec\n" "real-time_speed: N/A\n" "current_position: N/A\n" -@@ -2689,10 +2671,7 @@ int osd_scrub_dump(struct osd_device *dev, char *buf, int len) +@@ -2759,10 +2741,7 @@ int osd_scrub_dump(struct osd_device *dev, char *buf, int len) } if (rc <= 0) goto out; @@ -744,5 +804,5 @@ index 18a0a2a..38f5d29 100644 out: up_read(&scrub->os_rwsem); -- -1.8.5.1 +1.8.5.3 diff --git a/sys-cluster/lustre/files/0010-LU-3319-procfs-update-shared-server-side-core-proc-h.patch b/sys-cluster/lustre/files/0010-LU-3319-procfs-update-shared-server-side-core-proc-h.patch deleted file mode 100644 index 01afb45f4..000000000 --- a/sys-cluster/lustre/files/0010-LU-3319-procfs-update-shared-server-side-core-proc-h.patch +++ /dev/null @@ -1,1260 +0,0 @@ -From 7ae65a1edcb16232d34ead46860f6390ce93f583 Mon Sep 17 00:00:00 2001 -From: James Simmons <uja.ornl@gmail.com> -Date: Tue, 3 Dec 2013 16:30:21 -0500 -Subject: [PATCH 10/18] LU-3319 procfs: update shared server side core proc - handling to seq_files - -Several of the server side abstact layers such as mdt,mgs -etc share several common proc handling routines. This patch -adds the seq_file version so that the stack can gradually -be ported over to these new methods. - -Signed-off-by: James Simmons <uja.ornl@gmail.com> -Change-Id: I2dd64046fdd4d2bb6f7550bb49cf1c9ef703c157 ---- - libcfs/include/libcfs/libcfs_hash.h | 5 + - libcfs/libcfs/hash.c | 80 ++++++ - lustre/include/dt_object.h | 8 + - lustre/include/lprocfs_status.h | 101 ++++++-- - lustre/obdclass/dt_object.c | 96 +++++++- - lustre/obdclass/lprocfs_jobstats.c | 47 +++- - lustre/obdclass/lprocfs_status.c | 467 ++++++++++++++++++++++++++++++++---- - lustre/ptlrpc/lproc_ptlrpc.c | 43 ---- - 8 files changed, 724 insertions(+), 123 deletions(-) - -diff --git a/libcfs/include/libcfs/libcfs_hash.h b/libcfs/include/libcfs/libcfs_hash.h -index e7d2dc8..07a12f6 100644 ---- a/libcfs/include/libcfs/libcfs_hash.h -+++ b/libcfs/include/libcfs/libcfs_hash.h -@@ -840,8 +840,13 @@ static inline void __cfs_hash_set_theta(cfs_hash_t *hs, int min, int max) - } - - /* Generic debug formatting routines mainly for proc handler */ -+#ifndef HAVE_ONLY_PROCFS_SEQ - int cfs_hash_debug_header(char *str, int size); - int cfs_hash_debug_str(cfs_hash_t *hs, char *str, int size); -+#endif -+struct seq_file; -+int cfs_hash_debug_header_seq(struct seq_file *m); -+int cfs_hash_debug_str_seq(cfs_hash_t *hs, struct seq_file *m); - - /* - * Generic djb2 hash algorithm for character arrays. -diff --git a/libcfs/libcfs/hash.c b/libcfs/libcfs/hash.c -index 35c64a0..0c4faf8 100644 ---- a/libcfs/libcfs/hash.c -+++ b/libcfs/libcfs/hash.c -@@ -2026,6 +2026,7 @@ void cfs_hash_rehash_key(cfs_hash_t *hs, const void *old_key, - } - EXPORT_SYMBOL(cfs_hash_rehash_key); - -+#ifndef HAVE_ONLY_PROCFS_SEQ - int cfs_hash_debug_header(char *str, int size) - { - return snprintf(str, size, "%-*s%6s%6s%6s%6s%6s%6s%6s%7s%8s%8s%8s%s\n", -@@ -2035,6 +2036,17 @@ int cfs_hash_debug_header(char *str, int size) - " distribution"); - } - EXPORT_SYMBOL(cfs_hash_debug_header); -+#endif -+ -+int cfs_hash_debug_header_seq(struct seq_file *m) -+{ -+ return seq_printf(m, "%-*s%6s%6s%6s%6s%6s%6s%6s%7s%8s%8s%8s%s\n", -+ CFS_HASH_BIGNAME_LEN, -+ "name", "cur", "min", "max", "theta", "t-min", "t-max", -+ "flags", "rehash", "count", "maxdep", "maxdepb", -+ " distribution"); -+} -+EXPORT_SYMBOL(cfs_hash_debug_header_seq); - - static cfs_hash_bucket_t ** - cfs_hash_full_bkts(cfs_hash_t *hs) -@@ -2060,6 +2072,7 @@ cfs_hash_full_nbkt(cfs_hash_t *hs) - CFS_HASH_RH_NBKT(hs) : CFS_HASH_NBKT(hs); - } - -+#ifndef HAVE_ONLY_PROCFS_SEQ - int cfs_hash_debug_str(cfs_hash_t *hs, char *str, int size) - { - int dist[8] = { 0, }; -@@ -2134,3 +2147,70 @@ int cfs_hash_debug_str(cfs_hash_t *hs, char *str, int size) - return c; - } - EXPORT_SYMBOL(cfs_hash_debug_str); -+#endif -+ -+int cfs_hash_debug_str_seq(cfs_hash_t *hs, struct seq_file *m) -+{ -+ int dist[8] = { 0, }; -+ int maxdep = -1; -+ int maxdepb = -1; -+ int total = 0; -+ int c = 0; -+ int theta; -+ int i; -+ -+ cfs_hash_lock(hs, 0); -+ theta = __cfs_hash_theta(hs); -+ -+ c += seq_printf(m, "%-*s ", CFS_HASH_BIGNAME_LEN, hs->hs_name); -+ c += seq_printf(m, "%5d ", 1 << hs->hs_cur_bits); -+ c += seq_printf(m, "%5d ", 1 << hs->hs_min_bits); -+ c += seq_printf(m, "%5d ", 1 << hs->hs_max_bits); -+ c += seq_printf(m, "%d.%03d ", __cfs_hash_theta_int(theta), -+ __cfs_hash_theta_frac(theta)); -+ c += seq_printf(m, "%d.%03d ", __cfs_hash_theta_int(hs->hs_min_theta), -+ __cfs_hash_theta_frac(hs->hs_min_theta)); -+ c += seq_printf(m, "%d.%03d ", __cfs_hash_theta_int(hs->hs_max_theta), -+ __cfs_hash_theta_frac(hs->hs_max_theta)); -+ c += seq_printf(m, " 0x%02x ", hs->hs_flags); -+ c += seq_printf(m, "%6d ", hs->hs_rehash_count); -+ -+ /* -+ * The distribution is a summary of the chained hash depth in -+ * each of the libcfs hash buckets. Each buckets hsb_count is -+ * divided by the hash theta value and used to generate a -+ * histogram of the hash distribution. A uniform hash will -+ * result in all hash buckets being close to the average thus -+ * only the first few entries in the histogram will be non-zero. -+ * If you hash function results in a non-uniform hash the will -+ * be observable by outlier bucks in the distribution histogram. -+ * -+ * Uniform hash distribution: 128/128/0/0/0/0/0/0 -+ * Non-Uniform hash distribution: 128/125/0/0/0/0/2/1 -+ */ -+ for (i = 0; i < cfs_hash_full_nbkt(hs); i++) { -+ cfs_hash_bd_t bd; -+ -+ bd.bd_bucket = cfs_hash_full_bkts(hs)[i]; -+ cfs_hash_bd_lock(hs, &bd, 0); -+ if (maxdep < bd.bd_bucket->hsb_depmax) { -+ maxdep = bd.bd_bucket->hsb_depmax; -+#ifdef __KERNEL__ -+ maxdepb = ffz(~maxdep); -+#endif -+ } -+ total += bd.bd_bucket->hsb_count; -+ dist[min(fls(bd.bd_bucket->hsb_count/max(theta,1)),7)]++; -+ cfs_hash_bd_unlock(hs, &bd, 0); -+ } -+ -+ c += seq_printf(m, "%7d ", total); -+ c += seq_printf(m, "%7d ", maxdep); -+ c += seq_printf(m, "%7d ", maxdepb); -+ for (i = 0; i < 8; i++) -+ c += seq_printf(m, "%d%c", dist[i], (i == 7) ? '\n' : '/'); -+ -+ cfs_hash_unlock(hs, 0); -+ return c; -+} -+EXPORT_SYMBOL(cfs_hash_debug_str_seq); -diff --git a/lustre/include/dt_object.h b/lustre/include/dt_object.h -index bdf559d..ba88a80 100644 ---- a/lustre/include/dt_object.h -+++ b/lustre/include/dt_object.h -@@ -1489,6 +1489,7 @@ int dt_global_init(void); - void dt_global_fini(void); - - # ifdef LPROCFS -+#ifndef HAVE_ONLY_PROCFS_SEQ - int lprocfs_dt_rd_blksize(char *page, char **start, off_t off, - int count, int *eof, void *data); - int lprocfs_dt_rd_kbytestotal(char *page, char **start, off_t off, -@@ -1501,6 +1502,13 @@ int lprocfs_dt_rd_filestotal(char *page, char **start, off_t off, - int count, int *eof, void *data); - int lprocfs_dt_rd_filesfree(char *page, char **start, off_t off, - int count, int *eof, void *data); -+#endif -+int lprocfs_dt_blksize_seq_show(struct seq_file *m, void *v); -+int lprocfs_dt_kbytestotal_seq_show(struct seq_file *m, void *v); -+int lprocfs_dt_kbytesfree_seq_show(struct seq_file *m, void *v); -+int lprocfs_dt_kbytesavail_seq_show(struct seq_file *m, void *v); -+int lprocfs_dt_filestotal_seq_show(struct seq_file *m, void *v); -+int lprocfs_dt_filesfree_seq_show(struct seq_file *m, void *v); - # endif /* LPROCFS */ - - #endif /* __LUSTRE_DT_OBJECT_H */ -diff --git a/lustre/include/lprocfs_status.h b/lustre/include/lprocfs_status.h -index 2080592..70f10a9 100644 ---- a/lustre/include/lprocfs_status.h -+++ b/lustre/include/lprocfs_status.h -@@ -603,12 +603,19 @@ extern struct proc_dir_entry * - lprocfs_add_symlink(const char *name, struct proc_dir_entry *parent, - const char *format, ...); - extern void lprocfs_free_per_client_stats(struct obd_device *obd); -+#ifdef HAVE_SERVER_SUPPORT -+#ifndef HAVE_ONLY_PROCFS_SEQ - extern int - lprocfs_nid_stats_clear_write(struct file *file, const char *buffer, - unsigned long count, void *data); - extern int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off, - int count, int *eof, void *data); -- -+#endif -+extern ssize_t -+lprocfs_nid_stats_clear_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off); -+extern int lprocfs_nid_stats_clear_seq_show(struct seq_file *file, void *data); -+#endif - extern int lprocfs_register_stats(cfs_proc_dir_entry_t *root, const char *name, - struct lprocfs_stats *stats); - -@@ -700,6 +707,9 @@ extern int lprocfs_conn_uuid_seq_show(struct seq_file *m, void *data); - extern int lprocfs_import_seq_show(struct seq_file *m, void *data); - extern int lprocfs_state_seq_show(struct seq_file *m, void *data); - extern int lprocfs_connect_flags_seq_show(struct seq_file *m, void *data); -+#ifdef HAVE_SERVER_SUPPORT -+extern int lprocfs_num_exports_seq_show(struct seq_file *m, void *data); -+#endif - struct adaptive_timeout; - #ifndef HAVE_ONLY_PROCFS_SEQ - extern int lprocfs_at_hist_helper(char *page, int count, int rc, -@@ -715,9 +725,11 @@ extern int lprocfs_timeouts_seq_show(struct seq_file *m, void *data); - extern ssize_t - lprocfs_timeouts_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off); -+#ifndef HAVE_ONLY_PROCFS_SEQ -+#ifdef HAVE_SERVER_SUPPORT - extern int lprocfs_wr_evict_client(struct file *file, const char *buffer, - unsigned long count, void *data); --#ifndef HAVE_ONLY_PROCFS_SEQ -+#endif - extern int lprocfs_wr_ping(struct file *file, const char *buffer, - unsigned long count, void *data); - extern int lprocfs_wr_import(struct file *file, const char *buffer, -@@ -727,6 +739,11 @@ extern int lprocfs_rd_pinger_recov(char *page, char **start, off_t off, - extern int lprocfs_wr_pinger_recov(struct file *file, const char *buffer, - unsigned long count, void *data); - #endif -+#ifdef HAVE_SERVER_SUPPORT -+extern ssize_t -+lprocfs_evict_client_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off); -+#endif - extern ssize_t - lprocfs_ping_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off); -@@ -785,10 +802,10 @@ void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx, - struct lprocfs_counter *cnt); - - #ifdef HAVE_SERVER_SUPPORT -+#ifndef HAVE_ONLY_PROCFS_SEQ - /* lprocfs_status.c: recovery status */ - int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off, - int count, int *eof, void *data); --#endif - /* lprocfs_statuc.c: hash statistics */ - int lprocfs_obd_rd_hash(char *page, char **start, off_t off, - int count, int *eof, void *data); -@@ -798,7 +815,19 @@ int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off, - int count, int *eof, void *data); - int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer, - unsigned long count, void *data); -+#endif -+/* lprocfs_status.c: recovery status */ -+int lprocfs_recovery_status_seq_show(struct seq_file *m, void *data); - -+/* lprocfs_status.c: hash statistics */ -+int lprocfs_hash_seq_show(struct seq_file *m, void *data); -+ -+/* lprocfs_status.c: IR factor */ -+int lprocfs_ir_factor_seq_show(struct seq_file *m, void *data); -+ssize_t -+lprocfs_ir_factor_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off); -+#endif - extern int lprocfs_single_release(cfs_inode_t *, struct file *); - extern int lprocfs_seq_release(cfs_inode_t *, struct file *); - -@@ -874,21 +903,23 @@ struct file_operations name##_fops = { \ - .release = lprocfs_single_release, \ - }; - -+/* lproc_ptlrpc.c */ -+struct ptlrpc_request; -+extern void target_print_req(void *seq_file, struct ptlrpc_request *req); -+ -+#ifdef HAVE_SERVER_SUPPORT - /* lprocfs_jobstats.c */ - int lprocfs_job_stats_log(struct obd_device *obd, char *jobid, - int event, long amount); - void lprocfs_job_stats_fini(struct obd_device *obd); - int lprocfs_job_stats_init(struct obd_device *obd, int cntr_num, - cntr_init_callback fn); -+#ifndef HAVE_ONLY_PROCFS_SEQ - int lprocfs_rd_job_interval(char *page, char **start, off_t off, - int count, int *eof, void *data); - int lprocfs_wr_job_interval(struct file *file, const char *buffer, - unsigned long count, void *data); - --/* lproc_ptlrpc.c */ --struct ptlrpc_request; --extern void target_print_req(void *seq_file, struct ptlrpc_request *req); -- - /* lproc_status.c */ - int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off, - int count, int *eof, void *data); -@@ -900,6 +931,24 @@ int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off, - int lprocfs_obd_wr_recovery_time_hard(struct file *file, - const char *buffer, - unsigned long count, void *data); -+int lprocfs_target_rd_instance(char *page, char **start, off_t off, -+ int count, int *eof, void *data); -+#endif -+int lprocfs_job_interval_seq_show(struct seq_file *m, void *data); -+ssize_t -+lprocfs_job_interval_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off); -+/* lproc_status.c */ -+int lprocfs_recovery_time_soft_seq_show(struct seq_file *m, void *data); -+ssize_t lprocfs_recovery_time_soft_seq_write(struct file *file, -+ const char *buffer, -+ size_t count, loff_t *off); -+int lprocfs_recovery_time_hard_seq_show(struct seq_file *m, void *data); -+ssize_t -+lprocfs_recovery_time_hard_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off); -+int lprocfs_target_instance_seq_show(struct seq_file *m, void *data); -+#endif - #ifndef HAVE_ONLY_PROCFS_SEQ - int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off, - int count, int *eof, void *data); -@@ -910,8 +959,6 @@ int lprocfs_obd_max_pages_per_rpc_seq_show(struct seq_file *m, void *data); - ssize_t - lprocfs_obd_max_pages_per_rpc_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off); --int lprocfs_target_rd_instance(char *page, char **start, off_t off, -- int count, int *eof, void *data); - - /* all quota proc functions */ - extern int lprocfs_quota_rd_bunit(char *page, char **start, -@@ -1032,7 +1079,26 @@ static inline void lprocfs_free_md_stats(struct obd_device *obddev) - struct obd_export; - static inline int lprocfs_add_clear_entry(struct obd_export *exp) - { return 0; } -+static inline void lprocfs_free_per_client_stats(struct obd_device *obd) -+{ return; } - #ifdef HAVE_SERVER_SUPPORT -+#ifndef HAVE_ONLY_PROCFS_SEQ -+static inline -+int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer, -+ unsigned long count, void *data) -+{return count;} -+static inline -+int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{return count;} -+#endif -+static inline -+ssize_t lprocfs_nid_stats_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) -+{return 0;} -+static inline -+int lprocfs_nid_stats_clear_seq_show(struct seq_file *m, void *data) -+{return 0;} - static inline int lprocfs_exp_setup(struct obd_export *exp,lnet_nid_t *peer_nid, - int *newnid) - { return 0; } -@@ -1050,17 +1116,6 @@ static inline struct proc_dir_entry * - lprocfs_add_symlink(const char *name, struct proc_dir_entry *parent, - const char *format, ...) - {return NULL; } --static inline void lprocfs_free_per_client_stats(struct obd_device *obd) --{ return; } --static inline --int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer, -- unsigned long count, void *data) --{return count;} --static inline --int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off, -- int count, int *eof, void *data) --{return count;} -- - #ifndef HAVE_ONLY_PROCFS_SEQ - static inline cfs_proc_dir_entry_t * - lprocfs_register(const char *name, cfs_proc_dir_entry_t *parent, -@@ -1145,10 +1200,12 @@ static inline int lprocfs_wr_timeouts(struct file *file, - const char *buffer, - unsigned long count, void *data) - { return 0; } -+#ifdef HAVE_SERVER_SUPPORT - static inline int lprocfs_wr_evict_client(struct file *file, - const char *buffer, - unsigned long count, void *data) - { return 0; } -+#endif - static inline int lprocfs_wr_ping(struct file *file, const char *buffer, - unsigned long count, void *data) - { return 0; } -@@ -1173,8 +1230,10 @@ static inline int lprocfs_state_seq_show(struct seq_file *m, void *data) - { return 0; } - static inline int lprocfs_connect_flags_seq_show(struct seq_file *m, void *data) - { return 0; } -+#ifdef HAVE_SERVER_SUPPORT - static inline int lprocfs_num_exports_seq_show(struct seq_file *m, void *data) - { return 0; } -+#endif - struct adaptive_timeout; - static inline int lprocfs_seq_at_hist_helper(struct seq_file *m, - struct adaptive_timeout *at) -@@ -1185,10 +1244,12 @@ static inline ssize_t - lprocfs_timeouts_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) - { return 0; } -+#ifdef HAVE_SERVER_SUPPORT - static inline ssize_t - lprocfs_evict_client_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) - { return 0; } -+#endif - static inline ssize_t - lprocfs_ping_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) -diff --git a/lustre/obdclass/dt_object.c b/lustre/obdclass/dt_object.c -index deb5863..242a45d 100644 ---- a/lustre/obdclass/dt_object.c -+++ b/lustre/obdclass/dt_object.c -@@ -936,7 +936,7 @@ out: - EXPORT_SYMBOL(dt_index_read); - - #ifdef LPROCFS -- -+#ifndef HAVE_ONLY_PROCFS_SEQ - int lprocfs_dt_rd_blksize(char *page, char **start, off_t off, - int count, int *eof, void *data) - { -@@ -1051,5 +1051,99 @@ int lprocfs_dt_rd_filesfree(char *page, char **start, off_t off, - return rc; - } - EXPORT_SYMBOL(lprocfs_dt_rd_filesfree); -+#endif -+ -+int lprocfs_dt_blksize_seq_show(struct seq_file *m, void *v) -+{ -+ struct dt_device *dt = m->private; -+ struct obd_statfs osfs; -+ -+ int rc = dt_statfs(NULL, dt, &osfs); -+ if (rc == 0) -+ seq_printf(m, "%u\n", (unsigned) osfs.os_bsize); -+ return rc; -+} -+EXPORT_SYMBOL(lprocfs_dt_blksize_seq_show); -+ -+int lprocfs_dt_kbytestotal_seq_show(struct seq_file *m, void *v) -+{ -+ struct dt_device *dt = m->private; -+ struct obd_statfs osfs; -+ -+ int rc = dt_statfs(NULL, dt, &osfs); -+ if (rc == 0) { -+ __u32 blk_size = osfs.os_bsize >> 10; -+ __u64 result = osfs.os_blocks; -+ -+ while (blk_size >>= 1) -+ result <<= 1; -+ -+ seq_printf(m, LPU64"\n", result); -+ } -+ return rc; -+} -+EXPORT_SYMBOL(lprocfs_dt_kbytestotal_seq_show); -+ -+int lprocfs_dt_kbytesfree_seq_show(struct seq_file *m, void *v) -+{ -+ struct dt_device *dt = m->private; -+ struct obd_statfs osfs; -+ -+ int rc = dt_statfs(NULL, dt, &osfs); -+ if (rc == 0) { -+ __u32 blk_size = osfs.os_bsize >> 10; -+ __u64 result = osfs.os_bfree; -+ -+ while (blk_size >>= 1) -+ result <<= 1; -+ -+ seq_printf(m, LPU64"\n", result); -+ } -+ return rc; -+} -+EXPORT_SYMBOL(lprocfs_dt_kbytesfree_seq_show); -+ -+int lprocfs_dt_kbytesavail_seq_show(struct seq_file *m, void *v) -+{ -+ struct dt_device *dt = m->private; -+ struct obd_statfs osfs; -+ -+ int rc = dt_statfs(NULL, dt, &osfs); -+ if (rc == 0) { -+ __u32 blk_size = osfs.os_bsize >> 10; -+ __u64 result = osfs.os_bavail; -+ -+ while (blk_size >>= 1) -+ result <<= 1; -+ -+ seq_printf(m, LPU64"\n", result); -+ } -+ return rc; -+} -+EXPORT_SYMBOL(lprocfs_dt_kbytesavail_seq_show); -+ -+int lprocfs_dt_filestotal_seq_show(struct seq_file *m, void *v) -+{ -+ struct dt_device *dt = m->private; -+ struct obd_statfs osfs; -+ -+ int rc = dt_statfs(NULL, dt, &osfs); -+ if (rc == 0) -+ seq_printf(m, LPU64"\n", osfs.os_files); -+ return rc; -+} -+EXPORT_SYMBOL(lprocfs_dt_filestotal_seq_show); -+ -+int lprocfs_dt_filesfree_seq_show(struct seq_file *m, void *v) -+{ -+ struct dt_device *dt = m->private; -+ struct obd_statfs osfs; -+ -+ int rc = dt_statfs(NULL, dt, &osfs); -+ if (rc == 0) -+ seq_printf(m, LPU64"\n", osfs.os_ffree); -+ return rc; -+} -+EXPORT_SYMBOL(lprocfs_dt_filesfree_seq_show); - - #endif /* LPROCFS */ -diff --git a/lustre/obdclass/lprocfs_jobstats.c b/lustre/obdclass/lprocfs_jobstats.c -index f67e426..4e16a17 100644 ---- a/lustre/obdclass/lprocfs_jobstats.c -+++ b/lustre/obdclass/lprocfs_jobstats.c -@@ -416,18 +416,17 @@ struct seq_operations lprocfs_jobstats_seq_sops = { - - static int lprocfs_jobstats_seq_open(struct inode *inode, struct file *file) - { -- struct proc_dir_entry *dp = PDE(inode); - struct seq_file *seq; - int rc; - -- if (LPROCFS_ENTRY_CHECK(dp)) -+ if (LPROCFS_ENTRY_CHECK(PDE(inode))) - return -ENOENT; - - rc = seq_open(file, &lprocfs_jobstats_seq_sops); - if (rc) - return rc; - seq = file->private_data; -- seq->private = dp->data; -+ seq->private = PDE_DATA(inode); - return 0; - } - -@@ -520,19 +519,18 @@ int lprocfs_job_stats_init(struct obd_device *obd, int cntr_num, - stats->ojs_last_cleanup = cfs_time_current_sec(); - - LPROCFS_WRITE_ENTRY(); -- entry = create_proc_entry("job_stats", 0644, obd->obd_proc_entry); -+ entry = proc_create_data("job_stats", 0644, obd->obd_proc_entry, -+ &lprocfs_jobstats_seq_fops, stats); - LPROCFS_WRITE_EXIT(); -- if (entry) { -- entry->proc_fops = &lprocfs_jobstats_seq_fops; -- entry->data = stats; -- RETURN(0); -- } else { -+ if (entry == NULL) { - lprocfs_job_stats_fini(obd); - RETURN(-ENOMEM); - } -+ RETURN(0); - } - EXPORT_SYMBOL(lprocfs_job_stats_init); - -+#ifndef HAVE_ONLY_PROCFS_SEQ - int lprocfs_rd_job_interval(char *page, char **start, off_t off, - int count, int *eof, void *data) - { -@@ -567,5 +565,36 @@ int lprocfs_wr_job_interval(struct file *file, const char *buffer, - - } - EXPORT_SYMBOL(lprocfs_wr_job_interval); -+#endif -+int lprocfs_job_interval_seq_show(struct seq_file *m, void *data) -+{ -+ struct obd_device *obd = m->private; -+ struct obd_job_stats *stats; -+ -+ LASSERT(obd != NULL); -+ stats = &obd->u.obt.obt_jobstats; -+ return seq_printf(m, "%d\n", stats->ojs_cleanup_interval); -+} -+EXPORT_SYMBOL(lprocfs_job_interval_seq_show); -+ -+ssize_t -+lprocfs_job_interval_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) -+{ -+ struct obd_device *obd = ((struct seq_file *)file->private_data)->private; -+ struct obd_job_stats *stats; -+ int val, rc; -+ -+ LASSERT(obd != NULL); -+ stats = &obd->u.obt.obt_jobstats; -+ -+ rc = lprocfs_write_helper(buffer, count, &val); -+ if (rc) -+ return rc; - -+ stats->ojs_cleanup_interval = val; -+ lprocfs_job_cleanup(stats, true); -+ return count; -+} -+EXPORT_SYMBOL(lprocfs_job_interval_seq_write); - #endif /* LPROCFS*/ -diff --git a/lustre/obdclass/lprocfs_status.c b/lustre/obdclass/lprocfs_status.c -index 0c805be..a33cbf2 100644 ---- a/lustre/obdclass/lprocfs_status.c -+++ b/lustre/obdclass/lprocfs_status.c -@@ -288,25 +288,104 @@ static struct file_operations lprocfs_generic_fops = { }; - #ifdef HAVE_SERVER_SUPPORT - int lprocfs_evict_client_open(struct inode *inode, struct file *f) - { -- struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode); -- struct obd_device *obd = dp->data; -- -- cfs_atomic_inc(&obd->obd_evict_inprogress); -+ struct obd_device *obd = PDE_DATA(f->f_dentry->d_inode); - -- return 0; -+ cfs_atomic_inc(&obd->obd_evict_inprogress); -+ return 0; - } - - int lprocfs_evict_client_release(struct inode *inode, struct file *f) - { -- struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode); -- struct obd_device *obd = dp->data; -+ struct obd_device *obd = PDE_DATA(f->f_dentry->d_inode); - - cfs_atomic_dec(&obd->obd_evict_inprogress); - wake_up(&obd->obd_evict_inprogress_waitq); -- - return 0; - } - -+#define BUFLEN (UUID_MAX + 5) -+ -+#ifndef HAVE_ONLY_PROCFS_SEQ -+int lprocfs_wr_evict_client(struct file *file, const char *buffer, -+ unsigned long count, void *data) -+{ -+ struct obd_device *obd = data; -+ char *kbuf; -+ char *tmpbuf; -+ -+ OBD_ALLOC(kbuf, BUFLEN); -+ if (kbuf == NULL) -+ return -ENOMEM; -+ -+ /* -+ * OBD_ALLOC() will zero kbuf, but we only copy BUFLEN - 1 -+ * bytes into kbuf, to ensure that the string is NUL-terminated. -+ * UUID_MAX should include a trailing NUL already. -+ */ -+ if (copy_from_user(kbuf, buffer, -+ min_t(unsigned long, BUFLEN - 1, count))) { -+ count = -EFAULT; -+ goto out; -+ } -+ tmpbuf = cfs_firststr(kbuf, min_t(unsigned long, BUFLEN - 1, count)); -+ class_incref(obd, __FUNCTION__, current); -+ -+ if (strncmp(tmpbuf, "nid:", 4) == 0) -+ obd_export_evict_by_nid(obd, tmpbuf + 4); -+ else if (strncmp(tmpbuf, "uuid:", 5) == 0) -+ obd_export_evict_by_uuid(obd, tmpbuf + 5); -+ else -+ obd_export_evict_by_uuid(obd, tmpbuf); -+ -+ class_decref(obd, __FUNCTION__, current); -+out: -+ OBD_FREE(kbuf, BUFLEN); -+ return count; -+} -+EXPORT_SYMBOL(lprocfs_wr_evict_client); -+#endif -+ -+ssize_t -+lprocfs_evict_client_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) -+{ -+ struct obd_device *obd = ((struct seq_file *)file->private_data)->private; -+ char *tmpbuf, *kbuf; -+ -+ OBD_ALLOC(kbuf, BUFLEN); -+ if (kbuf == NULL) -+ return -ENOMEM; -+ -+ /* -+ * OBD_ALLOC() will zero kbuf, but we only copy BUFLEN - 1 -+ * bytes into kbuf, to ensure that the string is NUL-terminated. -+ * UUID_MAX should include a trailing NUL already. -+ */ -+ if (copy_from_user(kbuf, buffer, -+ min_t(unsigned long, BUFLEN - 1, count))) { -+ count = -EFAULT; -+ goto out; -+ } -+ tmpbuf = cfs_firststr(kbuf, min_t(unsigned long, BUFLEN - 1, count)); -+ class_incref(obd, __FUNCTION__, current); -+ -+ if (strncmp(tmpbuf, "nid:", 4) == 0) -+ obd_export_evict_by_nid(obd, tmpbuf + 4); -+ else if (strncmp(tmpbuf, "uuid:", 5) == 0) -+ obd_export_evict_by_uuid(obd, tmpbuf + 5); -+ else -+ obd_export_evict_by_uuid(obd, tmpbuf); -+ -+ class_decref(obd, __FUNCTION__, current); -+ -+out: -+ OBD_FREE(kbuf, BUFLEN); -+ return count; -+} -+EXPORT_SYMBOL(lprocfs_evict_client_seq_write); -+ -+#undef BUFLEN -+ - struct file_operations lprocfs_evict_client_fops = { - .owner = THIS_MODULE, - .read = lprocfs_fops_read, -@@ -1228,6 +1307,17 @@ int lprocfs_connect_flags_seq_show(struct seq_file *m, void *data) - } - EXPORT_SYMBOL(lprocfs_connect_flags_seq_show); - -+#ifdef HAVE_SERVER_SUPPORT -+int lprocfs_num_exports_seq_show(struct seq_file *m, void *data) -+{ -+ struct obd_device *obd = data; -+ -+ LASSERT(obd != NULL); -+ return seq_printf(m, "%u\n", obd->obd_num_exports); -+} -+EXPORT_SYMBOL(lprocfs_num_exports_seq_show); -+#endif -+ - #ifndef HAVE_ONLY_PROCFS_SEQ - - int lprocfs_rd_uint(char *page, char **start, off_t off, -@@ -1743,6 +1833,7 @@ int lprocfs_rd_connect_flags(char *page, char **start, off_t off, - } - EXPORT_SYMBOL(lprocfs_rd_connect_flags); - -+#ifdef HAVE_SERVER_SUPPORT - int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count, - int *eof, void *data) - { -@@ -1753,6 +1844,7 @@ int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count, - return snprintf(page, count, "%u\n", obd->obd_num_exports); - } - EXPORT_SYMBOL(lprocfs_rd_num_exports); -+#endif - - int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count, - int *eof, void *data) -@@ -2436,6 +2528,112 @@ void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats) - } - EXPORT_SYMBOL(lprocfs_init_ldlm_stats); - -+#ifdef HAVE_SERVER_SUPPORT -+/* No one appears to be using this ?? */ -+int lprocfs_exp_nid_seq_show(struct seq_file *m, void *data) -+{ -+ struct obd_export *exp = m->private; -+ LASSERT(exp != NULL); -+ return seq_printf(m, "%s\n", obd_export_nid2str(exp)); -+} -+ -+int lprocfs_exp_print_uuid_seq(cfs_hash_t *hs, cfs_hash_bd_t *bd, -+ cfs_hlist_node_t *hnode, void *cb_data) -+ -+{ -+ struct obd_export *exp = cfs_hash_object(hs, hnode); -+ struct seq_file *m = cb_data; -+ -+ if (exp->exp_nid_stats) -+ seq_printf(m, "%s\n", obd_uuid2str(&exp->exp_client_uuid)); -+ return 0; -+} -+ -+int lprocfs_exp_uuid_seq_show(struct seq_file *m, void *data) -+{ -+ struct nid_stat *stats = m->private; -+ struct obd_device *obd = stats->nid_obd; -+ -+ cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid, -+ lprocfs_exp_print_uuid_seq, m); -+ return 0; -+} -+LPROC_SEQ_FOPS_RO(lprocfs_exp_uuid); -+ -+int lprocfs_exp_print_hash_seq(cfs_hash_t *hs, cfs_hash_bd_t *bd, -+ cfs_hlist_node_t *hnode, void *cb_data) -+ -+{ -+ struct seq_file *m = cb_data; -+ struct obd_export *exp = cfs_hash_object(hs, hnode); -+ -+ if (exp->exp_lock_hash != NULL) { -+ cfs_hash_debug_header_seq(m); -+ cfs_hash_debug_str_seq(hs, m); -+ } -+ return 0; -+} -+ -+int lprocfs_exp_hash_seq_show(struct seq_file *m, void *data) -+{ -+ struct nid_stat *stats = m->private; -+ struct obd_device *obd = stats->nid_obd; -+ -+ cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid, -+ lprocfs_exp_print_hash_seq, m); -+ return 0; -+} -+LPROC_SEQ_FOPS_RO(lprocfs_exp_hash); -+ -+int lprocfs_nid_stats_clear_seq_show(struct seq_file *m, void *data) -+{ -+ return seq_printf(m, "%s\n", "Write into this file to clear all nid " -+ "stats and stale nid entries"); -+} -+EXPORT_SYMBOL(lprocfs_nid_stats_clear_seq_show); -+ -+static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data) -+{ -+ struct nid_stat *stat = obj; -+ ENTRY; -+ -+ CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count)); -+ if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) { -+ /* object has only hash references. */ -+ spin_lock(&stat->nid_obd->obd_nid_lock); -+ cfs_list_move(&stat->nid_list, data); -+ spin_unlock(&stat->nid_obd->obd_nid_lock); -+ RETURN(1); -+ } -+ /* we has reference to object - only clear data*/ -+ if (stat->nid_stats) -+ lprocfs_clear_stats(stat->nid_stats); -+ -+ RETURN(0); -+} -+ -+ssize_t -+lprocfs_nid_stats_clear_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) -+{ -+ struct obd_device *obd = ((struct seq_file *)file->private_data)->private; -+ struct nid_stat *client_stat; -+ CFS_LIST_HEAD(free_list); -+ -+ cfs_hash_cond_del(obd->obd_nid_stats_hash, -+ lprocfs_nid_stats_clear_write_cb, &free_list); -+ -+ while (!cfs_list_empty(&free_list)) { -+ client_stat = cfs_list_entry(free_list.next, struct nid_stat, -+ nid_list); -+ cfs_list_del_init(&client_stat->nid_list); -+ lprocfs_free_client_stats(client_stat); -+ } -+ return count; -+} -+EXPORT_SYMBOL(lprocfs_nid_stats_clear_seq_write); -+ -+#ifndef HAVE_ONLY_PROCFS_SEQ - int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count, - int *eof, void *data) - { -@@ -2538,26 +2736,6 @@ int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off, - } - EXPORT_SYMBOL(lprocfs_nid_stats_clear_read); - --static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data) --{ -- struct nid_stat *stat = obj; -- ENTRY; -- -- CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count)); -- if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) { -- /* object has only hash references. */ -- spin_lock(&stat->nid_obd->obd_nid_lock); -- cfs_list_move(&stat->nid_list, data); -- spin_unlock(&stat->nid_obd->obd_nid_lock); -- RETURN(1); -- } -- /* we has reference to object - only clear data*/ -- if (stat->nid_stats) -- lprocfs_clear_stats(stat->nid_stats); -- -- RETURN(0); --} -- - int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer, - unsigned long count, void *data) - { -@@ -2578,8 +2756,8 @@ int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer, - return count; - } - EXPORT_SYMBOL(lprocfs_nid_stats_clear_write); -+#endif - --#ifdef HAVE_SERVER_SUPPORT - int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid) - { - struct nid_stat *new_stat, *old_stat; -@@ -2638,11 +2816,17 @@ int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid) - if (buffer == NULL) - GOTO(destroy_new, rc = -ENOMEM); - -- memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE); -+ memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE); -+#ifndef HAVE_ONLY_PROCFS_SEQ - new_stat->nid_proc = lprocfs_register(buffer, -- obd->obd_proc_exports_entry, -- NULL, NULL); -- OBD_FREE(buffer, LNET_NIDSTR_SIZE); -+ obd->obd_proc_exports_entry, -+ NULL, NULL); -+#else -+ new_stat->nid_proc = lprocfs_seq_register(buffer, -+ obd->obd_proc_exports_entry, -+ NULL, NULL); -+#endif -+ OBD_FREE(buffer, LNET_NIDSTR_SIZE); - - if (IS_ERR(new_stat->nid_proc)) { - rc = PTR_ERR(new_stat->nid_proc); -@@ -2652,16 +2836,26 @@ int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid) - GOTO(destroy_new_ns, rc); - } - -+#ifndef HAVE_ONLY_PROCFS_SEQ - entry = lprocfs_add_simple(new_stat->nid_proc, "uuid", - lprocfs_exp_rd_uuid, NULL, new_stat, NULL); -+#else -+ entry = lprocfs_add_simple(new_stat->nid_proc, "uuid", -+ new_stat, &lprocfs_exp_uuid_fops); -+#endif - if (IS_ERR(entry)) { - CWARN("Error adding the NID stats file\n"); - rc = PTR_ERR(entry); - GOTO(destroy_new_ns, rc); - } - -+#ifndef HAVE_ONLY_PROCFS_SEQ - entry = lprocfs_add_simple(new_stat->nid_proc, "hash", - lprocfs_exp_rd_hash, NULL, new_stat, NULL); -+#else -+ entry = lprocfs_add_simple(new_stat->nid_proc, "hash", -+ new_stat, &lprocfs_exp_hash_fops); -+#endif - if (IS_ERR(entry)) { - CWARN("Error adding the hash file\n"); - rc = PTR_ERR(entry); -@@ -3066,6 +3260,181 @@ void lprocfs_oh_clear(struct obd_histogram *oh) - } - EXPORT_SYMBOL(lprocfs_oh_clear); - -+#ifdef HAVE_SERVER_SUPPORT -+int lprocfs_hash_seq_show(struct seq_file *m, void *data) -+{ -+ struct obd_device *obd = m->private; -+ int c = 0; -+ -+ if (obd == NULL) -+ return 0; -+ -+ c += cfs_hash_debug_header_seq(m); -+ c += cfs_hash_debug_str_seq(obd->obd_uuid_hash, m); -+ c += cfs_hash_debug_str_seq(obd->obd_nid_hash, m); -+ c += cfs_hash_debug_str_seq(obd->obd_nid_stats_hash, m); -+ return c; -+} -+EXPORT_SYMBOL(lprocfs_hash_seq_show); -+ -+int lprocfs_recovery_status_seq_show(struct seq_file *m, void *data) -+{ -+ struct obd_device *obd = m->private; -+ -+ LASSERT(obd != NULL); -+ -+ seq_printf(m, "status: \n"); -+ if (obd->obd_max_recoverable_clients == 0) { -+ seq_printf(m, "INACTIVE\n"); -+ goto out; -+ } -+ -+ /* sampled unlocked, but really... */ -+ if (obd->obd_recovering == 0) { -+ seq_printf(m, "COMPLETE\n"); -+ seq_printf(m, "recovery_start: %lu\n", obd->obd_recovery_start); -+ seq_printf(m, "recovery_duration: %lu\n", -+ obd->obd_recovery_end - obd->obd_recovery_start); -+ /* Number of clients that have completed recovery */ -+ seq_printf(m, "completed_clients: %d/%d\n", -+ obd->obd_max_recoverable_clients - -+ obd->obd_stale_clients, -+ obd->obd_max_recoverable_clients); -+ seq_printf(m, "replayed_requests: %d\n", -+ obd->obd_replayed_requests); -+ seq_printf(m, "last_transno: "LPD64"\n", -+ obd->obd_next_recovery_transno - 1); -+ seq_printf(m, "VBR: %s\n", obd->obd_version_recov ? -+ "ENABLED" : "DISABLED"); -+ seq_printf(m, "IR: %s\n", obd->obd_no_ir ? -+ "DISABLED" : "ENABLED"); -+ goto out; -+ } -+ -+ seq_printf(m, "RECOVERING\n"); -+ seq_printf(m, "recovery_start: %lu\n", obd->obd_recovery_start); -+ seq_printf(m, "time_remaining: %lu\n", -+ cfs_time_current_sec() >= -+ obd->obd_recovery_start + -+ obd->obd_recovery_timeout ? 0 : -+ obd->obd_recovery_start + -+ obd->obd_recovery_timeout - -+ cfs_time_current_sec()); -+ seq_printf(m, "connected_clients: %d/%d\n", -+ cfs_atomic_read(&obd->obd_connected_clients), -+ obd->obd_max_recoverable_clients); -+ /* Number of clients that have completed recovery */ -+ seq_printf(m, "req_replay_clients: %d\n", -+ cfs_atomic_read(&obd->obd_req_replay_clients)); -+ seq_printf(m, "lock_repay_clients: %d\n", -+ cfs_atomic_read(&obd->obd_lock_replay_clients)); -+ seq_printf(m, "completed_clients: %d\n", -+ cfs_atomic_read(&obd->obd_connected_clients) - -+ cfs_atomic_read(&obd->obd_lock_replay_clients)); -+ seq_printf(m, "evicted_clients: %d\n", obd->obd_stale_clients); -+ seq_printf(m, "replayed_requests: %d\n", obd->obd_replayed_requests); -+ seq_printf(m, "queued_requests: %d\n", -+ obd->obd_requests_queued_for_recovery); -+ seq_printf(m, "next_transno: "LPD64"\n", -+ obd->obd_next_recovery_transno); -+out: -+ return 0; -+} -+EXPORT_SYMBOL(lprocfs_recovery_status_seq_show); -+ -+int lprocfs_ir_factor_seq_show(struct seq_file *m, void *data) -+{ -+ struct obd_device *obd = m->private; -+ -+ LASSERT(obd != NULL); -+ return seq_printf(m, "%d\n", obd->obd_recovery_ir_factor); -+} -+EXPORT_SYMBOL(lprocfs_ir_factor_seq_show); -+ -+ssize_t -+lprocfs_ir_factor_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) -+{ -+ struct obd_device *obd = ((struct seq_file *)file->private_data)->private; -+ int val, rc; -+ -+ LASSERT(obd != NULL); -+ rc = lprocfs_write_helper(buffer, count, &val); -+ if (rc) -+ return rc; -+ -+ if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX) -+ return -EINVAL; -+ -+ obd->obd_recovery_ir_factor = val; -+ return count; -+} -+EXPORT_SYMBOL(lprocfs_ir_factor_seq_write); -+ -+int lprocfs_recovery_time_soft_seq_show(struct seq_file *m, void *data) -+{ -+ struct obd_device *obd = m->private; -+ -+ LASSERT(obd != NULL); -+ return seq_printf(m, "%d\n", obd->obd_recovery_timeout); -+} -+EXPORT_SYMBOL(lprocfs_recovery_time_soft_seq_show); -+ -+ssize_t -+lprocfs_recovery_time_soft_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) -+{ -+ struct obd_device *obd = ((struct seq_file *)file->private_data)->private; -+ int val, rc; -+ -+ LASSERT(obd != NULL); -+ rc = lprocfs_write_helper(buffer, count, &val); -+ if (rc) -+ return rc; -+ -+ obd->obd_recovery_timeout = val; -+ return count; -+} -+EXPORT_SYMBOL(lprocfs_recovery_time_soft_seq_write); -+ -+int lprocfs_recovery_time_hard_seq_show(struct seq_file *m, void *data) -+{ -+ struct obd_device *obd = m->private; -+ -+ LASSERT(obd != NULL); -+ return seq_printf(m, "%u\n", obd->obd_recovery_time_hard); -+} -+EXPORT_SYMBOL(lprocfs_recovery_time_hard_seq_show); -+ -+ssize_t -+lprocfs_recovery_time_hard_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) -+{ -+ struct obd_device *obd = ((struct seq_file *)file->private_data)->private; -+ int val, rc; -+ -+ LASSERT(obd != NULL); -+ rc = lprocfs_write_helper(buffer, count, &val); -+ if (rc) -+ return rc; -+ -+ obd->obd_recovery_time_hard = val; -+ return count; -+} -+EXPORT_SYMBOL(lprocfs_recovery_time_hard_seq_write); -+ -+int lprocfs_target_instance_seq_show(struct seq_file *m, void *data) -+{ -+ struct obd_device *obd = m->private; -+ struct obd_device_target *target = &obd->u.obt; -+ -+ LASSERT(obd != NULL); -+ LASSERT(target->obt_magic == OBT_MAGIC); -+ return seq_printf(m, "%u\n", obd->u.obt.obt_instance); -+} -+EXPORT_SYMBOL(lprocfs_target_instance_seq_show); -+ -+#ifndef HAVE_ONLY_PROCFS_SEQ - int lprocfs_obd_rd_hash(char *page, char **start, off_t off, - int count, int *eof, void *data) - { -@@ -3084,7 +3453,6 @@ int lprocfs_obd_rd_hash(char *page, char **start, off_t off, - } - EXPORT_SYMBOL(lprocfs_obd_rd_hash); - --#ifdef HAVE_SERVER_SUPPORT - int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off, - int count, int *eof, void *data) - { -@@ -3210,7 +3578,6 @@ out: - return min(count, len - (int)off); - } - EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status); --#endif - - int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off, - int count, int *eof, void *data) -@@ -3295,6 +3662,21 @@ int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer, - } - EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard); - -+int lprocfs_target_rd_instance(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ struct obd_device *obd = (struct obd_device *)data; -+ struct obd_device_target *target = &obd->u.obt; -+ -+ LASSERT(obd != NULL); -+ LASSERT(target->obt_magic == OBT_MAGIC); -+ *eof = 1; -+ return snprintf(page, count, "%u\n", obd->u.obt.obt_instance); -+} -+EXPORT_SYMBOL(lprocfs_target_rd_instance); -+#endif /* HAVE_ONLY_PROCFS_SEQ */ -+#endif /* HAVE_SERVER_SUPPORT */ -+ - int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off, - int count, int *eof, void *data) - { -@@ -3321,19 +3703,4 @@ int lprocfs_obd_max_pages_per_rpc_seq_show(struct seq_file *m, void *data) - return rc; - } - EXPORT_SYMBOL(lprocfs_obd_max_pages_per_rpc_seq_show); -- --#ifdef HAVE_SERVER_SUPPORT --int lprocfs_target_rd_instance(char *page, char **start, off_t off, -- int count, int *eof, void *data) --{ -- struct obd_device *obd = (struct obd_device *)data; -- struct obd_device_target *target = &obd->u.obt; -- -- LASSERT(obd != NULL); -- LASSERT(target->obt_magic == OBT_MAGIC); -- *eof = 1; -- return snprintf(page, count, "%u\n", obd->u.obt.obt_instance); --} --EXPORT_SYMBOL(lprocfs_target_rd_instance); --#endif - #endif /* LPROCFS*/ -diff --git a/lustre/ptlrpc/lproc_ptlrpc.c b/lustre/ptlrpc/lproc_ptlrpc.c -index 024169e..076b5e2 100644 ---- a/lustre/ptlrpc/lproc_ptlrpc.c -+++ b/lustre/ptlrpc/lproc_ptlrpc.c -@@ -1170,49 +1170,6 @@ void ptlrpc_lprocfs_unregister_obd(struct obd_device *obd) - } - EXPORT_SYMBOL(ptlrpc_lprocfs_unregister_obd); - --#define BUFLEN (UUID_MAX + 5) -- --int lprocfs_wr_evict_client(struct file *file, const char *buffer, -- unsigned long count, void *data) --{ -- struct obd_device *obd = data; -- char *kbuf; -- char *tmpbuf; -- -- OBD_ALLOC(kbuf, BUFLEN); -- if (kbuf == NULL) -- return -ENOMEM; -- -- /* -- * OBD_ALLOC() will zero kbuf, but we only copy BUFLEN - 1 -- * bytes into kbuf, to ensure that the string is NUL-terminated. -- * UUID_MAX should include a trailing NUL already. -- */ -- if (copy_from_user(kbuf, buffer, -- min_t(unsigned long, BUFLEN - 1, count))) { -- count = -EFAULT; -- goto out; -- } -- tmpbuf = cfs_firststr(kbuf, min_t(unsigned long, BUFLEN - 1, count)); -- class_incref(obd, __FUNCTION__, current); -- -- if (strncmp(tmpbuf, "nid:", 4) == 0) -- obd_export_evict_by_nid(obd, tmpbuf + 4); -- else if (strncmp(tmpbuf, "uuid:", 5) == 0) -- obd_export_evict_by_uuid(obd, tmpbuf + 5); -- else -- obd_export_evict_by_uuid(obd, tmpbuf); -- -- class_decref(obd, __FUNCTION__, current); -- --out: -- OBD_FREE(kbuf, BUFLEN); -- return count; --} --EXPORT_SYMBOL(lprocfs_wr_evict_client); -- --#undef BUFLEN -- - #ifndef HAVE_ONLY_PROCFS_SEQ - int lprocfs_wr_ping(struct file *file, const char *buffer, - unsigned long count, void *data) --- -1.8.5.1 - diff --git a/sys-cluster/lustre/files/0011-LU-3373-osd-ldiskfs-readdir-replace-by-iterate.patch b/sys-cluster/lustre/files/0011-LU-3373-osd-ldiskfs-readdir-replace-by-iterate.patch new file mode 100644 index 000000000..3b1a7e51e --- /dev/null +++ b/sys-cluster/lustre/files/0011-LU-3373-osd-ldiskfs-readdir-replace-by-iterate.patch @@ -0,0 +1,140 @@ +From 508cde3f8347e7d6a6d299cbdfce537ebc29650c Mon Sep 17 00:00:00 2001 +From: yangsheng <yang.sheng@intel.com> +Date: Fri, 8 Nov 2013 22:31:36 +0800 +Subject: [PATCH 11/13] LU-3373 osd-ldiskfs: readdir replace by iterate + +Use iterate instead of readdir callback in iop. + +Signed-off-by: yang sheng <yang.sheng@intel.com> +Change-Id: Icb08292009c965ca693814e854ae2e77b3e7a4f0 +--- + lustre/osd-ldiskfs/osd_handler.c | 32 +++++++++++++++++++++++++------- + lustre/osd-ldiskfs/osd_scrub.c | 18 +++++++++++++++++- + 2 files changed, 42 insertions(+), 8 deletions(-) + +diff --git a/lustre/osd-ldiskfs/osd_handler.c b/lustre/osd-ldiskfs/osd_handler.c +index dfaa542..f635394 100644 +--- a/lustre/osd-ldiskfs/osd_handler.c ++++ b/lustre/osd-ldiskfs/osd_handler.c +@@ -4733,6 +4733,12 @@ static void osd_it_ea_put(const struct lu_env *env, struct dt_it *di) + { + } + ++struct osd_filldir_cbs { ++#ifdef HAVE_DIR_CONTEXT ++ struct dir_context ctx; ++#endif ++ struct osd_it_ea *it; ++}; + /** + * It is called internally by ->readdir(). It fills the + * iterator's in-memory data structure with required +@@ -4744,11 +4750,11 @@ static void osd_it_ea_put(const struct lu_env *env, struct dt_it *di) + * \retval 0 on success + * \retval 1 on buffer full + */ +-static int osd_ldiskfs_filldir(char *buf, const char *name, int namelen, ++static int osd_ldiskfs_filldir(void *buf, const char *name, int namelen, + loff_t offset, __u64 ino, + unsigned d_type) + { +- struct osd_it_ea *it = (struct osd_it_ea *)buf; ++ struct osd_it_ea *it = ((struct osd_filldir_cbs *)buf)->it; + struct osd_object *obj = it->oie_obj; + struct osd_it_ea_dirent *ent = it->oie_dirent; + struct lu_fid *fid = &ent->oied_fid; +@@ -4811,7 +4817,14 @@ static int osd_ldiskfs_it_fill(const struct lu_env *env, + struct osd_object *obj = it->oie_obj; + struct inode *inode = obj->oo_inode; + struct htree_lock *hlock = NULL; +- int result = 0; ++ struct file *filp = &it->oie_file; ++ int rc = 0; ++ struct osd_filldir_cbs buf = { ++#ifdef HAVE_DIR_CONTEXT ++ .ctx.actor = osd_ldiskfs_filldir, ++#endif ++ .it = it ++ }; + + ENTRY; + it->oie_dirent = it->oie_buf; +@@ -4825,8 +4838,13 @@ static int osd_ldiskfs_it_fill(const struct lu_env *env, + down_read(&obj->oo_ext_idx_sem); + } + +- result = inode->i_fop->readdir(&it->oie_file, it, +- (filldir_t) osd_ldiskfs_filldir); ++#ifdef HAVE_DIR_CONTEXT ++ buf.ctx.pos = filp->f_pos; ++ rc = inode->i_fop->iterate(filp, &buf.ctx); ++ filp->f_pos = buf.ctx.pos; ++#else ++ rc = inode->i_fop->readdir(filp, &buf, osd_ldiskfs_filldir); ++#endif + + if (hlock != NULL) + ldiskfs_htree_unlock(hlock); +@@ -4834,13 +4852,13 @@ static int osd_ldiskfs_it_fill(const struct lu_env *env, + up_read(&obj->oo_ext_idx_sem); + + if (it->oie_rd_dirent == 0) { +- result = -EIO; ++ rc = -EIO; + } else { + it->oie_dirent = it->oie_buf; + it->oie_it_dirent = 1; + } + +- RETURN(result); ++ RETURN(rc); + } + + /** +diff --git a/lustre/osd-ldiskfs/osd_scrub.c b/lustre/osd-ldiskfs/osd_scrub.c +index 1002913..8d19c1e 100644 +--- a/lustre/osd-ldiskfs/osd_scrub.c ++++ b/lustre/osd-ldiskfs/osd_scrub.c +@@ -1465,6 +1465,10 @@ struct osd_ios_item { + }; + + struct osd_ios_filldir_buf { ++#ifdef HAVE_DIR_CONTEXT ++ /* please keep it as first member */ ++ struct dir_context ctx; ++#endif + struct osd_thread_info *oifb_info; + struct osd_device *oifb_dev; + struct dentry *oifb_dentry; +@@ -1760,7 +1764,13 @@ static int + osd_ios_general_scan(struct osd_thread_info *info, struct osd_device *dev, + struct dentry *dentry, filldir_t filldir) + { +- struct osd_ios_filldir_buf buf = { info, dev, dentry }; ++ struct osd_ios_filldir_buf buf = { ++#ifdef HAVE_DIR_CONTEXT ++ .ctx.actor = filldir, ++#endif ++ .oifb_info = info, ++ .oifb_dev = dev, ++ .oifb_dentry = dentry }; + struct file *filp = &info->oti_it_ea.oie_file; + struct inode *inode = dentry->d_inode; + const struct file_operations *fops = inode->i_fop; +@@ -1777,7 +1787,13 @@ osd_ios_general_scan(struct osd_thread_info *info, struct osd_device *dev, + filp->private_data = NULL; + set_file_inode(filp, inode); + ++#ifdef HAVE_DIR_CONTEXT ++ buf.ctx.pos = filp->f_pos; ++ rc = fops->iterate(filp, &buf.ctx); ++ filp->f_pos = buf.ctx.pos; ++#else + rc = fops->readdir(filp, &buf, filldir); ++#endif + fops->release(inode, filp); + + RETURN(rc); +-- +1.8.5.3 + diff --git a/sys-cluster/lustre/files/0012-LU-3974-llite-use-new-struct-dir_context.patch b/sys-cluster/lustre/files/0012-LU-3974-llite-use-new-struct-dir_context.patch new file mode 100644 index 000000000..29696dd1c --- /dev/null +++ b/sys-cluster/lustre/files/0012-LU-3974-llite-use-new-struct-dir_context.patch @@ -0,0 +1,262 @@ +From a93c1a0d6dfaa1a17e0806c5a3f71996af15fb20 Mon Sep 17 00:00:00 2001 +From: James Simmons <uja.ornl@gmail.com> +Date: Mon, 20 Jan 2014 21:23:00 -0500 +Subject: [PATCH 12/13] LU-3974 llite: use new struct dir_context + +The readdir and nfs code over time has added more +parameters to be passed to be processed. For the 3.11 +kernel a new struct dir_context was introduced to +minimize the impact of future expansion. This patch +addresses this change. + +Signed-off-by: James Simmons <uja.ornl@gmail.com> +Change-Id: Ib42bf8cb06635a2a64e63b294d79e66ac82a1a5b +Signed-off-by: Alexey Shvetsov <alexxy@gentoo.org> +--- + lustre/autoconf/lustre-core.m4 | 20 +++++++++++++ + lustre/llite/dir.c | 65 ++++++++++++++++++++++++++++++++++-------- + lustre/llite/llite_internal.h | 14 +++++++-- + lustre/llite/llite_nfs.c | 17 +++++++---- + 4 files changed, 96 insertions(+), 20 deletions(-) + +diff --git a/lustre/autoconf/lustre-core.m4 b/lustre/autoconf/lustre-core.m4 +index e6207c9..f44a277 100644 +--- a/lustre/autoconf/lustre-core.m4 ++++ b/lustre/autoconf/lustre-core.m4 +@@ -1349,6 +1349,25 @@ LB_LINUX_TRY_COMPILE([ + ]) + + # ++# 3.11 readdir now takes the new struct dir_context ++# ++AC_DEFUN([LC_HAVE_DIR_CONTEXT], ++[AC_MSG_CHECKING([if dir_context exist]) ++LB_LINUX_TRY_COMPILE([ ++ #include <linux/fs.h> ++],[ ++ struct dir_context ctx; ++ ++ ctx.pos = 0; ++],[ ++ AC_DEFINE(HAVE_DIR_CONTEXT, 1, [dir_context exist]) ++ AC_MSG_RESULT([yes]) ++],[ ++ AC_MSG_RESULT([no]) ++]) ++]) ++ ++# + # 3.11 dentry_operations.d_compare() taken 5 arguments. + # + AC_DEFUN([LC_D_COMPARE_5ARGS], +@@ -1523,6 +1542,7 @@ AC_DEFUN([LC_PROG_LINUX], + LC_BLKDEV_RELEASE_RETURN_INT + + # 3.11 ++ LC_HAVE_DIR_CONTEXT + LC_D_COMPARE_5ARGS + LC_HAVE_DCOUNT + +diff --git a/lustre/llite/dir.c b/lustre/llite/dir.c +index dc5d623..5009934 100644 +--- a/lustre/llite/dir.c ++++ b/lustre/llite/dir.c +@@ -195,9 +195,27 @@ struct lu_dirent *ll_dir_entry_next(struct inode *dir, + return entry; + } + ++void ll_dir_entry_end(struct inode *dir, struct md_op_data *op_data, ++ struct lu_dirent *ent) ++{ ++ struct lu_dirent *entry; ++ struct md_callback cb_op; ++ ++ cb_op.md_blocking_ast = ll_md_blocking_ast; ++ op_data->op_cli_flags = CLI_READENT_END; ++ md_read_entry(ll_i2mdexp(dir), op_data, &cb_op, &entry); ++ return; ++} ++ ++#ifdef HAVE_DIR_CONTEXT ++int ll_dir_read(struct inode *inode, struct md_op_data *op_data, ++ struct dir_context *ctx) ++{ ++#else + int ll_dir_read(struct inode *inode, struct md_op_data *op_data, + void *cookie, filldir_t filldir) + { ++#endif + struct ll_sb_info *sbi = ll_i2sbi(inode); + struct ll_dir_chain chain; + struct lu_dirent *ent; +@@ -241,12 +259,17 @@ int ll_dir_read(struct inode *inode, struct md_op_data *op_data, + fid_le_to_cpu(&fid, &ent->lde_fid); + ino = cl_fid_build_ino(&fid, api32); + type = ll_dirent_type_get(ent); ++ ++#ifdef HAVE_DIR_CONTEXT + /* For 'll_nfs_get_name_filldir()', it will try + * to access the 'ent' through its 'lde_name', + * so the parameter 'name' for 'filldir()' must + * be part of the 'ent'. */ ++ done = !dir_emit(ctx, ent->lde_name, namelen, ino, type); ++#else + done = filldir(cookie, ent->lde_name, namelen, lhash, + ino, type); ++#endif + if (done) { + if (op_data->op_hash_offset != MDS_DIR_END_OFF) + op_data->op_hash_offset = last_hash; +@@ -268,7 +291,11 @@ int ll_dir_read(struct inode *inode, struct md_op_data *op_data, + RETURN(rc); + } + ++#ifdef HAVE_DIR_CONTEXT ++static int ll_iterate(struct file *filp, struct dir_context *ctx) ++#else + static int ll_readdir(struct file *filp, void *cookie, filldir_t filldir) ++#endif + { + struct inode *inode = filp->f_dentry->d_inode; + struct ll_file_data *lfd = LUSTRE_FPRIVATE(filp); +@@ -305,22 +332,32 @@ static int ll_readdir(struct file *filp, void *cookie, filldir_t filldir) + + op_data->op_hash_offset = pos; + op_data->op_max_pages = sbi->ll_md_brw_size >> PAGE_CACHE_SHIFT; ++#ifdef HAVE_DIR_CONTEXT ++ ctx->pos = pos; ++ rc = ll_dir_read(inode, op_data, ctx); ++ pos = ctx->pos; ++#else + rc = ll_dir_read(inode, op_data, cookie, filldir); ++#endif + if (lfd != NULL) + lfd->lfd_pos = op_data->op_hash_offset; + + if (pos == MDS_DIR_END_OFF) { + if (api32) +- filp->f_pos = LL_DIR_END_OFF_32BIT; ++ pos = LL_DIR_END_OFF_32BIT; + else +- filp->f_pos = LL_DIR_END_OFF; ++ pos = LL_DIR_END_OFF; + } else { + if (api32 && hash64) +- filp->f_pos = op_data->op_hash_offset >> 32; ++ pos = op_data->op_hash_offset >> 32; + else +- filp->f_pos = op_data->op_hash_offset; ++ pos = op_data->op_hash_offset; + } +- ++#ifdef HAVE_DIR_CONTEXT ++ ctx->pos = pos; ++#else ++ filp->f_pos = pos; ++#endif + ll_finish_md_op_data(op_data); + filp->f_version = inode->i_version; + #ifdef HAVE_TOUCH_ATIME_1ARG +@@ -1702,11 +1739,15 @@ int ll_dir_release(struct inode *inode, struct file *file) + } + + struct file_operations ll_dir_operations = { +- .llseek = ll_dir_seek, +- .open = ll_dir_open, +- .release = ll_dir_release, +- .read = generic_read_dir, +- .readdir = ll_readdir, +- .unlocked_ioctl = ll_dir_ioctl, +- .fsync = ll_fsync, ++ .llseek = ll_dir_seek, ++ .open = ll_dir_open, ++ .release = ll_dir_release, ++ .read = generic_read_dir, ++#ifdef HAVE_DIR_CONTEXT ++ .iterate = ll_iterate, ++#else ++ .readdir = ll_readdir, ++#endif ++ .unlocked_ioctl = ll_dir_ioctl, ++ .fsync = ll_fsync, + }; +diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h +index 5c22795..251a218 100644 +--- a/lustre/llite/llite_internal.h ++++ b/lustre/llite/llite_internal.h +@@ -91,9 +91,12 @@ extern struct file_operations ll_pgcache_seq_fops; + #define REMOTE_PERM_HASHSIZE 16 + + struct ll_getname_data { +- char *lgd_name; /* points to a buffer with NAME_MAX+1 size */ +- struct lu_fid lgd_fid; /* target fid we are looking for */ +- int lgd_found; /* inode matched? */ ++#ifdef HAVE_DIR_CONTEXT ++ struct dir_context ctx; ++#endif ++ char *lgd_name; /* points to a buffer with NAME_MAX+1 size */ ++ struct lu_fid lgd_fid; /* target fid we are looking for */ ++ int lgd_found; /* inode matched? */ + }; + + /* llite setxid/access permission for user on remote client */ +@@ -718,8 +721,13 @@ static void ll_stats_ops_tally(struct ll_sb_info *sbi, int op, int count) {} + /* llite/dir.c */ + extern struct file_operations ll_dir_operations; + extern struct inode_operations ll_dir_inode_operations; ++#ifdef HAVE_DIR_CONTEXT ++int ll_dir_read(struct inode *inode, struct md_op_data *op_data, ++ struct dir_context *ctx); ++#else + int ll_dir_read(struct inode *inode, struct md_op_data *op_data, + void *cookie, filldir_t filldir); ++#endif + int ll_get_mdt_idx(struct inode *inode); + + struct lu_dirent *ll_dir_entry_start(struct inode *dir, +diff --git a/lustre/llite/llite_nfs.c b/lustre/llite/llite_nfs.c +index 68616e9..faad453 100644 +--- a/lustre/llite/llite_nfs.c ++++ b/lustre/llite/llite_nfs.c +@@ -236,7 +236,14 @@ static int ll_get_name(struct dentry *dentry, char *name, + struct dentry *child) + { + struct inode *dir = dentry->d_inode; +- struct ll_getname_data lgd; ++ struct ll_getname_data lgd = { ++ .lgd_name = name, ++ .lgd_fid = ll_i2info(child->d_inode)->lli_fid, ++#ifdef HAVE_DIR_CONTEXT ++ .ctx.actor = ll_nfs_get_name_filldir, ++#endif ++ .lgd_found = 0, ++ }; + struct md_op_data *op_data; + int rc; + ENTRY; +@@ -247,10 +254,6 @@ static int ll_get_name(struct dentry *dentry, char *name, + if (!dir->i_fop) + GOTO(out, rc = -EINVAL); + +- lgd.lgd_name = name; +- lgd.lgd_fid = ll_i2info(child->d_inode)->lli_fid; +- lgd.lgd_found = 0; +- + op_data = ll_prep_md_op_data(NULL, dir, dir, NULL, 0, 0, + LUSTRE_OPC_ANY, dir); + if (IS_ERR(op_data)) +@@ -260,7 +263,11 @@ static int ll_get_name(struct dentry *dentry, char *name, + op_data->op_max_pages = + ll_i2sbi(dir)->ll_md_brw_size >> PAGE_CACHE_SHIFT; + mutex_lock(&dir->i_mutex); ++#ifdef HAVE_DIR_CONTEXT ++ rc = ll_dir_read(dir, op_data, &lgd.ctx); ++#else + rc = ll_dir_read(dir, op_data, &lgd, ll_nfs_get_name_filldir); ++#endif + mutex_unlock(&dir->i_mutex); + ll_finish_md_op_data(op_data); + if (!rc && !lgd.lgd_found) +-- +1.8.5.3 + diff --git a/sys-cluster/lustre/files/0013-LU-3319-procfs-move-ofd-proc-handling-to-seq_files.patch b/sys-cluster/lustre/files/0013-LU-3319-procfs-move-ofd-proc-handling-to-seq_files.patch deleted file mode 100644 index cb8fd79c6..000000000 --- a/sys-cluster/lustre/files/0013-LU-3319-procfs-move-ofd-proc-handling-to-seq_files.patch +++ /dev/null @@ -1,759 +0,0 @@ -From 8fa5fb0ecac2a7b0279e0010bfe74acb107c37d8 Mon Sep 17 00:00:00 2001 -From: James Simmons <uja.ornl@gmail.com> -Date: Thu, 14 Nov 2013 19:47:36 -0500 -Subject: [PATCH 13/18] LU-3319 procfs: move ofd proc handling to seq_files - -With 3.10 linux kernel and above proc handling now only -uses struct seq_files. This patch migrates the ofd -layer proc entries over to using seq_files. - -Signed-off-by: James Simmons <uja.ornl@gmail.com> -Change-Id: Id8f77d72fd35755f1b7b1c17fcf27e0731bd5ac1 ---- - lustre/obdclass/lprocfs_status.c | 9 +- - lustre/ofd/lproc_ofd.c | 352 +++++++++++++++++---------------------- - lustre/ofd/ofd_dev.c | 41 ++--- - lustre/ofd/ofd_internal.h | 7 +- - 4 files changed, 180 insertions(+), 229 deletions(-) - -diff --git a/lustre/obdclass/lprocfs_status.c b/lustre/obdclass/lprocfs_status.c -index a33cbf2..bd6741e 100644 ---- a/lustre/obdclass/lprocfs_status.c -+++ b/lustre/obdclass/lprocfs_status.c -@@ -387,11 +387,10 @@ EXPORT_SYMBOL(lprocfs_evict_client_seq_write); - #undef BUFLEN - - struct file_operations lprocfs_evict_client_fops = { -- .owner = THIS_MODULE, -- .read = lprocfs_fops_read, -- .write = lprocfs_fops_write, -- .open = lprocfs_evict_client_open, -- .release = lprocfs_evict_client_release, -+ .owner = THIS_MODULE, -+ .open = lprocfs_evict_client_open, -+ .release = lprocfs_evict_client_release, -+ .write = lprocfs_evict_client_seq_write, - }; - EXPORT_SYMBOL(lprocfs_evict_client_fops); - #endif -diff --git a/lustre/ofd/lproc_ofd.c b/lustre/ofd/lproc_ofd.c -index 4354497..f462d63 100644 ---- a/lustre/ofd/lproc_ofd.c -+++ b/lustre/ofd/lproc_ofd.c -@@ -46,80 +46,74 @@ - - #ifdef LPROCFS - --static int lprocfs_ofd_rd_seqs(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int ofd_seqs_seq_show(struct seq_file *m, void *data) - { -- struct obd_device *obd = (struct obd_device *)data; -+ struct obd_device *obd = m->private; - struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); - -- *eof = 1; -- return snprintf(page, count, "%u\n", ofd->ofd_seq_count); -+ return seq_printf(m, "%u\n", ofd->ofd_seq_count); - } -+LPROC_SEQ_FOPS_RO(ofd_seqs); - --static int lprocfs_ofd_rd_tot_dirty(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int ofd_tot_dirty_seq_show(struct seq_file *m, void *data) - { -- struct obd_device *obd = (struct obd_device *)data; -+ struct obd_device *obd = m->private; - struct ofd_device *ofd; - - LASSERT(obd != NULL); - ofd = ofd_dev(obd->obd_lu_dev); -- *eof = 1; -- return snprintf(page, count, LPU64"\n", ofd->ofd_tot_dirty); -+ return seq_printf(m, LPU64"\n", ofd->ofd_tot_dirty); - } -+LPROC_SEQ_FOPS_RO(ofd_tot_dirty); - --static int lprocfs_ofd_rd_tot_granted(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int ofd_tot_granted_seq_show(struct seq_file *m, void *data) - { -- struct obd_device *obd = (struct obd_device *)data; -+ struct obd_device *obd = m->private; - struct ofd_device *ofd; - - LASSERT(obd != NULL); - ofd = ofd_dev(obd->obd_lu_dev); -- *eof = 1; -- return snprintf(page, count, LPU64"\n", ofd->ofd_tot_granted); -+ return seq_printf(m, LPU64"\n", ofd->ofd_tot_granted); - } -+LPROC_SEQ_FOPS_RO(ofd_tot_granted); - --static int lprocfs_ofd_rd_tot_pending(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int ofd_tot_pending_seq_show(struct seq_file *m, void *data) - { -- struct obd_device *obd = (struct obd_device *)data; -+ struct obd_device *obd = m->private; - struct ofd_device *ofd; - - LASSERT(obd != NULL); - ofd = ofd_dev(obd->obd_lu_dev); -- *eof = 1; -- return snprintf(page, count, LPU64"\n", ofd->ofd_tot_pending); -+ return seq_printf(m, LPU64"\n", ofd->ofd_tot_pending); - } -+LPROC_SEQ_FOPS_RO(ofd_tot_pending); - --static int lprocfs_ofd_rd_grant_precreate(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int ofd_grant_precreate_seq_show(struct seq_file *m, void *data) - { -- struct obd_device *obd = (struct obd_device *)data; -+ struct obd_device *obd = m->private; - - LASSERT(obd != NULL); -- *eof = 1; -- return snprintf(page, count, "%ld\n", -+ return seq_printf(m, "%ld\n", - obd->obd_self_export->exp_filter_data.fed_grant); - } -+LPROC_SEQ_FOPS_RO(ofd_grant_precreate); - --static int lprocfs_ofd_rd_grant_ratio(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int ofd_grant_ratio_seq_show(struct seq_file *m, void *data) - { -- struct obd_device *obd = (struct obd_device *)data; -+ struct obd_device *obd = m->private; - struct ofd_device *ofd; - - LASSERT(obd != NULL); - ofd = ofd_dev(obd->obd_lu_dev); -- *eof = 1; -- return snprintf(page, count, "%d%%\n", -+ return seq_printf(m, "%d%%\n", - (int) ofd_grant_reserved(ofd, 100)); - } - --static int lprocfs_ofd_wr_grant_ratio(struct file *file, const char *buffer, -- unsigned long count, void *data) -+static ssize_t -+ofd_grant_ratio_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) - { -- struct obd_device *obd = (struct obd_device *)data; -+ struct obd_device *obd = ((struct seq_file *)file->private_data)->private; - struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); - int val; - int rc; -@@ -143,23 +137,23 @@ static int lprocfs_ofd_wr_grant_ratio(struct file *file, const char *buffer, - spin_unlock(&ofd->ofd_grant_lock); - return count; - } -+LPROC_SEQ_FOPS(ofd_grant_ratio); - --static int lprocfs_ofd_rd_precreate_batch(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int ofd_precreate_batch_seq_show(struct seq_file *m, void *data) - { -- struct obd_device *obd = (struct obd_device *)data; -+ struct obd_device *obd = m->private; - struct ofd_device *ofd; - - LASSERT(obd != NULL); - ofd = ofd_dev(obd->obd_lu_dev); -- *eof = 1; -- return snprintf(page, count, "%d\n", ofd->ofd_precreate_batch); -+ return seq_printf(m, "%d\n", ofd->ofd_precreate_batch); - } - --static int lprocfs_ofd_wr_precreate_batch(struct file *file, const char *buffer, -- unsigned long count, void *data) -+static ssize_t -+ofd_precreate_batch_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) - { -- struct obd_device *obd = (struct obd_device *)data; -+ struct obd_device *obd = ((struct seq_file *)file->private_data)->private; - struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); - int val; - int rc; -@@ -176,11 +170,11 @@ static int lprocfs_ofd_wr_precreate_batch(struct file *file, const char *buffer, - spin_unlock(&ofd->ofd_batch_lock); - return count; - } -+LPROC_SEQ_FOPS(ofd_precreate_batch); - --static int lprocfs_ofd_rd_last_id(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int ofd_last_id_seq_show(struct seq_file *m, void *data) - { -- struct obd_device *obd = data; -+ struct obd_device *obd = m->private; - struct ofd_device *ofd; - struct ofd_seq *oseq = NULL; - int retval = 0, rc; -@@ -198,35 +192,31 @@ static int lprocfs_ofd_rd_last_id(char *page, char **start, off_t off, - fid_idif_seq(ostid_id(&oseq->os_oi), - ofd->ofd_lut.lut_lsd.lsd_osd_index) : - ostid_seq(&oseq->os_oi); -- rc = snprintf(page, count, DOSTID"\n", seq, -- ostid_id(&oseq->os_oi)); -+ rc = seq_printf(m, DOSTID"\n", seq, ostid_id(&oseq->os_oi)); - if (rc < 0) { - retval = rc; - break; - } -- page += rc; -- count -= rc; - retval += rc; - } - read_unlock(&ofd->ofd_seq_list_lock); - return retval; - } -+LPROC_SEQ_FOPS_RO(ofd_last_id); - --int lprocfs_ofd_rd_fmd_max_num(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+int ofd_fmd_max_num_seq_show(struct seq_file *m, void *data) - { -- struct obd_device *obd = data; -+ struct obd_device *obd = m->private; - struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); -- int rc; - -- rc = snprintf(page, count, "%u\n", ofd->ofd_fmd_max_num); -- return rc; -+ return seq_printf(m, "%u\n", ofd->ofd_fmd_max_num); - } - --int lprocfs_ofd_wr_fmd_max_num(struct file *file, const char *buffer, -- unsigned long count, void *data) -+ssize_t -+ofd_fmd_max_num_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) - { -- struct obd_device *obd = data; -+ struct obd_device *obd = ((struct seq_file *)file->private_data)->private; - struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); - int val; - int rc; -@@ -241,22 +231,21 @@ int lprocfs_ofd_wr_fmd_max_num(struct file *file, const char *buffer, - ofd->ofd_fmd_max_num = val; - return count; - } -+LPROC_SEQ_FOPS(ofd_fmd_max_num); - --int lprocfs_ofd_rd_fmd_max_age(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+int ofd_fmd_max_age_seq_show(struct seq_file *m, void *data) - { -- struct obd_device *obd = data; -+ struct obd_device *obd = m->private; - struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); -- int rc; - -- rc = snprintf(page, count, "%ld\n", ofd->ofd_fmd_max_age / HZ); -- return rc; -+ return seq_printf(m, "%ld\n", ofd->ofd_fmd_max_age / HZ); - } - --int lprocfs_ofd_wr_fmd_max_age(struct file *file, const char *buffer, -- unsigned long count, void *data) -+ssize_t -+ofd_fmd_max_age_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) - { -- struct obd_device *obd = data; -+ struct obd_device *obd = ((struct seq_file *)file->private_data)->private; - struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); - int val; - int rc; -@@ -271,22 +260,21 @@ int lprocfs_ofd_wr_fmd_max_age(struct file *file, const char *buffer, - ofd->ofd_fmd_max_age = val * HZ; - return count; - } -+LPROC_SEQ_FOPS(ofd_fmd_max_age); - --static int lprocfs_ofd_rd_capa(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int ofd_capa_seq_show(struct seq_file *m, void *data) - { -- struct obd_device *obd = data; -- int rc; -+ struct obd_device *obd = m->private; - -- rc = snprintf(page, count, "capability on: %s\n", -- obd->u.filter.fo_fl_oss_capa ? "oss" : ""); -- return rc; -+ return seq_printf(m, "capability on: %s\n", -+ obd->u.filter.fo_fl_oss_capa ? "oss" : ""); - } - --static int lprocfs_ofd_wr_capa(struct file *file, const char *buffer, -- unsigned long count, void *data) -+static ssize_t -+ofd_capa_seq_write(struct file *file, const char *buffer, size_t count, -+ loff_t *off) - { -- struct obd_device *obd = data; -+ struct obd_device *obd = ((struct seq_file *)file->private_data)->private; - int val, rc; - - rc = lprocfs_write_helper(buffer, count, &val); -@@ -305,28 +293,29 @@ static int lprocfs_ofd_wr_capa(struct file *file, const char *buffer, - val ? "enabled" : "disabled"); - return count; - } -+LPROC_SEQ_FOPS(ofd_capa); - --static int lprocfs_ofd_rd_capa_count(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int ofd_capa_count_seq_show(struct seq_file *m, void *data) - { -- return snprintf(page, count, "%d %d\n", -+ return seq_printf(m, "%d %d\n", - capa_count[CAPA_SITE_CLIENT], - capa_count[CAPA_SITE_SERVER]); - } -+LPROC_SEQ_FOPS_RO(ofd_capa_count); - --int lprocfs_ofd_rd_degraded(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+int ofd_degraded_seq_show(struct seq_file *m, void *data) - { -- struct obd_device *obd = data; -+ struct obd_device *obd = m->private; - struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); - -- return snprintf(page, count, "%u\n", ofd->ofd_raid_degraded); -+ return seq_printf(m, "%u\n", ofd->ofd_raid_degraded); - } - --int lprocfs_ofd_wr_degraded(struct file *file, const char *buffer, -- unsigned long count, void *data) -+ssize_t -+ofd_degraded_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) - { -- struct obd_device *obd = data; -+ struct obd_device *obd = ((struct seq_file *)file->private_data)->private; - struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); - int val, rc; - -@@ -337,38 +326,35 @@ int lprocfs_ofd_wr_degraded(struct file *file, const char *buffer, - spin_lock(&ofd->ofd_flags_lock); - ofd->ofd_raid_degraded = !!val; - spin_unlock(&ofd->ofd_flags_lock); -- - return count; - } -+LPROC_SEQ_FOPS(ofd_degraded); - --int lprocfs_ofd_rd_fstype(char *page, char **start, off_t off, int count, -- int *eof, void *data) -+int ofd_fstype_seq_show(struct seq_file *m, void *data) - { -- struct obd_device *obd = data; -+ struct obd_device *obd = m->private; - struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); - struct lu_device *d; - - LASSERT(ofd->ofd_osd); - d = &ofd->ofd_osd->dd_lu_dev; - LASSERT(d->ld_type); -- return snprintf(page, count, "%s\n", d->ld_type->ldt_name); -+ return seq_printf(m, "%s\n", d->ld_type->ldt_name); - } -+LPROC_SEQ_FOPS_RO(ofd_fstype); - --int lprocfs_ofd_rd_syncjournal(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+int ofd_syncjournal_seq_show(struct seq_file *m, void *data) - { -- struct obd_device *obd = data; -+ struct obd_device *obd = m->private; - struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); -- int rc; - -- rc = snprintf(page, count, "%u\n", ofd->ofd_syncjournal); -- return rc; -+ return seq_printf(m, "%u\n", ofd->ofd_syncjournal); - } - --int lprocfs_ofd_wr_syncjournal(struct file *file, const char *buffer, -- unsigned long count, void *data) -+ssize_t ofd_syncjournal_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) - { -- struct obd_device *obd = data; -+ struct obd_device *obd = ((struct seq_file *)file->private_data)->private; - struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); - int val; - int rc; -@@ -387,27 +373,26 @@ int lprocfs_ofd_wr_syncjournal(struct file *file, const char *buffer, - - return count; - } -+LPROC_SEQ_FOPS(ofd_syncjournal); - - static char *sync_on_cancel_states[] = {"never", - "blocking", - "always" }; - --int lprocfs_ofd_rd_sync_lock_cancel(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+int ofd_sync_lock_cancel_seq_show(struct seq_file *m, void *data) - { -- struct obd_device *obd = data; -+ struct obd_device *obd = m->private; - struct lu_target *tgt = obd->u.obt.obt_lut; -- int rc; - -- rc = snprintf(page, count, "%s\n", -- sync_on_cancel_states[tgt->lut_sync_lock_cancel]); -- return rc; -+ return seq_printf(m, "%s\n", -+ sync_on_cancel_states[tgt->lut_sync_lock_cancel]); - } - --int lprocfs_ofd_wr_sync_lock_cancel(struct file *file, const char *buffer, -- unsigned long count, void *data) -+ssize_t -+ofd_sync_lock_cancel_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) - { -- struct obd_device *obd = data; -+ struct obd_device *obd = ((struct seq_file *)file->private_data)->private; - struct lu_target *tgt = obd->u.obt.obt_lut; - int val = -1; - int i; -@@ -435,22 +420,21 @@ int lprocfs_ofd_wr_sync_lock_cancel(struct file *file, const char *buffer, - spin_unlock(&tgt->lut_flags_lock); - return count; - } -+LPROC_SEQ_FOPS(ofd_sync_lock_cancel); - --int lprocfs_ofd_rd_grant_compat_disable(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+int ofd_grant_compat_disable_seq_show(struct seq_file *m, void *data) - { -- struct obd_device *obd = data; -+ struct obd_device *obd = m->private; - struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); -- int rc; - -- rc = snprintf(page, count, "%u\n", ofd->ofd_grant_compat_disable); -- return rc; -+ return seq_printf(m, "%u\n", ofd->ofd_grant_compat_disable); - } - --int lprocfs_ofd_wr_grant_compat_disable(struct file *file, const char *buffer, -- unsigned long count, void *data) -+ssize_t -+ofd_grant_compat_disable_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) - { -- struct obd_device *obd = data; -+ struct obd_device *obd = ((struct seq_file *)file->private_data)->private; - struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); - int val; - int rc; -@@ -469,86 +453,64 @@ int lprocfs_ofd_wr_grant_compat_disable(struct file *file, const char *buffer, - return count; - } - --int lprocfs_ofd_rd_soft_sync_limit(char *page, char **start, off_t off, -- int count, int *eof, void *data) --{ -- struct obd_device *obd = data; -- struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); -- -- return lprocfs_rd_uint(page, start, off, count, eof, -- &ofd->ofd_soft_sync_limit); --} -- --int lprocfs_ofd_wr_soft_sync_limit(struct file *file, const char *buffer, -- unsigned long count, void *data) --{ -- struct obd_device *obd = data; -- struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); -- -- return lprocfs_wr_uint(file, buffer, count, &ofd->ofd_soft_sync_limit); --} -- --static struct lprocfs_vars lprocfs_ofd_obd_vars[] = { -- { "uuid", lprocfs_rd_uuid, 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 }, -- { "filestotal", lprocfs_rd_filestotal, 0, 0 }, -- { "filesfree", lprocfs_rd_filesfree, 0, 0 }, -- { "seqs_allocated", lprocfs_ofd_rd_seqs, 0, 0 }, -- { "fstype", lprocfs_ofd_rd_fstype, 0, 0 }, -- { "last_id", lprocfs_ofd_rd_last_id, 0, 0 }, -- { "tot_dirty", lprocfs_ofd_rd_tot_dirty, 0, 0 }, -- { "tot_pending", lprocfs_ofd_rd_tot_pending, 0, 0 }, -- { "tot_granted", lprocfs_ofd_rd_tot_granted, 0, 0 }, -- { "grant_precreate", lprocfs_ofd_rd_grant_precreate, 0, 0 }, -- { "grant_ratio", lprocfs_ofd_rd_grant_ratio, -- lprocfs_ofd_wr_grant_ratio, 0, 0 }, -- { "precreate_batch", lprocfs_ofd_rd_precreate_batch, -- lprocfs_ofd_wr_precreate_batch, 0 }, -- { "recovery_status", lprocfs_obd_rd_recovery_status, 0, 0 }, -- { "recovery_time_soft", lprocfs_obd_rd_recovery_time_soft, -- lprocfs_obd_wr_recovery_time_soft, 0}, -- { "recovery_time_hard", lprocfs_obd_rd_recovery_time_hard, -- lprocfs_obd_wr_recovery_time_hard, 0}, -- { "evict_client", 0, lprocfs_wr_evict_client, 0, -- &lprocfs_evict_client_fops}, -- { "num_exports", lprocfs_rd_num_exports, 0, 0 }, -- { "degraded", lprocfs_ofd_rd_degraded, -- lprocfs_ofd_wr_degraded, 0}, -- { "sync_journal", lprocfs_ofd_rd_syncjournal, -- lprocfs_ofd_wr_syncjournal, 0 }, -- { "sync_on_lock_cancel", lprocfs_ofd_rd_sync_lock_cancel, -- lprocfs_ofd_wr_sync_lock_cancel, 0 }, -- { "instance", lprocfs_target_rd_instance, 0 }, -- { "ir_factor", lprocfs_obd_rd_ir_factor, -- lprocfs_obd_wr_ir_factor, 0}, -- { "grant_compat_disable", lprocfs_ofd_rd_grant_compat_disable, -- lprocfs_ofd_wr_grant_compat_disable, 0 }, -- { "client_cache_count", lprocfs_ofd_rd_fmd_max_num, -- lprocfs_ofd_wr_fmd_max_num, 0 }, -- { "client_cache_seconds", lprocfs_ofd_rd_fmd_max_age, -- lprocfs_ofd_wr_fmd_max_age, 0 }, -- { "capa", lprocfs_ofd_rd_capa, -- lprocfs_ofd_wr_capa, 0 }, -- { "capa_count", lprocfs_ofd_rd_capa_count, 0, 0 }, -- { "job_cleanup_interval", lprocfs_rd_job_interval, -- lprocfs_wr_job_interval, 0}, -- { "soft_sync_limit", lprocfs_ofd_rd_soft_sync_limit, -- lprocfs_ofd_wr_soft_sync_limit, 0}, -- { 0 } --}; -- --static struct lprocfs_vars lprocfs_ofd_module_vars[] = { -- { "num_refs", lprocfs_rd_numrefs, 0, 0 }, -+LPROC_SEQ_FOPS(ofd_grant_compat_disable); -+ -+LPROC_SEQ_FOPS_RO_TYPE(ofd, uuid); -+LPROC_SEQ_FOPS_RO_TYPE(ofd, blksize); -+LPROC_SEQ_FOPS_RO_TYPE(ofd, kbytestotal); -+LPROC_SEQ_FOPS_RO_TYPE(ofd, kbytesfree); -+LPROC_SEQ_FOPS_RO_TYPE(ofd, kbytesavail); -+LPROC_SEQ_FOPS_RO_TYPE(ofd, filestotal); -+LPROC_SEQ_FOPS_RO_TYPE(ofd, filesfree); -+ -+LPROC_SEQ_FOPS_RO_TYPE(ofd, recovery_status); -+LPROC_SEQ_FOPS_RW_TYPE(ofd, recovery_time_soft); -+LPROC_SEQ_FOPS_RW_TYPE(ofd, recovery_time_hard); -+LPROC_SEQ_FOPS_WO_TYPE(ofd, evict_client); -+LPROC_SEQ_FOPS_RO_TYPE(ofd, num_exports); -+LPROC_SEQ_FOPS_RO_TYPE(ofd, target_instance); -+LPROC_SEQ_FOPS_RW_TYPE(ofd, ir_factor); -+LPROC_SEQ_FOPS_RW_TYPE(ofd, job_interval); -+ -+static struct lprocfs_seq_vars lprocfs_ofd_obd_vars[] = { -+ { "uuid", &ofd_uuid_fops }, -+ { "blocksize", &ofd_blksize_fops }, -+ { "kbytestotal", &ofd_kbytestotal_fops }, -+ { "kbytesfree", &ofd_kbytesfree_fops }, -+ { "kbytesavail", &ofd_kbytesavail_fops }, -+ { "filestotal", &ofd_filestotal_fops }, -+ { "filesfree", &ofd_filesfree_fops }, -+ { "seqs_allocated", &ofd_seqs_fops }, -+ { "fstype", &ofd_fstype_fops }, -+ { "last_id", &ofd_last_id_fops }, -+ { "tot_dirty", &ofd_tot_dirty_fops }, -+ { "tot_pending", &ofd_tot_pending_fops }, -+ { "tot_granted", &ofd_tot_granted_fops }, -+ { "grant_precreate", &ofd_grant_precreate_fops }, -+ { "grant_ratio", &ofd_grant_ratio_fops }, -+ { "precreate_batch", &ofd_precreate_batch_fops }, -+ { "recovery_status", &ofd_recovery_status_fops }, -+ { "recovery_time_soft", &ofd_recovery_time_soft_fops }, -+ { "recovery_time_hard", &ofd_recovery_time_hard_fops }, -+ { "evict_client", &ofd_evict_client_fops }, -+ { "num_exports", &ofd_num_exports_fops }, -+ { "degraded", &ofd_degraded_fops }, -+ { "sync_journal", &ofd_syncjournal_fops }, -+ { "sync_on_lock_cancel", &ofd_sync_lock_cancel_fops }, -+ { "instance", &ofd_target_instance_fops }, -+ { "ir_factor", &ofd_ir_factor_fops }, -+ { "grant_compat_disable", &ofd_grant_compat_disable_fops }, -+ { "client_cache_count", &ofd_fmd_max_num_fops }, -+ { "client_cache_seconds", &ofd_fmd_max_age_fops }, -+ { "capa", &ofd_capa_fops }, -+ { "capa_count", &ofd_capa_count_fops }, -+ { "job_cleanup_interval", &ofd_job_interval_fops }, - { 0 } - }; - --void lprocfs_ofd_init_vars(struct lprocfs_static_vars *lvars) -+void lprocfs_ofd_init_vars(struct obd_device *obd) - { -- lvars->module_vars = lprocfs_ofd_module_vars; -- lvars->obd_vars = lprocfs_ofd_obd_vars; -+ obd->obd_vars = lprocfs_ofd_obd_vars; - } - - void ofd_stats_counter_init(struct lprocfs_stats *stats) -diff --git a/lustre/ofd/ofd_dev.c b/lustre/ofd/ofd_dev.c -index 2bdbde6..e3b8358 100644 ---- a/lustre/ofd/ofd_dev.c -+++ b/lustre/ofd/ofd_dev.c -@@ -206,8 +206,7 @@ static int ofd_process_config(const struct lu_env *env, struct lu_device *d, - - switch (cfg->lcfg_command) { - case LCFG_PARAM: { -- struct lprocfs_static_vars lvars; -- -+ struct obd_device *obd = ofd_obd(m); - /* For interoperability */ - struct cfg_interop_param *ptr = NULL; - struct lustre_cfg *old_cfg = NULL; -@@ -240,8 +239,7 @@ static int ofd_process_config(const struct lu_env *env, struct lu_device *d, - } - } - -- lprocfs_ofd_init_vars(&lvars); -- rc = class_process_proc_param(PARAM_OST, lvars.obd_vars, cfg, -+ rc = class_process_proc_seq_param(PARAM_OST, obd->obd_vars, cfg, - d->ld_obd); - if (rc > 0 || rc == -ENOSYS) - /* we don't understand; pass it on */ -@@ -422,9 +420,10 @@ static struct lu_device_operations ofd_lu_ops = { - .ldo_prepare = ofd_prepare, - }; - -+LPROC_SEQ_FOPS(lprocfs_nid_stats_clear); -+ - static int ofd_procfs_init(struct ofd_device *ofd) - { -- struct lprocfs_static_vars lvars; - struct obd_device *obd = ofd_obd(ofd); - cfs_proc_dir_entry_t *entry; - int rc = 0; -@@ -433,8 +432,8 @@ static int ofd_procfs_init(struct ofd_device *ofd) - - /* lprocfs must be setup before the ofd so state can be safely added - * to /proc incrementally as the ofd is setup */ -- lprocfs_ofd_init_vars(&lvars); -- rc = lprocfs_obd_setup(obd, lvars.obd_vars); -+ lprocfs_ofd_init_vars(obd); -+ rc = lprocfs_seq_obd_setup(obd); - if (rc) { - CERROR("%s: lprocfs_obd_setup failed: %d.\n", - obd->obd_name, rc); -@@ -450,7 +449,7 @@ static int ofd_procfs_init(struct ofd_device *ofd) - - obd->obd_uses_nid_stats = 1; - -- entry = lprocfs_register("exports", obd->obd_proc_entry, NULL, NULL); -+ entry = lprocfs_seq_register("exports", obd->obd_proc_entry, NULL, NULL); - if (IS_ERR(entry)) { - rc = PTR_ERR(entry); - CERROR("%s: error %d setting up lprocfs for %s\n", -@@ -460,8 +459,10 @@ static int ofd_procfs_init(struct ofd_device *ofd) - obd->obd_proc_exports_entry = entry; - - entry = lprocfs_add_simple(obd->obd_proc_exports_entry, "clear", -- lprocfs_nid_stats_clear_read, -- lprocfs_nid_stats_clear_write, obd, NULL); -+#ifndef HAVE_ONLY_PROCFS_SEQ -+ NULL, NULL, -+#endif -+ obd, &lprocfs_nid_stats_clear_fops); - if (IS_ERR(entry)) { - rc = PTR_ERR(entry); - CERROR("%s: add proc entry 'clear' failed: %d.\n", -@@ -477,7 +478,7 @@ static int ofd_procfs_init(struct ofd_device *ofd) - GOTO(remove_entry_clear, rc); - RETURN(0); - remove_entry_clear: -- lprocfs_remove_proc_entry("clear", obd->obd_proc_exports_entry); -+ lprocfs_remove(&obd->obd_proc_exports_entry); - obd_cleanup: - lprocfs_obd_cleanup(obd); - lprocfs_free_obd_stats(obd); -@@ -487,7 +488,7 @@ obd_cleanup: - - static void ofd_procfs_add_brw_stats_symlink(struct ofd_device *ofd) - { -- struct obd_device *obd = ofd_obd(ofd); -+ /*struct obd_device *obd = ofd_obd(ofd); - struct obd_device *osd_obd = ofd->ofd_osd_exp->exp_obd; - cfs_proc_dir_entry_t *osd_root = osd_obd->obd_type->typ_procroot; - cfs_proc_dir_entry_t *osd_dir; -@@ -516,20 +517,15 @@ static void ofd_procfs_add_brw_stats_symlink(struct ofd_device *ofd) - lprocfs_add_symlink("writethrough_cache_enable", - obd->obd_proc_entry, - "../../%s/%s/writethrough_cache_enable", -- osd_root->name, osd_dir->name); -+ osd_root->name, osd_dir->name);*/ - } - - static void ofd_procfs_fini(struct ofd_device *ofd) - { - struct obd_device *obd = ofd_obd(ofd); - -- lprocfs_remove_proc_entry("writethrough_cache_enable", -- obd->obd_proc_entry); -- lprocfs_remove_proc_entry("readcache_max_filesize", -- obd->obd_proc_entry); -- lprocfs_remove_proc_entry("read_cache_enable", obd->obd_proc_entry); -- lprocfs_remove_proc_entry("brw_stats", obd->obd_proc_entry); -- lprocfs_remove_proc_entry("clear", obd->obd_proc_exports_entry); -+ lprocfs_remove(&obd->obd_proc_exports_entry); -+ lprocfs_remove(&obd->obd_proc_entry); - lprocfs_free_per_client_stats(obd); - lprocfs_obd_cleanup(obd); - lprocfs_free_obd_stats(obd); -@@ -1889,7 +1885,6 @@ static struct lu_device_type ofd_device_type = { - - int __init ofd_init(void) - { -- struct lprocfs_static_vars lvars; - int rc; - - rc = lu_kmem_init(ofd_caches); -@@ -1902,11 +1897,9 @@ int __init ofd_init(void) - return(rc); - } - -- lprocfs_ofd_init_vars(&lvars); -- - rc = class_register_type(&ofd_obd_ops, NULL, NULL, - #ifndef HAVE_ONLY_PROCFS_SEQ -- lvars.module_vars, -+ NULL, - #endif - LUSTRE_OST_NAME, &ofd_device_type); - return rc; -diff --git a/lustre/ofd/ofd_internal.h b/lustre/ofd/ofd_internal.h -index 9285a1f..6acae49 100644 ---- a/lustre/ofd/ofd_internal.h -+++ b/lustre/ofd/ofd_internal.h -@@ -383,13 +383,10 @@ int ofd_txn_stop_cb(const struct lu_env *env, struct thandle *txn, - - /* lproc_ofd.c */ - #ifdef LPROCFS --void lprocfs_ofd_init_vars(struct lprocfs_static_vars *lvars); -+void lprocfs_ofd_init_vars(struct obd_device *obd); - void ofd_stats_counter_init(struct lprocfs_stats *stats); - #else --static void lprocfs_ofd_init_vars(struct lprocfs_static_vars *lvars) --{ -- memset(lvars, 0, sizeof(*lvars)); --} -+static void lprocfs_ofd_init_vars(struct obd_device *obd) {} - static inline void ofd_stats_counter_init(struct lprocfs_stats *stats) {} - #endif - --- -1.8.5.1 - diff --git a/sys-cluster/lustre/files/0005-LU-3974-llite-invalidatepage-api-changed.patch b/sys-cluster/lustre/files/0013-LU-3974-llite-invalidatepage-api-changed.patch index 63efe17eb..2886b55de 100644 --- a/sys-cluster/lustre/files/0005-LU-3974-llite-invalidatepage-api-changed.patch +++ b/sys-cluster/lustre/files/0013-LU-3974-llite-invalidatepage-api-changed.patch @@ -1,7 +1,7 @@ -From 2725bc0f3bc5fa7706b9a475ccb0c191f21ca884 Mon Sep 17 00:00:00 2001 +From 48a712836dff9f15b8d17b9e34caa6acfebf22ce Mon Sep 17 00:00:00 2001 From: James Simmons <uja.ornl@gmail.com> Date: Tue, 24 Sep 2013 12:29:47 -0400 -Subject: [PATCH 05/18] LU-3974 llite: invalidatepage api changed +Subject: [PATCH 13/13] LU-3974 llite: invalidatepage api changed Until recently invalidating pages from the buffer cache was dependent only on the page passed in and the start @@ -19,10 +19,10 @@ Change-Id: Iedf458b20b2604bc3099d5ae38bf0ad07df83bd3 3 files changed, 48 insertions(+), 15 deletions(-) diff --git a/lustre/autoconf/lustre-core.m4 b/lustre/autoconf/lustre-core.m4 -index 3ac55d6..ab94acd 100644 +index f44a277..5409fde 100644 --- a/lustre/autoconf/lustre-core.m4 +++ b/lustre/autoconf/lustre-core.m4 -@@ -1287,6 +1287,25 @@ LB_LINUX_TRY_COMPILE([ +@@ -1349,6 +1349,25 @@ LB_LINUX_TRY_COMPILE([ ]) # @@ -48,7 +48,7 @@ index 3ac55d6..ab94acd 100644 # 3.11 readdir now takes the new struct dir_context # AC_DEFUN([LC_HAVE_DIR_CONTEXT], -@@ -1442,6 +1461,7 @@ AC_DEFUN([LC_PROG_LINUX], +@@ -1542,6 +1561,7 @@ AC_DEFUN([LC_PROG_LINUX], LC_BLKDEV_RELEASE_RETURN_INT # 3.11 @@ -130,5 +130,5 @@ index 9365c74..bee7996 100644 if (!IS_ERR(env)) { inode = vmpage->mapping->host; -- -1.8.5.1 +1.8.5.3 diff --git a/sys-cluster/lustre/files/0017-LU-3319-procfs-move-mdd-proc-handling-to-seq_files.patch b/sys-cluster/lustre/files/0017-LU-3319-procfs-move-mdd-proc-handling-to-seq_files.patch deleted file mode 100644 index aff2b8563..000000000 --- a/sys-cluster/lustre/files/0017-LU-3319-procfs-move-mdd-proc-handling-to-seq_files.patch +++ /dev/null @@ -1,788 +0,0 @@ -From d32db1df1792f96fa9aa88ca949b403946a92eef Mon Sep 17 00:00:00 2001 -From: James Simmons <uja.ornl@gmail.com> -Date: Mon, 2 Dec 2013 12:40:35 -0500 -Subject: [PATCH 17/18] LU-3319 procfs: move mdd proc handling to seq_files - -With 3.10 linux kernel and above proc handling now only -uses struct seq_files. This patch migrates the mdd -layer proc entries over to using seq_files. - -Signed-off-by: James Simmons <uja.ornl@gmail.com> -Change-Id: I61b7df6bfd5efd0f12e3ca1a1813b7b62d493168 ---- - lustre/include/lustre_lfsck.h | 4 +- - lustre/lfsck/lfsck_internal.h | 9 +- - lustre/lfsck/lfsck_lib.c | 68 ++++------- - lustre/lfsck/lfsck_namespace.c | 61 +++------- - lustre/mdd/mdd_device.c | 25 ++-- - lustre/mdd/mdd_internal.h | 1 - - lustre/mdd/mdd_lproc.c | 259 +++++++++++++++++------------------------ - 7 files changed, 162 insertions(+), 265 deletions(-) - -diff --git a/lustre/include/lustre_lfsck.h b/lustre/include/lustre_lfsck.h -index f75d507..e491933 100644 ---- a/lustre/include/lustre_lfsck.h -+++ b/lustre/include/lustre_lfsck.h -@@ -52,9 +52,9 @@ int lfsck_start(const struct lu_env *env, struct dt_device *key, - int lfsck_stop(const struct lu_env *env, struct dt_device *key, - bool pause); - --int lfsck_get_speed(struct dt_device *key, void *buf, int len); -+int lfsck_get_speed(struct seq_file *m, struct dt_device *key); - int lfsck_set_speed(struct dt_device *key, int val); - --int lfsck_dump(struct dt_device *key, void *buf, int len, __u16 type); -+int lfsck_dump(struct seq_file *m, struct dt_device *key, __u16 type); - - #endif /* _LUSTRE_LFSCK_H */ -diff --git a/lustre/lfsck/lfsck_internal.h b/lustre/lfsck/lfsck_internal.h -index 56cdff0..50eb341 100644 ---- a/lustre/lfsck/lfsck_internal.h -+++ b/lustre/lfsck/lfsck_internal.h -@@ -229,8 +229,7 @@ struct lfsck_operations { - - int (*lfsck_dump)(const struct lu_env *env, - struct lfsck_component *com, -- char *buf, -- int len); -+ struct seq_file *m); - - int (*lfsck_double_scan)(const struct lu_env *env, - struct lfsck_component *com); -@@ -361,10 +360,10 @@ struct lfsck_thread_info { - /* lfsck_lib.c */ - void lfsck_component_cleanup(const struct lu_env *env, - struct lfsck_component *com); --int lfsck_bits_dump(char **buf, int *len, int bits, const char *names[], -+int lfsck_bits_dump(struct seq_file *m, int bits, const char *names[], - const char *prefix); --int lfsck_time_dump(char **buf, int *len, __u64 time, const char *prefix); --int lfsck_pos_dump(char **buf, int *len, struct lfsck_position *pos, -+int lfsck_time_dump(struct seq_file *m, __u64 time, const char *prefix); -+int lfsck_pos_dump(struct seq_file *m, struct lfsck_position *pos, - const char *prefix); - void lfsck_pos_fill(const struct lu_env *env, struct lfsck_instance *lfsck, - struct lfsck_position *pos, bool init); -diff --git a/lustre/lfsck/lfsck_lib.c b/lustre/lfsck/lfsck_lib.c -index 0da2614..da68358 100644 ---- a/lustre/lfsck/lfsck_lib.c -+++ b/lustre/lfsck/lfsck_lib.c -@@ -258,75 +258,49 @@ static inline int lfsck_instance_add(struct lfsck_instance *lfsck) - return 0; - } - --int lfsck_bits_dump(char **buf, int *len, int bits, const char *names[], -+int lfsck_bits_dump(struct seq_file *m, int bits, const char *names[], - const char *prefix) - { -- int save = *len; - int flag; -- int rc; - int i; - -- rc = snprintf(*buf, *len, "%s:%c", prefix, bits != 0 ? ' ' : '\n'); -- if (rc <= 0) -- return -ENOSPC; -+ seq_printf(m, "%s:%c", prefix, bits != 0 ? ' ' : '\n'); - -- *buf += rc; -- *len -= rc; - for (i = 0, flag = 1; bits != 0; i++, flag = 1 << i) { - if (flag & bits) { - bits &= ~flag; -- rc = snprintf(*buf, *len, "%s%c", names[i], -+ seq_printf(m, "%s%c", names[i], - bits != 0 ? ',' : '\n'); -- if (rc <= 0) -- return -ENOSPC; -- -- *buf += rc; -- *len -= rc; - } - } -- return save - *len; -+ return 0; - } - --int lfsck_time_dump(char **buf, int *len, __u64 time, const char *prefix) -+int lfsck_time_dump(struct seq_file *m, __u64 time, const char *prefix) - { -- int rc; -- - if (time != 0) -- rc = snprintf(*buf, *len, "%s: "LPU64" seconds\n", prefix, -- cfs_time_current_sec() - time); -+ seq_printf(m, "%s: "LPU64" seconds\n", prefix, -+ cfs_time_current_sec() - time); - else -- rc = snprintf(*buf, *len, "%s: N/A\n", prefix); -- if (rc <= 0) -- return -ENOSPC; -- -- *buf += rc; -- *len -= rc; -- return rc; -+ seq_printf(m, "%s: N/A\n", prefix); -+ return 0; - } - --int lfsck_pos_dump(char **buf, int *len, struct lfsck_position *pos, -+int lfsck_pos_dump(struct seq_file *m, struct lfsck_position *pos, - const char *prefix) - { -- int rc; -- - if (fid_is_zero(&pos->lp_dir_parent)) { - if (pos->lp_oit_cookie == 0) -- rc = snprintf(*buf, *len, "%s: N/A, N/A, N/A\n", -- prefix); -+ seq_printf(m, "%s: N/A, N/A, N/A\n", prefix); - else -- rc = snprintf(*buf, *len, "%s: "LPU64", N/A, N/A\n", -- prefix, pos->lp_oit_cookie); -+ seq_printf(m, "%s: "LPU64", N/A, N/A\n", -+ prefix, pos->lp_oit_cookie); - } else { -- rc = snprintf(*buf, *len, "%s: "LPU64", "DFID", "LPU64"\n", -- prefix, pos->lp_oit_cookie, -- PFID(&pos->lp_dir_parent), pos->lp_dir_cookie); -+ seq_printf(m, "%s: "LPU64", "DFID", "LPU64"\n", -+ prefix, pos->lp_oit_cookie, -+ PFID(&pos->lp_dir_parent), pos->lp_dir_cookie); - } -- if (rc <= 0) -- return -ENOSPC; -- -- *buf += rc; -- *len -= rc; -- return rc; -+ return 0; - } - - void lfsck_pos_fill(const struct lu_env *env, struct lfsck_instance *lfsck, -@@ -765,7 +739,7 @@ int lfsck_double_scan(const struct lu_env *env, struct lfsck_instance *lfsck) - - /* external interfaces */ - --int lfsck_get_speed(struct dt_device *key, void *buf, int len) -+int lfsck_get_speed(struct seq_file *m, struct dt_device *key) - { - struct lu_env env; - struct lfsck_instance *lfsck; -@@ -780,7 +754,7 @@ int lfsck_get_speed(struct dt_device *key, void *buf, int len) - if (rc != 0) - GOTO(out, rc); - -- rc = snprintf(buf, len, "%u\n", lfsck->li_bookmark_ram.lb_speed_limit); -+ seq_printf(m, "%u\n", lfsck->li_bookmark_ram.lb_speed_limit); - lu_env_fini(&env); - - GOTO(out, rc); -@@ -820,7 +794,7 @@ out: - } - EXPORT_SYMBOL(lfsck_set_speed); - --int lfsck_dump(struct dt_device *key, void *buf, int len, __u16 type) -+int lfsck_dump(struct seq_file *m, struct dt_device *key, __u16 type) - { - struct lu_env env; - struct lfsck_instance *lfsck; -@@ -840,7 +814,7 @@ int lfsck_dump(struct dt_device *key, void *buf, int len, __u16 type) - if (rc != 0) - GOTO(out, rc); - -- rc = com->lc_ops->lfsck_dump(&env, com, buf, len); -+ rc = com->lc_ops->lfsck_dump(&env, com, m); - lu_env_fini(&env); - - GOTO(out, rc); -diff --git a/lustre/lfsck/lfsck_namespace.c b/lustre/lfsck/lfsck_namespace.c -index 3cc043d..225351f 100644 ---- a/lustre/lfsck/lfsck_namespace.c -+++ b/lustre/lfsck/lfsck_namespace.c -@@ -1092,66 +1092,57 @@ static int lfsck_namespace_post(const struct lu_env *env, - - static int - lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com, -- char *buf, int len) -+ struct seq_file *m) - { - struct lfsck_instance *lfsck = com->lc_lfsck; - struct lfsck_bookmark *bk = &lfsck->li_bookmark_ram; - struct lfsck_namespace *ns = - (struct lfsck_namespace *)com->lc_file_ram; -- int save = len; -- int ret = -ENOSPC; - int rc; - - down_read(&com->lc_sem); -- rc = snprintf(buf, len, -- "name: lfsck_namespace\n" -+ seq_printf(m, "name: lfsck_namespace\n" - "magic: 0x%x\n" - "version: %d\n" - "status: %s\n", - ns->ln_magic, - bk->lb_version, - lfsck_status_names[ns->ln_status]); -- if (rc <= 0) -- goto out; - -- buf += rc; -- len -= rc; -- rc = lfsck_bits_dump(&buf, &len, ns->ln_flags, lfsck_flags_names, -- "flags"); -+ rc = lfsck_bits_dump(m, ns->ln_flags, lfsck_flags_names, "flags"); - if (rc < 0) - goto out; - -- rc = lfsck_bits_dump(&buf, &len, bk->lb_param, lfsck_param_names, -- "param"); -+ rc = lfsck_bits_dump(m, bk->lb_param, lfsck_param_names, "param"); - if (rc < 0) - goto out; - -- rc = lfsck_time_dump(&buf, &len, ns->ln_time_last_complete, -+ rc = lfsck_time_dump(m, ns->ln_time_last_complete, - "time_since_last_completed"); - if (rc < 0) - goto out; - -- rc = lfsck_time_dump(&buf, &len, ns->ln_time_latest_start, -+ rc = lfsck_time_dump(m, ns->ln_time_latest_start, - "time_since_latest_start"); - if (rc < 0) - goto out; - -- rc = lfsck_time_dump(&buf, &len, ns->ln_time_last_checkpoint, -+ rc = lfsck_time_dump(m, ns->ln_time_last_checkpoint, - "time_since_last_checkpoint"); - if (rc < 0) - goto out; - -- rc = lfsck_pos_dump(&buf, &len, &ns->ln_pos_latest_start, -+ rc = lfsck_pos_dump(m, &ns->ln_pos_latest_start, - "latest_start_position"); - if (rc < 0) - goto out; - -- rc = lfsck_pos_dump(&buf, &len, &ns->ln_pos_last_checkpoint, -+ rc = lfsck_pos_dump(m, &ns->ln_pos_last_checkpoint, - "last_checkpoint_position"); - if (rc < 0) - goto out; - -- rc = lfsck_pos_dump(&buf, &len, &ns->ln_pos_first_inconsistent, -+ rc = lfsck_pos_dump(m, &ns->ln_pos_first_inconsistent, - "first_failure_position"); - if (rc < 0) - goto out; -@@ -1171,8 +1162,7 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com, - do_div(new_checked, duration); - if (rtime != 0) - do_div(speed, rtime); -- rc = snprintf(buf, len, -- "checked_phase1: "LPU64"\n" -+ seq_printf(m, "checked_phase1: "LPU64"\n" - "checked_phase2: "LPU64"\n" - "updated_phase1: "LPU64"\n" - "updated_phase2: "LPU64"\n" -@@ -1204,11 +1194,6 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com, - ns->ln_run_time_phase2, - speed, - new_checked); -- if (rc <= 0) -- goto out; -- -- buf += rc; -- len -= rc; - - LASSERT(lfsck->li_di_oit != NULL); - -@@ -1237,9 +1222,7 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com, - pos.lp_dir_cookie = 0; - } - spin_unlock(&lfsck->li_lock); -- rc = lfsck_pos_dump(&buf, &len, &pos, "current_position"); -- if (rc <= 0) -- goto out; -+ lfsck_pos_dump(m, &pos, "current_position"); - } else if (ns->ln_status == LS_SCANNING_PHASE2) { - cfs_duration_t duration = cfs_time_current() - - lfsck->li_time_last_checkpoint; -@@ -1257,8 +1240,7 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com, - do_div(speed1, ns->ln_run_time_phase1); - if (rtime != 0) - do_div(speed2, rtime); -- rc = snprintf(buf, len, -- "checked_phase1: "LPU64"\n" -+ seq_printf(m, "checked_phase1: "LPU64"\n" - "checked_phase2: "LPU64"\n" - "updated_phase1: "LPU64"\n" - "updated_phase2: "LPU64"\n" -@@ -1293,11 +1275,6 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com, - speed2, - new_checked, - PFID(&ns->ln_fid_latest_scanned_phase2)); -- if (rc <= 0) -- goto out; -- -- buf += rc; -- len -= rc; - } else { - __u64 speed1 = ns->ln_items_checked; - __u64 speed2 = ns->ln_objs_checked_phase2; -@@ -1306,8 +1283,7 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com, - do_div(speed1, ns->ln_run_time_phase1); - if (ns->ln_run_time_phase2 != 0) - do_div(speed2, ns->ln_run_time_phase2); -- rc = snprintf(buf, len, -- "checked_phase1: "LPU64"\n" -+ seq_printf(m, "checked_phase1: "LPU64"\n" - "checked_phase2: "LPU64"\n" - "updated_phase1: "LPU64"\n" - "updated_phase2: "LPU64"\n" -@@ -1340,17 +1316,10 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com, - ns->ln_run_time_phase2, - speed1, - speed2); -- if (rc <= 0) -- goto out; -- -- buf += rc; -- len -= rc; - } -- ret = save - len; -- - out: - up_read(&com->lc_sem); -- return ret; -+ return 0; - } - - static int lfsck_namespace_double_scan(const struct lu_env *env, -diff --git a/lustre/mdd/mdd_device.c b/lustre/mdd/mdd_device.c -index 750281a..ee82f71 100644 ---- a/lustre/mdd/mdd_device.c -+++ b/lustre/mdd/mdd_device.c -@@ -812,16 +812,16 @@ static int mdd_process_config(const struct lu_env *env, - ENTRY; - - switch (cfg->lcfg_command) { -- case LCFG_PARAM: { -- struct lprocfs_static_vars lvars; -- -- lprocfs_mdd_init_vars(&lvars); -- rc = class_process_proc_param(PARAM_MDD, lvars.obd_vars, cfg,m); -- if (rc > 0 || rc == -ENOSYS) -- /* we don't understand; pass it on */ -- rc = next->ld_ops->ldo_process_config(env, next, cfg); -- break; -- } -+ case LCFG_PARAM: { -+ struct obd_device *obd = mdd2obd_dev(m); -+ -+ rc = class_process_proc_seq_param(PARAM_MDD, obd->obd_vars, -+ cfg, m); -+ if (rc > 0 || rc == -ENOSYS) -+ /* we don't understand; pass it on */ -+ rc = next->ld_ops->ldo_process_config(env, next, cfg); -+ break; -+ } - case LCFG_SETUP: - rc = next->ld_ops->ldo_process_config(env, next, cfg); - if (rc) -@@ -1492,11 +1492,8 @@ LU_CONTEXT_KEY_DEFINE(mdd, LCT_MD_THREAD); - - static int __init mdd_mod_init(void) - { -- struct lprocfs_static_vars lvars; - int rc; - -- lprocfs_mdd_init_vars(&lvars); -- - rc = lu_kmem_init(mdd_caches); - if (rc) - return rc; -@@ -1512,7 +1509,7 @@ static int __init mdd_mod_init(void) - - rc = class_register_type(&mdd_obd_device_ops, NULL, NULL, - #ifndef HAVE_ONLY_PROCFS_SEQ -- lvars.module_vars, -+ NULL, - #endif - LUSTRE_MDD_NAME, &mdd_device_type); - if (rc) -diff --git a/lustre/mdd/mdd_internal.h b/lustre/mdd/mdd_internal.h -index daa1dcb..5332b2c 100644 ---- a/lustre/mdd/mdd_internal.h -+++ b/lustre/mdd/mdd_internal.h -@@ -340,7 +340,6 @@ int orph_declare_index_delete(const struct lu_env *, struct mdd_object *, - struct thandle *); - - /* mdd_lproc.c */ --void lprocfs_mdd_init_vars(struct lprocfs_static_vars *lvars); - int mdd_procfs_init(struct mdd_device *mdd, const char *name); - int mdd_procfs_fini(struct mdd_device *mdd); - -diff --git a/lustre/mdd/mdd_lproc.c b/lustre/mdd/mdd_lproc.c -index bd23302..6ddacf7 100644 ---- a/lustre/mdd/mdd_lproc.c -+++ b/lustre/mdd/mdd_lproc.c -@@ -49,56 +49,13 @@ - #include <libcfs/libcfs_string.h> - #include "mdd_internal.h" - --int mdd_procfs_init(struct mdd_device *mdd, const char *name) -+static ssize_t -+mdd_atime_diff_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) - { -- struct lprocfs_static_vars lvars; -- struct obd_type *type; -- int rc; -- ENTRY; -- -- /* at the moment there is no linkage between lu_type -- * and obd_type, so we lookup obd_type this way */ -- type = class_search_type(LUSTRE_MDD_NAME); -- -- LASSERT(name != NULL); -- LASSERT(type != NULL); -- -- /* Find the type procroot and add the proc entry for this device */ -- lprocfs_mdd_init_vars(&lvars); -- mdd->mdd_proc_entry = lprocfs_register(name, type->typ_procroot, -- lvars.obd_vars, mdd); -- if (IS_ERR(mdd->mdd_proc_entry)) { -- rc = PTR_ERR(mdd->mdd_proc_entry); -- CERROR("Error %d setting up lprocfs for %s\n", -- rc, name); -- mdd->mdd_proc_entry = NULL; -- GOTO(out, rc); -- } -- -- rc = 0; -- -- EXIT; --out: -- if (rc) -- mdd_procfs_fini(mdd); -- return rc; --} -- --int mdd_procfs_fini(struct mdd_device *mdd) --{ -- if (mdd->mdd_proc_entry) { -- lprocfs_remove(&mdd->mdd_proc_entry); -- mdd->mdd_proc_entry = NULL; -- } -- RETURN(0); --} -- --static int lprocfs_wr_atime_diff(struct file *file, const char *buffer, -- unsigned long count, void *data) --{ -- struct mdd_device *mdd = data; -- char kernbuf[20], *end; -- unsigned long diff = 0; -+ struct mdd_device *mdd = ((struct seq_file *)file->private_data)->private; -+ char kernbuf[20], *end; -+ unsigned long diff = 0; - - if (count > (sizeof(kernbuf) - 1)) - return -EINVAL; -@@ -116,37 +73,34 @@ static int lprocfs_wr_atime_diff(struct file *file, const char *buffer, - return count; - } - --static int lprocfs_rd_atime_diff(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int mdd_atime_diff_seq_show(struct seq_file *m, void *data) - { -- struct mdd_device *mdd = data; -+ struct mdd_device *mdd = m->private; - -- *eof = 1; -- return snprintf(page, count, "%lu\n", mdd->mdd_atime_diff); -+ return seq_printf(m, "%lu\n", mdd->mdd_atime_diff); - } -- -+LPROC_SEQ_FOPS(mdd_atime_diff); - - /**** changelogs ****/ --static int lprocfs_rd_changelog_mask(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int mdd_changelog_mask_seq_show(struct seq_file *m, void *data) - { -- struct mdd_device *mdd = data; -- int i = 0, rc = 0; -- -- *eof = 1; -- while (i < CL_LAST) { -- if (mdd->mdd_cl.mc_mask & (1 << i)) -- rc += snprintf(page + rc, count - rc, "%s ", -- changelog_type2str(i)); -- i++; -- } -- return rc; -+ struct mdd_device *mdd = m->private; -+ int i = 0; -+ -+ while (i < CL_LAST) { -+ if (mdd->mdd_cl.mc_mask & (1 << i)) -+ seq_printf(m, "%s ", changelog_type2str(i)); -+ i++; -+ } -+ seq_printf(m, "\n"); -+ return 0; - } - --static int lprocfs_wr_changelog_mask(struct file *file, const char *buffer, -- unsigned long count, void *data) -+static ssize_t -+mdd_changelog_mask_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) - { -- struct mdd_device *mdd = data; -+ struct mdd_device *mdd = ((struct seq_file *)file->private_data)->private; - char *kernbuf; - int rc; - ENTRY; -@@ -168,45 +122,32 @@ out: - OBD_FREE(kernbuf, PAGE_CACHE_SIZE); - return rc; - } -- --struct cucb_data { -- char *page; -- int count; -- int idx; --}; -+LPROC_SEQ_FOPS(mdd_changelog_mask); - - static int lprocfs_changelog_users_cb(const struct lu_env *env, - struct llog_handle *llh, - struct llog_rec_hdr *hdr, void *data) - { -- struct llog_changelog_user_rec *rec; -- struct cucb_data *cucb = (struct cucb_data *)data; -- -- LASSERT(llh->lgh_hdr->llh_flags & LLOG_F_IS_PLAIN); -+ struct llog_changelog_user_rec *rec; -+ struct seq_file *m = data; - -- rec = (struct llog_changelog_user_rec *)hdr; -+ LASSERT(llh->lgh_hdr->llh_flags & LLOG_F_IS_PLAIN); - -- cucb->idx += snprintf(cucb->page + cucb->idx, cucb->count - cucb->idx, -- CHANGELOG_USER_PREFIX"%-3d "LPU64"\n", -- rec->cur_id, rec->cur_endrec); -- if (cucb->idx >= cucb->count) -- return -ENOSPC; -+ rec = (struct llog_changelog_user_rec *)hdr; - -- return 0; -+ seq_printf(m, CHANGELOG_USER_PREFIX"%-3d "LPU64"\n", -+ rec->cur_id, rec->cur_endrec); -+ return 0; - } - --static int lprocfs_rd_changelog_users(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int mdd_changelog_users_seq_show(struct seq_file *m, void *data) - { - struct lu_env env; -- struct mdd_device *mdd = data; -+ struct mdd_device *mdd = m->private; - struct llog_ctxt *ctxt; -- struct cucb_data cucb; - __u64 cur; - int rc; - -- *eof = 1; -- - ctxt = llog_get_context(mdd2obd_dev(mdd), - LLOG_CHANGELOG_USER_ORIG_CTXT); - if (ctxt == NULL) -@@ -223,37 +164,31 @@ static int lprocfs_rd_changelog_users(char *page, char **start, off_t off, - cur = mdd->mdd_cl.mc_index; - spin_unlock(&mdd->mdd_cl.mc_lock); - -- cucb.count = count; -- cucb.page = page; -- cucb.idx = 0; -- -- cucb.idx += snprintf(cucb.page + cucb.idx, cucb.count - cucb.idx, -- "current index: "LPU64"\n", cur); -- -- cucb.idx += snprintf(cucb.page + cucb.idx, cucb.count - cucb.idx, -- "%-5s %s\n", "ID", "index"); -+ seq_printf(m, "current index: "LPU64"\n", cur); -+ seq_printf(m, "%-5s %s\n", "ID", "index"); - - llog_cat_process(&env, ctxt->loc_handle, lprocfs_changelog_users_cb, -- &cucb, 0, 0); -+ &m, 0, 0); - - lu_env_fini(&env); - llog_ctxt_put(ctxt); -- return cucb.idx; -+ return 0; - } -+LPROC_SEQ_FOPS_RO(mdd_changelog_users); - --static int lprocfs_rd_sync_perm(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int mdd_sync_perm_seq_show(struct seq_file *m, void *data) - { -- struct mdd_device *mdd = data; -+ struct mdd_device *mdd = m->private; - -- LASSERT(mdd != NULL); -- return snprintf(page, count, "%d\n", mdd->mdd_sync_permission); -+ LASSERT(mdd != NULL); -+ return seq_printf(m, "%d\n", mdd->mdd_sync_permission); - } - --static int lprocfs_wr_sync_perm(struct file *file, const char *buffer, -- unsigned long count, void *data) -+static ssize_t -+mdd_sync_perm_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) - { -- struct mdd_device *mdd = data; -+ struct mdd_device *mdd = ((struct seq_file *)file->private_data)->private; - int val, rc; - - LASSERT(mdd != NULL); -@@ -264,24 +199,21 @@ static int lprocfs_wr_sync_perm(struct file *file, const char *buffer, - mdd->mdd_sync_permission = !!val; - return count; - } -+LPROC_SEQ_FOPS(mdd_sync_perm); - --static int lprocfs_rd_lfsck_speed_limit(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int mdd_lfsck_speed_limit_seq_show(struct seq_file *m, void *data) - { -- struct mdd_device *mdd = data; -- int rc; -+ struct mdd_device *mdd = m->private; - - LASSERT(mdd != NULL); -- *eof = 1; -- -- rc = lfsck_get_speed(mdd->mdd_bottom, page, count); -- return rc != 0 ? rc : count; -+ return lfsck_get_speed(m, mdd->mdd_bottom); - } - --static int lprocfs_wr_lfsck_speed_limit(struct file *file, const char *buffer, -- unsigned long count, void *data) -+static ssize_t -+mdd_lfsck_speed_limit_seq_write(struct file *file, const char *buffer, -+ size_t count, loff_t *off) - { -- struct mdd_device *mdd = data; -+ struct mdd_device *mdd = ((struct seq_file *)file->private_data)->private; - __u32 val; - int rc; - -@@ -293,40 +225,67 @@ static int lprocfs_wr_lfsck_speed_limit(struct file *file, const char *buffer, - rc = lfsck_set_speed(mdd->mdd_bottom, val); - return rc != 0 ? rc : count; - } -+LPROC_SEQ_FOPS(mdd_lfsck_speed_limit); - --static int lprocfs_rd_lfsck_namespace(char *page, char **start, off_t off, -- int count, int *eof, void *data) -+static int mdd_lfsck_namespace_seq_show(struct seq_file *m, void *data) - { -- struct mdd_device *mdd = data; -- int rc; -+ struct mdd_device *mdd = m->private; - - LASSERT(mdd != NULL); -- *eof = 1; -- -- rc = lfsck_dump(mdd->mdd_bottom, page, count, LT_NAMESPACE); -- return rc; -+ return lfsck_dump(m, mdd->mdd_bottom, LT_NAMESPACE); - } -- --static struct lprocfs_vars lprocfs_mdd_obd_vars[] = { -- { "atime_diff", lprocfs_rd_atime_diff, lprocfs_wr_atime_diff, 0 }, -- { "changelog_mask", lprocfs_rd_changelog_mask, -- lprocfs_wr_changelog_mask, 0 }, -- { "changelog_users", lprocfs_rd_changelog_users, 0, 0}, -- { "sync_permission", lprocfs_rd_sync_perm, lprocfs_wr_sync_perm, 0 }, -- { "lfsck_speed_limit", lprocfs_rd_lfsck_speed_limit, -- lprocfs_wr_lfsck_speed_limit, 0 }, -- { "lfsck_namespace", lprocfs_rd_lfsck_namespace, 0, 0 }, -+LPROC_SEQ_FOPS_RO(mdd_lfsck_namespace); -+ -+static struct lprocfs_seq_vars lprocfs_mdd_obd_vars[] = { -+ { "atime_diff", &mdd_atime_diff_fops }, -+ { "changelog_mask", &mdd_changelog_mask_fops }, -+ { "changelog_users", &mdd_changelog_users_fops }, -+ { "sync_permission", &mdd_sync_perm_fops }, -+ { "lfsck_speed_limit", &mdd_lfsck_speed_limit_fops }, -+ { "lfsck_namespace", &mdd_lfsck_namespace_fops }, - { 0 } - }; - --static struct lprocfs_vars lprocfs_mdd_module_vars[] = { -- { "num_refs", lprocfs_rd_numrefs, 0, 0 }, -- { 0 } --}; -- --void lprocfs_mdd_init_vars(struct lprocfs_static_vars *lvars) -+int mdd_procfs_init(struct mdd_device *mdd, const char *name) - { -- lvars->module_vars = lprocfs_mdd_module_vars; -- lvars->obd_vars = lprocfs_mdd_obd_vars; -+ struct obd_device *obd = class_name2obd(name); -+ struct obd_type *type; -+ int rc; -+ ENTRY; -+ -+ /* at the moment there is no linkage between lu_type -+ * and obd_type, so we lookup obd_type this way */ -+ type = class_search_type(LUSTRE_MDD_NAME); -+ -+ LASSERT(name != NULL); -+ LASSERT(type != NULL); -+ LASSERT(obd != NULL); -+ -+ /* Find the type procroot and add the proc entry for this device */ -+ obd->obd_vars = lprocfs_mdd_obd_vars; -+ mdd->mdd_proc_entry = lprocfs_seq_register(name, type->typ_procroot, -+ obd->obd_vars, mdd); -+ if (IS_ERR(mdd->mdd_proc_entry)) { -+ rc = PTR_ERR(mdd->mdd_proc_entry); -+ CERROR("Error %d setting up lprocfs for %s\n", -+ rc, name); -+ mdd->mdd_proc_entry = NULL; -+ GOTO(out, rc); -+ } -+ rc = 0; -+ -+ EXIT; -+out: -+ if (rc) -+ mdd_procfs_fini(mdd); -+ return rc; - } - -+int mdd_procfs_fini(struct mdd_device *mdd) -+{ -+ if (mdd->mdd_proc_entry) { -+ lprocfs_remove(&mdd->mdd_proc_entry); -+ mdd->mdd_proc_entry = NULL; -+ } -+ RETURN(0); -+} --- -1.8.5.1 - diff --git a/sys-cluster/lustre/lustre-9999.ebuild b/sys-cluster/lustre/lustre-9999.ebuild index a7fbbedfb..959fb1fd6 100644 --- a/sys-cluster/lustre/lustre-9999.ebuild +++ b/sys-cluster/lustre/lustre-9999.ebuild @@ -34,23 +34,18 @@ DEPEND="${RDEPEND} PATCHES=( "${FILESDIR}/0001-LU-2982-build-make-AC-check-for-linux-arch-sandbox-f.patch" - "${FILESDIR}/0002-LU-3373-ldiskfs-ldiskfs-patches-for-3.11.1-fc19.patch" - "${FILESDIR}/0003-LU-3974-llite-dentry-d_compare-changes-in-3.11.patch" - "${FILESDIR}/0004-LU-3974-llite-use-new-struct-dir_context.patch" - "${FILESDIR}/0005-LU-3974-llite-invalidatepage-api-changed.patch" - "${FILESDIR}/0006-LU-3319-procfs-move-llite-proc-handling-over-to-seq_.patch" - "${FILESDIR}/0007-LU-3319-procfs-move-lmv-proc-handling-over-to-seq_fi.patch" - "${FILESDIR}/0008-LU-3319-procfs-move-ldlm-proc-handling-over-to-seq_f.patch" - "${FILESDIR}/0009-LU-3319-procfs-move-ost-proc-handling-over-to-seq_fi.patch" - "${FILESDIR}/0010-LU-3319-procfs-update-shared-server-side-core-proc-h.patch" - "${FILESDIR}/0011-LU-3319-procfs-update-zfs-proc-handling-to-seq_files.patch" - "${FILESDIR}/0012-LU-3319-procfs-move-mgs-proc-handling-to-seq_files.patch" - "${FILESDIR}/0013-LU-3319-procfs-move-ofd-proc-handling-to-seq_files.patch" - "${FILESDIR}/0014-LU-3319-procfs-move-lod-proc-handling-to-seq_files.patch" - "${FILESDIR}/0015-LU-3319-procfs-move-osp-proc-handling-to-seq_files.patch" - "${FILESDIR}/0016-LU-3319-procfs-move-mdt-mds-proc-handling-to-seq_fil.patch" - "${FILESDIR}/0017-LU-3319-procfs-move-mdd-proc-handling-to-seq_files.patch" - "${FILESDIR}/0018-LU-3319-procfs-update-ldiskfs-proc-handling-to-seq_f.patch" + "${FILESDIR}/0002-LU-3319-lprocfs-client-side-cleanups.patch" + "${FILESDIR}/0003-LU-3319-procfs-fix-symlink-handling.patch" + "${FILESDIR}/0004-LU-3319-procfs-move-mgs-proc-handling-to-seq_files.patch" + "${FILESDIR}/0005-LU-3319-procfs-update-zfs-proc-handling-to-seq_files.patch" + "${FILESDIR}/0006-LU-3319-procfs-move-osp-proc-handling-to-seq_files.patch" + "${FILESDIR}/0007-LU-3319-procfs-move-lod-proc-handling-to-seq_files.patch" + "${FILESDIR}/0008-LU-3319-procfs-move-mdt-mds-proc-handling-to-seq_fil.patch" + "${FILESDIR}/0009-LU-3319-procfs-move-mdd-ofd-proc-handling-to-seq_fil.patch" + "${FILESDIR}/0010-LU-3319-procfs-update-ldiskfs-proc-handling-to-seq_f.patch" + "${FILESDIR}/0011-LU-3373-osd-ldiskfs-readdir-replace-by-iterate.patch" + "${FILESDIR}/0012-LU-3974-llite-use-new-struct-dir_context.patch" + "${FILESDIR}/0013-LU-3974-llite-invalidatepage-api-changed.patch" ) pkg_setup() { |