-static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n,
- loff_t * pos)
-{
- struct yaffs_obj *obj;
- int n_written, ipos;
- struct inode *inode;
- struct yaffs_dev *dev;
-
- obj = yaffs_dentry_to_obj(f->f_dentry);
-
- dev = obj->my_dev;
-
- yaffs_gross_lock(dev);
-
- inode = f->f_dentry->d_inode;
-
- if (!S_ISBLK(inode->i_mode) && f->f_flags & O_APPEND)
- ipos = inode->i_size;
- else
- ipos = *pos;
-
- if (!obj)
- T(YAFFS_TRACE_OS,
- (TSTR("yaffs_file_write: hey obj is null!\n")));
- else
- T(YAFFS_TRACE_OS,
- (TSTR("yaffs_file_write about to write writing %u(%x) bytes"
- "to object %d at %d(%x)\n"),
- (unsigned)n, (unsigned)n, obj->obj_id, ipos, ipos));
-
- n_written = yaffs_wr_file(obj, buf, ipos, n, 0);
-
- yaffs_touch_super(dev);
-
- T(YAFFS_TRACE_OS,
- (TSTR("yaffs_file_write: %d(%x) bytes written\n"),
- (unsigned)n, (unsigned)n));
-
- if (n_written > 0) {
- ipos += n_written;
- *pos = ipos;
- if (ipos > inode->i_size) {
- inode->i_size = ipos;
- inode->i_blocks = (ipos + 511) >> 9;
-
- T(YAFFS_TRACE_OS,
- (TSTR("yaffs_file_write size updated to %d bytes, "
- "%d blocks\n"), ipos, (int)(inode->i_blocks)));
- }
-
- }
- yaffs_gross_unlock(dev);
- return (n_written == 0) && (n > 0) ? -ENOSPC : n_written;
-}
-
-/* Space holding and freeing is done to ensure we have space available for write_begin/end */
-/* For now we just assume few parallel writes and check against a small number. */
-/* Todo: need to do this with a counter to handle parallel reads better */
-
-static ssize_t yaffs_hold_space(struct file *f)
-{
- struct yaffs_obj *obj;
- struct yaffs_dev *dev;
-
- int n_free_chunks;
-
- obj = yaffs_dentry_to_obj(f->f_dentry);
-
- dev = obj->my_dev;
-
- yaffs_gross_lock(dev);
-
- n_free_chunks = yaffs_get_n_free_chunks(dev);
-
- yaffs_gross_unlock(dev);
-
- return (n_free_chunks > 20) ? 1 : 0;
-}
-
-static void yaffs_release_space(struct file *f)
-{
- struct yaffs_obj *obj;
- struct yaffs_dev *dev;
-
- obj = yaffs_dentry_to_obj(f->f_dentry);
-
- dev = obj->my_dev;
-
- yaffs_gross_lock(dev);
-
- yaffs_gross_unlock(dev);
-}
-
-static loff_t yaffs_dir_llseek(struct file *file, loff_t offset, int origin)
-{
- long long retval;
-
- lock_kernel();
-
- switch (origin) {
- case 2:
- offset += i_size_read(file->f_path.dentry->d_inode);
- break;
- case 1:
- offset += file->f_pos;
- }
- retval = -EINVAL;
-
- if (offset >= 0) {
- if (offset != file->f_pos)
- file->f_pos = offset;
-
- retval = offset;
- }
- unlock_kernel();
- return retval;
-}
-
-static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
-{
- struct yaffs_obj *obj;
- struct yaffs_dev *dev;
- struct yaffs_search_context *sc;
- struct inode *inode = f->f_dentry->d_inode;
- unsigned long offset, curoffs;
- struct yaffs_obj *l;
- int ret_val = 0;
-
- char name[YAFFS_MAX_NAME_LENGTH + 1];
-
- obj = yaffs_dentry_to_obj(f->f_dentry);
- dev = obj->my_dev;
-
- yaffs_gross_lock(dev);
-
- yaffs_dev_to_lc(dev)->readdir_process = current;
-
- offset = f->f_pos;
-
- sc = yaffs_new_search(obj);
- if (!sc) {
- ret_val = -ENOMEM;
- goto out;
- }
-
- T(YAFFS_TRACE_OS,
- (TSTR("yaffs_readdir: starting at %d\n"), (int)offset));
-
- if (offset == 0) {
- T(YAFFS_TRACE_OS,
- (TSTR("yaffs_readdir: entry . ino %d \n"),
- (int)inode->i_ino));
- yaffs_gross_unlock(dev);
- if (filldir(dirent, ".", 1, offset, inode->i_ino, DT_DIR) < 0) {
- yaffs_gross_lock(dev);
- goto out;
- }
- yaffs_gross_lock(dev);
- offset++;
- f->f_pos++;
- }
- if (offset == 1) {
- T(YAFFS_TRACE_OS,
- (TSTR("yaffs_readdir: entry .. ino %d \n"),
- (int)f->f_dentry->d_parent->d_inode->i_ino));
- yaffs_gross_unlock(dev);
- if (filldir(dirent, "..", 2, offset,
- f->f_dentry->d_parent->d_inode->i_ino,
- DT_DIR) < 0) {
- yaffs_gross_lock(dev);
- goto out;
- }
- yaffs_gross_lock(dev);
- offset++;
- f->f_pos++;
- }
-
- curoffs = 1;
-
- /* If the directory has changed since the open or last call to
- readdir, rewind to after the 2 canned entries. */
- if (f->f_version != inode->i_version) {
- offset = 2;
- f->f_pos = offset;
- f->f_version = inode->i_version;
- }
-
- while (sc->next_return) {
- curoffs++;
- l = sc->next_return;
- if (curoffs >= offset) {
- int this_inode = yaffs_get_obj_inode(l);
- int this_type = yaffs_get_obj_type(l);
-
- yaffs_get_obj_name(l, name, YAFFS_MAX_NAME_LENGTH + 1);
- T(YAFFS_TRACE_OS,
- (TSTR("yaffs_readdir: %s inode %d\n"),
- name, yaffs_get_obj_inode(l)));
-
- yaffs_gross_unlock(dev);
-
- if (filldir(dirent,
- name,
- strlen(name),
- offset, this_inode, this_type) < 0) {
- yaffs_gross_lock(dev);
- goto out;
- }
-
- yaffs_gross_lock(dev);
-
- offset++;
- f->f_pos++;
- }
- yaffs_search_advance(sc);
- }
-
-out:
- yaffs_search_end(sc);
- yaffs_dev_to_lc(dev)->readdir_process = NULL;
- yaffs_gross_unlock(dev);
-
- return ret_val;
-}