Whamcloud - gitweb
LU-3828 mdt: hsm tunable can be set permanently
[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         rc = hsm_cdt_procfs_init(mdt);
233         if (rc) {
234                 CERROR("%s: cannot create hsm proc entries: rc = %d\n",
235                        mdt_obd_name(mdt), rc);
236                 return rc;
237         }
238         ptlrpc_lprocfs_register_obd(obd);
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) {
267                 lprocfs_remove_proc_entry("clear", obd->obd_proc_exports_entry);
268                 obd->obd_proc_exports_entry = NULL;
269         }
270         lprocfs_free_per_client_stats(obd);
271         lprocfs_obd_cleanup(obd);
272         hsm_cdt_procfs_fini(mdt);
273         ptlrpc_lprocfs_unregister_obd(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_opts.mo_oss_capa ? "oss" : "",
481                         mdt->mdt_opts.mo_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         mdt->mdt_opts.mo_oss_capa = (val & 0x1);
512         mdt->mdt_opts.mo_mds_capa = !!(val & 0x2);
513         mdt->mdt_capa_conf = 1;
514         LCONSOLE_INFO("MDS %s %s MDS fid capability.\n",
515                       mdt_obd_name(mdt),
516                       mdt->mdt_opts.mo_mds_capa ? "enabled" : "disabled");
517         LCONSOLE_INFO("MDS %s %s OSS fid capability.\n",
518                       mdt_obd_name(mdt),
519                       mdt->mdt_opts.mo_oss_capa ? "enabled" : "disabled");
520         return count;
521 }
522
523 static int lprocfs_rd_capa_count(char *page, char **start, off_t off,
524                                  int count, int *eof, void *data)
525 {
526         return snprintf(page, count, "%d %d\n",
527                         capa_count[CAPA_SITE_CLIENT],
528                         capa_count[CAPA_SITE_SERVER]);
529 }
530
531 static int lprocfs_rd_site_stats(char *page, char **start, off_t off,
532                                  int count, int *eof, void *data)
533 {
534         struct obd_device *obd = data;
535         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
536
537         return lu_site_stats_print(mdt_lu_site(mdt), page, count);
538 }
539
540 static int lprocfs_rd_capa_timeout(char *page, char **start, off_t off,
541                                    int count, int *eof, void *data)
542 {
543         struct obd_device *obd = data;
544         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
545
546         return snprintf(page, count, "%lu\n", mdt->mdt_capa_timeout);
547 }
548
549 static int lprocfs_wr_capa_timeout(struct file *file, const char *buffer,
550                                    unsigned long count, void *data)
551 {
552         struct obd_device *obd = data;
553         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
554         int val, rc;
555
556         rc = lprocfs_write_helper(buffer, count, &val);
557         if (rc)
558                 return rc;
559
560         mdt->mdt_capa_timeout = (unsigned long)val;
561         mdt->mdt_capa_conf = 1;
562         return count;
563 }
564
565 static int lprocfs_rd_ck_timeout(char *page, char **start, off_t off, int count,
566                                  int *eof, void *data)
567 {
568         struct obd_device *obd = data;
569         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
570
571         return snprintf(page, count, "%lu\n", mdt->mdt_ck_timeout);
572 }
573
574 static int lprocfs_wr_ck_timeout(struct file *file, const char *buffer,
575                                  unsigned long count, void *data)
576 {
577         struct obd_device *obd = data;
578         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
579         int val, rc;
580
581         rc = lprocfs_write_helper(buffer, count, &val);
582         if (rc)
583                 return rc;
584
585         mdt->mdt_ck_timeout = (unsigned long)val;
586         mdt->mdt_capa_conf = 1;
587         return count;
588 }
589
590 #define BUFLEN (UUID_MAX + 4)
591
592 static int lprocfs_mdt_wr_evict_client(struct file *file, const char *buffer,
593                                        unsigned long count, void *data)
594 {
595         char *kbuf;
596         char *tmpbuf;
597
598         OBD_ALLOC(kbuf, BUFLEN);
599         if (kbuf == NULL)
600                 return -ENOMEM;
601
602         /*
603          * OBD_ALLOC() will zero kbuf, but we only copy BUFLEN - 1
604          * bytes into kbuf, to ensure that the string is NUL-terminated.
605          * UUID_MAX should include a trailing NUL already.
606          */
607         if (copy_from_user(kbuf, buffer,
608                            min_t(unsigned long, BUFLEN - 1, count))) {
609                 count = -EFAULT;
610                 goto out;
611         }
612         tmpbuf = cfs_firststr(kbuf, min_t(unsigned long, BUFLEN - 1, count));
613
614         if (strncmp(tmpbuf, "nid:", 4) != 0) {
615                 count = lprocfs_wr_evict_client(file, buffer, count, data);
616                 goto out;
617         }
618
619         CERROR("NOT implement evict client by nid %s\n", tmpbuf);
620
621 out:
622         OBD_FREE(kbuf, BUFLEN);
623         return count;
624 }
625
626 #undef BUFLEN
627
628 static int lprocfs_rd_sec_level(char *page, char **start, off_t off,
629                                 int count, int *eof, void *data)
630 {
631         struct obd_device *obd = data;
632         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
633
634         return snprintf(page, count, "%d\n", mdt->mdt_sec_level);
635 }
636
637 static int lprocfs_wr_sec_level(struct file *file, const char *buffer,
638                                 unsigned long count, void *data)
639 {
640         struct obd_device *obd = data;
641         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
642         int val, rc;
643
644         rc = lprocfs_write_helper(buffer, count, &val);
645         if (rc)
646                 return rc;
647
648         if (val > LUSTRE_SEC_ALL || val < LUSTRE_SEC_NONE)
649                 return -EINVAL;
650
651         if (val == LUSTRE_SEC_SPECIFY) {
652                 CWARN("security level %d will be supported in future.\n",
653                       LUSTRE_SEC_SPECIFY);
654                 return -EINVAL;
655         }
656
657         mdt->mdt_sec_level = val;
658         return count;
659 }
660
661 static int lprocfs_rd_cos(char *page, char **start, off_t off,
662                               int count, int *eof, void *data)
663 {
664         struct obd_device *obd = data;
665         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
666
667         return snprintf(page, count, "%u\n", mdt_cos_is_enabled(mdt));
668 }
669
670 static int lprocfs_wr_cos(struct file *file, const char *buffer,
671                                   unsigned long count, void *data)
672 {
673         struct obd_device *obd = data;
674         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
675         int val, rc;
676
677         rc = lprocfs_write_helper(buffer, count, &val);
678         if (rc)
679                 return rc;
680         mdt_enable_cos(mdt, val);
681         return count;
682 }
683
684 static int lprocfs_rd_root_squash(char *page, char **start, off_t off,
685                                   int count, int *eof, void *data)
686 {
687         struct obd_device *obd = data;
688         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
689
690         return snprintf(page, count, "%u:%u\n", mdt->mdt_squash_uid,
691                         mdt->mdt_squash_gid);
692 }
693
694 static int safe_strtoul(const char *str, char **endp, unsigned long *res)
695 {
696         char n[24];
697
698         *res = simple_strtoul(str, endp, 0);
699         if (str == *endp)
700                 return 1;
701
702         sprintf(n, "%lu", *res);
703         if (strncmp(n, str, *endp - str))
704                 /* overflow */
705                 return 1;
706         return 0;
707 }
708
709 static int lprocfs_wr_root_squash(struct file *file, const char *buffer,
710                                   unsigned long count, void *data)
711 {
712         struct obd_device *obd = data;
713         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
714         int rc;
715         char kernbuf[50], *tmp, *end, *errmsg;
716         unsigned long uid, gid;
717         int nouid, nogid;
718         ENTRY;
719
720         if (count >= sizeof(kernbuf)) {
721                 errmsg = "string too long";
722                 GOTO(failed, rc = -EINVAL);
723         }
724         if (copy_from_user(kernbuf, buffer, count)) {
725                 errmsg = "bad address";
726                 GOTO(failed, rc = -EFAULT);
727         }
728         kernbuf[count] = '\0';
729
730         nouid = nogid = 0;
731         if (safe_strtoul(buffer, &tmp, &uid)) {
732                 uid = mdt->mdt_squash_uid;
733                 nouid = 1;
734         }
735
736         /* skip ':' */
737         if (*tmp == ':') {
738                 tmp++;
739                 if (safe_strtoul(tmp, &end, &gid)) {
740                         gid = mdt->mdt_squash_gid;
741                         nogid = 1;
742                 }
743         } else {
744                 gid = mdt->mdt_squash_gid;
745                 nogid = 1;
746         }
747
748         mdt->mdt_squash_uid = uid;
749         mdt->mdt_squash_gid = gid;
750
751         if (nouid && nogid) {
752                 errmsg = "needs uid:gid format";
753                 GOTO(failed, rc = -EINVAL);
754         }
755
756         LCONSOLE_INFO("%s: root_squash is set to %u:%u\n",
757                       mdt_obd_name(mdt),
758                       mdt->mdt_squash_uid,  mdt->mdt_squash_gid);
759         RETURN(count);
760
761 failed:
762         CWARN("%s: failed to set root_squash to \"%s\", %s: rc %d\n",
763               mdt_obd_name(mdt), buffer, errmsg, rc);
764         RETURN(rc);
765 }
766
767 static int lprocfs_rd_nosquash_nids(char *page, char **start, off_t off,
768                                     int count, int *eof, void *data)
769 {
770         struct obd_device *obd = data;
771         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
772
773         if (mdt->mdt_nosquash_str)
774                 return snprintf(page, count, "%s\n", mdt->mdt_nosquash_str);
775         return snprintf(page, count, "NONE\n");
776 }
777
778 static int lprocfs_wr_nosquash_nids(struct file *file, const char *buffer,
779                                     unsigned long count, void *data)
780 {
781         struct obd_device *obd = data;
782         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
783         int rc;
784         char *kernbuf, *errmsg;
785         cfs_list_t tmp;
786         ENTRY;
787
788         OBD_ALLOC(kernbuf, count + 1);
789         if (kernbuf == NULL) {
790                 errmsg = "no memory";
791                 GOTO(failed, rc = -ENOMEM);
792         }
793         if (copy_from_user(kernbuf, buffer, count)) {
794                 errmsg = "bad address";
795                 GOTO(failed, rc = -EFAULT);
796         }
797         kernbuf[count] = '\0';
798
799         if (!strcmp(kernbuf, "NONE") || !strcmp(kernbuf, "clear")) {
800                 /* empty string is special case */
801                 down_write(&mdt->mdt_squash_sem);
802                 if (!cfs_list_empty(&mdt->mdt_nosquash_nids)) {
803                         cfs_free_nidlist(&mdt->mdt_nosquash_nids);
804                         OBD_FREE(mdt->mdt_nosquash_str,
805                                  mdt->mdt_nosquash_strlen);
806                         mdt->mdt_nosquash_str = NULL;
807                         mdt->mdt_nosquash_strlen = 0;
808                 }
809                 up_write(&mdt->mdt_squash_sem);
810                 LCONSOLE_INFO("%s: nosquash_nids is cleared\n",
811                               mdt_obd_name(mdt));
812                 OBD_FREE(kernbuf, count + 1);
813                 RETURN(count);
814         }
815
816         CFS_INIT_LIST_HEAD(&tmp);
817         if (cfs_parse_nidlist(kernbuf, count, &tmp) <= 0) {
818                 errmsg = "can't parse";
819                 GOTO(failed, rc = -EINVAL);
820         }
821
822         down_write(&mdt->mdt_squash_sem);
823         if (!cfs_list_empty(&mdt->mdt_nosquash_nids)) {
824                 cfs_free_nidlist(&mdt->mdt_nosquash_nids);
825                 OBD_FREE(mdt->mdt_nosquash_str, mdt->mdt_nosquash_strlen);
826         }
827         mdt->mdt_nosquash_str = kernbuf;
828         mdt->mdt_nosquash_strlen = count + 1;
829         cfs_list_splice(&tmp, &mdt->mdt_nosquash_nids);
830
831         LCONSOLE_INFO("%s: nosquash_nids is set to %s\n",
832                       mdt_obd_name(mdt), kernbuf);
833         up_write(&mdt->mdt_squash_sem);
834         RETURN(count);
835
836 failed:
837         CWARN("%s: failed to set nosquash_nids to \"%s\", %s: rc %d\n",
838               mdt_obd_name(mdt), kernbuf, errmsg, rc);
839         if (kernbuf)
840                 OBD_FREE(kernbuf, count + 1);
841         RETURN(rc);
842 }
843
844 static int lprocfs_rd_mdt_som(char *page, char **start, off_t off,
845                               int count, int *eof, void *data)
846 {
847         struct obd_device *obd = data;
848         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
849
850         return snprintf(page, count, "%sabled\n",
851                         mdt->mdt_som_conf ? "en" : "dis");
852 }
853
854 static int lprocfs_wr_mdt_som(struct file *file, const char *buffer,
855                               unsigned long count, void *data)
856 {
857         struct obd_export *exp;
858         struct obd_device *obd = data;
859         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
860         char kernbuf[16];
861         unsigned long val = 0;
862
863         if (count > (sizeof(kernbuf) - 1))
864                 return -EINVAL;
865
866         if (copy_from_user(kernbuf, buffer, count))
867                 return -EFAULT;
868
869         kernbuf[count] = '\0';
870
871         if (!strcmp(kernbuf, "enabled"))
872                 val = 1;
873         else if (strcmp(kernbuf, "disabled"))
874                 return -EINVAL;
875
876         if (mdt->mdt_som_conf == val)
877                 return count;
878
879         if (!obd->obd_process_conf) {
880                 CERROR("Temporary SOM change is not supported, use lctl "
881                        "conf_param for permanent setting\n");
882                 return count;
883         }
884
885         /* 1 stands for self export. */
886         cfs_list_for_each_entry(exp, &obd->obd_exports, exp_obd_chain) {
887                 if (exp == obd->obd_self_export)
888                         continue;
889                 if (exp_connect_flags(exp) & OBD_CONNECT_MDS_MDS)
890                         continue;
891                 /* Some clients are already connected, skip the change */
892                 LCONSOLE_INFO("%s is already connected, SOM will be %s on "
893                               "the next mount\n", exp->exp_client_uuid.uuid,
894                               val ? "enabled" : "disabled");
895                 return count;
896         }
897
898         mdt->mdt_som_conf = val;
899         LCONSOLE_INFO("Enabling SOM\n");
900
901         return count;
902 }
903
904 static int lprocfs_rd_enable_remote_dir(char *page, char **start, off_t off,
905                                         int count, int *eof, void *data)
906 {
907         struct obd_device *obd = data;
908         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
909
910         return snprintf(page, count, "%u\n", mdt->mdt_enable_remote_dir);
911 }
912
913 static int lprocfs_wr_enable_remote_dir(struct file *file, const char *buffer,
914                                         unsigned long count, void *data)
915 {
916         struct obd_device *obd = data;
917         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
918         __u32 val;
919         int rc;
920
921         rc = lprocfs_write_helper(buffer, count, &val);
922         if (rc)
923                 return rc;
924
925         if (val > 1)
926                 return -ERANGE;
927
928         mdt->mdt_enable_remote_dir = val;
929         return count;
930 }
931
932 static int lprocfs_rd_enable_remote_dir_gid(char *page, char **start, off_t off,
933                                             int count, int *eof, void *data)
934 {
935         struct obd_device *obd = data;
936         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
937
938         return snprintf(page, count, "%d\n",
939                         (int)mdt->mdt_enable_remote_dir_gid);
940 }
941
942 static int lprocfs_wr_enable_remote_dir_gid(struct file *file,
943                                             const char *buffer,
944                                             unsigned long count, void *data)
945 {
946         struct obd_device *obd = data;
947         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
948         __u32 val;
949         int rc;
950
951         rc = lprocfs_write_helper(buffer, count, &val);
952         if (rc)
953                 return rc;
954
955         mdt->mdt_enable_remote_dir_gid = val;
956         return count;
957 }
958
959 static struct lprocfs_vars lprocfs_mdt_obd_vars[] = {
960         { "uuid",                       lprocfs_rd_uuid, NULL,
961                                         NULL, NULL, 0 },
962         { "recovery_status",            lprocfs_obd_rd_recovery_status, NULL,
963                                         NULL, NULL, 0 },
964         { "num_exports",                lprocfs_rd_num_exports, NULL,
965                                         NULL, NULL, 0 },
966         { "identity_expire",            lprocfs_rd_identity_expire,
967                                         lprocfs_wr_identity_expire,
968                                         NULL, NULL, 0 },
969         { "identity_acquire_expire",    lprocfs_rd_identity_acquire_expire,
970                                         lprocfs_wr_identity_acquire_expire,
971                                         NULL, NULL, 0 },
972         { "identity_upcall",            lprocfs_rd_identity_upcall,
973                                         lprocfs_wr_identity_upcall,
974                                         NULL, NULL, 0 },
975         { "identity_flush",             NULL, lprocfs_wr_identity_flush,
976                                         NULL, NULL, 0 },
977         { "identity_info",              NULL, lprocfs_wr_identity_info,
978                                         NULL, NULL, 0 },
979         { "capa",                       lprocfs_rd_capa,
980                                         lprocfs_wr_capa,
981                                         NULL, NULL, 0 },
982         { "capa_timeout",               lprocfs_rd_capa_timeout,
983                                         lprocfs_wr_capa_timeout,
984                                         NULL, NULL, 0 },
985         { "capa_key_timeout",           lprocfs_rd_ck_timeout,
986                                         lprocfs_wr_ck_timeout,
987                                         NULL, NULL, 0 },
988         { "capa_count",                 lprocfs_rd_capa_count, NULL,
989                                         NULL, NULL, 0 },
990         { "site_stats",                 lprocfs_rd_site_stats, NULL,
991                                         NULL, NULL, 0 },
992         { "evict_client",               NULL, lprocfs_mdt_wr_evict_client,
993                                         NULL, NULL, 0 },
994         { "hash_stats",                 lprocfs_obd_rd_hash, NULL,
995                                         NULL, NULL, 0 },
996         { "sec_level",                  lprocfs_rd_sec_level,
997                                         lprocfs_wr_sec_level,
998                                         NULL, NULL, 0 },
999         { "commit_on_sharing",          lprocfs_rd_cos, lprocfs_wr_cos,
1000                                         NULL, NULL, 0 },
1001         { "root_squash",                lprocfs_rd_root_squash,
1002                                         lprocfs_wr_root_squash,
1003                                         NULL, NULL, 0 },
1004         { "nosquash_nids",              lprocfs_rd_nosquash_nids,
1005                                         lprocfs_wr_nosquash_nids,
1006                                         NULL, NULL, 0 },
1007         { "som",                        lprocfs_rd_mdt_som,
1008                                         lprocfs_wr_mdt_som,
1009                                         NULL, NULL, 0 },
1010         { "instance",                   lprocfs_target_rd_instance, NULL,
1011                                         NULL, NULL, 0},
1012         { "ir_factor",                  lprocfs_obd_rd_ir_factor,
1013                                         lprocfs_obd_wr_ir_factor,
1014                                         NULL, NULL, 0 },
1015         { "job_cleanup_interval",       lprocfs_rd_job_interval,
1016                                         lprocfs_wr_job_interval,
1017                                         NULL, NULL, 0 },
1018         { "enable_remote_dir",          lprocfs_rd_enable_remote_dir,
1019                                         lprocfs_wr_enable_remote_dir,
1020                                         NULL, NULL, 0},
1021         { "enable_remote_dir_gid",      lprocfs_rd_enable_remote_dir_gid,
1022                                         lprocfs_wr_enable_remote_dir_gid,
1023                                         NULL, NULL, 0},
1024         { "hsm_control",                lprocfs_rd_hsm_cdt_control,
1025                                         lprocfs_wr_hsm_cdt_control,
1026                                         NULL, NULL, 0 },
1027         { 0 }
1028 };
1029
1030 static struct lprocfs_vars lprocfs_mdt_module_vars[] = {
1031         { "num_refs",                   lprocfs_rd_numrefs, NULL,
1032                                         NULL, NULL, 0 },
1033         { 0 }
1034 };
1035
1036 void lprocfs_mdt_init_vars(struct lprocfs_static_vars *lvars)
1037 {
1038         lvars->module_vars  = lprocfs_mdt_module_vars;
1039         lvars->obd_vars     = lprocfs_mdt_obd_vars;
1040 }
1041
1042 struct lprocfs_vars lprocfs_mds_obd_vars[] = {
1043         { "uuid",       lprocfs_rd_uuid, NULL, NULL, NULL, 0 },
1044         { 0 }
1045 };
1046
1047 struct lprocfs_vars lprocfs_mds_module_vars[] = {
1048         { "num_refs",   lprocfs_rd_numrefs, NULL, NULL, NULL, 0 },
1049         { 0 }
1050 };
1051
1052 void mdt_counter_incr(struct ptlrpc_request *req, int opcode)
1053 {
1054         struct obd_export *exp = req->rq_export;
1055
1056         if (exp->exp_obd && exp->exp_obd->obd_md_stats)
1057                 lprocfs_counter_incr(exp->exp_obd->obd_md_stats, opcode);
1058         if (exp->exp_nid_stats && exp->exp_nid_stats->nid_stats != NULL)
1059                 lprocfs_counter_incr(exp->exp_nid_stats->nid_stats, opcode);
1060         if (exp->exp_obd && exp->exp_obd->u.obt.obt_jobstats.ojs_hash &&
1061             (exp_connect_flags(exp) & OBD_CONNECT_JOBSTATS))
1062                 lprocfs_job_stats_log(exp->exp_obd,
1063                                       lustre_msg_get_jobid(req->rq_reqmsg),
1064                                       opcode, 1);
1065 }
1066
1067 void mdt_stats_counter_init(struct lprocfs_stats *stats)
1068 {
1069         lprocfs_counter_init(stats, LPROC_MDT_OPEN, 0, "open", "reqs");
1070         lprocfs_counter_init(stats, LPROC_MDT_CLOSE, 0, "close", "reqs");
1071         lprocfs_counter_init(stats, LPROC_MDT_MKNOD, 0, "mknod", "reqs");
1072         lprocfs_counter_init(stats, LPROC_MDT_LINK, 0, "link", "reqs");
1073         lprocfs_counter_init(stats, LPROC_MDT_UNLINK, 0, "unlink", "reqs");
1074         lprocfs_counter_init(stats, LPROC_MDT_MKDIR, 0, "mkdir", "reqs");
1075         lprocfs_counter_init(stats, LPROC_MDT_RMDIR, 0, "rmdir", "reqs");
1076         lprocfs_counter_init(stats, LPROC_MDT_RENAME, 0, "rename", "reqs");
1077         lprocfs_counter_init(stats, LPROC_MDT_GETATTR, 0, "getattr", "reqs");
1078         lprocfs_counter_init(stats, LPROC_MDT_SETATTR, 0, "setattr", "reqs");
1079         lprocfs_counter_init(stats, LPROC_MDT_GETXATTR, 0, "getxattr", "reqs");
1080         lprocfs_counter_init(stats, LPROC_MDT_SETXATTR, 0, "setxattr", "reqs");
1081         lprocfs_counter_init(stats, LPROC_MDT_STATFS, 0, "statfs", "reqs");
1082         lprocfs_counter_init(stats, LPROC_MDT_SYNC, 0, "sync", "reqs");
1083         lprocfs_counter_init(stats, LPROC_MDT_SAMEDIR_RENAME, 0,
1084                              "samedir_rename", "reqs");
1085         lprocfs_counter_init(stats, LPROC_MDT_CROSSDIR_RENAME, 0,
1086                              "crossdir_rename", "reqs");
1087 }