static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) { int over; struct p9_wstat st; int err; struct p9_fid *fid; int buflen; char *statbuf; int n, i = 0; P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name); fid = filp->private_data; buflen = fid->clnt->msize - P9_IOHDRSZ; statbuf = kmalloc(buflen, GFP_KERNEL); if (!statbuf) return -ENOMEM; while (1) { err = v9fs_file_readn(filp, statbuf, NULL, buflen, fid->rdir_fpos); if (err <= 0) break; n = err; while (i < n) { err = p9stat_read(statbuf + i, buflen-i, &st, fid->clnt->dotu); if (err) { P9_DPRINTK(P9_DEBUG_VFS, "returned %d\n", err); err = -EIO; p9stat_free(&st); goto free_and_exit; } i += st.size+2; fid->rdir_fpos += st.size+2; over = filldir(dirent, st.name, strlen(st.name), filp->f_pos, v9fs_qid2ino(&st.qid), dt_type(&st)); filp->f_pos += st.size+2; p9stat_free(&st); if (over) { err = 0; goto free_and_exit; } } } free_and_exit: kfree(statbuf); return err; }
static ssize_t v9fs_file_read(struct file *filp, char __user *udata, size_t count, loff_t * offset) { int ret; struct p9_fid *fid; P9_DPRINTK(P9_DEBUG_VFS, "count %zu offset %lld\n", count, *offset); fid = filp->private_data; if (count > (fid->clnt->msize - P9_IOHDRSZ)) ret = v9fs_file_readn(filp, NULL, udata, count, *offset); else ret = p9_client_read(fid, NULL, udata, *offset, count); if (ret > 0) *offset += ret; return ret; }
static int v9fs_vfs_readpage(struct file *filp, struct page *page) { int retval; loff_t offset; char *buffer; struct inode *inode; inode = page->mapping->host; P9_DPRINTK(P9_DEBUG_VFS, "\n"); BUG_ON(!PageLocked(page)); retval = v9fs_readpage_from_fscache(inode, page); if (retval == 0) return retval; buffer = kmap(page); offset = page_offset(page); retval = v9fs_file_readn(filp, buffer, NULL, PAGE_CACHE_SIZE, offset); if (retval < 0) { v9fs_uncache_page(inode, page); goto done; } memset(buffer + retval, 0, PAGE_CACHE_SIZE - retval); flush_dcache_page(page); SetPageUptodate(page); v9fs_readpage_to_fscache(inode, page); retval = 0; done: kunmap(page); unlock_page(page); return retval; }
static int v9fs_vfs_readpage(struct file *filp, struct page *page) { int retval; loff_t offset; char *buffer; P9_DPRINTK(P9_DEBUG_VFS, "\n"); buffer = kmap(page); offset = page_offset(page); retval = v9fs_file_readn(filp, buffer, NULL, PAGE_CACHE_SIZE, offset); if (retval < 0) goto done; memset(buffer + retval, 0, PAGE_CACHE_SIZE - retval); flush_dcache_page(page); SetPageUptodate(page); retval = 0; done: kunmap(page); unlock_page(page); return retval; }
static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) { int over; struct p9_wstat st; int err = 0; struct p9_fid *fid; int buflen; int reclen = 0; struct p9_rdir *rdir; P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name); fid = filp->private_data; buflen = fid->clnt->msize - P9_IOHDRSZ; err = v9fs_alloc_rdir_buf(filp, buflen); if (err) goto exit; rdir = (struct p9_rdir *) fid->rdir; err = mutex_lock_interruptible(&rdir->mutex); if (err) return err; while (err == 0) { if (rdir->tail == rdir->head) { err = v9fs_file_readn(filp, rdir->buf, NULL, buflen, filp->f_pos); if (err <= 0) goto unlock_and_exit; rdir->head = 0; rdir->tail = err; } while (rdir->head < rdir->tail) { p9stat_init(&st); err = p9stat_read(rdir->buf + rdir->head, rdir->tail - rdir->head, &st, fid->clnt->proto_version); if (err) { P9_DPRINTK(P9_DEBUG_VFS, "returned %d\n", err); err = -EIO; p9stat_free(&st); goto unlock_and_exit; } reclen = st.size+2; over = filldir(dirent, st.name, strlen(st.name), filp->f_pos, v9fs_qid2ino(&st.qid), dt_type(&st)); p9stat_free(&st); if (over) { err = 0; goto unlock_and_exit; } rdir->head += reclen; filp->f_pos += reclen; } } unlock_and_exit: mutex_unlock(&rdir->mutex); exit: return err; }