Whamcloud - gitweb
LU-1406 ofd: add procfs values
authorMikhail Pershin <tappro@whamcloud.com>
Mon, 21 May 2012 07:28:55 +0000 (11:28 +0400)
committerOleg Drokin <green@whamcloud.com>
Thu, 7 Jun 2012 22:13:20 +0000 (18:13 -0400)
Add procfs functionality to OFD

Signed-off-by: Mikhail Pershin <tappro@whamcloud.com>
Change-Id: If2c0a66479d9df8d585cde651244b86bf78636ce
Reviewed-on: http://review.whamcloud.com/2862
Tested-by: Hudson
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Alex Zhuravlev <bzzz@whamcloud.com>
lustre/ofd/lproc_ofd.c
lustre/ofd/ofd_dev.c
lustre/ofd/ofd_fs.c
lustre/ofd/ofd_internal.h
lustre/ofd/ofd_obd.c

index 4d104e5..e806a61 100644 (file)
 
 #define DEBUG_SUBSYSTEM S_CLASS
 
 
 #define DEBUG_SUBSYSTEM S_CLASS
 
-#include <linux/version.h>
-#include <lprocfs_status.h>
 #include <obd.h>
 #include <obd.h>
+#include <lprocfs_status.h>
 #include <linux/seq_file.h>
 #include <linux/seq_file.h>
-#include <linux/version.h>
 
 #include "ofd_internal.h"
 
 #ifdef LPROCFS
 
 
 #include "ofd_internal.h"
 
 #ifdef LPROCFS
 
+static int lprocfs_ofd_rd_groups(char *page, char **start, off_t off,
+                                int count, int *eof, void *data)
+{
+       struct obd_device *obd = (struct obd_device *)data;
+       struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev);
+
+       *eof = 1;
+       return snprintf(page, count, "%u\n", ofd->ofd_max_group);
+}
+
+static int lprocfs_ofd_rd_last_id(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);
+       int                      retval = 0, rc, i;
+
+       if (obd == NULL)
+               return 0;
+
+       for (i = FID_SEQ_OST_MDT0; i <= ofd->ofd_max_group; i++) {
+               rc = snprintf(page, count, LPU64"\n", ofd_last_id(ofd, i));
+               if (rc < 0) {
+                       retval = rc;
+                       break;
+               }
+               page += rc;
+               count -= rc;
+               retval += rc;
+       }
+       return retval;
+}
+
+static int lprocfs_ofd_rd_capa(char *page, char **start, off_t off,
+                              int count, int *eof, void *data)
+{
+       struct obd_device       *obd = data;
+       int                      rc;
+
+       rc = snprintf(page, count, "capability on: %s\n",
+                     obd->u.filter.fo_fl_oss_capa ? "oss" : "");
+       return rc;
+}
+
+static int lprocfs_ofd_wr_capa(struct file *file, const char *buffer,
+                              unsigned long count, void *data)
+{
+       struct obd_device       *obd = data;
+       int                      val, rc;
+
+       rc = lprocfs_write_helper(buffer, count, &val);
+       if (rc)
+               return rc;
+
+       if (val & ~0x1) {
+               CERROR("invalid capability mode, only 0/1 are accepted.\n"
+                      " 1: enable oss fid capability\n"
+                      " 0: disable oss fid capability\n");
+               return -EINVAL;
+       }
+
+       obd->u.filter.fo_fl_oss_capa = val;
+       LCONSOLE_INFO("OSS %s %s fid capability.\n", obd->obd_name,
+                     val ? "enabled" : "disabled");
+       return count;
+}
+
+static int lprocfs_ofd_rd_capa_count(char *page, char **start, off_t off,
+                                    int count, int *eof, void *data)
+{
+       return snprintf(page, count, "%d %d\n",
+                       capa_count[CAPA_SITE_CLIENT],
+                       capa_count[CAPA_SITE_SERVER]);
+}
+
+int lprocfs_ofd_rd_degraded(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 snprintf(page, count, "%u\n", ofd->ofd_raid_degraded);
+}
+
+int lprocfs_ofd_wr_degraded(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);
+       int                      val, rc;
+
+       rc = lprocfs_write_helper(buffer, count, &val);
+       if (rc)
+               return rc;
+
+       cfs_spin_lock(&ofd->ofd_flags_lock);
+       ofd->ofd_raid_degraded = !!val;
+       cfs_spin_unlock(&ofd->ofd_flags_lock);
+
+       return count;
+}
+
+int lprocfs_ofd_rd_fstype(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);
+       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);
+}
+
+int lprocfs_ofd_rd_syncjournal(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);
+       int                      rc;
+
+       rc = snprintf(page, count, "%u\n", ofd->ofd_syncjournal);
+       return rc;
+}
+
+int lprocfs_ofd_wr_syncjournal(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);
+       int                      val;
+       int                      rc;
+
+       rc = lprocfs_write_helper(buffer, count, &val);
+       if (rc)
+               return rc;
+
+       if (val < 0)
+               return -EINVAL;
+
+       cfs_spin_lock(&ofd->ofd_flags_lock);
+       ofd->ofd_syncjournal = !!val;
+       ofd_slc_set(ofd);
+       cfs_spin_unlock(&ofd->ofd_flags_lock);
+
+       return count;
+}
+
+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)
+{
+       struct obd_device       *obd = data;
+       struct ofd_device       *ofd = ofd_dev(obd->obd_lu_dev);
+       int                      rc;
+
+       rc = snprintf(page, count, "%s\n",
+                     sync_on_cancel_states[ofd->ofd_sync_lock_cancel]);
+       return rc;
+}
+
+int lprocfs_ofd_wr_sync_lock_cancel(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);
+       int                      val = -1;
+       int                      i;
+
+       for (i = 0 ; i < NUM_SYNC_ON_CANCEL_STATES; i++) {
+               if (memcmp(buffer, sync_on_cancel_states[i],
+                          strlen(sync_on_cancel_states[i])) == 0) {
+                       val = i;
+                       break;
+               }
+       }
+       if (val == -1) {
+               int rc;
+
+               rc = lprocfs_write_helper(buffer, count, &val);
+               if (rc)
+                       return rc;
+       }
+
+       if (val < 0 || val > 2)
+               return -EINVAL;
+
+       cfs_spin_lock(&ofd->ofd_flags_lock);
+       ofd->ofd_sync_lock_cancel = val;
+       cfs_spin_unlock(&ofd->ofd_flags_lock);
+       return count;
+}
+
 static struct lprocfs_vars lprocfs_ofd_obd_vars[] = {
 static struct lprocfs_vars lprocfs_ofd_obd_vars[] = {
-       { "uuid",         lprocfs_rd_uuid,          0, 0 },
+       { "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 },
+       { "filegroups",          lprocfs_ofd_rd_groups, 0, 0 },
+       { "fstype",              lprocfs_ofd_rd_fstype, 0, 0 },
+       { "last_id",             lprocfs_ofd_rd_last_id, 0, 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},
+       { "capa",                lprocfs_ofd_rd_capa,
+                                lprocfs_ofd_wr_capa, 0 },
+       { "capa_count",          lprocfs_ofd_rd_capa_count, 0, 0 },
        { 0 }
 };
 
        { 0 }
 };
 
@@ -58,10 +282,150 @@ static struct lprocfs_vars lprocfs_ofd_module_vars[] = {
        { 0 }
 };
 
        { 0 }
 };
 
+#define pct(a,b) (b ? a * 100 / b : 0)
+
+static void display_brw_stats(struct seq_file *seq, char *name, char *units,
+                             struct obd_histogram *read,
+                             struct obd_histogram *write, int log2)
+{
+       unsigned long   read_tot, write_tot, r, w, read_cum = 0, write_cum = 0;
+       int             i;
+
+       seq_printf(seq, "\n%26s read      |     write\n", " ");
+       seq_printf(seq, "%-22s %-5s %% cum %% |  %-5s %% cum %%\n",
+                  name, units, units);
+
+       read_tot = lprocfs_oh_sum(read);
+       write_tot = lprocfs_oh_sum(write);
+       for (i = 0; i < OBD_HIST_MAX; i++) {
+               r = read->oh_buckets[i];
+               w = write->oh_buckets[i];
+               read_cum += r;
+               write_cum += w;
+               if (read_cum == 0 && write_cum == 0)
+                       continue;
+
+               if (!log2)
+                       seq_printf(seq, "%u", i);
+               else if (i < 10)
+                       seq_printf(seq, "%u", 1 << i);
+               else if (i < 20)
+                       seq_printf(seq, "%uK", 1 << (i - 10));
+               else
+                       seq_printf(seq, "%uM", 1 << (i - 20));
+
+               seq_printf(seq, ":\t\t%10lu %3lu %3lu   | %4lu %3lu %3lu\n",
+                          r, pct(r, read_tot), pct(read_cum, read_tot),
+                          w, pct(w, write_tot), pct(write_cum, write_tot));
+
+               if (read_cum == read_tot && write_cum == write_tot)
+                       break;
+       }
+}
+
+static void brw_stats_show(struct seq_file *seq, struct brw_stats *brw_stats)
+{
+       struct timeval  now;
+       char            title[24];
+
+       /* this sampling races with updates */
+       cfs_gettimeofday(&now);
+       seq_printf(seq, "snapshot_time:         %lu.%lu (secs.usecs)\n",
+                  now.tv_sec, now.tv_usec);
+
+       display_brw_stats(seq, "pages per bulk r/w", "rpcs",
+                         &brw_stats->hist[BRW_R_PAGES],
+                         &brw_stats->hist[BRW_W_PAGES], 1);
+
+       display_brw_stats(seq, "discontiguous pages", "rpcs",
+                         &brw_stats->hist[BRW_R_DISCONT_PAGES],
+                         &brw_stats->hist[BRW_W_DISCONT_PAGES], 0);
+
+       display_brw_stats(seq, "discontiguous blocks", "rpcs",
+                         &brw_stats->hist[BRW_R_DISCONT_BLOCKS],
+                         &brw_stats->hist[BRW_W_DISCONT_BLOCKS], 0);
+
+       display_brw_stats(seq, "disk fragmented I/Os", "ios",
+                         &brw_stats->hist[BRW_R_DIO_FRAGS],
+                         &brw_stats->hist[BRW_W_DIO_FRAGS], 0);
+
+       display_brw_stats(seq, "disk I/Os in flight", "ios",
+                         &brw_stats->hist[BRW_R_RPC_HIST],
+                         &brw_stats->hist[BRW_W_RPC_HIST], 0);
+
+       sprintf(title, "I/O time (1/%ds)", CFS_HZ);
+       display_brw_stats(seq, title, "ios",
+                         &brw_stats->hist[BRW_R_IO_TIME],
+                         &brw_stats->hist[BRW_W_IO_TIME], 1);
+
+       display_brw_stats(seq, "disk I/O size", "ios",
+                         &brw_stats->hist[BRW_R_DISK_IOSIZE],
+                         &brw_stats->hist[BRW_W_DISK_IOSIZE], 1);
+}
+
+#undef pct
+
+static int ofd_brw_stats_seq_show(struct seq_file *seq, void *v)
+{
+       struct obd_device *dev = seq->private;
+       struct filter_obd *ofd = &dev->u.filter;
+
+       brw_stats_show(seq, &ofd->fo_filter_stats);
+
+       return 0;
+}
+
+static ssize_t ofd_brw_stats_seq_write(struct file *file, const char *buf,
+                                      size_t len, loff_t *off)
+{
+       struct seq_file         *seq = file->private_data;
+       struct obd_device       *dev = seq->private;
+       struct filter_obd       *ofd = &dev->u.filter;
+       int                      i;
+
+       for (i = 0; i < BRW_LAST; i++)
+               lprocfs_oh_clear(&ofd->fo_filter_stats.hist[i]);
+
+       return len;
+}
+
+LPROC_SEQ_FOPS(ofd_brw_stats);
+
+int lproc_ofd_attach_seqstat(struct obd_device *dev)
+{
+       return lprocfs_obd_seq_create(dev, "brw_stats", 0444,
+                                     &ofd_brw_stats_fops, dev);
+}
+
 void lprocfs_ofd_init_vars(struct lprocfs_static_vars *lvars)
 {
 void lprocfs_ofd_init_vars(struct lprocfs_static_vars *lvars)
 {
-       lvars->module_vars      = lprocfs_ofd_module_vars;
-       lvars->obd_vars         = lprocfs_ofd_obd_vars;
+       lvars->module_vars  = lprocfs_ofd_module_vars;
+       lvars->obd_vars     = lprocfs_ofd_obd_vars;
+}
+
+static int ofd_per_nid_stats_seq_show(struct seq_file *seq, void *v)
+{
+       nid_stat_t *stat = seq->private;
+
+       if (stat->nid_brw_stats)
+               brw_stats_show(seq, stat->nid_brw_stats);
+
+       return 0;
+}
+
+static ssize_t ofd_per_nid_stats_seq_write(struct file *file, const char *buf,
+                                          size_t len, loff_t *off)
+{
+       struct seq_file *seq = file->private_data;
+        nid_stat_t     *stat = seq->private;
+        int             i;
+
+       if (stat->nid_brw_stats)
+               for (i = 0; i < BRW_LAST; i++)
+                       lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
+
+       return len;
 }
 
 }
 
+LPROC_SEQ_FOPS(ofd_per_nid_stats);
 #endif /* LPROCFS */
 #endif /* LPROCFS */
index 7d9b436..b9104a4 100644 (file)
@@ -316,6 +316,82 @@ static struct lu_device_operations ofd_lu_ops = {
        .ldo_recovery_complete  = ofd_recovery_complete,
 };
 
        .ldo_recovery_complete  = ofd_recovery_complete,
 };
 
+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;
+
+       ENTRY;
+
+       /* 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);
+       if (rc) {
+               CERROR("%s: lprocfs_obd_setup failed: %d.\n",
+                      obd->obd_name, rc);
+               RETURN(rc);
+       }
+
+       rc = lprocfs_alloc_obd_stats(obd, LPROC_OFD_LAST);
+       if (rc) {
+               CERROR("%s: lprocfs_alloc_obd_stats failed: %d.\n",
+                      obd->obd_name, rc);
+               GOTO(obd_cleanup, rc);
+       }
+
+       /* Init OFD private stats here */
+       lprocfs_counter_init(obd->obd_stats, LPROC_OFD_READ_BYTES,
+                            LPROCFS_CNTR_AVGMINMAX, "read_bytes", "bytes");
+       lprocfs_counter_init(obd->obd_stats, LPROC_OFD_WRITE_BYTES,
+                            LPROCFS_CNTR_AVGMINMAX, "write_bytes", "bytes");
+
+       rc = lproc_ofd_attach_seqstat(obd);
+       if (rc) {
+               CERROR("%s: create seqstat failed: %d.\n", obd->obd_name, rc);
+               GOTO(free_obd_stats, rc);
+       }
+
+       entry = lprocfs_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",
+                      obd->obd_name, rc, "exports");
+               GOTO(free_obd_stats, rc);
+       }
+       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);
+       if (IS_ERR(entry)) {
+               rc = PTR_ERR(entry);
+               CERROR("%s: add proc entry 'clear' failed: %d.\n",
+                      obd->obd_name, rc);
+               GOTO(free_obd_stats, rc);
+       }
+       RETURN(0);
+
+free_obd_stats:
+       lprocfs_free_obd_stats(obd);
+obd_cleanup:
+       lprocfs_obd_cleanup(obd);
+       return rc;
+}
+
+static int ofd_procfs_fini(struct ofd_device *ofd)
+{
+       struct obd_device *obd = ofd_obd(ofd);
+
+       lprocfs_remove_proc_entry("clear", obd->obd_proc_exports_entry);
+       lprocfs_free_per_client_stats(obd);
+       lprocfs_free_obd_stats(obd);
+       lprocfs_obd_cleanup(obd);
+       return 0;
+}
+
 extern int ost_handle(struct ptlrpc_request *req);
 
 static int ofd_init0(const struct lu_env *env, struct ofd_device *m,
 extern int ost_handle(struct ptlrpc_request *req);
 
 static int ofd_init0(const struct lu_env *env, struct ofd_device *m,
@@ -340,6 +416,13 @@ static int ofd_init0(const struct lu_env *env, struct ofd_device *m,
 
        obd->u.obt.obt_magic = OBT_MAGIC;
 
 
        obd->u.obt.obt_magic = OBT_MAGIC;
 
+       cfs_spin_lock_init(&m->ofd_flags_lock);
+       m->ofd_raid_degraded = 0;
+       m->ofd_syncjournal = 0;
+       ofd_slc_set(m);
+
+       m->ofd_max_group = 0;
+
        cfs_rwlock_init(&obd->u.filter.fo_sptlrpc_lock);
        sptlrpc_rule_set_init(&obd->u.filter.fo_sptlrpc_rset);
 
        cfs_rwlock_init(&obd->u.filter.fo_sptlrpc_lock);
        sptlrpc_rule_set_init(&obd->u.filter.fo_sptlrpc_rset);
 
@@ -354,6 +437,12 @@ static int ofd_init0(const struct lu_env *env, struct ofd_device *m,
        /* set this lu_device to obd, because error handling need it */
        obd->obd_lu_dev = &m->ofd_dt_dev.dd_lu_dev;
 
        /* set this lu_device to obd, because error handling need it */
        obd->obd_lu_dev = &m->ofd_dt_dev.dd_lu_dev;
 
+       rc = ofd_procfs_init(m);
+       if (rc) {
+               CERROR("Can't init ofd lprocfs, rc %d\n", rc);
+               RETURN(rc);
+       }
+
        /* No connection accepted until configurations will finish */
        obd->obd_no_conn = 1;
        obd->obd_replayable = 1;
        /* No connection accepted until configurations will finish */
        obd->obd_no_conn = 1;
        obd->obd_replayable = 1;
@@ -372,7 +461,7 @@ static int ofd_init0(const struct lu_env *env, struct ofd_device *m,
 
        rc = lu_site_init(&m->ofd_site, &m->ofd_dt_dev.dd_lu_dev);
        if (rc)
 
        rc = lu_site_init(&m->ofd_site, &m->ofd_dt_dev.dd_lu_dev);
        if (rc)
-               GOTO(err_out, rc);
+               GOTO(err_fini_proc, rc);
        m->ofd_site.ls_top_dev = &m->ofd_dt_dev.dd_lu_dev;
 
        rc = ofd_stack_init(env, m, cfg);
        m->ofd_site.ls_top_dev = &m->ofd_dt_dev.dd_lu_dev;
 
        rc = ofd_stack_init(env, m, cfg);
@@ -423,7 +512,8 @@ err_fini_stack:
        ofd_stack_fini(env, m, &m->ofd_osd->dd_lu_dev);
 err_lu_site:
        lu_site_fini(&m->ofd_site);
        ofd_stack_fini(env, m, &m->ofd_osd->dd_lu_dev);
 err_lu_site:
        lu_site_fini(&m->ofd_site);
-err_out:
+err_fini_proc:
+       ofd_procfs_fini(m);
        return rc;
 }
 
        return rc;
 }
 
@@ -450,6 +540,7 @@ static void ofd_fini(const struct lu_env *env, struct ofd_device *m)
 
        ofd_stack_fini(env, m, m->ofd_site.ls_top_dev);
        lu_site_fini(&m->ofd_site);
 
        ofd_stack_fini(env, m, m->ofd_site.ls_top_dev);
        lu_site_fini(&m->ofd_site);
+       ofd_procfs_fini(m);
        LASSERT(cfs_atomic_read(&d->ld_ref) == 0);
        EXIT;
 }
        LASSERT(cfs_atomic_read(&d->ld_ref) == 0);
        EXIT;
 }
index 31bca72..7d14975 100644 (file)
@@ -324,7 +324,6 @@ int ofd_clients_data_init(const struct lu_env *env, struct ofd_device *ofd,
                fed = &exp->exp_filter_data;
                *fed->fed_ted.ted_lcd = *lcd;
 
                fed = &exp->exp_filter_data;
                *fed->fed_ted.ted_lcd = *lcd;
 
-               ofd_export_stats_init(ofd, exp, NULL);
                rc = lut_client_add(env, exp, cl_idx);
                LASSERTF(rc == 0, "rc = %d\n", rc); /* can't fail existing */
                /* VBR: set export last committed version */
                rc = lut_client_add(env, exp, cl_idx);
                LASSERTF(rc == 0, "rc = %d\n", rc); /* can't fail existing */
                /* VBR: set export last committed version */
index 2df6149..d701a3c 100644 (file)
                           OBD_INCOMPAT_COMMON_LR)
 #define OFD_MAX_GROUPS 256
 
                           OBD_INCOMPAT_COMMON_LR)
 #define OFD_MAX_GROUPS 256
 
+enum {
+       LPROC_OFD_READ_BYTES = 0,
+       LPROC_OFD_WRITE_BYTES = 1,
+       LPROC_OFD_LAST,
+};
+
 struct ofd_device {
        struct dt_device         ofd_dt_dev;
        struct dt_device        *ofd_osd;
 struct ofd_device {
        struct dt_device         ofd_dt_dev;
        struct dt_device        *ofd_osd;
@@ -69,6 +75,13 @@ struct ofd_device {
        struct dt_object        *ofd_lastid_obj[OFD_MAX_GROUPS];
        cfs_spinlock_t           ofd_objid_lock;
 
        struct dt_object        *ofd_lastid_obj[OFD_MAX_GROUPS];
        cfs_spinlock_t           ofd_objid_lock;
 
+       cfs_spinlock_t           ofd_flags_lock;
+       unsigned long            ofd_raid_degraded:1,
+                                /* sync journal on writes */
+                                ofd_syncjournal:1,
+                                /* sync on lock cancel */
+                                ofd_sync_lock_cancel:2;
+
        struct lu_site           ofd_site;
 };
 
        struct lu_site           ofd_site;
 };
 
@@ -122,12 +135,6 @@ struct ofd_thread_info {
        loff_t                           fti_off;
 };
 
        loff_t                           fti_off;
 };
 
-static inline int ofd_export_stats_init(struct ofd_device *ofd,
-                                       struct obd_export *exp, void *data)
-{
-       return 0;
-}
-
 extern void target_recovery_fini(struct obd_device *obd);
 extern void target_recovery_init(struct lu_target *lut, svc_handler_t handler);
 
 extern void target_recovery_fini(struct obd_device *obd);
 extern void target_recovery_init(struct lu_target *lut, svc_handler_t handler);
 
@@ -152,6 +159,8 @@ void ofd_fs_cleanup(const struct lu_env *env, struct ofd_device *ofd);
 
 /* lproc_ofd.c */
 void lprocfs_ofd_init_vars(struct lprocfs_static_vars *lvars);
 
 /* lproc_ofd.c */
 void lprocfs_ofd_init_vars(struct lprocfs_static_vars *lvars);
+int lproc_ofd_attach_seqstat(struct obd_device *dev);
+extern struct file_operations ofd_per_nid_stats_fops;
 
 static inline struct ofd_thread_info * ofd_info(const struct lu_env *env)
 {
 
 static inline struct ofd_thread_info * ofd_info(const struct lu_env *env)
 {
@@ -179,4 +188,15 @@ static inline struct ofd_thread_info * ofd_info_init(const struct lu_env *env,
        return info;
 }
 
        return info;
 }
 
+/* sync on lock cancel is useless when we force a journal flush,
+ * and if we enable async journal commit, we should also turn on
+ * sync on lock cancel if it is not enabled already. */
+static inline void ofd_slc_set(struct ofd_device *ofd)
+{
+       if (ofd->ofd_syncjournal == 1)
+               ofd->ofd_sync_lock_cancel = NEVER_SYNC_ON_CANCEL;
+       else if (ofd->ofd_sync_lock_cancel == NEVER_SYNC_ON_CANCEL)
+               ofd->ofd_sync_lock_cancel = ALWAYS_SYNC_ON_CANCEL;
+}
+
 #endif /* _OFD_INTERNAL_H */
 #endif /* _OFD_INTERNAL_H */
index 6a1a3c7..ec13b71 100644 (file)
 #include "ofd_internal.h"
 #include <obd_cksum.h>
 
 #include "ofd_internal.h"
 #include <obd_cksum.h>
 
+static int ofd_export_stats_init(struct ofd_device *ofd,
+                                struct obd_export *exp, void *client_nid)
+{
+       struct obd_device       *obd = ofd_obd(ofd);
+       struct nid_stat         *stats;
+       int                      num_stats, i;
+       int                      rc, newnid = 0;
+
+       ENTRY;
+
+       if (obd_uuid_equals(&exp->exp_client_uuid, &obd->obd_uuid))
+               /* Self-export gets no proc entry */
+               RETURN(0);
+
+       rc = lprocfs_exp_setup(exp, client_nid, &newnid);
+       if (rc) {
+               /* Mask error for already created
+                * /proc entries */
+               if (rc == -EALREADY)
+                       rc = 0;
+               RETURN(rc);
+       }
+
+       if (newnid == 0)
+               RETURN(0);
+
+       stats = exp->exp_nid_stats;
+       LASSERT(stats != NULL);
+
+       OBD_ALLOC(stats->nid_brw_stats, sizeof(struct brw_stats));
+       if (stats->nid_brw_stats == NULL)
+               GOTO(clean, rc = -ENOMEM);
+
+       for (i = 0; i < BRW_LAST; i++)
+               cfs_spin_lock_init(&stats->nid_brw_stats->hist[i].oh_lock);
+
+       rc = lprocfs_seq_create(stats->nid_proc, "brw_stats", 0644,
+                               &ofd_per_nid_stats_fops, stats);
+       if (rc)
+               CWARN("Error adding the brw_stats file\n");
+
+       num_stats = (sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
+                    LPROC_OFD_LAST - 1;
+
+       stats->nid_stats = lprocfs_alloc_stats(num_stats,
+                                              LPROCFS_STATS_FLAG_NOPERCPU);
+       if (stats->nid_stats == NULL)
+               return -ENOMEM;
+
+       lprocfs_init_ops_stats(LPROC_OFD_LAST, stats->nid_stats);
+       lprocfs_counter_init(stats->nid_stats, LPROC_OFD_READ_BYTES,
+                            LPROCFS_CNTR_AVGMINMAX, "read_bytes", "bytes");
+       lprocfs_counter_init(stats->nid_stats, LPROC_OFD_WRITE_BYTES,
+                            LPROCFS_CNTR_AVGMINMAX, "write_bytes", "bytes");
+
+       rc = lprocfs_register_stats(stats->nid_proc, "stats",
+                                   stats->nid_stats);
+       if (rc)
+               GOTO(clean, rc);
+
+       rc = lprocfs_nid_ldlm_stats_init(stats);
+       if (rc) {
+               lprocfs_free_stats(&stats->nid_stats);
+               GOTO(clean, rc);
+       }
+
+       RETURN(0);
+clean:
+       return rc;
+}
+
 static int ofd_parse_connect_data(const struct lu_env *env,
                                  struct obd_export *exp,
                                  struct obd_connect_data *data)
 static int ofd_parse_connect_data(const struct lu_env *env,
                                  struct obd_export *exp,
                                  struct obd_connect_data *data)
@@ -160,7 +231,8 @@ static int ofd_obd_reconnect(const struct lu_env *env, struct obd_export *exp,
                             struct obd_device *obd, struct obd_uuid *cluuid,
                             struct obd_connect_data *data, void *localdata)
 {
                             struct obd_device *obd, struct obd_uuid *cluuid,
                             struct obd_connect_data *data, void *localdata)
 {
-       int rc;
+       struct ofd_device       *ofd = ofd_dev(obd->obd_lu_dev);
+       int                      rc;
 
        ENTRY;
 
 
        ENTRY;
 
@@ -175,6 +247,8 @@ static int ofd_obd_reconnect(const struct lu_env *env, struct obd_export *exp,
 
        ofd_info_init(env, exp);
        rc = ofd_parse_connect_data(env, exp, data);
 
        ofd_info_init(env, exp);
        rc = ofd_parse_connect_data(env, exp, data);
+       if (rc == 0)
+               ofd_export_stats_init(ofd, exp, localdata);
 
        RETURN(rc);
 }
 
        RETURN(rc);
 }
@@ -214,7 +288,6 @@ static int ofd_obd_connect(const struct lu_env *env, struct obd_export **_exp,
        if (rc)
                GOTO(out, rc);
 
        if (rc)
                GOTO(out, rc);
 
-       ofd_export_stats_init(ofd, exp, localdata);
        group = data->ocd_group;
        if (obd->obd_replayable) {
                struct tg_export_data *ted = &exp->exp_target_data;
        group = data->ocd_group;
        if (obd->obd_replayable) {
                struct tg_export_data *ted = &exp->exp_target_data;
@@ -224,6 +297,7 @@ static int ofd_obd_connect(const struct lu_env *env, struct obd_export **_exp,
                rc = lut_client_new(env, exp);
                if (rc != 0)
                        GOTO(out, rc);
                rc = lut_client_new(env, exp);
                if (rc != 0)
                        GOTO(out, rc);
+               ofd_export_stats_init(ofd, exp, localdata);
        }
        if (group == 0)
                GOTO(out, rc = 0);
        }
        if (group == 0)
                GOTO(out, rc = 0);
@@ -450,6 +524,10 @@ static int ofd_statfs(const struct lu_env *env,  struct obd_export *exp,
        if (OBD_FAIL_CHECK_VALUE(OBD_FAIL_OST_ENOINO,
                                 ofd->ofd_lut.lut_lsd.lsd_ost_index))
                osfs->os_ffree = 0;
        if (OBD_FAIL_CHECK_VALUE(OBD_FAIL_OST_ENOINO,
                                 ofd->ofd_lut.lut_lsd.lsd_ost_index))
                osfs->os_ffree = 0;
+
+       /* OS_STATE_READONLY can be set by OSD already */
+       if (ofd->ofd_raid_degraded)
+               osfs->os_state |= OS_STATE_DEGRADED;
        EXIT;
 out:
        return rc;
        EXIT;
 out:
        return rc;