static int nfs_file_read(struct inode *inode, struct file *file, char *buf, int count) { int result; int hunk; int i; int n; struct nfs_fattr fattr; char *data; off_t pos; if (!inode) { printk("nfs_file_read: inode = NULL\n"); return -EINVAL; } if (!S_ISREG(inode->i_mode)) { printk("nfs_file_read: read from non-file, mode %07o\n", inode->i_mode); return -EINVAL; } pos = file->f_pos; if (file->f_pos + count > inode->i_size) count = inode->i_size - pos; if (count <= 0) return 0; n = NFS_SERVER(inode)->rsize; data = (char *) kmalloc(n, GFP_KERNEL); for (i = 0; i < count; i += n) { hunk = count - i; if (hunk > n) hunk = n; result = nfs_proc_read(NFS_SERVER(inode), NFS_FH(inode), pos, hunk, data, &fattr); if (result < 0) { kfree_s(data, n); return result; } memcpy_tofs(buf, data, result); pos += result; buf += result; if (result < n) { i += result; break; } } file->f_pos = pos; kfree_s(data, n); nfs_refresh_inode(inode, &fattr); return i; }
static inline int do_read_nfs_sync(struct inode * inode, struct page * page) { struct nfs_fattr fattr; int result, refresh = 0; int count = PAGE_SIZE; int rsize = NFS_SERVER(inode)->rsize; char *buf = (char *) page_address(page); unsigned long pos = page->offset; dprintk("NFS: do_read_nfs_sync(%p)\n", page); set_bit(PG_locked, &page->flags); clear_bit(PG_error, &page->flags); do { if (count < rsize) rsize = count; result = nfs_proc_read(NFS_SERVER(inode), NFS_FH(inode), pos, rsize, buf, &fattr); dprintk("nfs_proc_read(%s, (%x,%lx), %ld, %d, %p) = %d\n", NFS_SERVER(inode)->hostname, inode->i_dev, inode->i_ino, pos, rsize, buf, result); /* * Even if we had a partial success we can't mark the page * cache valid. */ if (result < 0) goto io_error; refresh = 1; count -= result; pos += result; buf += result; if (result < rsize) break; } while (count); memset(buf, 0, count); set_bit(PG_uptodate, &page->flags); result = 0; io_error: if (refresh) nfs_refresh_inode(inode, &fattr); clear_bit(PG_locked, &page->flags); wake_up(&page->wait); return result; }
/* * Fill in the supplied page for mmap */ static unsigned long nfs_file_mmap_nopage(struct vm_area_struct * area, unsigned long address, unsigned long page, int no_share) { struct inode * inode = area->vm_inode; unsigned int clear; unsigned long tmp; int n; int i; int pos; struct nfs_fattr fattr; address &= PAGE_MASK; pos = address - area->vm_start + area->vm_offset; clear = 0; if (address + PAGE_SIZE > area->vm_end) { clear = address + PAGE_SIZE - area->vm_end; } n = NFS_SERVER(inode)->rsize; /* what we can read in one go */ for (i = 0; i < (PAGE_SIZE - clear); i += n) { int hunk, result; hunk = PAGE_SIZE - i; if (hunk > n) hunk = n; result = nfs_proc_read(NFS_SERVER(inode), NFS_FH(inode), pos, hunk, (char *) (page + i), &fattr, 0); if (result < 0) break; pos += result; if (result < n) { i += result; break; } } #ifdef doweneedthishere nfs_refresh_inode(inode, &fattr); #endif tmp = page + PAGE_SIZE; while (clear--) { *(char *)--tmp = 0; } return page; }
static int nfs_file_read(struct inode *inode, struct file *file, char *buf, int count) { int result, hunk, i, n, fs; struct nfs_fattr fattr; char *data; off_t pos; if (!inode) { printk("nfs_file_read: inode = NULL\n"); return -EINVAL; } if (!S_ISREG(inode->i_mode)) { printk("nfs_file_read: read from non-file, mode %07o\n", inode->i_mode); return -EINVAL; } pos = file->f_pos; if (pos + count > inode->i_size) count = inode->i_size - pos; if (count <= 0) return 0; ++num_requests; cli(); for (i = 0; i < READ_CACHE_SIZE; i++) if ((cache[i].inode_num == inode->i_ino) && (cache[i].file_pos <= pos) && (cache[i].file_pos + cache[i].len >= pos + count) && (abs(jiffies - cache[i].time) <= EXPIRE_CACHE)) break; if (i < READ_CACHE_SIZE) { ++cache[i].in_use; sti(); ++num_cache_hits; memcpy_tofs(buf, cache[i].buf + pos - cache[i].file_pos, count); --cache[i].in_use; file->f_pos += count; return count; } sti(); n = NFS_SERVER(inode)->rsize; for (i = 0; i < count - n; i += n) { result = nfs_proc_read(NFS_SERVER(inode), NFS_FH(inode), pos, n, buf, &fattr, 1); if (result < 0) return result; pos += result; buf += result; if (result < n) { file->f_pos = pos; nfs_refresh_inode(inode, &fattr); return i + result; } } fs = 0; if (!(data = (char *)kmalloc(n, GFP_KERNEL))) { data = buf; fs = 1; } result = nfs_proc_read(NFS_SERVER(inode), NFS_FH(inode), pos, n, data, &fattr, fs); if (result < 0) { if (!fs) kfree_s(data, n); return result; } hunk = count - i; if (result < hunk) hunk = result; if (fs) { file->f_pos = pos + hunk; nfs_refresh_inode(inode, &fattr); return i + hunk; } memcpy_tofs(buf, data, hunk); file->f_pos = pos + hunk; nfs_refresh_inode(inode, &fattr); cli(); if (cache[tail].in_use == 0) { if (cache[tail].buf) kfree_s(cache[tail].buf, cache[tail].buf_size); cache[tail].buf = data; cache[tail].buf_size = n; cache[tail].inode_num = inode->i_ino; cache[tail].file_pos = pos; cache[tail].len = result; cache[tail].time = jiffies; if (++tail >= READ_CACHE_SIZE) tail = 0; } else kfree_s(data, n); sti(); return i + hunk; }