Fixed merge goof and incorported the vserver 1.9.2 specific changes.
authorMarc Fiuczynski <mef@cs.princeton.edu>
Mon, 7 Mar 2005 20:23:50 +0000 (20:23 +0000)
committerMarc Fiuczynski <mef@cs.princeton.edu>
Mon, 7 Mar 2005 20:23:50 +0000 (20:23 +0000)
Note that the vserver specific changes are no longer part of 1.9.3
and subsequent versions.

fs/nfs/file.c

index 91bd053..ee2addb 100644 (file)
@@ -72,7 +72,7 @@ struct inode_operations nfs_file_inode_operations = {
 
 static int nfs_check_flags(int flags)
 {
-       if ((flags & (O_APPEND | O_DIRECT)) == (O_APPEND | O_DIRECT))
+       if (flags & (O_APPEND | O_DIRECT))
                return -EINVAL;
 
        return 0;
@@ -89,7 +89,7 @@ nfs_file_open(struct inode *inode, struct file *filp)
        int res;
 
        res = nfs_check_flags(filp->f_flags);
-       if (res)
+       if (!res)
                return res;
 
        lock_kernel();
@@ -156,7 +156,163 @@ nfs_file_read(struct kiocb *iocb, char __user * buf, size_t count, loff_t pos)
 }
 
 static ssize_t
-nfs_file_sendfile(struct file *f
+nfs_file_sendfile(struct file *filp, loff_t *ppos, size_t count,
+               read_actor_t actor, void *target)
+{
+       struct dentry *dentry = filp->f_dentry;
+       struct inode *inode = dentry->d_inode;
+       ssize_t res;
+
+       dfprintk(VFS, "nfs: sendfile(%s/%s, %lu@%Lu)\n",
+               dentry->d_parent->d_name.name, dentry->d_name.name,
+               (unsigned long) count, (unsigned long long) *ppos);
+
+       res = nfs_revalidate_inode(NFS_SERVER(inode), inode);
+       if (!res)
+               res = generic_file_sendfile(filp, ppos, count, actor, target);
+       return res;
+}
+
+static int
+nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
+{
+       struct dentry *dentry = file->f_dentry;
+       struct inode *inode = dentry->d_inode;
+       int     status;
+
+       dfprintk(VFS, "nfs: mmap(%s/%s)\n",
+               dentry->d_parent->d_name.name, dentry->d_name.name);
+
+       status = nfs_revalidate_inode(NFS_SERVER(inode), inode);
+       if (!status)
+               status = generic_file_mmap(file, vma);
+       return status;
+}
+
+/*
+ * Flush any dirty pages for this process, and check for write errors.
+ * The return status from this call provides a reliable indication of
+ * whether any write errors occurred for this process.
+ */
+static int
+nfs_fsync(struct file *file, struct dentry *dentry, int datasync)
+{
+       struct inode *inode = dentry->d_inode;
+       int status;
+
+       dfprintk(VFS, "nfs: fsync(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino);
+
+       lock_kernel();
+       status = nfs_wb_all(inode);
+       if (!status) {
+               status = file->f_error;
+               file->f_error = 0;
+       }
+       unlock_kernel();
+       return status;
+}
+
+/*
+ * This does the "real" work of the write. The generic routine has
+ * allocated the page, locked it, done all the page alignment stuff
+ * calculations etc. Now we should just copy the data from user
+ * space and write it back to the real medium..
+ *
+ * If the writer ends up delaying the write, the writer needs to
+ * increment the page use counts until he is done with the page.
+ */
+static int nfs_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
+{
+       return nfs_flush_incompatible(file, page);
+}
+
+static int nfs_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to)
+{
+       long status;
+
+       lock_kernel();
+       status = nfs_updatepage(file, page, offset, to-offset);
+       unlock_kernel();
+       return status;
+}
+
+struct address_space_operations nfs_file_aops = {
+       .readpage = nfs_readpage,
+       .readpages = nfs_readpages,
+       .set_page_dirty = __set_page_dirty_nobuffers,
+       .writepage = nfs_writepage,
+       .writepages = nfs_writepages,
+       .prepare_write = nfs_prepare_write,
+       .commit_write = nfs_commit_write,
+#ifdef CONFIG_NFS_DIRECTIO
+       .direct_IO = nfs_direct_IO,
+#endif
+};
+
+/* 
+ * Write to a file (through the page cache).
+ */
+static ssize_t
+nfs_file_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t pos)
+{
+       struct dentry * dentry = iocb->ki_filp->f_dentry;
+       struct inode * inode = dentry->d_inode;
+       ssize_t result;
+
+#ifdef CONFIG_NFS_DIRECTIO
+       if (iocb->ki_filp->f_flags & O_DIRECT)
+               return nfs_file_direct_write(iocb, buf, count, pos);
+#endif
+
+       dfprintk(VFS, "nfs: write(%s/%s(%ld), %lu@%lu)\n",
+               dentry->d_parent->d_name.name, dentry->d_name.name,
+               inode->i_ino, (unsigned long) count, (unsigned long) pos);
+
+       result = -EBUSY;
+       if (IS_SWAPFILE(inode))
+               goto out_swapfile;
+       result = nfs_revalidate_inode(NFS_SERVER(inode), inode);
+       if (result)
+               goto out;
+
+       result = count;
+       if (!count)
+               goto out;
+
+       result = generic_file_aio_write(iocb, buf, count, pos);
+out:
+       return result;
+
+out_swapfile:
+       printk(KERN_INFO "NFS: attempt to write to active swap file!\n");
+       goto out;
+}
+
+/*
+ * Lock a (portion of) a file
+ */
+int
+nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
+{
+       struct inode * inode = filp->f_mapping->host;
+       int     status = 0;
+       int     status2;
+
+       dprintk("NFS: nfs_lock(f=%s/%ld, t=%x, fl=%x, r=%Ld:%Ld)\n",
+                       inode->i_sb->s_id, inode->i_ino,
+                       fl->fl_type, fl->fl_flags,
+                       (long long)fl->fl_start, (long long)fl->fl_end);
+
+       if (!inode)
+               return -EINVAL;
+
+       /* No mandatory locks over NFS */
+       if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
+               return -ENOLCK;
+
+       if (NFS_PROTO(inode)->version != 4) {
+               /* Fake OK code if mounted without NLM support */
+               if (NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM) {
                        if (IS_GETLK(cmd))
                                status = LOCK_USE_CLNT;
                        goto out_ok;