aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/dir.c49
-rw-r--r--fs/nfs/file.c42
2 files changed, 76 insertions, 15 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 73f96acd5d..ff6155f5e8 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -528,19 +528,39 @@ static inline void nfs_renew_times(struct dentry * dentry)
528 dentry->d_time = jiffies; 528 dentry->d_time = jiffies;
529} 529}
530 530
531/*
532 * Return the intent data that applies to this particular path component
533 *
534 * Note that the current set of intents only apply to the very last
535 * component of the path.
536 * We check for this using LOOKUP_CONTINUE and LOOKUP_PARENT.
537 */
538static inline unsigned int nfs_lookup_check_intent(struct nameidata *nd, unsigned int mask)
539{
540 if (nd->flags & (LOOKUP_CONTINUE|LOOKUP_PARENT))
541 return 0;
542 return nd->flags & mask;
543}
544
545/*
546 * Inode and filehandle revalidation for lookups.
547 *
548 * We force revalidation in the cases where the VFS sets LOOKUP_REVAL,
549 * or if the intent information indicates that we're about to open this
550 * particular file and the "nocto" mount flag is not set.
551 *
552 */
531static inline 553static inline
532int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd) 554int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd)
533{ 555{
534 struct nfs_server *server = NFS_SERVER(inode); 556 struct nfs_server *server = NFS_SERVER(inode);
535 557
536 if (nd != NULL) { 558 if (nd != NULL) {
537 int ndflags = nd->flags;
538 /* VFS wants an on-the-wire revalidation */ 559 /* VFS wants an on-the-wire revalidation */
539 if (ndflags & LOOKUP_REVAL) 560 if (nd->flags & LOOKUP_REVAL)
540 goto out_force; 561 goto out_force;
541 /* This is an open(2) */ 562 /* This is an open(2) */
542 if ((ndflags & LOOKUP_OPEN) && 563 if (nfs_lookup_check_intent(nd, LOOKUP_OPEN) != 0 &&
543 !(ndflags & LOOKUP_CONTINUE) &&
544 !(server->flags & NFS_MOUNT_NOCTO)) 564 !(server->flags & NFS_MOUNT_NOCTO))
545 goto out_force; 565 goto out_force;
546 } 566 }
@@ -560,12 +580,8 @@ static inline
560int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry, 580int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry,
561 struct nameidata *nd) 581 struct nameidata *nd)
562{ 582{
563 int ndflags = 0;
564
565 if (nd)
566 ndflags = nd->flags;
567 /* Don't revalidate a negative dentry if we're creating a new file */ 583 /* Don't revalidate a negative dentry if we're creating a new file */
568 if ((ndflags & LOOKUP_CREATE) && !(ndflags & LOOKUP_CONTINUE)) 584 if (nd != NULL && nfs_lookup_check_intent(nd, LOOKUP_CREATE) != 0)
569 return 0; 585 return 0;
570 return !nfs_check_verifier(dir, dentry); 586 return !nfs_check_verifier(dir, dentry);
571} 587}
@@ -700,12 +716,16 @@ struct dentry_operations nfs_dentry_operations = {
700 .d_iput = nfs_dentry_iput, 716 .d_iput = nfs_dentry_iput,
701}; 717};
702 718
719/*
720 * Use intent information to check whether or not we're going to do
721 * an O_EXCL create using this path component.
722 */
703static inline 723static inline
704int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd) 724int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd)
705{ 725{
706 if (NFS_PROTO(dir)->version == 2) 726 if (NFS_PROTO(dir)->version == 2)
707 return 0; 727 return 0;
708 if (!nd || (nd->flags & LOOKUP_CONTINUE) || !(nd->flags & LOOKUP_CREATE)) 728 if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_CREATE) == 0)
709 return 0; 729 return 0;
710 return (nd->intent.open.flags & O_EXCL) != 0; 730 return (nd->intent.open.flags & O_EXCL) != 0;
711} 731}
@@ -772,12 +792,13 @@ struct dentry_operations nfs4_dentry_operations = {
772 .d_iput = nfs_dentry_iput, 792 .d_iput = nfs_dentry_iput,
773}; 793};
774 794
795/*
796 * Use intent information to determine whether we need to substitute
797 * the NFSv4-style stateful OPEN for the LOOKUP call
798 */
775static int is_atomic_open(struct inode *dir, struct nameidata *nd) 799static int is_atomic_open(struct inode *dir, struct nameidata *nd)
776{ 800{
777 if (!nd) 801 if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_OPEN) == 0)
778 return 0;
779 /* Check that we are indeed trying to open this file */
780 if ((nd->flags & LOOKUP_CONTINUE) || !(nd->flags & LOOKUP_OPEN))
781 return 0; 802 return 0;
782 /* NFS does not (yet) have a stateful open for directories */ 803 /* NFS does not (yet) have a stateful open for directories */
783 if (nd->flags & LOOKUP_DIRECTORY) 804 if (nd->flags & LOOKUP_DIRECTORY)
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index f06eee6dcf..55c9075924 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -37,6 +37,7 @@
37 37
38static int nfs_file_open(struct inode *, struct file *); 38static int nfs_file_open(struct inode *, struct file *);
39static int nfs_file_release(struct inode *, struct file *); 39static int nfs_file_release(struct inode *, struct file *);
40static loff_t nfs_file_llseek(struct file *file, loff_t offset, int origin);
40static int nfs_file_mmap(struct file *, struct vm_area_struct *); 41static int nfs_file_mmap(struct file *, struct vm_area_struct *);
41static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *); 42static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *);
42static ssize_t nfs_file_read(struct kiocb *, char __user *, size_t, loff_t); 43static ssize_t nfs_file_read(struct kiocb *, char __user *, size_t, loff_t);
@@ -48,7 +49,7 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl);
48static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl); 49static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl);
49 50
50struct file_operations nfs_file_operations = { 51struct file_operations nfs_file_operations = {
51 .llseek = remote_llseek, 52 .llseek = nfs_file_llseek,
52 .read = do_sync_read, 53 .read = do_sync_read,
53 .write = do_sync_write, 54 .write = do_sync_write,
54 .aio_read = nfs_file_read, 55 .aio_read = nfs_file_read,
@@ -114,6 +115,45 @@ nfs_file_release(struct inode *inode, struct file *filp)
114 return NFS_PROTO(inode)->file_release(inode, filp); 115 return NFS_PROTO(inode)->file_release(inode, filp);
115} 116}
116 117
118/**
119 * nfs_revalidate_size - Revalidate the file size
120 * @inode - pointer to inode struct
121 * @file - pointer to struct file
122 *
123 * Revalidates the file length. This is basically a wrapper around
124 * nfs_revalidate_inode() that takes into account the fact that we may
125 * have cached writes (in which case we don't care about the server's
126 * idea of what the file length is), or O_DIRECT (in which case we
127 * shouldn't trust the cache).
128 */
129static int nfs_revalidate_file_size(struct inode *inode, struct file *filp)
130{
131 struct nfs_server *server = NFS_SERVER(inode);
132 struct nfs_inode *nfsi = NFS_I(inode);
133
134 if (server->flags & NFS_MOUNT_NOAC)
135 goto force_reval;
136 if (filp->f_flags & O_DIRECT)
137 goto force_reval;
138 if (nfsi->npages != 0)
139 return 0;
140 return nfs_revalidate_inode(server, inode);
141force_reval:
142 return __nfs_revalidate_inode(server, inode);
143}
144
145static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin)
146{
147 /* origin == SEEK_END => we must revalidate the cached file length */
148 if (origin == 2) {
149 struct inode *inode = filp->f_mapping->host;
150 int retval = nfs_revalidate_file_size(inode, filp);
151 if (retval < 0)
152 return (loff_t)retval;
153 }
154 return remote_llseek(filp, offset, origin);
155}
156
117/* 157/*
118 * Flush all dirty pages, and check for write errors. 158 * Flush all dirty pages, and check for write errors.
119 * 159 *