^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* -*- mode: c; c-basic-offset: 8; -*-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * vim: noexpandtab sw=8 ts=8 sts=0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * filecheck.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Code which implements online file check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (C) 2016 SuSE. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/kmod.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/kobject.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/sysctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <cluster/masklog.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "ocfs2.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include "ocfs2_fs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include "stackglue.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "inode.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include "filecheck.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) /* File check error strings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * must correspond with error number in header file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static const char * const ocfs2_filecheck_errs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) "SUCCESS",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) "FAILED",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) "INPROGRESS",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) "READONLY",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) "INJBD",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) "INVALIDINO",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) "BLOCKECC",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) "BLOCKNO",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) "VALIDFLAG",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) "GENERATION",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) "UNSUPPORTED"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct ocfs2_filecheck_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct list_head fe_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) unsigned long fe_ino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) unsigned int fe_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) unsigned int fe_done:1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) unsigned int fe_status:31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct ocfs2_filecheck_args {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) unsigned int fa_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) unsigned long fa_ino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) unsigned int fa_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static const char *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) ocfs2_filecheck_error(int errno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (!errno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return ocfs2_filecheck_errs[errno];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) BUG_ON(errno < OCFS2_FILECHECK_ERR_START ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) errno > OCFS2_FILECHECK_ERR_END);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return ocfs2_filecheck_errs[errno - OCFS2_FILECHECK_ERR_START + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static ssize_t ocfs2_filecheck_attr_show(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) struct kobj_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) char *buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static ssize_t ocfs2_filecheck_attr_store(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct kobj_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) const char *buf, size_t count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static struct kobj_attribute ocfs2_filecheck_attr_chk =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) __ATTR(check, S_IRUSR | S_IWUSR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) ocfs2_filecheck_attr_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) ocfs2_filecheck_attr_store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static struct kobj_attribute ocfs2_filecheck_attr_fix =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) __ATTR(fix, S_IRUSR | S_IWUSR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) ocfs2_filecheck_attr_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) ocfs2_filecheck_attr_store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static struct kobj_attribute ocfs2_filecheck_attr_set =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) __ATTR(set, S_IRUSR | S_IWUSR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) ocfs2_filecheck_attr_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) ocfs2_filecheck_attr_store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static struct attribute *ocfs2_filecheck_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) &ocfs2_filecheck_attr_chk.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) &ocfs2_filecheck_attr_fix.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) &ocfs2_filecheck_attr_set.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static void ocfs2_filecheck_release(struct kobject *kobj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct ocfs2_filecheck_sysfs_entry *entry = container_of(kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct ocfs2_filecheck_sysfs_entry, fs_kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) complete(&entry->fs_kobj_unregister);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) ocfs2_filecheck_show(struct kobject *kobj, struct attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) ssize_t ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) struct kobj_attribute *kattr = container_of(attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) struct kobj_attribute, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) kobject_get(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (kattr->show)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) ret = kattr->show(kobj, kattr, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) kobject_put(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) ocfs2_filecheck_store(struct kobject *kobj, struct attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) ssize_t ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) struct kobj_attribute *kattr = container_of(attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct kobj_attribute, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) kobject_get(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (kattr->store)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) ret = kattr->store(kobj, kattr, buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) kobject_put(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static const struct sysfs_ops ocfs2_filecheck_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) .show = ocfs2_filecheck_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) .store = ocfs2_filecheck_store,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static struct kobj_type ocfs2_ktype_filecheck = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) .default_attrs = ocfs2_filecheck_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) .sysfs_ops = &ocfs2_filecheck_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) .release = ocfs2_filecheck_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) ocfs2_filecheck_sysfs_free(struct ocfs2_filecheck_sysfs_entry *entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) struct ocfs2_filecheck_entry *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) spin_lock(&entry->fs_fcheck->fc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) while (!list_empty(&entry->fs_fcheck->fc_head)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) p = list_first_entry(&entry->fs_fcheck->fc_head,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) struct ocfs2_filecheck_entry, fe_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) list_del(&p->fe_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) BUG_ON(!p->fe_done); /* To free a undone file check entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) kfree(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) spin_unlock(&entry->fs_fcheck->fc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) kfree(entry->fs_fcheck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) entry->fs_fcheck = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) int ocfs2_filecheck_create_sysfs(struct ocfs2_super *osb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) struct ocfs2_filecheck *fcheck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) struct ocfs2_filecheck_sysfs_entry *entry = &osb->osb_fc_ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) fcheck = kmalloc(sizeof(struct ocfs2_filecheck), GFP_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if (!fcheck)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) INIT_LIST_HEAD(&fcheck->fc_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) spin_lock_init(&fcheck->fc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) fcheck->fc_max = OCFS2_FILECHECK_MINSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) fcheck->fc_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) fcheck->fc_done = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) entry->fs_kobj.kset = osb->osb_dev_kset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) init_completion(&entry->fs_kobj_unregister);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) ret = kobject_init_and_add(&entry->fs_kobj, &ocfs2_ktype_filecheck,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) NULL, "filecheck");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) kobject_put(&entry->fs_kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) kfree(fcheck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) entry->fs_fcheck = fcheck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) void ocfs2_filecheck_remove_sysfs(struct ocfs2_super *osb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (!osb->osb_fc_ent.fs_fcheck)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) kobject_del(&osb->osb_fc_ent.fs_kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) kobject_put(&osb->osb_fc_ent.fs_kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) wait_for_completion(&osb->osb_fc_ent.fs_kobj_unregister);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) ocfs2_filecheck_sysfs_free(&osb->osb_fc_ent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) ocfs2_filecheck_erase_entries(struct ocfs2_filecheck_sysfs_entry *ent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) unsigned int count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) ocfs2_filecheck_adjust_max(struct ocfs2_filecheck_sysfs_entry *ent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) unsigned int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if ((len < OCFS2_FILECHECK_MINSIZE) || (len > OCFS2_FILECHECK_MAXSIZE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) spin_lock(&ent->fs_fcheck->fc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (len < (ent->fs_fcheck->fc_size - ent->fs_fcheck->fc_done)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) mlog(ML_NOTICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) "Cannot set online file check maximum entry number "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) "to %u due to too many pending entries(%u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) len, ent->fs_fcheck->fc_size - ent->fs_fcheck->fc_done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (len < ent->fs_fcheck->fc_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) BUG_ON(!ocfs2_filecheck_erase_entries(ent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) ent->fs_fcheck->fc_size - len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) ent->fs_fcheck->fc_max = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) spin_unlock(&ent->fs_fcheck->fc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) #define OCFS2_FILECHECK_ARGS_LEN 24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) ocfs2_filecheck_args_get_long(const char *buf, size_t count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) unsigned long *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) char buffer[OCFS2_FILECHECK_ARGS_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) memcpy(buffer, buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) buffer[count] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (kstrtoul(buffer, 0, val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) ocfs2_filecheck_type_parse(const char *name, unsigned int *type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (!strncmp(name, "fix", 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) *type = OCFS2_FILECHECK_TYPE_FIX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) else if (!strncmp(name, "check", 6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) *type = OCFS2_FILECHECK_TYPE_CHK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) else if (!strncmp(name, "set", 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) *type = OCFS2_FILECHECK_TYPE_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) ocfs2_filecheck_args_parse(const char *name, const char *buf, size_t count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) struct ocfs2_filecheck_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) unsigned long val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) unsigned int type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) /* too short/long args length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if ((count < 1) || (count >= OCFS2_FILECHECK_ARGS_LEN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (ocfs2_filecheck_type_parse(name, &type))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (ocfs2_filecheck_args_get_long(buf, count, &val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (val <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) args->fa_type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (type == OCFS2_FILECHECK_TYPE_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) args->fa_len = (unsigned int)val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) args->fa_ino = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) static ssize_t ocfs2_filecheck_attr_show(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) struct kobj_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) ssize_t ret = 0, total = 0, remain = PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) unsigned int type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) struct ocfs2_filecheck_entry *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) struct ocfs2_filecheck_sysfs_entry *ent = container_of(kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) struct ocfs2_filecheck_sysfs_entry, fs_kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (ocfs2_filecheck_type_parse(attr->attr.name, &type))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if (type == OCFS2_FILECHECK_TYPE_SET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) spin_lock(&ent->fs_fcheck->fc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) total = snprintf(buf, remain, "%u\n", ent->fs_fcheck->fc_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) spin_unlock(&ent->fs_fcheck->fc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) ret = snprintf(buf, remain, "INO\t\tDONE\tERROR\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) total += ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) remain -= ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) spin_lock(&ent->fs_fcheck->fc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) list_for_each_entry(p, &ent->fs_fcheck->fc_head, fe_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (p->fe_type != type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) ret = snprintf(buf + total, remain, "%lu\t\t%u\t%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) p->fe_ino, p->fe_done,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) ocfs2_filecheck_error(p->fe_status));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (ret >= remain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) /* snprintf() didn't fit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) total = -E2BIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) total += ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) remain -= ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) spin_unlock(&ent->fs_fcheck->fc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) return total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) ocfs2_filecheck_is_dup_entry(struct ocfs2_filecheck_sysfs_entry *ent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) unsigned long ino)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) struct ocfs2_filecheck_entry *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) list_for_each_entry(p, &ent->fs_fcheck->fc_head, fe_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (!p->fe_done) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (p->fe_ino == ino)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) ocfs2_filecheck_erase_entry(struct ocfs2_filecheck_sysfs_entry *ent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) struct ocfs2_filecheck_entry *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) list_for_each_entry(p, &ent->fs_fcheck->fc_head, fe_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (p->fe_done) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) list_del(&p->fe_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) kfree(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) ent->fs_fcheck->fc_size--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) ent->fs_fcheck->fc_done--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) ocfs2_filecheck_erase_entries(struct ocfs2_filecheck_sysfs_entry *ent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) unsigned int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) unsigned int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) unsigned int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) while (i++ < count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if (ocfs2_filecheck_erase_entry(ent))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) ret++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) return (ret == count ? 1 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) ocfs2_filecheck_done_entry(struct ocfs2_filecheck_sysfs_entry *ent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) struct ocfs2_filecheck_entry *entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) spin_lock(&ent->fs_fcheck->fc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) entry->fe_done = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) ent->fs_fcheck->fc_done++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) spin_unlock(&ent->fs_fcheck->fc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) static unsigned int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) ocfs2_filecheck_handle(struct ocfs2_super *osb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) unsigned long ino, unsigned int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) unsigned int ret = OCFS2_FILECHECK_ERR_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) struct inode *inode = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) inode = ocfs2_iget(osb, ino, flags, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if (IS_ERR(inode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) rc = (int)(-(long)inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (rc >= OCFS2_FILECHECK_ERR_START &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) rc < OCFS2_FILECHECK_ERR_END)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) ret = rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) ret = OCFS2_FILECHECK_ERR_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) iput(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) ocfs2_filecheck_handle_entry(struct ocfs2_filecheck_sysfs_entry *ent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) struct ocfs2_filecheck_entry *entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) struct ocfs2_super *osb = container_of(ent, struct ocfs2_super,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) osb_fc_ent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (entry->fe_type == OCFS2_FILECHECK_TYPE_CHK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) entry->fe_status = ocfs2_filecheck_handle(osb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) entry->fe_ino, OCFS2_FI_FLAG_FILECHECK_CHK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) else if (entry->fe_type == OCFS2_FILECHECK_TYPE_FIX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) entry->fe_status = ocfs2_filecheck_handle(osb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) entry->fe_ino, OCFS2_FI_FLAG_FILECHECK_FIX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) entry->fe_status = OCFS2_FILECHECK_ERR_UNSUPPORTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) ocfs2_filecheck_done_entry(ent, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) static ssize_t ocfs2_filecheck_attr_store(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) struct kobj_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) ssize_t ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) struct ocfs2_filecheck_args args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) struct ocfs2_filecheck_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) struct ocfs2_filecheck_sysfs_entry *ent = container_of(kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) struct ocfs2_filecheck_sysfs_entry, fs_kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) if (ocfs2_filecheck_args_parse(attr->attr.name, buf, count, &args))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) if (args.fa_type == OCFS2_FILECHECK_TYPE_SET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) ret = ocfs2_filecheck_adjust_max(ent, args.fa_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) entry = kmalloc(sizeof(struct ocfs2_filecheck_entry), GFP_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) if (!entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) spin_lock(&ent->fs_fcheck->fc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) if (ocfs2_filecheck_is_dup_entry(ent, args.fa_ino)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) ret = -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) kfree(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) } else if ((ent->fs_fcheck->fc_size >= ent->fs_fcheck->fc_max) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) (ent->fs_fcheck->fc_done == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) mlog(ML_NOTICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) "Cannot do more file check "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) "since file check queue(%u) is full now\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) ent->fs_fcheck->fc_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) ret = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) kfree(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) if ((ent->fs_fcheck->fc_size >= ent->fs_fcheck->fc_max) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) (ent->fs_fcheck->fc_done > 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) /* Delete the oldest entry which was done,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) * make sure the entry size in list does
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) * not exceed maximum value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) BUG_ON(!ocfs2_filecheck_erase_entry(ent));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) entry->fe_ino = args.fa_ino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) entry->fe_type = args.fa_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) entry->fe_done = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) entry->fe_status = OCFS2_FILECHECK_ERR_INPROGRESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) list_add_tail(&entry->fe_list, &ent->fs_fcheck->fc_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) ent->fs_fcheck->fc_size++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) spin_unlock(&ent->fs_fcheck->fc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) ocfs2_filecheck_handle_entry(ent, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) return (!ret ? count : ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }