Whamcloud - gitweb
LU-1778 llite: fix inconsistencies of root squash feature
[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,
291                                       const char __user *buffer,
292                                       unsigned long count, void *data)
293 {
294         struct obd_device *obd = data;
295         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
296         int rc, val;
297
298         rc = lprocfs_write_helper(buffer, count, &val);
299         if (rc)
300                 return rc;
301
302         mdt->mdt_identity_cache->uc_entry_expire = val;
303         return count;
304 }
305
306 static int lprocfs_rd_identity_acquire_expire(char *page, char **start,
307                                               off_t off, int count, int *eof,
308                                               void *data)
309 {
310         struct obd_device *obd = data;
311         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
312
313         *eof = 1;
314         return snprintf(page, count, "%u\n",
315                         mdt->mdt_identity_cache->uc_acquire_expire);
316 }
317
318 static int lprocfs_wr_identity_acquire_expire(struct file *file,
319                                               const char __user *buffer,
320                                               unsigned long count,
321                                               void *data)
322 {
323         struct obd_device *obd = data;
324         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
325         int rc, val;
326
327         rc = lprocfs_write_helper(buffer, count, &val);
328         if (rc)
329                 return rc;
330
331         mdt->mdt_identity_cache->uc_acquire_expire = val;
332         return count;
333 }
334
335 static int lprocfs_rd_identity_upcall(char *page, char **start, off_t off,
336                                       int count, int *eof, void *data)
337 {
338         struct obd_device *obd = data;
339         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
340         struct upcall_cache *hash = mdt->mdt_identity_cache;
341         int len;
342
343         *eof = 1;
344         read_lock(&hash->uc_upcall_rwlock);
345         len = snprintf(page, count, "%s\n", hash->uc_upcall);
346         read_unlock(&hash->uc_upcall_rwlock);
347         return len;
348 }
349
350 static int lprocfs_wr_identity_upcall(struct file *file,
351                                       const char __user *buffer,
352                                       unsigned long count, void *data)
353 {
354         struct obd_device       *obd = data;
355         struct mdt_device       *mdt = mdt_dev(obd->obd_lu_dev);
356         struct upcall_cache     *hash = mdt->mdt_identity_cache;
357         int                      rc;
358         char                    *kernbuf;
359
360         if (count >= UC_CACHE_UPCALL_MAXPATH) {
361                 CERROR("%s: identity upcall too long\n", mdt_obd_name(mdt));
362                 return -EINVAL;
363         }
364         OBD_ALLOC(kernbuf, count + 1);
365         if (kernbuf == NULL)
366                 GOTO(failed, rc = -ENOMEM);
367         if (copy_from_user(kernbuf, buffer, count))
368                 GOTO(failed, rc = -EFAULT);
369
370         /* Remove any extraneous bits from the upcall (e.g. linefeeds) */
371         write_lock(&hash->uc_upcall_rwlock);
372         sscanf(kernbuf, "%s", hash->uc_upcall);
373         write_unlock(&hash->uc_upcall_rwlock);
374
375         if (strcmp(hash->uc_name, mdt_obd_name(mdt)) != 0)
376                 CWARN("%s: write to upcall name %s\n",
377                       mdt_obd_name(mdt), hash->uc_upcall);
378
379         if (strcmp(hash->uc_upcall, "NONE") == 0 && mdt->mdt_opts.mo_acl)
380                 CWARN("%s: disable \"identity_upcall\" with ACL enabled maybe "
381                       "cause unexpected \"EACCESS\"\n", mdt_obd_name(mdt));
382
383         CDEBUG(D_CONFIG, "%s: identity upcall set to %s\n", mdt_obd_name(mdt),
384                hash->uc_upcall);
385         OBD_FREE(kernbuf, count + 1);
386         RETURN(count);
387
388  failed:
389         if (kernbuf)
390                 OBD_FREE(kernbuf, count + 1);
391         RETURN(rc);
392 }
393
394 static int lprocfs_wr_identity_flush(struct file *file,
395                                      const char __user *buffer,
396                                      unsigned long count, void *data)
397 {
398         struct obd_device *obd = data;
399         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
400         int rc, uid;
401
402         rc = lprocfs_write_helper(buffer, count, &uid);
403         if (rc)
404                 return rc;
405
406         mdt_flush_identity(mdt->mdt_identity_cache, uid);
407         return count;
408 }
409
410 static int lprocfs_wr_identity_info(struct file *file,
411                                     const char __user *buffer,
412                                     unsigned long count, void *data)
413 {
414         struct obd_device *obd = data;
415         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
416         struct identity_downcall_data *param;
417         int size = sizeof(*param), rc, checked = 0;
418
419 again:
420         if (count < size) {
421                 CERROR("%s: invalid data count = %lu, size = %d\n",
422                        mdt_obd_name(mdt), count, size);
423                 return -EINVAL;
424         }
425
426         OBD_ALLOC(param, size);
427         if (param == NULL)
428                 return -ENOMEM;
429
430         if (copy_from_user(param, buffer, size)) {
431                 CERROR("%s: bad identity data\n", mdt_obd_name(mdt));
432                 GOTO(out, rc = -EFAULT);
433         }
434
435         if (checked == 0) {
436                 checked = 1;
437                 if (param->idd_magic != IDENTITY_DOWNCALL_MAGIC) {
438                         CERROR("%s: MDS identity downcall bad params\n",
439                                mdt_obd_name(mdt));
440                         GOTO(out, rc = -EINVAL);
441                 }
442
443                 if (param->idd_nperms > N_PERMS_MAX) {
444                         CERROR("%s: perm count %d more than maximum %d\n",
445                                mdt_obd_name(mdt), param->idd_nperms,
446                                N_PERMS_MAX);
447                         GOTO(out, rc = -EINVAL);
448                 }
449
450                 if (param->idd_ngroups > NGROUPS_MAX) {
451                         CERROR("%s: group count %d more than maximum %d\n",
452                                mdt_obd_name(mdt), param->idd_ngroups,
453                                NGROUPS_MAX);
454                         GOTO(out, rc = -EINVAL);
455                 }
456
457                 if (param->idd_ngroups) {
458                         rc = param->idd_ngroups; /* save idd_ngroups */
459                         OBD_FREE(param, size);
460                         size = offsetof(struct identity_downcall_data,
461                                         idd_groups[rc]);
462                         goto again;
463                 }
464         }
465
466         rc = upcall_cache_downcall(mdt->mdt_identity_cache, param->idd_err,
467                                    param->idd_uid, param);
468
469 out:
470         if (param != NULL)
471                 OBD_FREE(param, size);
472
473         return rc ? rc : count;
474 }
475
476 /* for debug only */
477 static int lprocfs_rd_capa(char *page, char **start, off_t off,
478                            int count, int *eof, void *data)
479 {
480         struct obd_device *obd = data;
481         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
482
483         return snprintf(page, count, "capability on: %s %s\n",
484                         mdt->mdt_lut.lut_oss_capa ? "oss" : "",
485                         mdt->mdt_lut.lut_mds_capa ? "mds" : "");
486 }
487
488 static int lprocfs_wr_capa(struct file *file, const char __user *buffer,
489                            unsigned long count, void *data)
490 {
491         struct obd_device *obd = data;
492         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
493         int val, rc;
494
495         rc = lprocfs_write_helper(buffer, count, &val);
496         if (rc)
497                 return rc;
498
499         if (val < 0 || val > 3) {
500                 CERROR("invalid capability mode, only 0/2/3 is accepted.\n"
501                        " 0:  disable fid capability\n"
502                        " 2:  enable MDS fid capability\n"
503                        " 3:  enable both MDS and OSS fid capability\n");
504                 return -EINVAL;
505         }
506
507         /* OSS fid capability needs enable both MDS and OSS fid capability on
508          * MDS */
509         if (val == 1) {
510                 CERROR("can't enable OSS fid capability only, you should use "
511                        "'3' to enable both MDS and OSS fid capability.\n");
512                 return -EINVAL;
513         }
514
515         spin_lock(&mdt->mdt_lut.lut_flags_lock);
516         mdt->mdt_lut.lut_oss_capa = !!(val & 0x1);
517         mdt->mdt_lut.lut_mds_capa = !!(val & 0x2);
518         spin_unlock(&mdt->mdt_lut.lut_flags_lock);
519         mdt->mdt_capa_conf = 1;
520         LCONSOLE_INFO("MDS %s %s MDS fid capability.\n",
521                       mdt_obd_name(mdt),
522                       mdt->mdt_lut.lut_mds_capa ? "enabled" : "disabled");
523         LCONSOLE_INFO("MDS %s %s OSS fid capability.\n",
524                       mdt_obd_name(mdt),
525                       mdt->mdt_lut.lut_oss_capa ? "enabled" : "disabled");
526         return count;
527 }
528
529 static int lprocfs_rd_capa_count(char *page, char **start, off_t off,
530                                  int count, int *eof, void *data)
531 {
532         return snprintf(page, count, "%d %d\n",
533                         capa_count[CAPA_SITE_CLIENT],
534                         capa_count[CAPA_SITE_SERVER]);
535 }
536
537 static int lprocfs_rd_site_stats(char *page, char **start, off_t off,
538                                  int count, int *eof, void *data)
539 {
540         struct obd_device *obd = data;
541         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
542
543         return lu_site_stats_print(mdt_lu_site(mdt), page, count);
544 }
545
546 static int lprocfs_rd_capa_timeout(char *page, char **start, off_t off,
547                                    int count, int *eof, void *data)
548 {
549         struct obd_device *obd = data;
550         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
551
552         return snprintf(page, count, "%lu\n", mdt->mdt_capa_timeout);
553 }
554
555 static int lprocfs_wr_capa_timeout(struct file *file, const char __user *buffer,
556                                    unsigned long count, void *data)
557 {
558         struct obd_device *obd = data;
559         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
560         int val, rc;
561
562         rc = lprocfs_write_helper(buffer, count, &val);
563         if (rc)
564                 return rc;
565
566         mdt->mdt_capa_timeout = (unsigned long)val;
567         mdt->mdt_capa_conf = 1;
568         return count;
569 }
570
571 static int lprocfs_rd_ck_timeout(char *page, char **start, off_t off, int count,
572                                  int *eof, void *data)
573 {
574         struct obd_device *obd = data;
575         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
576
577         return snprintf(page, count, "%lu\n", mdt->mdt_ck_timeout);
578 }
579
580 static int lprocfs_wr_ck_timeout(struct file *file, const char __user *buffer,
581                                  unsigned long count, void *data)
582 {
583         struct obd_device *obd = data;
584         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
585         int val, rc;
586
587         rc = lprocfs_write_helper(buffer, count, &val);
588         if (rc)
589                 return rc;
590
591         mdt->mdt_ck_timeout = (unsigned long)val;
592         mdt->mdt_capa_conf = 1;
593         return count;
594 }
595
596 #define BUFLEN (UUID_MAX + 4)
597
598 static int lprocfs_mdt_wr_evict_client(struct file *file,
599                                        const char __user *buffer,
600                                        unsigned long count, void *data)
601 {
602         char *kbuf;
603         char *tmpbuf;
604
605         OBD_ALLOC(kbuf, BUFLEN);
606         if (kbuf == NULL)
607                 return -ENOMEM;
608
609         /*
610          * OBD_ALLOC() will zero kbuf, but we only copy BUFLEN - 1
611          * bytes into kbuf, to ensure that the string is NUL-terminated.
612          * UUID_MAX should include a trailing NUL already.
613          */
614         if (copy_from_user(kbuf, buffer,
615                            min_t(unsigned long, BUFLEN - 1, count))) {
616                 count = -EFAULT;
617                 goto out;
618         }
619         tmpbuf = cfs_firststr(kbuf, min_t(unsigned long, BUFLEN - 1, count));
620
621         if (strncmp(tmpbuf, "nid:", 4) != 0) {
622                 count = lprocfs_wr_evict_client(file, buffer, count, data);
623                 goto out;
624         }
625
626         CERROR("NOT implement evict client by nid %s\n", tmpbuf);
627
628 out:
629         OBD_FREE(kbuf, BUFLEN);
630         return count;
631 }
632
633 #undef BUFLEN
634
635 static int lprocfs_rd_sec_level(char *page, char **start, off_t off,
636                                 int count, int *eof, void *data)
637 {
638         struct obd_device *obd = data;
639         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
640
641         return snprintf(page, count, "%d\n", mdt->mdt_lut.lut_sec_level);
642 }
643
644 static int lprocfs_wr_sec_level(struct file *file, const char __user *buffer,
645                                 unsigned long count, void *data)
646 {
647         struct obd_device *obd = data;
648         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
649         int val, rc;
650
651         rc = lprocfs_write_helper(buffer, count, &val);
652         if (rc)
653                 return rc;
654
655         if (val > LUSTRE_SEC_ALL || val < LUSTRE_SEC_NONE)
656                 return -EINVAL;
657
658         if (val == LUSTRE_SEC_SPECIFY) {
659                 CWARN("security level %d will be supported in future.\n",
660                       LUSTRE_SEC_SPECIFY);
661                 return -EINVAL;
662         }
663
664         mdt->mdt_lut.lut_sec_level = val;
665         return count;
666 }
667
668 static int lprocfs_rd_cos(char *page, char **start, off_t off,
669                               int count, int *eof, void *data)
670 {
671         struct obd_device *obd = data;
672         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
673
674         return snprintf(page, count, "%u\n", mdt_cos_is_enabled(mdt));
675 }
676
677 static int lprocfs_wr_cos(struct file *file, const char __user *buffer,
678                           unsigned long count, void *data)
679 {
680         struct obd_device *obd = data;
681         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
682         int val, rc;
683
684         rc = lprocfs_write_helper(buffer, count, &val);
685         if (rc)
686                 return rc;
687         mdt_enable_cos(mdt, val);
688         return count;
689 }
690
691 static int lprocfs_rd_mdt_root_squash(char *page, char **start, off_t off,
692                                       int count, int *eof, void *data)
693 {
694         struct obd_device *obd = data;
695         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
696         struct root_squash_info *squash = &mdt->mdt_squash;
697
698         return snprintf(page, count, "%u:%u\n", squash->rsi_uid,
699                         squash->rsi_gid);
700 }
701
702 static int lprocfs_wr_mdt_root_squash(struct file *file,
703                                       const char __user *buffer,
704                                       unsigned long count, void *data)
705 {
706         struct obd_device *obd = data;
707         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
708         struct root_squash_info *squash = &mdt->mdt_squash;
709
710         return lprocfs_wr_root_squash(buffer, count, squash,
711                                       mdt_obd_name(mdt));
712 }
713
714 static int lprocfs_rd_mdt_nosquash_nids(char *page, char **start, off_t off,
715                                         int count, int *eof, void *data)
716 {
717         struct obd_device *obd = data;
718         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
719         struct root_squash_info *squash = &mdt->mdt_squash;
720         int rc;
721
722         down_read(&squash->rsi_sem);
723         if (!list_empty(&squash->rsi_nosquash_nids)) {
724                 rc = cfs_print_nidlist(page, count, &squash->rsi_nosquash_nids);
725                 rc += snprintf(page + rc, count - rc, "\n");
726         } else
727                 rc = snprintf(page, count, "NONE\n");
728         up_read(&squash->rsi_sem);
729
730         return rc;
731 }
732
733 static int lprocfs_wr_mdt_nosquash_nids(struct file *file,
734                                         const char __user *buffer,
735                                         unsigned long count, void *data)
736 {
737         struct obd_device *obd = data;
738         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
739         struct root_squash_info *squash = &mdt->mdt_squash;
740
741         return lprocfs_wr_nosquash_nids(buffer, count, squash,
742                                         mdt_obd_name(mdt));
743 }
744
745 static int lprocfs_rd_mdt_som(char *page, char **start, off_t off,
746                               int count, int *eof, void *data)
747 {
748         struct obd_device *obd = data;
749         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
750
751         return snprintf(page, count, "%sabled\n",
752                         mdt->mdt_som_conf ? "en" : "dis");
753 }
754
755 static int lprocfs_wr_mdt_som(struct file *file, const char __user *buffer,
756                               unsigned long count, void *data)
757 {
758         struct obd_export *exp;
759         struct obd_device *obd = data;
760         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
761         char kernbuf[16];
762         unsigned long val = 0;
763
764         if (count > (sizeof(kernbuf) - 1))
765                 return -EINVAL;
766
767         if (copy_from_user(kernbuf, buffer, count))
768                 return -EFAULT;
769
770         kernbuf[count] = '\0';
771
772         if (!strcmp(kernbuf, "enabled"))
773                 val = 1;
774         else if (strcmp(kernbuf, "disabled"))
775                 return -EINVAL;
776
777         if (mdt->mdt_som_conf == val)
778                 return count;
779
780         if (!obd->obd_process_conf) {
781                 CERROR("Temporary SOM change is not supported, use lctl "
782                        "conf_param for permanent setting\n");
783                 return count;
784         }
785
786         /* 1 stands for self export. */
787         cfs_list_for_each_entry(exp, &obd->obd_exports, exp_obd_chain) {
788                 if (exp == obd->obd_self_export)
789                         continue;
790                 if (exp_connect_flags(exp) & OBD_CONNECT_MDS_MDS)
791                         continue;
792                 /* Some clients are already connected, skip the change */
793                 LCONSOLE_INFO("%s is already connected, SOM will be %s on "
794                               "the next mount\n", exp->exp_client_uuid.uuid,
795                               val ? "enabled" : "disabled");
796                 return count;
797         }
798
799         mdt->mdt_som_conf = val;
800         LCONSOLE_INFO("Enabling SOM\n");
801
802         return count;
803 }
804
805 static int lprocfs_rd_enable_remote_dir(char *page, char **start, off_t off,
806                                         int count, int *eof, void *data)
807 {
808         struct obd_device *obd = data;
809         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
810
811         return snprintf(page, count, "%u\n", mdt->mdt_enable_remote_dir);
812 }
813
814 static int lprocfs_wr_enable_remote_dir(struct file *file,
815                                         const char __user *buffer,
816                                         unsigned long count, void *data)
817 {
818         struct obd_device *obd = data;
819         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
820         __u32 val;
821         int rc;
822
823         rc = lprocfs_write_helper(buffer, count, &val);
824         if (rc)
825                 return rc;
826
827         if (val > 1)
828                 return -ERANGE;
829
830         mdt->mdt_enable_remote_dir = val;
831         return count;
832 }
833
834 static int lprocfs_rd_enable_remote_dir_gid(char *page, char **start, off_t off,
835                                             int count, int *eof, void *data)
836 {
837         struct obd_device *obd = data;
838         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
839
840         return snprintf(page, count, "%d\n",
841                         (int)mdt->mdt_enable_remote_dir_gid);
842 }
843
844 static int lprocfs_wr_enable_remote_dir_gid(struct file *file,
845                                             const char __user *buffer,
846                                             unsigned long count, void *data)
847 {
848         struct obd_device *obd = data;
849         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
850         __u32 val;
851         int rc;
852
853         rc = lprocfs_write_helper(buffer, count, &val);
854         if (rc)
855                 return rc;
856
857         mdt->mdt_enable_remote_dir_gid = val;
858         return count;
859 }
860
861 static struct lprocfs_vars lprocfs_mdt_obd_vars[] = {
862         { "uuid",                       lprocfs_rd_uuid, NULL,
863                                         NULL, NULL, 0 },
864         { "recovery_status",            lprocfs_obd_rd_recovery_status, NULL,
865                                         NULL, NULL, 0 },
866         { "num_exports",                lprocfs_rd_num_exports, NULL,
867                                         NULL, NULL, 0 },
868         { "identity_expire",            lprocfs_rd_identity_expire,
869                                         lprocfs_wr_identity_expire,
870                                         NULL, NULL, 0 },
871         { "identity_acquire_expire",    lprocfs_rd_identity_acquire_expire,
872                                         lprocfs_wr_identity_acquire_expire,
873                                         NULL, NULL, 0 },
874         { "identity_upcall",            lprocfs_rd_identity_upcall,
875                                         lprocfs_wr_identity_upcall,
876                                         NULL, NULL, 0 },
877         { "identity_flush",             NULL, lprocfs_wr_identity_flush,
878                                         NULL, NULL, 0 },
879         { "identity_info",              NULL, lprocfs_wr_identity_info,
880                                         NULL, NULL, 0 },
881         { "capa",                       lprocfs_rd_capa,
882                                         lprocfs_wr_capa,
883                                         NULL, NULL, 0 },
884         { "capa_timeout",               lprocfs_rd_capa_timeout,
885                                         lprocfs_wr_capa_timeout,
886                                         NULL, NULL, 0 },
887         { "capa_key_timeout",           lprocfs_rd_ck_timeout,
888                                         lprocfs_wr_ck_timeout,
889                                         NULL, NULL, 0 },
890         { "capa_count",                 lprocfs_rd_capa_count, NULL,
891                                         NULL, NULL, 0 },
892         { "site_stats",                 lprocfs_rd_site_stats, NULL,
893                                         NULL, NULL, 0 },
894         { "evict_client",               NULL, lprocfs_mdt_wr_evict_client,
895                                         NULL, NULL, 0 },
896         { "hash_stats",                 lprocfs_obd_rd_hash, NULL,
897                                         NULL, NULL, 0 },
898         { "sec_level",                  lprocfs_rd_sec_level,
899                                         lprocfs_wr_sec_level,
900                                         NULL, NULL, 0 },
901         { "commit_on_sharing",          lprocfs_rd_cos, lprocfs_wr_cos,
902                                         NULL, NULL, 0 },
903         { "root_squash",                lprocfs_rd_mdt_root_squash,
904                                         lprocfs_wr_mdt_root_squash,
905                                         NULL, NULL, 0 },
906         { "nosquash_nids",              lprocfs_rd_mdt_nosquash_nids,
907                                         lprocfs_wr_mdt_nosquash_nids,
908                                         NULL, NULL, 0 },
909         { "som",                        lprocfs_rd_mdt_som,
910                                         lprocfs_wr_mdt_som,
911                                         NULL, NULL, 0 },
912         { "instance",                   lprocfs_target_rd_instance, NULL,
913                                         NULL, NULL, 0},
914         { "ir_factor",                  lprocfs_obd_rd_ir_factor,
915                                         lprocfs_obd_wr_ir_factor,
916                                         NULL, NULL, 0 },
917         { "job_cleanup_interval",       lprocfs_rd_job_interval,
918                                         lprocfs_wr_job_interval,
919                                         NULL, NULL, 0 },
920         { "enable_remote_dir",          lprocfs_rd_enable_remote_dir,
921                                         lprocfs_wr_enable_remote_dir,
922                                         NULL, NULL, 0},
923         { "enable_remote_dir_gid",      lprocfs_rd_enable_remote_dir_gid,
924                                         lprocfs_wr_enable_remote_dir_gid,
925                                         NULL, NULL, 0},
926         { "hsm_control",                lprocfs_rd_hsm_cdt_control,
927                                         lprocfs_wr_hsm_cdt_control,
928                                         NULL, NULL, 0 },
929         { 0 }
930 };
931
932 static struct lprocfs_vars lprocfs_mdt_module_vars[] = {
933         { "num_refs",                   lprocfs_rd_numrefs, NULL,
934                                         NULL, NULL, 0 },
935         { 0 }
936 };
937
938 void lprocfs_mdt_init_vars(struct lprocfs_static_vars *lvars)
939 {
940         lvars->module_vars  = lprocfs_mdt_module_vars;
941         lvars->obd_vars     = lprocfs_mdt_obd_vars;
942 }
943
944 struct lprocfs_vars lprocfs_mds_obd_vars[] = {
945         { "uuid",       lprocfs_rd_uuid, NULL, NULL, NULL, 0 },
946         { 0 }
947 };
948
949 struct lprocfs_vars lprocfs_mds_module_vars[] = {
950         { "num_refs",   lprocfs_rd_numrefs, NULL, NULL, NULL, 0 },
951         { 0 }
952 };
953
954 int lprocfs_mdt_print_open_files(cfs_hash_t *hs, cfs_hash_bd_t *bd,
955                                  cfs_hlist_node_t *hnode, void *v)
956 {
957         struct obd_export       *exp = cfs_hash_object(hs, hnode);
958         struct seq_file         *seq = v;
959
960         if (exp->exp_lock_hash != NULL) {
961                 struct mdt_export_data  *med = &exp->exp_mdt_data;
962                 struct mdt_file_data    *mfd;
963
964                 spin_lock(&med->med_open_lock);
965                 cfs_list_for_each_entry(mfd, &med->med_open_head, mfd_list) {
966                         seq_printf(seq, DFID"\n",
967                                    PFID(mdt_object_fid(mfd->mfd_object)));
968                 }
969                 spin_unlock(&med->med_open_lock);
970         }
971
972         return 0;
973 }
974
975 int lprocfs_mdt_open_files_seq_show(struct seq_file *seq, void *v)
976 {
977         struct nid_stat *stats = seq->private;
978         struct obd_device *obd = stats->nid_obd;
979
980         cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
981                               lprocfs_mdt_print_open_files, seq);
982
983         return 0;
984 }
985
986 int lprocfs_mdt_open_files_seq_open(struct inode *inode, struct file *file)
987 {
988         struct proc_dir_entry   *dp = PDE(inode);
989         struct seq_file         *seq;
990         struct nid_stat         *tmp;
991         int                     rc;
992
993         if (LPROCFS_ENTRY_CHECK(dp))
994                 return -ENOENT;
995
996         tmp = dp->data;
997         rc = single_open(file, &lprocfs_mdt_open_files_seq_show, NULL);
998         if (rc != 0)
999                 return rc;
1000
1001         seq = file->private_data;
1002         seq->private = tmp;
1003
1004         return 0;
1005 }
1006
1007 void mdt_counter_incr(struct ptlrpc_request *req, int opcode)
1008 {
1009         struct obd_export *exp = req->rq_export;
1010
1011         if (exp->exp_obd && exp->exp_obd->obd_md_stats)
1012                 lprocfs_counter_incr(exp->exp_obd->obd_md_stats, opcode);
1013         if (exp->exp_nid_stats && exp->exp_nid_stats->nid_stats != NULL)
1014                 lprocfs_counter_incr(exp->exp_nid_stats->nid_stats, opcode);
1015         if (exp->exp_obd && exp->exp_obd->u.obt.obt_jobstats.ojs_hash &&
1016             (exp_connect_flags(exp) & OBD_CONNECT_JOBSTATS))
1017                 lprocfs_job_stats_log(exp->exp_obd,
1018                                       lustre_msg_get_jobid(req->rq_reqmsg),
1019                                       opcode, 1);
1020 }
1021
1022 void mdt_stats_counter_init(struct lprocfs_stats *stats)
1023 {
1024         lprocfs_counter_init(stats, LPROC_MDT_OPEN, 0, "open", "reqs");
1025         lprocfs_counter_init(stats, LPROC_MDT_CLOSE, 0, "close", "reqs");
1026         lprocfs_counter_init(stats, LPROC_MDT_MKNOD, 0, "mknod", "reqs");
1027         lprocfs_counter_init(stats, LPROC_MDT_LINK, 0, "link", "reqs");
1028         lprocfs_counter_init(stats, LPROC_MDT_UNLINK, 0, "unlink", "reqs");
1029         lprocfs_counter_init(stats, LPROC_MDT_MKDIR, 0, "mkdir", "reqs");
1030         lprocfs_counter_init(stats, LPROC_MDT_RMDIR, 0, "rmdir", "reqs");
1031         lprocfs_counter_init(stats, LPROC_MDT_RENAME, 0, "rename", "reqs");
1032         lprocfs_counter_init(stats, LPROC_MDT_GETATTR, 0, "getattr", "reqs");
1033         lprocfs_counter_init(stats, LPROC_MDT_SETATTR, 0, "setattr", "reqs");
1034         lprocfs_counter_init(stats, LPROC_MDT_GETXATTR, 0, "getxattr", "reqs");
1035         lprocfs_counter_init(stats, LPROC_MDT_SETXATTR, 0, "setxattr", "reqs");
1036         lprocfs_counter_init(stats, LPROC_MDT_STATFS, 0, "statfs", "reqs");
1037         lprocfs_counter_init(stats, LPROC_MDT_SYNC, 0, "sync", "reqs");
1038         lprocfs_counter_init(stats, LPROC_MDT_SAMEDIR_RENAME, 0,
1039                              "samedir_rename", "reqs");
1040         lprocfs_counter_init(stats, LPROC_MDT_CROSSDIR_RENAME, 0,
1041                              "crossdir_rename", "reqs");
1042 }