linux/fs/gfs2/sys.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
   3 * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
   4 *
   5 * This copyrighted material is made available to anyone wishing to use,
   6 * modify, copy, or redistribute it subject to the terms and conditions
   7 * of the GNU General Public License version 2.
   8 */
   9
  10#include <linux/sched.h>
  11#include <linux/slab.h>
  12#include <linux/spinlock.h>
  13#include <linux/completion.h>
  14#include <linux/buffer_head.h>
  15#include <linux/module.h>
  16#include <linux/kobject.h>
  17#include <linux/gfs2_ondisk.h>
  18#include <linux/lm_interface.h>
  19#include <asm/uaccess.h>
  20
  21#include "gfs2.h"
  22#include "incore.h"
  23#include "sys.h"
  24#include "super.h"
  25#include "glock.h"
  26#include "quota.h"
  27#include "util.h"
  28
  29char *gfs2_sys_margs;
  30spinlock_t gfs2_sys_margs_lock;
  31
  32static ssize_t id_show(struct gfs2_sbd *sdp, char *buf)
  33{
  34        return snprintf(buf, PAGE_SIZE, "%u:%u\n",
  35                        MAJOR(sdp->sd_vfs->s_dev), MINOR(sdp->sd_vfs->s_dev));
  36}
  37
  38static ssize_t fsname_show(struct gfs2_sbd *sdp, char *buf)
  39{
  40        return snprintf(buf, PAGE_SIZE, "%s\n", sdp->sd_fsname);
  41}
  42
  43static ssize_t freeze_show(struct gfs2_sbd *sdp, char *buf)
  44{
  45        unsigned int count;
  46
  47        mutex_lock(&sdp->sd_freeze_lock);
  48        count = sdp->sd_freeze_count;
  49        mutex_unlock(&sdp->sd_freeze_lock);
  50
  51        return snprintf(buf, PAGE_SIZE, "%u\n", count);
  52}
  53
  54static ssize_t freeze_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
  55{
  56        ssize_t ret = len;
  57        int error = 0;
  58        int n = simple_strtol(buf, NULL, 0);
  59
  60        if (!capable(CAP_SYS_ADMIN))
  61                return -EACCES;
  62
  63        switch (n) {
  64        case 0:
  65                gfs2_unfreeze_fs(sdp);
  66                break;
  67        case 1:
  68                error = gfs2_freeze_fs(sdp);
  69                break;
  70        default:
  71                ret = -EINVAL;
  72        }
  73
  74        if (error)
  75                fs_warn(sdp, "freeze %d error %d", n, error);
  76
  77        return ret;
  78}
  79
  80static ssize_t withdraw_show(struct gfs2_sbd *sdp, char *buf)
  81{
  82        unsigned int b = test_bit(SDF_SHUTDOWN, &sdp->sd_flags);
  83        return snprintf(buf, PAGE_SIZE, "%u\n", b);
  84}
  85
  86static ssize_t withdraw_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
  87{
  88        if (!capable(CAP_SYS_ADMIN))
  89                return -EACCES;
  90
  91        if (simple_strtol(buf, NULL, 0) != 1)
  92                return -EINVAL;
  93
  94        gfs2_lm_withdraw(sdp,
  95                "GFS2: fsid=%s: withdrawing from cluster at user's request\n",
  96                sdp->sd_fsname);
  97        return len;
  98}
  99
 100static ssize_t statfs_sync_store(struct gfs2_sbd *sdp, const char *buf,
 101                                 size_t len)
 102{
 103        if (!capable(CAP_SYS_ADMIN))
 104                return -EACCES;
 105
 106        if (simple_strtol(buf, NULL, 0) != 1)
 107                return -EINVAL;
 108
 109        gfs2_statfs_sync(sdp);
 110        return len;
 111}
 112
 113static ssize_t quota_sync_store(struct gfs2_sbd *sdp, const char *buf,
 114                                size_t len)
 115{
 116        if (!capable(CAP_SYS_ADMIN))
 117                return -EACCES;
 118
 119        if (simple_strtol(buf, NULL, 0) != 1)
 120                return -EINVAL;
 121
 122        gfs2_quota_sync(sdp);
 123        return len;
 124}
 125
 126static ssize_t quota_refresh_user_store(struct gfs2_sbd *sdp, const char *buf,
 127                                        size_t len)
 128{
 129        u32 id;
 130
 131        if (!capable(CAP_SYS_ADMIN))
 132                return -EACCES;
 133
 134        id = simple_strtoul(buf, NULL, 0);
 135
 136        gfs2_quota_refresh(sdp, 1, id);
 137        return len;
 138}
 139
 140static ssize_t quota_refresh_group_store(struct gfs2_sbd *sdp, const char *buf,
 141                                         size_t len)
 142{
 143        u32 id;
 144
 145        if (!capable(CAP_SYS_ADMIN))
 146                return -EACCES;
 147
 148        id = simple_strtoul(buf, NULL, 0);
 149
 150        gfs2_quota_refresh(sdp, 0, id);
 151        return len;
 152}
 153
 154struct gfs2_attr {
 155        struct attribute attr;
 156        ssize_t (*show)(struct gfs2_sbd *, char *);
 157        ssize_t (*store)(struct gfs2_sbd *, const char *, size_t);
 158};
 159
 160#define GFS2_ATTR(name, mode, show, store) \
 161static struct gfs2_attr gfs2_attr_##name = __ATTR(name, mode, show, store)
 162
 163GFS2_ATTR(id,                  0444, id_show,       NULL);
 164GFS2_ATTR(fsname,              0444, fsname_show,   NULL);
 165GFS2_ATTR(freeze,              0644, freeze_show,   freeze_store);
 166GFS2_ATTR(withdraw,            0644, withdraw_show, withdraw_store);
 167GFS2_ATTR(statfs_sync,         0200, NULL,          statfs_sync_store);
 168GFS2_ATTR(quota_sync,          0200, NULL,          quota_sync_store);
 169GFS2_ATTR(quota_refresh_user,  0200, NULL,          quota_refresh_user_store);
 170GFS2_ATTR(quota_refresh_group, 0200, NULL,          quota_refresh_group_store);
 171
 172static struct attribute *gfs2_attrs[] = {
 173        &gfs2_attr_id.attr,
 174        &gfs2_attr_fsname.attr,
 175        &gfs2_attr_freeze.attr,
 176        &gfs2_attr_withdraw.attr,
 177        &gfs2_attr_statfs_sync.attr,
 178        &gfs2_attr_quota_sync.attr,
 179        &gfs2_attr_quota_refresh_user.attr,
 180        &gfs2_attr_quota_refresh_group.attr,
 181        NULL,
 182};
 183
 184static ssize_t gfs2_attr_show(struct kobject *kobj, struct attribute *attr,
 185                              char *buf)
 186{
 187        struct gfs2_sbd *sdp = container_of(kobj, struct gfs2_sbd, sd_kobj);
 188        struct gfs2_attr *a = container_of(attr, struct gfs2_attr, attr);
 189        return a->show ? a->show(sdp, buf) : 0;
 190}
 191
 192static ssize_t gfs2_attr_store(struct kobject *kobj, struct attribute *attr,
 193                               const char *buf, size_t len)
 194{
 195        struct gfs2_sbd *sdp = container_of(kobj, struct gfs2_sbd, sd_kobj);
 196        struct gfs2_attr *a = container_of(attr, struct gfs2_attr, attr);
 197        return a->store ? a->store(sdp, buf, len) : len;
 198}
 199
 200static struct sysfs_ops gfs2_attr_ops = {
 201        .show  = gfs2_attr_show,
 202        .store = gfs2_attr_store,
 203};
 204
 205static struct kobj_type gfs2_ktype = {
 206        .default_attrs = gfs2_attrs,
 207        .sysfs_ops     = &gfs2_attr_ops,
 208};
 209
 210static struct kset *gfs2_kset;
 211
 212/*
 213 * display struct lm_lockstruct fields
 214 */
 215
 216struct lockstruct_attr {
 217        struct attribute attr;
 218        ssize_t (*show)(struct gfs2_sbd *, char *);
 219};
 220
 221#define LOCKSTRUCT_ATTR(name, fmt)                                          \
 222static ssize_t name##_show(struct gfs2_sbd *sdp, char *buf)                 \
 223{                                                                           \
 224        return snprintf(buf, PAGE_SIZE, fmt, sdp->sd_lockstruct.ls_##name); \
 225}                                                                           \
 226static struct lockstruct_attr lockstruct_attr_##name = __ATTR_RO(name)
 227
 228LOCKSTRUCT_ATTR(jid,      "%u\n");
 229LOCKSTRUCT_ATTR(first,    "%u\n");
 230LOCKSTRUCT_ATTR(lvb_size, "%u\n");
 231LOCKSTRUCT_ATTR(flags,    "%d\n");
 232
 233static struct attribute *lockstruct_attrs[] = {
 234        &lockstruct_attr_jid.attr,
 235        &lockstruct_attr_first.attr,
 236        &lockstruct_attr_lvb_size.attr,
 237        &lockstruct_attr_flags.attr,
 238        NULL,
 239};
 240
 241/*
 242 * display struct gfs2_args fields
 243 */
 244
 245struct args_attr {
 246        struct attribute attr;
 247        ssize_t (*show)(struct gfs2_sbd *, char *);
 248};
 249
 250#define ARGS_ATTR(name, fmt)                                                \
 251static ssize_t name##_show(struct gfs2_sbd *sdp, char *buf)                 \
 252{                                                                           \
 253        return snprintf(buf, PAGE_SIZE, fmt, sdp->sd_args.ar_##name);       \
 254}                                                                           \
 255static struct args_attr args_attr_##name = __ATTR_RO(name)
 256
 257ARGS_ATTR(lockproto,       "%s\n");
 258ARGS_ATTR(locktable,       "%s\n");
 259ARGS_ATTR(hostdata,        "%s\n");
 260ARGS_ATTR(spectator,       "%d\n");
 261ARGS_ATTR(ignore_local_fs, "%d\n");
 262ARGS_ATTR(localcaching,    "%d\n");
 263ARGS_ATTR(localflocks,     "%d\n");
 264ARGS_ATTR(debug,           "%d\n");
 265ARGS_ATTR(upgrade,         "%d\n");
 266ARGS_ATTR(num_glockd,      "%u\n");
 267ARGS_ATTR(posix_acl,       "%d\n");
 268ARGS_ATTR(quota,           "%u\n");
 269ARGS_ATTR(suiddir,         "%d\n");
 270ARGS_ATTR(data,            "%d\n");
 271
 272static struct attribute *args_attrs[] = {
 273        &args_attr_lockproto.attr,
 274        &args_attr_locktable.attr,
 275        &args_attr_hostdata.attr,
 276        &args_attr_spectator.attr,
 277        &args_attr_ignore_local_fs.attr,
 278        &args_attr_localcaching.attr,
 279        &args_attr_localflocks.attr,
 280        &args_attr_debug.attr,
 281        &args_attr_upgrade.attr,
 282        &args_attr_num_glockd.attr,
 283        &args_attr_posix_acl.attr,
 284        &args_attr_quota.attr,
 285        &args_attr_suiddir.attr,
 286        &args_attr_data.attr,
 287        NULL,
 288};
 289
 290/*
 291 * display counters from superblock
 292 */
 293
 294struct counters_attr {
 295        struct attribute attr;
 296        ssize_t (*show)(struct gfs2_sbd *, char *);
 297};
 298
 299#define COUNTERS_ATTR(name, fmt)                                            \
 300static ssize_t name##_show(struct gfs2_sbd *sdp, char *buf)                 \
 301{                                                                           \
 302        return snprintf(buf, PAGE_SIZE, fmt,                                \
 303                        (unsigned int)atomic_read(&sdp->sd_##name));        \
 304}                                                                           \
 305static struct counters_attr counters_attr_##name = __ATTR_RO(name)
 306
 307COUNTERS_ATTR(reclaimed,        "%u\n");
 308
 309static struct attribute *counters_attrs[] = {
 310        &counters_attr_reclaimed.attr,
 311        NULL,
 312};
 313
 314/*
 315 * get and set struct gfs2_tune fields
 316 */
 317
 318static ssize_t quota_scale_show(struct gfs2_sbd *sdp, char *buf)
 319{
 320        return snprintf(buf, PAGE_SIZE, "%u %u\n",
 321                        sdp->sd_tune.gt_quota_scale_num,
 322                        sdp->sd_tune.gt_quota_scale_den);
 323}
 324
 325static ssize_t quota_scale_store(struct gfs2_sbd *sdp, const char *buf,
 326                                 size_t len)
 327{
 328        struct gfs2_tune *gt = &sdp->sd_tune;
 329        unsigned int x, y;
 330
 331        if (!capable(CAP_SYS_ADMIN))
 332                return -EACCES;
 333
 334        if (sscanf(buf, "%u %u", &x, &y) != 2 || !y)
 335                return -EINVAL;
 336
 337        spin_lock(&gt->gt_spin);
 338        gt->gt_quota_scale_num = x;
 339        gt->gt_quota_scale_den = y;
 340        spin_unlock(&gt->gt_spin);
 341        return len;
 342}
 343
 344static ssize_t tune_set(struct gfs2_sbd *sdp, unsigned int *field,
 345                        int check_zero, const char *buf, size_t len)
 346{
 347        struct gfs2_tune *gt = &sdp->sd_tune;
 348        unsigned int x;
 349
 350        if (!capable(CAP_SYS_ADMIN))
 351                return -EACCES;
 352
 353        x = simple_strtoul(buf, NULL, 0);
 354
 355        if (check_zero && !x)
 356                return -EINVAL;
 357
 358        spin_lock(&gt->gt_spin);
 359        *field = x;
 360        spin_unlock(&gt->gt_spin);
 361        return len;
 362}
 363
 364struct tune_attr {
 365        struct attribute attr;
 366        ssize_t (*show)(struct gfs2_sbd *, char *);
 367        ssize_t (*store)(struct gfs2_sbd *, const char *, size_t);
 368};
 369
 370#define TUNE_ATTR_3(name, show, store)                                        \
 371static struct tune_attr tune_attr_##name = __ATTR(name, 0644, show, store)
 372
 373#define TUNE_ATTR_2(name, store)                                              \
 374static ssize_t name##_show(struct gfs2_sbd *sdp, char *buf)                   \
 375{                                                                             \
 376        return snprintf(buf, PAGE_SIZE, "%u\n", sdp->sd_tune.gt_##name);      \
 377}                                                                             \
 378TUNE_ATTR_3(name, name##_show, store)
 379
 380#define TUNE_ATTR(name, check_zero)                                           \
 381static ssize_t name##_store(struct gfs2_sbd *sdp, const char *buf, size_t len)\
 382{                                                                             \
 383        return tune_set(sdp, &sdp->sd_tune.gt_##name, check_zero, buf, len);  \
 384}                                                                             \
 385TUNE_ATTR_2(name, name##_store)
 386
 387#define TUNE_ATTR_DAEMON(name, process)                                       \
 388static ssize_t name##_store(struct gfs2_sbd *sdp, const char *buf, size_t len)\
 389{                                                                             \
 390        ssize_t r = tune_set(sdp, &sdp->sd_tune.gt_##name, 1, buf, len);      \
 391        wake_up_process(sdp->sd_##process);                                   \
 392        return r;                                                             \
 393}                                                                             \
 394TUNE_ATTR_2(name, name##_store)
 395
 396TUNE_ATTR(demote_secs, 0);
 397TUNE_ATTR(incore_log_blocks, 0);
 398TUNE_ATTR(log_flush_secs, 0);
 399TUNE_ATTR(quota_warn_period, 0);
 400TUNE_ATTR(quota_quantum, 0);
 401TUNE_ATTR(max_readahead, 0);
 402TUNE_ATTR(complain_secs, 0);
 403TUNE_ATTR(statfs_slow, 0);
 404TUNE_ATTR(new_files_jdata, 0);
 405TUNE_ATTR(quota_simul_sync, 1);
 406TUNE_ATTR(quota_cache_secs, 1);
 407TUNE_ATTR(stall_secs, 1);
 408TUNE_ATTR(statfs_quantum, 1);
 409TUNE_ATTR_DAEMON(recoverd_secs, recoverd_process);
 410TUNE_ATTR_DAEMON(logd_secs, logd_process);
 411TUNE_ATTR_DAEMON(quotad_secs, quotad_process);
 412TUNE_ATTR_3(quota_scale, quota_scale_show, quota_scale_store);
 413
 414static struct attribute *tune_attrs[] = {
 415        &tune_attr_demote_secs.attr,
 416        &tune_attr_incore_log_blocks.attr,
 417        &tune_attr_log_flush_secs.attr,
 418        &tune_attr_quota_warn_period.attr,
 419        &tune_attr_quota_quantum.attr,
 420        &tune_attr_max_readahead.attr,
 421        &tune_attr_complain_secs.attr,
 422        &tune_attr_statfs_slow.attr,
 423        &tune_attr_quota_simul_sync.attr,
 424        &tune_attr_quota_cache_secs.attr,
 425        &tune_attr_stall_secs.attr,
 426        &tune_attr_statfs_quantum.attr,
 427        &tune_attr_recoverd_secs.attr,
 428        &tune_attr_logd_secs.attr,
 429        &tune_attr_quotad_secs.attr,
 430        &tune_attr_quota_scale.attr,
 431        &tune_attr_new_files_jdata.attr,
 432        NULL,
 433};
 434
 435static struct attribute_group lockstruct_group = {
 436        .name = "lockstruct",
 437        .attrs = lockstruct_attrs,
 438};
 439
 440static struct attribute_group counters_group = {
 441        .name = "counters",
 442        .attrs = counters_attrs,
 443};
 444
 445static struct attribute_group args_group = {
 446        .name = "args",
 447        .attrs = args_attrs,
 448};
 449
 450static struct attribute_group tune_group = {
 451        .name = "tune",
 452        .attrs = tune_attrs,
 453};
 454
 455int gfs2_sys_fs_add(struct gfs2_sbd *sdp)
 456{
 457        int error;
 458
 459        sdp->sd_kobj.kset = gfs2_kset;
 460        error = kobject_init_and_add(&sdp->sd_kobj, &gfs2_ktype, NULL,
 461                                     "%s", sdp->sd_table_name);
 462        if (error)
 463                goto fail;
 464
 465        error = sysfs_create_group(&sdp->sd_kobj, &lockstruct_group);
 466        if (error)
 467                goto fail_reg;
 468
 469        error = sysfs_create_group(&sdp->sd_kobj, &counters_group);
 470        if (error)
 471                goto fail_lockstruct;
 472
 473        error = sysfs_create_group(&sdp->sd_kobj, &args_group);
 474        if (error)
 475                goto fail_counters;
 476
 477        error = sysfs_create_group(&sdp->sd_kobj, &tune_group);
 478        if (error)
 479                goto fail_args;
 480
 481        kobject_uevent(&sdp->sd_kobj, KOBJ_ADD);
 482        return 0;
 483
 484fail_args:
 485        sysfs_remove_group(&sdp->sd_kobj, &args_group);
 486fail_counters:
 487        sysfs_remove_group(&sdp->sd_kobj, &counters_group);
 488fail_lockstruct:
 489        sysfs_remove_group(&sdp->sd_kobj, &lockstruct_group);
 490fail_reg:
 491        kobject_put(&sdp->sd_kobj);
 492fail:
 493        fs_err(sdp, "error %d adding sysfs files", error);
 494        return error;
 495}
 496
 497void gfs2_sys_fs_del(struct gfs2_sbd *sdp)
 498{
 499        sysfs_remove_group(&sdp->sd_kobj, &tune_group);
 500        sysfs_remove_group(&sdp->sd_kobj, &args_group);
 501        sysfs_remove_group(&sdp->sd_kobj, &counters_group);
 502        sysfs_remove_group(&sdp->sd_kobj, &lockstruct_group);
 503        kobject_put(&sdp->sd_kobj);
 504}
 505
 506int gfs2_sys_init(void)
 507{
 508        gfs2_sys_margs = NULL;
 509        spin_lock_init(&gfs2_sys_margs_lock);
 510        gfs2_kset = kset_create_and_add("gfs2", NULL, fs_kobj);
 511        if (!gfs2_kset)
 512                return -ENOMEM;
 513        return 0;
 514}
 515
 516void gfs2_sys_uninit(void)
 517{
 518        kfree(gfs2_sys_margs);
 519        kset_unregister(gfs2_kset);
 520}
 521
 522
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.