| /* |
| * linux/fs/nfs/file.c |
| * |
| * Copyright (C) 1992 Rick Sladkey |
| * |
| * nfs regular file handling functions |
| */ |
| |
| #include <asm/segment.h> |
| #include <asm/system.h> |
| |
| #include <linux/sched.h> |
| #include <linux/kernel.h> |
| #include <linux/errno.h> |
| #include <linux/fcntl.h> |
| #include <linux/stat.h> |
| #include <linux/mm.h> |
| #include <linux/nfs_fs.h> |
| |
| static int nfs_file_read(struct inode *, struct file *, char *, int); |
| static int nfs_file_write(struct inode *, struct file *, char *, int); |
| |
| static struct file_operations nfs_file_operations = { |
| NULL, /* lseek - default */ |
| nfs_file_read, /* read */ |
| nfs_file_write, /* write */ |
| NULL, /* readdir - bad */ |
| NULL, /* select - default */ |
| NULL, /* ioctl - default */ |
| NULL, /* mmap */ |
| NULL, /* no special open is needed */ |
| NULL, /* release */ |
| NULL /* fsync */ |
| }; |
| |
| struct inode_operations nfs_file_inode_operations = { |
| &nfs_file_operations, /* default file operations */ |
| NULL, /* create */ |
| NULL, /* lookup */ |
| NULL, /* link */ |
| NULL, /* unlink */ |
| NULL, /* symlink */ |
| NULL, /* mkdir */ |
| NULL, /* rmdir */ |
| NULL, /* mknod */ |
| NULL, /* rename */ |
| NULL, /* readlink */ |
| NULL, /* follow_link */ |
| NULL, /* bmap */ |
| NULL /* truncate */ |
| }; |
| |
| 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 int nfs_file_write(struct inode *inode, struct file *file, char *buf, |
| int count) |
| { |
| int result; |
| int hunk; |
| int i; |
| int n; |
| struct nfs_fattr fattr; |
| char *data; |
| int pos; |
| |
| if (!inode) { |
| printk("nfs_file_write: inode = NULL\n"); |
| return -EINVAL; |
| } |
| if (!S_ISREG(inode->i_mode)) { |
| printk("nfs_file_write: write to non-file, mode %07o\n", |
| inode->i_mode); |
| return -EINVAL; |
| } |
| if (count <= 0) |
| return 0; |
| pos = file->f_pos; |
| if (file->f_flags & O_APPEND) |
| pos = inode->i_size; |
| n = NFS_SERVER(inode)->wsize; |
| data = (char *) kmalloc(n, GFP_KERNEL); |
| for (i = 0; i < count; i += n) { |
| hunk = count - i; |
| if (hunk >= n) |
| hunk = n; |
| memcpy_fromfs(data, buf, hunk); |
| result = nfs_proc_write(NFS_SERVER(inode), NFS_FH(inode), |
| pos, hunk, data, &fattr); |
| if (result < 0) { |
| kfree_s(data, n); |
| return result; |
| } |
| pos += hunk; |
| buf += hunk; |
| if (hunk < n) { |
| i += hunk; |
| break; |
| } |
| } |
| file->f_pos = pos; |
| kfree_s(data, n); |
| nfs_refresh_inode(inode, &fattr); |
| return i; |
| } |
| |