Whamcloud - gitweb
0ee5148906a8ea8c33fb8494ac21d9485046fcb0
[fs/lustre-release.git] / lustre / mdt / mdt_lproc.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2011, 2013, Intel Corporation.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lustre/mdt/mdt_lproc.c
37  *
38  * Author: Lai Siyao <lsy@clusterfs.com>
39  * Author: Fan Yong <fanyong@clusterfs.com>
40  */
41
42 #define DEBUG_SUBSYSTEM S_MDS
43
44 #include <linux/version.h>
45 #include <asm/statfs.h>
46
47 #include <linux/module.h>
48
49 /* LUSTRE_VERSION_CODE */
50 #include <lustre_ver.h>
51 /*
52  * struct OBD_{ALLOC,FREE}*()
53  * MDT_FAIL_CHECK
54  */
55 #include <obd_support.h>
56 /* struct obd_export */
57 #include <lustre_export.h>
58 /* struct obd_device */
59 #include <obd.h>
60 #include <obd_class.h>
61 #include <lustre_mds.h>
62 #include <lprocfs_status.h>
63 #include "mdt_internal.h"
64 #include <lnet/lib-lnet.h>
65
66 /**
67  * The rename stats output would be YAML formats, like
68  * rename_stats:
69  * - snapshot_time: 1234567890.123456
70  * - same_dir:
71  *     4kB: { samples: 1230, pct: 33, cum_pct: 45 }
72  *     8kB: { samples: 1242, pct: 33, cum_pct: 78 }
73  *     16kB: { samples: 132, pct: 3, cum_pct: 81 }
74  * - crossdir_src:
75  *     4kB: { samples: 123, pct: 33, cum_pct: 45 }
76  *     8kB: { samples: 124, pct: 33, cum_pct: 78 }
77  *     16kB: { samples: 12, pct: 3, cum_pct: 81 }
78  * - crossdir_tgt:
79  *     4kB: { samples: 123, pct: 33, cum_pct: 45 }
80  *     8kB: { samples: 124, pct: 33, cum_pct: 78 }
81  *     16kB: { samples: 12, pct: 3, cum_pct: 81 }
82  **/
83
84 #define pct(a, b) (b ? a * 100 / b : 0)
85
86 static void display_rename_stats(struct seq_file *seq, char *name,
87                                  struct obd_histogram *hist)
88 {
89         unsigned long tot, t, cum = 0;
90         int i;
91
92         tot = lprocfs_oh_sum(hist);
93         if (tot > 0)
94                 seq_printf(seq, "- %-15s\n", name);
95         /* dir size start from 4K, start i from 10(2^10) here */
96         for (i = 0; i < OBD_HIST_MAX; i++) {
97                 t = hist->oh_buckets[i];
98                 cum += t;
99                 if (cum == 0)
100                         continue;
101
102                 if (i < 10)
103                         seq_printf(seq, "%6s%d%s", " ", 1<< i, "bytes:");
104                 else if (i < 20)
105                         seq_printf(seq, "%6s%d%s", " ", 1<<(i-10), "KB:");
106                 else
107                         seq_printf(seq, "%6s%d%s", " ", 1<<(i-20), "MB:");
108
109                 seq_printf(seq, " { sample: %3lu, pct: %3lu, cum_pct: %3lu }\n",
110                            t, pct(t, tot), pct(cum, tot));
111
112                 if (cum == tot)
113                         break;
114         }
115 }
116
117 static void rename_stats_show(struct seq_file *seq,
118                               struct rename_stats *rename_stats)
119 {
120         struct timeval now;
121
122         /* this sampling races with updates */
123         do_gettimeofday(&now);
124         seq_printf(seq, "rename_stats:\n");
125         seq_printf(seq, "- %-15s %lu.%lu\n", "snapshot_time:",
126                    now.tv_sec, now.tv_usec);
127
128         display_rename_stats(seq, "same_dir",
129                              &rename_stats->hist[RENAME_SAMEDIR_SIZE]);
130         display_rename_stats(seq, "crossdir_src",
131                              &rename_stats->hist[RENAME_CROSSDIR_SRC_SIZE]);
132         display_rename_stats(seq, "crossdir_tgt",
133                              &rename_stats->hist[RENAME_CROSSDIR_TGT_SIZE]);
134 }
135
136 #undef pct
137
138 static int mdt_rename_stats_seq_show(struct seq_file *seq, void *v)
139 {
140         struct mdt_device *mdt = seq->private;
141
142         rename_stats_show(seq, &mdt->mdt_rename_stats);
143
144         return 0;
145 }
146
147 static ssize_t mdt_rename_stats_seq_write(struct file *file, const char *buf,
148                                           size_t len, loff_t *off)
149 {
150         struct seq_file *seq = file->private_data;
151         struct mdt_device *mdt = seq->private;
152         int i;
153
154         for (i = 0; i < RENAME_LAST; i++)
155                 lprocfs_oh_clear(&mdt->mdt_rename_stats.hist[i]);
156
157         return len;
158 }
159
160 LPROC_SEQ_FOPS(mdt_rename_stats);
161
162 static int lproc_mdt_attach_rename_seqstat(struct mdt_device *mdt)
163 {
164         int i;
165
166         for (i = 0; i < RENAME_LAST; i++)
167                 spin_lock_init(&mdt->mdt_rename_stats.hist[i].oh_lock);
168
169         return lprocfs_obd_seq_create(mdt2obd_dev(mdt), "rename_stats", 0644,
170                                       &mdt_rename_stats_fops, mdt);
171 }
172
173 void mdt_rename_counter_tally(struct mdt_thread_info *info,
174                               struct mdt_device *mdt,
175                               struct ptlrpc_request *req,
176                               struct mdt_object *src,
177                               struct mdt_object *tgt)
178 {
179         struct md_attr *ma = &info->mti_attr;
180         struct rename_stats *rstats = &mdt->mdt_rename_stats;
181         int rc;
182
183         ma->ma_need = MA_INODE;
184         ma->ma_valid = 0;
185         rc = mo_attr_get(info->mti_env, mdt_object_child(src), ma);
186         if (rc) {
187                 CERROR("%s: "DFID" attr_get, rc = %d\n",
188                        mdt_obd_name(mdt), PFID(mdt_object_fid(src)), rc);
189                 return;
190         }
191
192         if (src == tgt) {
193                 mdt_counter_incr(req, LPROC_MDT_SAMEDIR_RENAME);
194                 lprocfs_oh_tally_log2(&rstats->hist[RENAME_SAMEDIR_SIZE],
195                                       (unsigned int)ma->ma_attr.la_size);
196                 return;
197         }
198
199         mdt_counter_incr(req, LPROC_MDT_CROSSDIR_RENAME);
200         lprocfs_oh_tally_log2(&rstats->hist[RENAME_CROSSDIR_SRC_SIZE],
201                               (unsigned int)ma->ma_attr.la_size);
202
203         ma->ma_need = MA_INODE;
204         ma->ma_valid = 0;
205         rc = mo_attr_get(info->mti_env, mdt_object_child(tgt), ma);
206         if (rc) {
207                 CERROR("%s: "DFID" attr_get, rc = %d\n",
208                        mdt_obd_name(mdt), PFID(mdt_object_fid(tgt)), rc);
209                 return;
210         }
211
212         lprocfs_oh_tally_log2(&rstats->hist[RENAME_CROSSDIR_TGT_SIZE],
213                               (unsigned int)ma->ma_attr.la_size);
214 }
215
216 int mdt_procfs_init(struct mdt_device *mdt, const char *name)
217 {
218         struct obd_device               *obd = mdt2obd_dev(mdt);
219         struct lprocfs_static_vars       lvars;
220         int                              rc;
221         ENTRY;
222
223         LASSERT(name != NULL);
224
225         lprocfs_mdt_init_vars(&lvars);
226         rc = lprocfs_obd_setup(obd, lvars.obd_vars);
227         if (rc) {
228                 CERROR("%s: cannot create proc entries: rc = %d\n",
229                        mdt_obd_name(mdt), rc);
230                 return rc;
231         }
232
233         rc = hsm_cdt_procfs_init(mdt);
234         if (rc) {
235                 CERROR("%s: cannot create hsm proc entries: rc = %d\n",
236                        mdt_obd_name(mdt), rc);
237                 return rc;
238         }
239
240         obd->obd_proc_exports_entry = proc_mkdir("exports",
241                                                  obd->obd_proc_entry);
242         if (obd->obd_proc_exports_entry)
243                 lprocfs_add_simple(obd->obd_proc_exports_entry,
244                                    "clear", lprocfs_nid_stats_clear_read,
245                                    lprocfs_nid_stats_clear_write, obd, NULL);
246         rc = lprocfs_alloc_md_stats(obd, LPROC_MDT_LAST);
247         if (rc)
248                 return rc;
249         mdt_stats_counter_init(obd->obd_md_stats);
250
251         rc = lprocfs_job_stats_init(obd, LPROC_MDT_LAST,
252                                     mdt_stats_counter_init);
253
254         rc = lproc_mdt_attach_rename_seqstat(mdt);
255         if (rc)
256                 CERROR("%s: MDT can not create rename stats rc = %d\n",
257                        mdt_obd_name(mdt), rc);
258
259         RETURN(rc);
260 }
261
262 void mdt_procfs_fini(struct mdt_device *mdt)
263 {
264         struct obd_device *obd = mdt2obd_dev(mdt);
265
266         if (obd->obd_proc_exports_entry != NULL) {
267                 lprocfs_remove_proc_entry("clear", obd->obd_proc_exports_entry);
268                 obd->obd_proc_exports_entry = NULL;
269         }
270
271         lprocfs_free_per_client_stats(obd);
272         hsm_cdt_procfs_fini(mdt);
273         lprocfs_obd_cleanup(obd);
274         lprocfs_free_md_stats(obd);
275         lprocfs_free_obd_stats(obd);
276         lprocfs_job_stats_fini(obd);
277 }
278
279 static int lprocfs_rd_identity_expire(char *page, char **start, off_t off,
280                                       int count, int *eof, void *data)
281 {
282         struct obd_device *obd = data;
283         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
284
285         *eof = 1;
286         return snprintf(page, count, "%u\n",
287                         mdt->mdt_identity_cache->uc_entry_expire);
288 }
289
290 static int lprocfs_wr_identity_expire(struct file *file, const char *buffer,
291                                       unsigned long count, void *data)
292 {
293         struct obd_device *obd = data;
294         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
295         int rc, val;
296
297         rc = lprocfs_write_helper(buffer, count, &val);
298         if (rc)
299                 return rc;
300
301         mdt->mdt_identity_cache->uc_entry_expire = val;
302         return count;
303 }
304
305 static int lprocfs_rd_identity_acquire_expire(char *page, char **start,
306                                               off_t off, int count, int *eof,
307                                               void *data)
308 {
309         struct obd_device *obd = data;
310         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
311
312         *eof = 1;
313         return snprintf(page, count, "%u\n",
314                         mdt->mdt_identity_cache->uc_acquire_expire);
315 }
316
317 static int lprocfs_wr_identity_acquire_expire(struct file *file,
318                                               const char *buffer,
319                                               unsigned long count,
320                                               void *data)
321 {
322         struct obd_device *obd = data;
323         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
324         int rc, val;
325
326         rc = lprocfs_write_helper(buffer, count, &val);
327         if (rc)
328                 return rc;
329
330         mdt->mdt_identity_cache->uc_acquire_expire = val;
331         return count;
332 }
333
334 static int lprocfs_rd_identity_upcall(char *page, char **start, off_t off,
335                                       int count, int *eof, void *data)
336 {
337         struct obd_device *obd = data;
338         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
339         struct upcall_cache *hash = mdt->mdt_identity_cache;
340         int len;
341
342         *eof = 1;
343         read_lock(&hash->uc_upcall_rwlock);
344         len = snprintf(page, count, "%s\n", hash->uc_upcall);
345         read_unlock(&hash->uc_upcall_rwlock);
346         return len;
347 }
348
349 static int lprocfs_wr_identity_upcall(struct file *file, const char *buffer,
350                                       unsigned long count, void *data)
351 {
352         struct obd_device       *obd = data;
353         struct mdt_device       *mdt = mdt_dev(obd->obd_lu_dev);
354         struct upcall_cache     *hash = mdt->mdt_identity_cache;
355         int                      rc;
356         char                    *kernbuf;
357
358         if (count >= UC_CACHE_UPCALL_MAXPATH) {
359                 CERROR("%s: identity upcall too long\n", mdt_obd_name(mdt));
360                 return -EINVAL;
361         }
362         OBD_ALLOC(kernbuf, count + 1);
363         if (kernbuf == NULL)
364                 GOTO(failed, rc = -ENOMEM);
365         if (copy_from_user(kernbuf, buffer, count))
366                 GOTO(failed, rc = -EFAULT);
367
368         /* Remove any extraneous bits from the upcall (e.g. linefeeds) */
369         write_lock(&hash->uc_upcall_rwlock);
370         sscanf(kernbuf, "%s", hash->uc_upcall);
371         write_unlock(&hash->uc_upcall_rwlock);
372
373         if (strcmp(hash->uc_name, mdt_obd_name(mdt)) != 0)
374                 CWARN("%s: write to upcall name %s\n",
375                       mdt_obd_name(mdt), hash->uc_upcall);
376
377         if (strcmp(hash->uc_upcall, "NONE") == 0 && mdt->mdt_opts.mo_acl)
378                 CWARN("%s: disable \"identity_upcall\" with ACL enabled maybe "
379                       "cause unexpected \"EACCESS\"\n", mdt_obd_name(mdt));
380
381         CDEBUG(D_CONFIG, "%s: identity upcall set to %s\n", mdt_obd_name(mdt),
382                hash->uc_upcall);
383         OBD_FREE(kernbuf, count + 1);
384         RETURN(count);
385
386  failed:
387         if (kernbuf)
388                 OBD_FREE(kernbuf, count + 1);
389         RETURN(rc);
390 }
391
392 static int lprocfs_wr_identity_flush(struct file *file, const char *buffer,
393                                      unsigned long count, void *data)
394 {
395         struct obd_device *obd = data;
396         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
397         int rc, uid;
398
399         rc = lprocfs_write_helper(buffer, count, &uid);
400         if (rc)
401                 return rc;
402
403         mdt_flush_identity(mdt->mdt_identity_cache, uid);
404         return count;
405 }
406
407 static int lprocfs_wr_identity_info(struct file *file, const char *buffer,
408                                     unsigned long count, void *data)
409 {
410         struct obd_device *obd = data;
411         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
412         struct identity_downcall_data *param;
413         int size = sizeof(*param), rc, checked = 0;
414
415 again:
416         if (count < size) {
417                 CERROR("%s: invalid data count = %lu, size = %d\n",
418                        mdt_obd_name(mdt), count, size);
419                 return -EINVAL;
420         }
421
422         OBD_ALLOC(param, size);
423         if (param == NULL)
424                 return -ENOMEM;
425
426         if (copy_from_user(param, buffer, size)) {
427                 CERROR("%s: bad identity data\n", mdt_obd_name(mdt));
428                 GOTO(out, rc = -EFAULT);
429         }
430
431         if (checked == 0) {
432                 checked = 1;
433                 if (param->idd_magic != IDENTITY_DOWNCALL_MAGIC) {
434                         CERROR("%s: MDS identity downcall bad params\n",
435                                mdt_obd_name(mdt));
436                         GOTO(out, rc = -EINVAL);
437                 }
438
439                 if (param->idd_nperms > N_PERMS_MAX) {
440                         CERROR("%s: perm count %d more than maximum %d\n",
441                                mdt_obd_name(mdt), param->idd_nperms,
442                                N_PERMS_MAX);
443                         GOTO(out, rc = -EINVAL);
444                 }
445
446                 if (param->idd_ngroups > NGROUPS_MAX) {
447                         CERROR("%s: group count %d more than maximum %d\n",
448                                mdt_obd_name(mdt), param->idd_ngroups,
449                                NGROUPS_MAX);
450                         GOTO(out, rc = -EINVAL);
451                 }
452
453                 if (param->idd_ngroups) {
454                         rc = param->idd_ngroups; /* save idd_ngroups */
455                         OBD_FREE(param, size);
456                         size = offsetof(struct identity_downcall_data,
457                                         idd_groups[rc]);
458                         goto again;
459                 }
460         }
461
462         rc = upcall_cache_downcall(mdt->mdt_identity_cache, param->idd_err,
463                                    param->idd_uid, param);
464
465 out:
466         if (param != NULL)
467                 OBD_FREE(param, size);
468
469         return rc ? rc : count;
470 }
471
472 /* for debug only */
473 static int lprocfs_rd_capa(char *page, char **start, off_t off,
474                            int count, int *eof, void *data)
475 {
476         struct obd_device *obd = data;
477         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
478
479         return snprintf(page, count, "capability on: %s %s\n",
480                         mdt->mdt_lut.lut_oss_capa ? "oss" : "",
481                         mdt->mdt_lut.lut_mds_capa ? "mds" : "");
482 }
483
484 static int lprocfs_wr_capa(struct file *file, const char *buffer,
485                            unsigned long count, void *data)
486 {
487         struct obd_device *obd = data;
488         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
489         int val, rc;
490
491         rc = lprocfs_write_helper(buffer, count, &val);
492         if (rc)
493                 return rc;
494
495         if (val < 0 || val > 3) {
496                 CERROR("invalid capability mode, only 0/2/3 is accepted.\n"
497                        " 0:  disable fid capability\n"
498                        " 2:  enable MDS fid capability\n"
499                        " 3:  enable both MDS and OSS fid capability\n");
500                 return -EINVAL;
501         }
502
503         /* OSS fid capability needs enable both MDS and OSS fid capability on
504          * MDS */
505         if (val == 1) {
506                 CERROR("can't enable OSS fid capability only, you should use "
507                        "'3' to enable both MDS and OSS fid capability.\n");
508                 return -EINVAL;
509         }
510
511         spin_lock(&mdt->mdt_lut.lut_flags_lock);
512         mdt->mdt_lut.lut_oss_capa = !!(val & 0x1);
513         mdt->mdt_lut.lut_mds_capa = !!(val & 0x2);
514         spin_unlock(&mdt->mdt_lut.lut_flags_lock);
515         mdt->mdt_capa_conf = 1;
516         LCONSOLE_INFO("MDS %s %s MDS fid capability.\n",
517                       mdt_obd_name(mdt),
518                       mdt->mdt_lut.lut_mds_capa ? "enabled" : "disabled");
519         LCONSOLE_INFO("MDS %s %s OSS fid capability.\n",
520                       mdt_obd_name(mdt),
521                       mdt->mdt_lut.lut_oss_capa ? "enabled" : "disabled");
522         return count;
523 }
524
525 static int lprocfs_rd_capa_count(char *page, char **start, off_t off,
526                                  int count, int *eof, void *data)
527 {
528         return snprintf(page, count, "%d %d\n",
529                         capa_count[CAPA_SITE_CLIENT],
530                         capa_count[CAPA_SITE_SERVER]);
531 }
532
533 static int lprocfs_rd_site_stats(char *page, char **start, off_t off,
534                                  int count, int *eof, void *data)
535 {
536         struct obd_device *obd = data;
537         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
538
539         return lu_site_stats_print(mdt_lu_site(mdt), page, count);
540 }
541
542 static int lprocfs_rd_capa_timeout(char *page, char **start, off_t off,
543                                    int count, int *eof, void *data)
544 {
545         struct obd_device *obd = data;
546         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
547
548         return snprintf(page, count, "%lu\n", mdt->mdt_capa_timeout);
549 }
550
551 static int lprocfs_wr_capa_timeout(struct file *file, const char *buffer,
552                                    unsigned long count, void *data)
553 {
554         struct obd_device *obd = data;
555         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
556         int val, rc;
557
558         rc = lprocfs_write_helper(buffer, count, &val);
559         if (rc)
560                 return rc;
561
562         mdt->mdt_capa_timeout = (unsigned long)val;
563         mdt->mdt_capa_conf = 1;
564         return count;
565 }
566
567 static int lprocfs_rd_ck_timeout(char *page, char **start, off_t off, int count,
568                                  int *eof, void *data)
569 {
570         struct obd_device *obd = data;
571         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
572
573         return snprintf(page, count, "%lu\n", mdt->mdt_ck_timeout);
574 }
575
576 static int lprocfs_wr_ck_timeout(struct file *file, const char *buffer,
577                                  unsigned long count, void *data)
578 {
579         struct obd_device *obd = data;
580         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
581         int val, rc;
582
583         rc = lprocfs_write_helper(buffer, count, &val);
584         if (rc)
585                 return rc;
586
587         mdt->mdt_ck_timeout = (unsigned long)val;
588         mdt->mdt_capa_conf = 1;
589         return count;
590 }
591
592 #define BUFLEN (UUID_MAX + 4)
593
594 static int lprocfs_mdt_wr_evict_client(struct file *file, const char *buffer,
595                                        unsigned long count, void *data)
596 {
597         char *kbuf;
598         char *tmpbuf;
599
600         OBD_ALLOC(kbuf, BUFLEN);
601         if (kbuf == NULL)
602                 return -ENOMEM;
603
604         /*
605          * OBD_ALLOC() will zero kbuf, but we only copy BUFLEN - 1
606          * bytes into kbuf, to ensure that the string is NUL-terminated.
607          * UUID_MAX should include a trailing NUL already.
608          */
609         if (copy_from_user(kbuf, buffer,
610                            min_t(unsigned long, BUFLEN - 1, count))) {
611                 count = -EFAULT;
612                 goto out;
613         }
614         tmpbuf = cfs_firststr(kbuf, min_t(unsigned long, BUFLEN - 1, count));
615
616         if (strncmp(tmpbuf, "nid:", 4) != 0) {
617                 count = lprocfs_wr_evict_client(file, buffer, count, data);
618                 goto out;
619         }
620
621         CERROR("NOT implement evict client by nid %s\n", tmpbuf);
622
623 out:
624         OBD_FREE(kbuf, BUFLEN);
625         return count;
626 }
627
628 #undef BUFLEN
629
630 static int lprocfs_rd_sec_level(char *page, char **start, off_t off,
631                                 int count, int *eof, void *data)
632 {
633         struct obd_device *obd = data;
634         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
635
636         return snprintf(page, count, "%d\n", mdt->mdt_lut.lut_sec_level);
637 }
638
639 static int lprocfs_wr_sec_level(struct file *file, const char *buffer,
640                                 unsigned long count, void *data)
641 {
642         struct obd_device *obd = data;
643         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
644         int val, rc;
645
646         rc = lprocfs_write_helper(buffer, count, &val);
647         if (rc)
648                 return rc;
649
650         if (val > LUSTRE_SEC_ALL || val < LUSTRE_SEC_NONE)
651                 return -EINVAL;
652
653         if (val == LUSTRE_SEC_SPECIFY) {
654                 CWARN("security level %d will be supported in future.\n",
655                       LUSTRE_SEC_SPECIFY);
656                 return -EINVAL;
657         }
658
659         mdt->mdt_lut.lut_sec_level = val;
660         return count;
661 }
662
663 static int lprocfs_rd_cos(char *page, char **start, off_t off,
664                               int count, int *eof, void *data)
665 {
666         struct obd_device *obd = data;
667         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
668
669         return snprintf(page, count, "%u\n", mdt_cos_is_enabled(mdt));
670 }
671
672 static int lprocfs_wr_cos(struct file *file, const char *buffer,
673                                   unsigned long count, void *data)
674 {
675         struct obd_device *obd = data;
676         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
677         int val, rc;
678
679         rc = lprocfs_write_helper(buffer, count, &val);
680         if (rc)
681                 return rc;
682         mdt_enable_cos(mdt, val);
683         return count;
684 }
685
686 static int lprocfs_rd_root_squash(char *page, char **start, off_t off,
687                                   int count, int *eof, void *data)
688 {
689         struct obd_device *obd = data;
690         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
691
692         return snprintf(page, count, "%u:%u\n", mdt->mdt_squash_uid,
693                         mdt->mdt_squash_gid);
694 }
695
696 static int safe_strtoul(const char *str, char **endp, unsigned long *res)
697 {
698         char n[24];
699
700         *res = simple_strtoul(str, endp, 0);
701         if (str == *endp)
702                 return 1;
703
704         sprintf(n, "%lu", *res);
705         if (strncmp(n, str, *endp - str))
706                 /* overflow */
707                 return 1;
708         return 0;
709 }
710
711 static int lprocfs_wr_root_squash(struct file *file, const char *buffer,
712                                   unsigned long count, void *data)
713 {
714         struct obd_device *obd = data;
715         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
716         int rc;
717         char kernbuf[50], *tmp, *end, *errmsg;
718         unsigned long uid, gid;
719         int nouid, nogid;
720         ENTRY;
721
722         if (count >= sizeof(kernbuf)) {
723                 errmsg = "string too long";
724                 GOTO(failed, rc = -EINVAL);
725         }
726         if (copy_from_user(kernbuf, buffer, count)) {
727                 errmsg = "bad address";
728                 GOTO(failed, rc = -EFAULT);
729         }
730         kernbuf[count] = '\0';
731
732         nouid = nogid = 0;
733         if (safe_strtoul(buffer, &tmp, &uid)) {
734                 uid = mdt->mdt_squash_uid;
735                 nouid = 1;
736         }
737
738         /* skip ':' */
739         if (*tmp == ':') {
740                 tmp++;
741                 if (safe_strtoul(tmp, &end, &gid)) {
742                         gid = mdt->mdt_squash_gid;
743                         nogid = 1;
744                 }
745         } else {
746                 gid = mdt->mdt_squash_gid;
747                 nogid = 1;
748         }
749
750         mdt->mdt_squash_uid = uid;
751         mdt->mdt_squash_gid = gid;
752
753         if (nouid && nogid) {
754                 errmsg = "needs uid:gid format";
755                 GOTO(failed, rc = -EINVAL);
756         }
757
758         LCONSOLE_INFO("%s: root_squash is set to %u:%u\n",
759                       mdt_obd_name(mdt),
760                       mdt->mdt_squash_uid,  mdt->mdt_squash_gid);
761         RETURN(count);
762
763 failed:
764         CWARN("%s: failed to set root_squash to \"%s\", %s: rc %d\n",
765               mdt_obd_name(mdt), buffer, errmsg, rc);
766         RETURN(rc);
767 }
768
769 static int lprocfs_rd_nosquash_nids(char *page, char **start, off_t off,
770                                     int count, int *eof, void *data)
771 {
772         struct obd_device *obd = data;
773         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
774
775         if (mdt->mdt_nosquash_str)
776                 return snprintf(page, count, "%s\n", mdt->mdt_nosquash_str);
777         return snprintf(page, count, "NONE\n");
778 }
779
780 static int lprocfs_wr_nosquash_nids(struct file *file, const char *buffer,
781                                     unsigned long count, void *data)
782 {
783         struct obd_device *obd = data;
784         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
785         int rc;
786         char *kernbuf, *errmsg;
787         cfs_list_t tmp;
788         ENTRY;
789
790         OBD_ALLOC(kernbuf, count + 1);
791         if (kernbuf == NULL) {
792                 errmsg = "no memory";
793                 GOTO(failed, rc = -ENOMEM);
794         }
795         if (copy_from_user(kernbuf, buffer, count)) {
796                 errmsg = "bad address";
797                 GOTO(failed, rc = -EFAULT);
798         }
799         kernbuf[count] = '\0';
800
801         if (!strcmp(kernbuf, "NONE") || !strcmp(kernbuf, "clear")) {
802                 /* empty string is special case */
803                 down_write(&mdt->mdt_squash_sem);
804                 if (!cfs_list_empty(&mdt->mdt_nosquash_nids)) {
805                         cfs_free_nidlist(&mdt->mdt_nosquash_nids);
806                         OBD_FREE(mdt->mdt_nosquash_str,
807                                  mdt->mdt_nosquash_strlen);
808                         mdt->mdt_nosquash_str = NULL;
809                         mdt->mdt_nosquash_strlen = 0;
810                 }
811                 up_write(&mdt->mdt_squash_sem);
812                 LCONSOLE_INFO("%s: nosquash_nids is cleared\n",
813                               mdt_obd_name(mdt));
814                 OBD_FREE(kernbuf, count + 1);
815                 RETURN(count);
816         }
817
818         CFS_INIT_LIST_HEAD(&tmp);
819         if (cfs_parse_nidlist(kernbuf, count, &tmp) <= 0) {
820                 errmsg = "can't parse";
821                 GOTO(failed, rc = -EINVAL);
822         }
823
824         down_write(&mdt->mdt_squash_sem);
825         if (!cfs_list_empty(&mdt->mdt_nosquash_nids)) {
826                 cfs_free_nidlist(&mdt->mdt_nosquash_nids);
827                 OBD_FREE(mdt->mdt_nosquash_str, mdt->mdt_nosquash_strlen);
828         }
829         mdt->mdt_nosquash_str = kernbuf;
830         mdt->mdt_nosquash_strlen = count + 1;
831         cfs_list_splice(&tmp, &mdt->mdt_nosquash_nids);
832
833         LCONSOLE_INFO("%s: nosquash_nids is set to %s\n",
834                       mdt_obd_name(mdt), kernbuf);
835         up_write(&mdt->mdt_squash_sem);
836         RETURN(count);
837
838 failed:
839         CWARN("%s: failed to set nosquash_nids to \"%s\", %s: rc %d\n",
840               mdt_obd_name(mdt), kernbuf, errmsg, rc);
841         if (kernbuf)
842                 OBD_FREE(kernbuf, count + 1);
843         RETURN(rc);
844 }
845
846 static int lprocfs_rd_mdt_som(char *page, char **start, off_t off,
847                               int count, int *eof, void *data)
848 {
849         struct obd_device *obd = data;
850         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
851
852         return snprintf(page, count, "%sabled\n",
853                         mdt->mdt_som_conf ? "en" : "dis");
854 }
855
856 static int lprocfs_wr_mdt_som(struct file *file, const char *buffer,
857                               unsigned long count, void *data)
858 {
859         struct obd_export *exp;
860         struct obd_device *obd = data;
861         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
862         char kernbuf[16];
863         unsigned long val = 0;
864
865         if (count > (sizeof(kernbuf) - 1))
866                 return -EINVAL;
867
868         if (copy_from_user(kernbuf, buffer, count))
869                 return -EFAULT;
870
871         kernbuf[count] = '\0';
872
873         if (!strcmp(kernbuf, "enabled"))
874                 val = 1;
875         else if (strcmp(kernbuf, "disabled"))
876                 return -EINVAL;
877
878         if (mdt->mdt_som_conf == val)
879                 return count;
880
881         if (!obd->obd_process_conf) {
882                 CERROR("Temporary SOM change is not supported, use lctl "
883                        "conf_param for permanent setting\n");
884                 return count;
885         }
886
887         /* 1 stands for self export. */
888         cfs_list_for_each_entry(exp, &obd->obd_exports, exp_obd_chain) {
889                 if (exp == obd->obd_self_export)
890                         continue;
891                 if (exp_connect_flags(exp) & OBD_CONNECT_MDS_MDS)
892                         continue;
893                 /* Some clients are already connected, skip the change */
894                 LCONSOLE_INFO("%s is already connected, SOM will be %s on "
895                               "the next mount\n", exp->exp_client_uuid.uuid,
896                               val ? "enabled" : "disabled");
897                 return count;
898         }
899
900         mdt->mdt_som_conf = val;
901         LCONSOLE_INFO("Enabling SOM\n");
902
903         return count;
904 }
905
906 static int lprocfs_rd_enable_remote_dir(char *page, char **start, off_t off,
907                                         int count, int *eof, void *data)
908 {
909         struct obd_device *obd = data;
910         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
911
912         return snprintf(page, count, "%u\n", mdt->mdt_enable_remote_dir);
913 }
914
915 static int lprocfs_wr_enable_remote_dir(struct file *file, const char *buffer,
916                                         unsigned long count, void *data)
917 {
918         struct obd_device *obd = data;
919         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
920         __u32 val;
921         int rc;
922
923         rc = lprocfs_write_helper(buffer, count, &val);
924         if (rc)
925                 return rc;
926
927         if (val > 1)
928                 return -ERANGE;
929
930         mdt->mdt_enable_remote_dir = val;
931         return count;
932 }
933
934 static int lprocfs_rd_enable_remote_dir_gid(char *page, char **start, off_t off,
935                                             int count, int *eof, void *data)
936 {
937         struct obd_device *obd = data;
938         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
939
940         return snprintf(page, count, "%d\n",
941                         (int)mdt->mdt_enable_remote_dir_gid);
942 }
943
944 static int lprocfs_wr_enable_remote_dir_gid(struct file *file,
945                                             const char *buffer,
946                                             unsigned long count, void *data)
947 {
948         struct obd_device *obd = data;
949         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
950         __u32 val;
951         int rc;
952
953         rc = lprocfs_write_helper(buffer, count, &val);
954         if (rc)
955                 return rc;
956
957         mdt->mdt_enable_remote_dir_gid = val;
958         return count;
959 }
960
961 static struct lprocfs_vars lprocfs_mdt_obd_vars[] = {
962         { "uuid",                       lprocfs_rd_uuid, NULL,
963                                         NULL, NULL, 0 },
964         { "recovery_status",            lprocfs_obd_rd_recovery_status, NULL,
965                                         NULL, NULL, 0 },
966         { "num_exports",                lprocfs_rd_num_exports, NULL,
967                                         NULL, NULL, 0 },
968         { "identity_expire",            lprocfs_rd_identity_expire,
969                                         lprocfs_wr_identity_expire,
970                                         NULL, NULL, 0 },
971         { "identity_acquire_expire",    lprocfs_rd_identity_acquire_expire,
972                                         lprocfs_wr_identity_acquire_expire,
973                                         NULL, NULL, 0 },
974         { "identity_upcall",            lprocfs_rd_identity_upcall,
975                                         lprocfs_wr_identity_upcall,
976                                         NULL, NULL, 0 },
977         { "identity_flush",             NULL, lprocfs_wr_identity_flush,
978                                         NULL, NULL, 0 },
979         { "identity_info",              NULL, lprocfs_wr_identity_info,
980                                         NULL, NULL, 0 },
981         { "capa",                       lprocfs_rd_capa,
982                                         lprocfs_wr_capa,
983                                         NULL, NULL, 0 },
984         { "capa_timeout",               lprocfs_rd_capa_timeout,
985                                         lprocfs_wr_capa_timeout,
986                                         NULL, NULL, 0 },
987         { "capa_key_timeout",           lprocfs_rd_ck_timeout,
988                                         lprocfs_wr_ck_timeout,
989                                         NULL, NULL, 0 },
990         { "capa_count",                 lprocfs_rd_capa_count, NULL,
991                                         NULL, NULL, 0 },
992         { "site_stats",                 lprocfs_rd_site_stats, NULL,
993                                         NULL, NULL, 0 },
994         { "evict_client",               NULL, lprocfs_mdt_wr_evict_client,
995                                         NULL, NULL, 0 },
996         { "hash_stats",                 lprocfs_obd_rd_hash, NULL,
997                                         NULL, NULL, 0 },
998         { "sec_level",                  lprocfs_rd_sec_level,
999                                         lprocfs_wr_sec_level,
1000                                         NULL, NULL, 0 },
1001         { "commit_on_sharing",          lprocfs_rd_cos, lprocfs_wr_cos,
1002                                         NULL, NULL, 0 },
1003         { "root_squash",                lprocfs_rd_root_squash,
1004                                         lprocfs_wr_root_squash,
1005                                         NULL, NULL, 0 },
1006         { "nosquash_nids",              lprocfs_rd_nosquash_nids,
1007                                         lprocfs_wr_nosquash_nids,
1008                                         NULL, NULL, 0 },
1009         { "som",                        lprocfs_rd_mdt_som,
1010                                         lprocfs_wr_mdt_som,
1011                                         NULL, NULL, 0 },
1012         { "instance",                   lprocfs_target_rd_instance, NULL,
1013                                         NULL, NULL, 0},
1014         { "ir_factor",                  lprocfs_obd_rd_ir_factor,
1015                                         lprocfs_obd_wr_ir_factor,
1016                                         NULL, NULL, 0 },
1017         { "job_cleanup_interval",       lprocfs_rd_job_interval,
1018                                         lprocfs_wr_job_interval,
1019                                         NULL, NULL, 0 },
1020         { "enable_remote_dir",          lprocfs_rd_enable_remote_dir,
1021                                         lprocfs_wr_enable_remote_dir,
1022                                         NULL, NULL, 0},
1023         { "enable_remote_dir_gid",      lprocfs_rd_enable_remote_dir_gid,
1024                                         lprocfs_wr_enable_remote_dir_gid,
1025                                         NULL, NULL, 0},
1026         { "hsm_control",                lprocfs_rd_hsm_cdt_control,
1027                                         lprocfs_wr_hsm_cdt_control,
1028                                         NULL, NULL, 0 },
1029         { 0 }
1030 };
1031
1032 static struct lprocfs_vars lprocfs_mdt_module_vars[] = {
1033         { "num_refs",                   lprocfs_rd_numrefs, NULL,
1034                                         NULL, NULL, 0 },
1035         { 0 }
1036 };
1037
1038 void lprocfs_mdt_init_vars(struct lprocfs_static_vars *lvars)
1039 {
1040         lvars->module_vars  = lprocfs_mdt_module_vars;
1041         lvars->obd_vars     = lprocfs_mdt_obd_vars;
1042 }
1043
1044 struct lprocfs_vars lprocfs_mds_obd_vars[] = {
1045         { "uuid",       lprocfs_rd_uuid, NULL, NULL, NULL, 0 },
1046         { 0 }
1047 };
1048
1049 struct lprocfs_vars lprocfs_mds_module_vars[] = {
1050         { "num_refs",   lprocfs_rd_numrefs, NULL, NULL, NULL, 0 },
1051         { 0 }
1052 };
1053
1054 int lprocfs_mdt_print_open_files(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1055                                  cfs_hlist_node_t *hnode, void *v)
1056 {
1057         struct obd_export       *exp = cfs_hash_object(hs, hnode);
1058         struct seq_file         *seq = v;
1059
1060         if (exp->exp_lock_hash != NULL) {
1061                 struct mdt_export_data  *med = &exp->exp_mdt_data;
1062                 struct mdt_file_data    *mfd;
1063
1064                 spin_lock(&med->med_open_lock);
1065                 cfs_list_for_each_entry(mfd, &med->med_open_head, mfd_list) {
1066                         seq_printf(seq, DFID"\n",
1067                                    PFID(mdt_object_fid(mfd->mfd_object)));
1068                 }
1069                 spin_unlock(&med->med_open_lock);
1070         }
1071
1072         return 0;
1073 }
1074
1075 int lprocfs_mdt_open_files_seq_show(struct seq_file *seq, void *v)
1076 {
1077         struct nid_stat *stats = seq->private;
1078         struct obd_device *obd = stats->nid_obd;
1079
1080         cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1081                               lprocfs_mdt_print_open_files, seq);
1082
1083         return 0;
1084 }
1085
1086 int lprocfs_mdt_open_files_seq_open(struct inode *inode, struct file *file)
1087 {
1088         struct proc_dir_entry   *dp = PDE(inode);
1089         struct seq_file         *seq;
1090         struct nid_stat         *tmp;
1091         int                     rc;
1092
1093         if (LPROCFS_ENTRY_CHECK(dp))
1094                 return -ENOENT;
1095
1096         tmp = dp->data;
1097         rc = single_open(file, &lprocfs_mdt_open_files_seq_show, NULL);
1098         if (rc != 0)
1099                 return rc;
1100
1101         seq = file->private_data;
1102         seq->private = tmp;
1103
1104         return 0;
1105 }
1106
1107 void mdt_counter_incr(struct ptlrpc_request *req, int opcode)
1108 {
1109         struct obd_export *exp = req->rq_export;
1110
1111         if (exp->exp_obd && exp->exp_obd->obd_md_stats)
1112                 lprocfs_counter_incr(exp->exp_obd->obd_md_stats, opcode);
1113         if (exp->exp_nid_stats && exp->exp_nid_stats->nid_stats != NULL)
1114                 lprocfs_counter_incr(exp->exp_nid_stats->nid_stats, opcode);
1115         if (exp->exp_obd && exp->exp_obd->u.obt.obt_jobstats.ojs_hash &&
1116             (exp_connect_flags(exp) & OBD_CONNECT_JOBSTATS))
1117                 lprocfs_job_stats_log(exp->exp_obd,
1118                                       lustre_msg_get_jobid(req->rq_reqmsg),
1119                                       opcode, 1);
1120 }
1121
1122 void mdt_stats_counter_init(struct lprocfs_stats *stats)
1123 {
1124         lprocfs_counter_init(stats, LPROC_MDT_OPEN, 0, "open", "reqs");
1125         lprocfs_counter_init(stats, LPROC_MDT_CLOSE, 0, "close", "reqs");
1126         lprocfs_counter_init(stats, LPROC_MDT_MKNOD, 0, "mknod", "reqs");
1127         lprocfs_counter_init(stats, LPROC_MDT_LINK, 0, "link", "reqs");
1128         lprocfs_counter_init(stats, LPROC_MDT_UNLINK, 0, "unlink", "reqs");
1129         lprocfs_counter_init(stats, LPROC_MDT_MKDIR, 0, "mkdir", "reqs");
1130         lprocfs_counter_init(stats, LPROC_MDT_RMDIR, 0, "rmdir", "reqs");
1131         lprocfs_counter_init(stats, LPROC_MDT_RENAME, 0, "rename", "reqs");
1132         lprocfs_counter_init(stats, LPROC_MDT_GETATTR, 0, "getattr", "reqs");
1133         lprocfs_counter_init(stats, LPROC_MDT_SETATTR, 0, "setattr", "reqs");
1134         lprocfs_counter_init(stats, LPROC_MDT_GETXATTR, 0, "getxattr", "reqs");
1135         lprocfs_counter_init(stats, LPROC_MDT_SETXATTR, 0, "setxattr", "reqs");
1136         lprocfs_counter_init(stats, LPROC_MDT_STATFS, 0, "statfs", "reqs");
1137         lprocfs_counter_init(stats, LPROC_MDT_SYNC, 0, "sync", "reqs");
1138         lprocfs_counter_init(stats, LPROC_MDT_SAMEDIR_RENAME, 0,
1139                              "samedir_rename", "reqs");
1140         lprocfs_counter_init(stats, LPROC_MDT_CROSSDIR_RENAME, 0,
1141                              "crossdir_rename", "reqs");
1142 }