示例#1
0
/**
 *  \<\<private\>\> Helper callback method when filling the entry's
 * pathname The entry fills in its name and the '/' as prefix to the
 * current end of the buffer.
 *
 * @param *self - pointer to this instance
 * @param *buf_data - buffer data that contain pointer to the buffer and
 *                    its current length.
 */
static void tcmi_ctlfs_add_path(struct tcmi_ctlfs_entry *self, void *buf_data)
{
    struct {
        char *buffer;
        int length;
    } *buf = buf_data;

    int cur = strlen(tcmi_ctlfs_entry_name(self));
    mdbg(INFO4, "Adding.. %s, buffer length=%d", tcmi_ctlfs_entry_name(self), buf->length);

    /* back up enough to print entry name with '/' prefix */
    buf->length -= cur;
    strncpy(buf->buffer + buf->length, tcmi_ctlfs_entry_name(self), cur);
    *(buf->buffer + --(buf->length)) = '/';

    mdbg(INFO4, "New buffer length=%d", buf->length);
}
示例#2
0
/**
 *  \<\<private\>\> This private method is responsible for freeing any
 * resources the entry is currently using(currently nothing). When
 * possible the child class is also notified.  The instance is
 * eventually destroyed.
 *
 * @param *self - pointer to this instance
 * @return 0
 */
static inline void tcmi_ctlfs_entry_release(struct tcmi_ctlfs_entry *self)
{
    mdbg(INFO4, "entry '%s' is being freed(%p)",
         tcmi_ctlfs_entry_name(self), self);
    /* free child class instance data? */
    if (self->entry_ops && self->entry_ops->entry_release) {
        self->entry_ops->entry_release(self);
    }

    kfree(self);
}
示例#3
0
/**
 * \<\<public\>\> This method is used when initializing a new entry.
 * It follows these steps:
 *
 * - converts the nameformat string and the args into a regular string
 * This will be the name assigned to the dentry
 * - checks whether we have a valid parent directory
 * - check whether an entry with the same name already exists
 * in the parent directory entry(if so, an error is returned)
 * - creates a new inode with the specified super block and operations
 * - creates a new dentry associated with the inode.
 * - sets a entry_operations specific to this particular entry type
 * This supports polymorphism.
 *
 * @param *self - pointer to this instance
 * @param *parent - pointer to the parent entry - has to be a directory
 * @param *mode - file type and access rights for the inode
 * @param *entry_ops - custom operations of the child class
 * @param *i_ops - inode operations
 * @param *f_ops - file operations(also stored in the new inode)
 * @param namefmt - nameformat string (printf style)
 * @param args - arguments to the format string
 * @return 0 upon success
 */
int tcmi_ctlfs_entry_init(struct tcmi_ctlfs_entry *self,
                          struct tcmi_ctlfs_entry *parent,
                          mode_t mode,
                          struct tcmi_ctlfs_ops *entry_ops,
                          const struct inode_operations *i_ops,
                          const struct file_operations *f_ops,
                          const char namefmt[], va_list args)
{
    struct inode *dir;
    struct inode *inode;

    vsnprintf(self->name, sizeof(self->name), namefmt, args);
    mdbg(INFO4, "Initializing a new tcmi_ctlfs_entry, '%s'(%p)", self->name, self);
    if (!parent) {
        mdbg(ERR4, "Can't initialized new entry '%s', no parent specified! ", self->name);
        goto exit0;
    }
    mdbg(INFO4, "Parent entry='%s'", tcmi_ctlfs_entry_name(parent));
    /* */
    dir = parent->dentry->d_inode;
    if (!S_ISDIR(dir->i_mode)) {
        mdbg(ERR3, "Can't initialize new entry '%s', parent entry is not a directory!", self->name);
        goto exit0;
    }


    /* check parent for an entry with 'name' */
    if (tcmi_ctlfs_entry_exists(parent, self->name)) {
        mdbg(ERR3,"Can't initialize new entry '%s', parent entry contains an entry of the same name!",
             self->name);
        goto exit0;
    }

    /* allocate a new inode */
    if (!(inode = tcmi_ctlfs_get_inode(dir, dir->i_sb, mode, i_ops, f_ops))) {
        mdbg(ERR3, "Failed to allocate an inode for '%s'", self->name);
        goto exit0;
    }
    /* allocate a new dentry, associated with the inode */
    if (tcmi_ctlfs_entry_alloc_dentry(self, parent, inode)) {
        mdbg(ERR3, "Failed to allocate a new dentry for %s", self->name);
        goto exit1;
    }
    /* Custom operations of the child class */
    self->entry_ops = entry_ops;
    d_set_d_op(self->dentry, self->dentry->d_op);		//Fix for new kernel, this function set dentry->flags according to dentry->op | by Jiri Rakosnik
    return 0;
    /* error handling */
exit1:
    iput(inode);
exit0:
    return -ENOSPC;
}
示例#4
0
/**
 *  \<\<private\>\> Helper callback function when calculating entry
 *  pathname length.
 *
 * @param *self - pointer to this instance
 * @param *curr_length - pointer to the current length
 */
static void tcmi_ctlfs_add_length(struct tcmi_ctlfs_entry *self, void *curr_length)
{
    /* + 1 accounts for '/' */
    (*((int *)curr_length)) += strlen(tcmi_ctlfs_entry_name(self)) + 1;
}
示例#5
0
/** 
 * \<\<private\>\> This method is used to free the data associated with the
 * symlink. The target entry's reference is decremented as
 * the symlink doesn't need the target entry anymore.
 * 
 * @param *entry - points to the symlink that is to be freed
 * @return 0 upon success
 */
static void tcmi_ctlfs_symlink_release(struct tcmi_ctlfs_entry *entry)
{
	struct tcmi_ctlfs_symlink *symlink = TCMI_CTLFS_SYMLINK(entry);
	mdbg(INFO3, "Target entry '%s' released", tcmi_ctlfs_entry_name(symlink->target_entry));
	tcmi_ctlfs_entry_put(symlink->target_entry);
}