/* * A simple attribute can only be 4096 characters. Why 4k? Because the * original code limited it to PAGE_SIZE. That's a bad idea, though, * because an attribute of 16k on ia64 won't work on x86. So we limit to * 4k, our minimum common page size.
*/ #define SIMPLE_ATTR_SIZE 4096
/* we don't support switching read/write modes */ if (buffer->write_in_progress) {
retval = -ETXTBSY; goto out;
}
buffer->read_in_progress = true;
if (buffer->needs_read_fill) { /* perform first read with buf == NULL to get extent */
down_read(&frag->frag_sem); if (!frag->frag_dead)
len = buffer->bin_attr->read(buffer->item, NULL, 0); else
len = -ENOENT;
up_read(&frag->frag_sem); if (len <= 0) {
retval = len; goto out;
}
/* do not exceed the maximum value */ if (buffer->cb_max_size && len > buffer->cb_max_size) {
retval = -EFBIG; goto out;
}
/* Fill @buffer with data coming from @from. */ staticint fill_write_buffer(struct configfs_buffer *buffer, struct iov_iter *from)
{ int copied;
if (!buffer->page)
buffer->page = (char *)__get_free_pages(GFP_KERNEL, 0); if (!buffer->page) return -ENOMEM;
copied = copy_from_iter(buffer->page, SIMPLE_ATTR_SIZE - 1, from);
buffer->needs_read_fill = 1; /* if buf is assumed to contain a string, terminate it by \0,
* so e.g. sscanf() can scan the string easily */
buffer->page[copied] = 0; return copied ? : -EFAULT;
}
staticint
flush_write_buffer(struct file *file, struct configfs_buffer *buffer, size_t count)
{ struct configfs_fragment *frag = to_frag(file); int res = -ENOENT;
down_read(&frag->frag_sem); if (!frag->frag_dead)
res = buffer->attr->store(buffer->item, buffer->page, count);
up_read(&frag->frag_sem); return res;
}
/* * There is no easy way for us to know if userspace is only doing a partial * write, so we don't support them. We expect the entire buffer to come on the * first write. * Hint: if you're writing a value, first read the file, modify only the value * you're changing, then write entire buffer back.
*/ static ssize_t configfs_write_iter(struct kiocb *iocb, struct iov_iter *from)
{ struct file *file = iocb->ki_filp; struct configfs_buffer *buffer = file->private_data; int len;
mutex_lock(&buffer->mutex);
len = fill_write_buffer(buffer, from); if (len > 0)
len = flush_write_buffer(file, buffer, len); if (len > 0)
iocb->ki_pos += len;
mutex_unlock(&buffer->mutex); return len;
}
buffer->owner = attr->ca_owner; /* Grab the module reference for this attribute if we have one */
error = -ENODEV; if (!try_module_get(buffer->owner)) goto out_free_buffer;
error = -EACCES; if (!buffer->item->ci_type) goto out_put_module;
buffer->ops = buffer->item->ci_type->ct_item_ops;
/* File needs write support. * The inode's perms must say it's ok, * and we must have a store method.
*/ if (file->f_mode & FMODE_WRITE) { if (!(inode->i_mode & S_IWUGO)) goto out_put_module; if ((type & CONFIGFS_ITEM_ATTR) && !attr->store) goto out_put_module; if ((type & CONFIGFS_ITEM_BIN_ATTR) && !buffer->bin_attr->write) goto out_put_module;
}
/* File needs read support. * The inode's perms must say it's ok, and we there * must be a show method for it.
*/ if (file->f_mode & FMODE_READ) { if (!(inode->i_mode & S_IRUGO)) goto out_put_module; if ((type & CONFIGFS_ITEM_ATTR) && !attr->show) goto out_put_module; if ((type & CONFIGFS_ITEM_BIN_ATTR) && !buffer->bin_attr->read) goto out_put_module;
}
if (buffer->write_in_progress) { struct configfs_fragment *frag = to_frag(file);
down_read(&frag->frag_sem); if (!frag->frag_dead) { /* result of ->release() is ignored */
buffer->bin_attr->write(buffer->item,
buffer->bin_buffer,
buffer->bin_buffer_size);
}
up_read(&frag->frag_sem);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.