diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-04-29 21:13:14 +0000 |
---|---|---|
committer | <ralf@linux-mips.org> | 1997-04-29 21:13:14 +0000 |
commit | 19c9bba94152148523ba0f7ef7cffe3d45656b11 (patch) | |
tree | 40b1cb534496a7f1ca0f5c314a523c69f1fee464 /fs/nfs/file.c | |
parent | 7206675c40394c78a90e74812bbdbf8cf3cca1be (diff) |
Import of Linux/MIPS 2.1.36
Diffstat (limited to 'fs/nfs/file.c')
-rw-r--r-- | fs/nfs/file.c | 203 |
1 files changed, 136 insertions, 67 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 5ec19b0c2..ca42719bd 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -21,18 +21,24 @@ #include <linux/errno.h> #include <linux/fcntl.h> #include <linux/stat.h> -#include <linux/mm.h> #include <linux/nfs_fs.h> +#include <linux/mm.h> #include <linux/malloc.h> #include <linux/pagemap.h> +#include <linux/lockd/bind.h> -#include <asm/uaccess.h> +#include <asm/segment.h> #include <asm/system.h> -static int nfs_file_mmap(struct inode *, struct file *, struct vm_area_struct *); +#define NFSDBG_FACILITY NFSDBG_FILE + +static int nfs_file_mmap(struct inode *, struct file *, + struct vm_area_struct *); static long nfs_file_read(struct inode *, struct file *, char *, unsigned long); -static long nfs_file_write(struct inode *, struct file *, const char *, unsigned long); -static int nfs_fsync(struct inode *, struct file *); +static long nfs_file_write(struct inode *, struct file *, + const char *, unsigned long); +static int nfs_file_close(struct inode *, struct file *); +static int nfs_fsync(struct inode *, struct file *); static struct file_operations nfs_file_operations = { NULL, /* lseek - default */ @@ -43,8 +49,12 @@ static struct file_operations nfs_file_operations = { NULL, /* ioctl - default */ nfs_file_mmap, /* mmap */ NULL, /* no special open is needed */ - NULL, /* release */ + nfs_file_close, /* release */ nfs_fsync, /* fsync */ + NULL, /* fasync */ + NULL, /* check_media_change */ + NULL, /* revalidate */ + nfs_lock, /* lock */ }; struct inode_operations nfs_file_inode_operations = { @@ -61,97 +71,156 @@ struct inode_operations nfs_file_inode_operations = { NULL, /* readlink */ NULL, /* follow_link */ nfs_readpage, /* readpage */ - NULL, /* writepage */ + nfs_writepage, /* writepage */ NULL, /* bmap */ - NULL /* truncate */ + NULL, /* truncate */ + NULL, /* permission */ + NULL, /* smap */ + nfs_updatepage, /* updatepage */ + nfs_revalidate, /* revalidate */ }; -static inline void revalidate_inode(struct nfs_server * server, struct inode * inode) +/* Hack for future NFS swap support */ +#ifndef IS_SWAPFILE +# define IS_SWAPFILE(inode) (0) +#endif + + +static int +nfs_file_close(struct inode *inode, struct file *file) { - struct nfs_fattr fattr; - - if (jiffies - NFS_READTIME(inode) < NFS_ATTRTIMEO(inode)) - return; - - NFS_READTIME(inode) = jiffies; - if (nfs_proc_getattr(server, NFS_FH(inode), &fattr) == 0) { - nfs_refresh_inode(inode, &fattr); - if (fattr.mtime.seconds == NFS_OLDMTIME(inode)) { - if ((NFS_ATTRTIMEO(inode) <<= 1) > server->acregmax) - NFS_ATTRTIMEO(inode) = server->acregmax; - return; - } - NFS_OLDMTIME(inode) = fattr.mtime.seconds; - } - invalidate_inode_pages(inode); -} + int status; + dfprintk(VFS, "nfs: close(%x/%ld)\n", inode->i_dev, inode->i_ino); -static long nfs_file_read(struct inode * inode, struct file * file, - char * buf, unsigned long count) + if ((status = nfs_flush_dirty_pages(inode, 0, 0)) < 0) + return status; + return nfs_write_error(inode); +} + +static long +nfs_file_read(struct inode * inode, struct file * file, + char * buf, unsigned long count) { - revalidate_inode(NFS_SERVER(inode), inode); + int status; + + dfprintk(VFS, "nfs: read(%x/%ld, %lu@%lu)\n", + inode->i_dev, inode->i_ino, count, + (unsigned long) file->f_pos); + + if ((status = nfs_revalidate_inode(NFS_SERVER(inode), inode)) < 0) + return status; return generic_file_read(inode, file, buf, count); } -static int nfs_file_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma) +static int +nfs_file_mmap(struct inode * inode, struct file * file, + struct vm_area_struct * vma) { - revalidate_inode(NFS_SERVER(inode), inode); + int status; + + dfprintk(VFS, "nfs: mmap(%x/%ld)\n", inode->i_dev, inode->i_ino); + + if ((status = nfs_revalidate_inode(NFS_SERVER(inode), inode)) < 0) + return status; return generic_file_mmap(inode, file, vma); } static int nfs_fsync(struct inode *inode, struct file *file) { - return 0; + dfprintk(VFS, "nfs: fsync(%x/%ld)\n", inode->i_dev, inode->i_ino); + + return nfs_flush_dirty_pages(inode, 0, 0); } -static long nfs_file_write(struct inode *inode, struct file *file, - const char *buf, unsigned long count) +/* + * Write to a file (through the page cache). + */ +static long +nfs_file_write(struct inode *inode, struct file *file, + const char *buf, unsigned long count) { - int result, written, wsize; - struct nfs_fattr fattr; - unsigned long pos; + int result; + + dfprintk(VFS, "nfs: write(%x/%ld (%d), %lu@%lu)\n", + inode->i_dev, inode->i_ino, inode->i_count, + count, (unsigned long) file->f_pos); if (!inode) { printk("nfs_file_write: inode = NULL\n"); return -EINVAL; } + if (IS_SWAPFILE(inode)) { + printk("NFS: attempt to write to active swap file!\n"); + return -EBUSY; + } + if ((result = nfs_revalidate_inode(NFS_SERVER(inode), inode)) < 0) + return result; if (!S_ISREG(inode->i_mode)) { printk("nfs_file_write: write to non-file, mode %07o\n", - (unsigned int) inode->i_mode); + inode->i_mode); return -EINVAL; } - if (count == 0) + if (count <= 0) return 0; - pos = file->f_pos; - if (file->f_flags & O_APPEND) - pos = inode->i_size; - wsize = NFS_SERVER(inode)->wsize; - result = 0; - written = 0; - while (written < count) { - int hunk = count - written; - if (hunk >= wsize) - hunk = wsize; - result = nfs_proc_write(inode, - pos, hunk, buf, &fattr); - if (result < 0) - break; - pos += hunk; - buf += hunk; - written += hunk; - if (hunk < wsize) - break; - } - if (!written) + /* Return error from previous async call */ + if ((result = nfs_write_error(inode)) < 0) return result; - file->f_pos = pos; - if (pos > inode->i_size) - inode->i_size = pos; - /* Avoid possible Solaris 2.5 nfsd bug */ - if (inode->i_ino == fattr.fileid) - nfs_refresh_inode(inode, &fattr); - return written; + + return generic_file_write(inode, file, buf, count); } +/* + * Lock a (portion of) a file + */ +int +nfs_lock(struct inode *inode, struct file *filp, int cmd, struct file_lock *fl) +{ + int status; + + dprintk("NFS: nfs_lock(f=%4x/%ld, t=%x, fl=%x, r=%ld:%ld)\n", + filp->f_inode->i_dev, filp->f_inode->i_ino, + fl->fl_type, fl->fl_flags, + fl->fl_start, fl->fl_end); + + if (!(inode = filp->f_inode)) + return -EINVAL; + + /* No mandatory locks over NFS */ + if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) + return -ENOLCK; + + /* Fake OK code if mounted without NLM support */ + if (NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM) + return 0; + + /* + * No BSD flocks over NFS allowed. + * Note: we could try to fake a POSIX lock request here by + * using ((u32) filp | 0x80000000) or some such as the pid. + * Not sure whether that would be unique, though, or whether + * that would break in other places. + */ + if (!fl->fl_owner || (fl->fl_flags & (FL_POSIX|FL_BROKEN)) != FL_POSIX) + return -ENOLCK; + + /* If unlocking a file region, flush dirty pages (unless we've + * been killed by a signal, that is). */ + if (cmd == F_SETLK && fl->fl_type == F_UNLCK + && !(current->signal & ~current->blocked)) { + status = nfs_flush_dirty_pages(inode, + fl->fl_start, fl->fl_end == NLM_OFFSET_MAX? 0 : + fl->fl_end - fl->fl_start + 1); + if (status < 0) + return status; + } + + if ((status = nlmclnt_proc(inode, cmd, fl)) < 0) + return status; + + /* Here, we could turn off write-back of pages in the + * locked file region */ + + return 0; +} |