HEX
Server: LiteSpeed
System: Linux CentOS-79-64-minimal 3.10.0-1160.119.1.el7.x86_64 #1 SMP Tue Jun 4 14:43:51 UTC 2024 x86_64
User: vishn3436 (5293)
PHP: 8.0.15
Disabled: NONE
Upload Files
File: //usr/src/dattobd-0.11.2/proc_seq_file.c
#include "cow_manager.h"
#include "dattobd.h"
#include "includes.h"
#include "ioctl_handlers.h"
#include "module_control.h"
#include "snap_device.h"
#include "tracer_helper.h"

static void *dattobd_proc_start(struct seq_file *m, loff_t *pos);
static void *dattobd_proc_next(struct seq_file *m, void *v, loff_t *pos);
static void dattobd_proc_stop(struct seq_file *m, void *v);
static int dattobd_proc_show(struct seq_file *m, void *v);
static int dattobd_proc_open(struct inode *inode, struct file *filp);
static int dattobd_proc_release(struct inode *inode, struct file *file);

#ifndef HAVE_PROC_OPS
//#if LINUX_VERSION_CODE < KERNEL_VERSION(5,6,0)
static const struct file_operations dattobd_proc_fops = {
        .owner = THIS_MODULE,
        .open = dattobd_proc_open,
        .read = seq_read,
        .llseek = seq_lseek,
        .release = dattobd_proc_release,
};
#else
static const struct proc_ops dattobd_proc_fops = {
        .proc_open = dattobd_proc_open,
        .proc_read = seq_read,
        .proc_lseek = seq_lseek,
        .proc_release = dattobd_proc_release,
};
#endif

static const struct seq_operations dattobd_seq_proc_ops = {
        .start = dattobd_proc_start,
        .next = dattobd_proc_next,
        .stop = dattobd_proc_stop,
        .show = dattobd_proc_show,
};

#ifndef HAVE_PROC_OPS

/**
 * get_proc_fops() - Retrieves a file operations struct pointer
 *
 * Return:
 * The &struct file_operations object pointer.
 */
const struct file_operations* get_proc_fops(void)
{
        return &dattobd_proc_fops;
}

#else // HAVE_PROC_OPS

/**
 * get_proc_fops() - Retrieves a file operations struct pointer
 *
 * Return:
 * The &struct file_operations object pointer.
 */
const struct proc_ops* get_proc_fops(void)
{
        return &dattobd_proc_fops;
}

#endif // HAVE_PROC_OPS

/**
 * dattobd_proc_get_idx() - Turns offset into pointer into @snap_devices array.
 * @pos: An offset into the array of @snap_devices.
 *
 * Return:
 * * NULL - invalid @pos supplied, indicates "past end of file."
 * * !NULL - a void* pointer into the @snap_devices array.
 */
static void *dattobd_proc_get_idx(loff_t pos)
{
        if (pos > highest_minor)
                return NULL;
        return &snap_devices[pos];
}

/**
 * dattobd_proc_start() - Prepares to iterate through the @snap_devices array.
 *
 * @m: Pointer to a seq_file structure.
 * @pos: the previous offset from the last iteration session.
 *
 * Return:
 * * NULL - @pos does not translate to a valid @snap_devices entry.
 * * SEQ_START_TOKEN - A new iteration from the start so print a header first.
 * * otherwise - Pointer into @snap_devices at offset @pos.
 */
static void *dattobd_proc_start(struct seq_file *m, loff_t *pos)
{
        /*
         * Depending on how much we've printed thus far our *_stop() might
         * be called followed by an invocation of this function with a non-
         * zero @pos with the expectation that we continue from where we
         * left off.
         */ 
        if (*pos == 0)
                return SEQ_START_TOKEN;
        return dattobd_proc_get_idx(*pos - 1);
}

/**
 * dattobd_proc_next() - Return the next entry to *_show() and advance @pos.
 *
 * @m: The sequence file structure.
 * @v: The value last returned from *_start() or *_next()
 * @pos: The value passed in represents the position of the next item in
 *       the snap_devices array.  The value returned holds the position that
 *       start() could use to find the next snap_device.
 *
 * Return:
 * * NULL - @pos does not represent a valid entry in @snap_devices.
 * * otherwise - A pointer to the entry to *_show().
 */
static void *dattobd_proc_next(struct seq_file *m, void *v, loff_t *pos)
{
        void *dev = dattobd_proc_get_idx(*pos);
        ++*pos;
        return dev;
}

/** dattobd_proc_stop() - Always called at the end of iterating through the
 *                        @snap_devices array.
 * @m: The sequence file structure.
 * @v: The value last returned from *_start() or *_next()
 *
 * The end of iterating through the array is identified by a NULL return
 * value from either *_start() or *_next().
 */
static void dattobd_proc_stop(struct seq_file *m, void *v)
{
        /* Nothing to do since we're iterating through a global array. */
}

/** dattobd_proc_show() - Outputs information about a @snap_device.  Optionally
 *                        adds header and/or footer.
 * @m: The seq_file structure.
 * @v: The entry supplied from the last call to either *_start() or *_next().
 *
 * Return:
 * Always indicates success with a zero value.
 */
static int dattobd_proc_show(struct seq_file *m, void *v)
{
        struct snap_device **dev_ptr = v;
        struct snap_device *dev = NULL;

        // print the header if the "pointer" really an indication to do so
        if (dev_ptr == SEQ_START_TOKEN) {
                seq_printf(m, "{\n");
                seq_printf(m, "\t\"version\": \"%s\",\n", DATTOBD_VERSION);
                seq_printf(m, "\t\"devices\": [\n");
        }

        // if the pointer is actually a device print it
        if (dev_ptr != SEQ_START_TOKEN && *dev_ptr != NULL) {
                int error;
                dev = *dev_ptr;

                if (dev->sd_minor != lowest_minor)
                        seq_printf(m, ",\n");
                seq_printf(m, "\t\t{\n");
                seq_printf(m, "\t\t\t\"minor\": %u,\n", dev->sd_minor);
                seq_printf(m, "\t\t\t\"cow_file\": \"%s\",\n",
                           dev->sd_cow_path);
                seq_printf(m, "\t\t\t\"block_device\": \"%s\",\n",
                           dev->sd_bdev_path);
                seq_printf(m, "\t\t\t\"max_cache\": %lu,\n",
                           (dev->sd_cache_size) ?
                                   dev->sd_cache_size :
                                   dattobd_cow_max_memory_default);

                if (!test_bit(UNVERIFIED, &dev->sd_state)) {
                        seq_printf(m, "\t\t\t\"fallocate\": %llu,\n",
                                   ((unsigned long long)dev->sd_falloc_size) *
                                           1024 * 1024);

                        if (dev->sd_cow) {
                                int i;
                                seq_printf(
                                        m, "\t\t\t\"seq_id\": %llu,\n",
                                        (unsigned long long)dev->sd_cow->seqid);

                                seq_printf(m, "\t\t\t\"uuid\": \"");
                                for (i = 0; i < COW_UUID_SIZE; i++) {
                                        seq_printf(m, "%02x",
                                                   dev->sd_cow->uuid[i]);
                                }
                                seq_printf(m, "\",\n");

                                if (dev->sd_cow->version > COW_VERSION_0) {
                                        seq_printf(m,
                                                   "\t\t\t\"version\": %llu,\n",
                                                   dev->sd_cow->version);
                                        seq_printf(
                                                m,
                                                "\t\t\t\"nr_changed_blocks\": "
                                                "%llu,\n",
                                                dev->sd_cow->nr_changed_blocks);
                                }
                        }
                }

                error = tracer_read_fail_state(dev);
                if (error)
                        seq_printf(m, "\t\t\t\"error\": %d,\n", error);

                seq_printf(m, "\t\t\t\"state\": %lu\n", dev->sd_state);
                seq_printf(m, "\t\t}");
        }

        // print the footer if there are no devices to print or if this device
        // has the highest minor
        if ((dev_ptr == SEQ_START_TOKEN && lowest_minor > highest_minor) ||
            (dev && dev->sd_minor == highest_minor)) {
                seq_printf(m, "\n\t]\n");
                seq_printf(m, "}\n");
        }

        return 0;
}

static int dattobd_proc_open(struct inode *inode, struct file *filp)
{
        mutex_lock(&ioctl_mutex);
        return seq_open(filp, &dattobd_seq_proc_ops);
}

static int dattobd_proc_release(struct inode *inode, struct file *file)
{
        seq_release(inode, file);
        mutex_unlock(&ioctl_mutex);
        return 0;
}