aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/file.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@tglx.tec.linutronix.de>2005-06-26 17:20:36 -0400
committerThomas Gleixner <tglx@mtd.linutronix.de>2005-06-26 17:20:36 -0400
commit7ca6448dbfb398bba36eda3c01bc14b86c3675be (patch)
tree82d934ebf07f22a2c64c3b6d82ec24082878b43a /fs/nfs/file.c
parentf1f67a9874f1a4bba1adff6d694aa52e5f52ff1a (diff)
parent7d681b23d6cc14a8c026ea6756242cb522cbbcae (diff)
Merge with rsync://fileserver/linux
Update to Linus latest
Diffstat (limited to 'fs/nfs/file.c')
-rw-r--r--fs/nfs/file.c88
1 files changed, 81 insertions, 7 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index f06eee6dcff5..5621ba9885f4 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,
@@ -70,6 +71,18 @@ struct inode_operations nfs_file_inode_operations = {
70 .setattr = nfs_setattr, 71 .setattr = nfs_setattr,
71}; 72};
72 73
74#ifdef CONFIG_NFS_V3
75struct inode_operations nfs3_file_inode_operations = {
76 .permission = nfs_permission,
77 .getattr = nfs_getattr,
78 .setattr = nfs_setattr,
79 .listxattr = nfs3_listxattr,
80 .getxattr = nfs3_getxattr,
81 .setxattr = nfs3_setxattr,
82 .removexattr = nfs3_removexattr,
83};
84#endif /* CONFIG_NFS_v3 */
85
73/* Hack for future NFS swap support */ 86/* Hack for future NFS swap support */
74#ifndef IS_SWAPFILE 87#ifndef IS_SWAPFILE
75# define IS_SWAPFILE(inode) (0) 88# define IS_SWAPFILE(inode) (0)
@@ -114,6 +127,61 @@ nfs_file_release(struct inode *inode, struct file *filp)
114 return NFS_PROTO(inode)->file_release(inode, filp); 127 return NFS_PROTO(inode)->file_release(inode, filp);
115} 128}
116 129
130/**
131 * nfs_revalidate_file - Revalidate the page cache & related metadata
132 * @inode - pointer to inode struct
133 * @file - pointer to file
134 */
135static int nfs_revalidate_file(struct inode *inode, struct file *filp)
136{
137 int retval = 0;
138
139 if ((NFS_FLAGS(inode) & NFS_INO_REVAL_PAGECACHE) || nfs_attribute_timeout(inode))
140 retval = __nfs_revalidate_inode(NFS_SERVER(inode), inode);
141 nfs_revalidate_mapping(inode, filp->f_mapping);
142 return 0;
143}
144
145/**
146 * nfs_revalidate_size - Revalidate the file size
147 * @inode - pointer to inode struct
148 * @file - pointer to struct file
149 *
150 * Revalidates the file length. This is basically a wrapper around
151 * nfs_revalidate_inode() that takes into account the fact that we may
152 * have cached writes (in which case we don't care about the server's
153 * idea of what the file length is), or O_DIRECT (in which case we
154 * shouldn't trust the cache).
155 */
156static int nfs_revalidate_file_size(struct inode *inode, struct file *filp)
157{
158 struct nfs_server *server = NFS_SERVER(inode);
159 struct nfs_inode *nfsi = NFS_I(inode);
160
161 if (server->flags & NFS_MOUNT_NOAC)
162 goto force_reval;
163 if (filp->f_flags & O_DIRECT)
164 goto force_reval;
165 if (nfsi->npages != 0)
166 return 0;
167 if (!(NFS_FLAGS(inode) & NFS_INO_REVAL_PAGECACHE) && !nfs_attribute_timeout(inode))
168 return 0;
169force_reval:
170 return __nfs_revalidate_inode(server, inode);
171}
172
173static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin)
174{
175 /* origin == SEEK_END => we must revalidate the cached file length */
176 if (origin == 2) {
177 struct inode *inode = filp->f_mapping->host;
178 int retval = nfs_revalidate_file_size(inode, filp);
179 if (retval < 0)
180 return (loff_t)retval;
181 }
182 return remote_llseek(filp, offset, origin);
183}
184
117/* 185/*
118 * Flush all dirty pages, and check for write errors. 186 * Flush all dirty pages, and check for write errors.
119 * 187 *
@@ -158,7 +226,7 @@ nfs_file_read(struct kiocb *iocb, char __user * buf, size_t count, loff_t pos)
158 dentry->d_parent->d_name.name, dentry->d_name.name, 226 dentry->d_parent->d_name.name, dentry->d_name.name,
159 (unsigned long) count, (unsigned long) pos); 227 (unsigned long) count, (unsigned long) pos);
160 228
161 result = nfs_revalidate_inode(NFS_SERVER(inode), inode); 229 result = nfs_revalidate_file(inode, iocb->ki_filp);
162 if (!result) 230 if (!result)
163 result = generic_file_aio_read(iocb, buf, count, pos); 231 result = generic_file_aio_read(iocb, buf, count, pos);
164 return result; 232 return result;
@@ -176,7 +244,7 @@ nfs_file_sendfile(struct file *filp, loff_t *ppos, size_t count,
176 dentry->d_parent->d_name.name, dentry->d_name.name, 244 dentry->d_parent->d_name.name, dentry->d_name.name,
177 (unsigned long) count, (unsigned long long) *ppos); 245 (unsigned long) count, (unsigned long long) *ppos);
178 246
179 res = nfs_revalidate_inode(NFS_SERVER(inode), inode); 247 res = nfs_revalidate_file(inode, filp);
180 if (!res) 248 if (!res)
181 res = generic_file_sendfile(filp, ppos, count, actor, target); 249 res = generic_file_sendfile(filp, ppos, count, actor, target);
182 return res; 250 return res;
@@ -192,7 +260,7 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
192 dfprintk(VFS, "nfs: mmap(%s/%s)\n", 260 dfprintk(VFS, "nfs: mmap(%s/%s)\n",
193 dentry->d_parent->d_name.name, dentry->d_name.name); 261 dentry->d_parent->d_name.name, dentry->d_name.name);
194 262
195 status = nfs_revalidate_inode(NFS_SERVER(inode), inode); 263 status = nfs_revalidate_file(inode, file);
196 if (!status) 264 if (!status)
197 status = generic_file_mmap(file, vma); 265 status = generic_file_mmap(file, vma);
198 return status; 266 return status;
@@ -281,9 +349,15 @@ nfs_file_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t
281 result = -EBUSY; 349 result = -EBUSY;
282 if (IS_SWAPFILE(inode)) 350 if (IS_SWAPFILE(inode))
283 goto out_swapfile; 351 goto out_swapfile;
284 result = nfs_revalidate_inode(NFS_SERVER(inode), inode); 352 /*
285 if (result) 353 * O_APPEND implies that we must revalidate the file length.
286 goto out; 354 */
355 if (iocb->ki_filp->f_flags & O_APPEND) {
356 result = nfs_revalidate_file_size(inode, iocb->ki_filp);
357 if (result)
358 goto out;
359 }
360 nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping);
287 361
288 result = count; 362 result = count;
289 if (!count) 363 if (!count)