[funini.com] -> [kei@sodan] -> Kernel Reading

root/fs/sysfs/group.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. remove_files
  2. create_files
  3. internal_create_group
  4. sysfs_create_group
  5. sysfs_update_group
  6. sysfs_remove_group

/*
 * fs/sysfs/group.c - Operations for adding/removing multiple files at once.
 *
 * Copyright (c) 2003 Patrick Mochel
 * Copyright (c) 2003 Open Source Development Lab
 *
 * This file is released undert the GPL v2. 
 *
 */

#include <linux/kobject.h>
#include <linux/module.h>
#include <linux/dcache.h>
#include <linux/namei.h>
#include <linux/err.h>
#include "sysfs.h"


static void remove_files(struct sysfs_dirent *dir_sd, struct kobject *kobj,
                         const struct attribute_group *grp)
{
        struct attribute *const* attr;
        int i;

        for (i = 0, attr = grp->attrs; *attr; i++, attr++)
                sysfs_hash_and_remove(dir_sd, (*attr)->name);
}

static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj,
                        const struct attribute_group *grp, int update)
{
        struct attribute *const* attr;
        int error = 0, i;

        for (i = 0, attr = grp->attrs; *attr && !error; i++, attr++) {
                mode_t mode = 0;

                /* in update mode, we're changing the permissions or
                 * visibility.  Do this by first removing then
                 * re-adding (if required) the file */
                if (update)
                        sysfs_hash_and_remove(dir_sd, (*attr)->name);
                if (grp->is_visible) {
                        mode = grp->is_visible(kobj, *attr, i);
                        if (!mode)
                                continue;
                }
                error = sysfs_add_file_mode(dir_sd, *attr, SYSFS_KOBJ_ATTR,
                                            (*attr)->mode | mode);
                if (unlikely(error))
                        break;
        }
        if (error)
                remove_files(dir_sd, kobj, grp);
        return error;
}


static int internal_create_group(struct kobject *kobj, int update,
                                 const struct attribute_group *grp)
{
        struct sysfs_dirent *sd;
        int error;

        BUG_ON(!kobj || (!update && !kobj->sd));

        /* Updates may happen before the object has been instantiated */
        if (unlikely(update && !kobj->sd))
                return -EINVAL;

        if (grp->name) {
                error = sysfs_create_subdir(kobj, grp->name, &sd);
                if (error)
                        return error;
        } else
                sd = kobj->sd;
        sysfs_get(sd);
        error = create_files(sd, kobj, grp, update);
        if (error) {
                if (grp->name)
                        sysfs_remove_subdir(sd);
        }
        sysfs_put(sd);
        return error;
}

/**
 * sysfs_create_group - given a directory kobject, create an attribute group
 * @kobj:       The kobject to create the group on
 * @grp:        The attribute group to create
 *
 * This function creates a group for the first time.  It will explicitly
 * warn and error if any of the attribute files being created already exist.
 *
 * Returns 0 on success or error.
 */
int sysfs_create_group(struct kobject *kobj,
                       const struct attribute_group *grp)
{
        return internal_create_group(kobj, 0, grp);
}

/**
 * sysfs_update_group - given a directory kobject, create an attribute group
 * @kobj:       The kobject to create the group on
 * @grp:        The attribute group to create
 *
 * This function updates an attribute group.  Unlike
 * sysfs_create_group(), it will explicitly not warn or error if any
 * of the attribute files being created already exist.  Furthermore,
 * if the visibility of the files has changed through the is_visible()
 * callback, it will update the permissions and add or remove the
 * relevant files.
 *
 * The primary use for this function is to call it after making a change
 * that affects group visibility.
 *
 * Returns 0 on success or error.
 */
int sysfs_update_group(struct kobject *kobj,
                       const struct attribute_group *grp)
{
        return internal_create_group(kobj, 1, grp);
}



void sysfs_remove_group(struct kobject * kobj, 
                        const struct attribute_group * grp)
{
        struct sysfs_dirent *dir_sd = kobj->sd;
        struct sysfs_dirent *sd;

        if (grp->name) {
                sd = sysfs_get_dirent(dir_sd, grp->name);
                if (!sd) {
                        WARN(!sd, KERN_WARNING "sysfs group %p not found for "
                                "kobject '%s'\n", grp, kobject_name(kobj));
                        return;
                }
        } else
                sd = sysfs_get(dir_sd);

        remove_files(sd, kobj, grp);
        if (grp->name)
                sysfs_remove_subdir(sd);

        sysfs_put(sd);
}


EXPORT_SYMBOL_GPL(sysfs_create_group);
EXPORT_SYMBOL_GPL(sysfs_update_group);
EXPORT_SYMBOL_GPL(sysfs_remove_group);

/* [<][>][^][v][top][bottom][index][help] */

[funini.com] -> [kei@sodan] -> Kernel Reading