Whamcloud - gitweb
fix error handling; kill possible memleak.
[fs/lustre-release.git] / lustre / mdd / mdd_lproc.c
1 /* -*- MODE: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  mdd/mdd_handler.c
5  *  Lustre Metadata Server (mdd) routines
6  *
7  *  Copyright (C) 2006 Cluster File Systems, Inc.
8  *   Author: Wang Di <wangdi@clusterfs.com>
9  *
10  *   This file is part of the Lustre file system, http://www.lustre.org
11  *   Lustre is a trademark of Cluster File Systems, Inc.
12  *
13  *   You may have signed or agreed to another license before downloading
14  *   this software.  If so, you are bound by the terms and conditions
15  *   of that agreement, and the following does not apply to you.  See the
16  *   LICENSE file included with this distribution for more information.
17  *
18  *   If you did not agree to a different license, then this copy of Lustre
19  *   is open source software; you can redistribute it and/or modify it
20  *   under the terms of version 2 of the GNU General Public License as
21  *   published by the Free Software Foundation.
22  *
23  *   In either case, Lustre is distributed in the hope that it will be
24  *   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
25  *   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26  *   license text for more details.
27  */
28 #ifndef EXPORT_SYMTAB
29 # define EXPORT_SYMTAB
30 #endif
31 #define DEBUG_SUBSYSTEM S_MDS
32
33 #include <linux/module.h>
34 #include <obd.h>
35 #include <obd_class.h>
36 #include <lustre_ver.h>
37 #include <obd_support.h>
38 #include <lprocfs_status.h>
39
40 #include <lustre/lustre_idl.h>
41
42 #include "mdd_internal.h"
43
44 static int mdd_procfs_init_stats(struct mdd_device *mdd, int num_stats)
45 {
46         struct lprocfs_stats *stats;
47         int rc;
48         ENTRY;
49         
50         stats = lprocfs_alloc_stats(num_stats);
51         if (!stats)
52                 RETURN(-ENOMEM);
53
54         rc = lprocfs_register_stats(mdd->mdd_proc_entry, "stats", stats);
55         if (rc != 0)
56                 GOTO(cleanup, rc);
57
58         mdd->mdd_stats = stats;
59
60         lprocfs_counter_init(mdd->mdd_stats, LPROC_MDD_OPEN,
61                              LPROCFS_CNTR_AVGMINMAX, "open", "time");
62         lprocfs_counter_init(mdd->mdd_stats, LPROC_MDD_CREATE,
63                              LPROCFS_CNTR_AVGMINMAX, "create", "time");
64         lprocfs_counter_init(mdd->mdd_stats, LPROC_MDD_INDEX_INSERT,
65                              LPROCFS_CNTR_AVGMINMAX, "index_insert", "time");
66         lprocfs_counter_init(mdd->mdd_stats, LPROC_MDD_INDEX_DELETE,
67                              LPROCFS_CNTR_AVGMINMAX, "index_delete", "time");
68         lprocfs_counter_init(mdd->mdd_stats, LPROC_MDD_UNLINK,
69                              LPROCFS_CNTR_AVGMINMAX, "unlink", "time");
70         lprocfs_counter_init(mdd->mdd_stats, LPROC_MDD_UNLINK_LOG,
71                              LPROCFS_CNTR_AVGMINMAX, "unlink_log", "time");
72         lprocfs_counter_init(mdd->mdd_stats, LPROC_MDD_LOV_CREATE,
73                              LPROCFS_CNTR_AVGMINMAX, "lov_create", "time");
74         lprocfs_counter_init(mdd->mdd_stats, LPROC_MDD_SET_MD,
75                              LPROCFS_CNTR_AVGMINMAX, "set_md", "time");
76         lprocfs_counter_init(mdd->mdd_stats, LPROC_MDD_GET_MD,
77                              LPROCFS_CNTR_AVGMINMAX, "get_md", "time");
78         lprocfs_counter_init(mdd->mdd_stats, LPROC_MDD_LOOKUP,
79                              LPROCFS_CNTR_AVGMINMAX, "lookup", "lookup");
80         EXIT;
81 cleanup:
82         if (rc) {
83                 lprocfs_free_stats(stats);
84                 mdd->mdd_stats = NULL;
85         }
86         return rc;
87 }
88
89 int mdd_procfs_fini(struct mdd_device *mdd)
90 {
91         if (mdd->mdd_stats) {
92                 lprocfs_free_stats(mdd->mdd_stats);
93                 mdd->mdd_stats = NULL;
94         }
95         if (mdd->mdd_proc_entry) {
96                  lprocfs_remove(mdd->mdd_proc_entry);
97                  mdd->mdd_proc_entry = NULL;
98         }
99         RETURN(0);
100 }
101
102 int mdd_procfs_init(struct mdd_device *mdd, const char *name)
103 {
104         struct lu_device    *ld = &mdd->mdd_md_dev.md_lu_dev;
105         struct obd_type     *type;
106         int                  rc;
107         ENTRY;
108
109         type = ld->ld_type->ldt_obd_type;
110         
111         LASSERT(name != NULL);
112         LASSERT(type != NULL);
113
114         /* Find the type procroot and add the proc entry for this device */
115         mdd->mdd_proc_entry = lprocfs_register(name, type->typ_procroot,
116                                                NULL, NULL);
117         if (IS_ERR(mdd->mdd_proc_entry)) {
118                 rc = PTR_ERR(mdd->mdd_proc_entry);
119                 CERROR("Error %d setting up lprocfs for %s\n", 
120                        rc, name);
121                 mdd->mdd_proc_entry = NULL;
122                 GOTO(out, rc);
123         }
124
125         rc = mdd_procfs_init_stats(mdd, LPROC_MDD_LAST);
126         EXIT;
127 out:
128         if (rc)
129                mdd_procfs_fini(mdd); 
130         return rc;
131 }
132
133 void mdd_lproc_time_start(struct mdd_device *mdd, struct timeval *start, int op)
134 {
135         do_gettimeofday(start);
136 }
137
138 void mdd_lproc_time_end(struct mdd_device *mdd, struct timeval *start, int op)
139 {
140         struct timeval end;
141         long timediff;
142
143         do_gettimeofday(&end);
144         timediff = cfs_timeval_sub(&end, start, NULL);
145
146         if (mdd->mdd_stats)
147                 lprocfs_counter_add(mdd->mdd_stats, op, timediff);
148         return;
149 }