diff options
author | Thomas Gleixner <tglx@tglx.tec.linutronix.de> | 2005-06-26 17:20:36 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@mtd.linutronix.de> | 2005-06-26 17:20:36 -0400 |
commit | 7ca6448dbfb398bba36eda3c01bc14b86c3675be (patch) | |
tree | 82d934ebf07f22a2c64c3b6d82ec24082878b43a /fs/nfs/file.c | |
parent | f1f67a9874f1a4bba1adff6d694aa52e5f52ff1a (diff) | |
parent | 7d681b23d6cc14a8c026ea6756242cb522cbbcae (diff) |
Merge with rsync://fileserver/linux
Update to Linus latest
Diffstat (limited to 'fs/nfs/file.c')
-rw-r--r-- | fs/nfs/file.c | 88 |
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 | ||
38 | static int nfs_file_open(struct inode *, struct file *); | 38 | static int nfs_file_open(struct inode *, struct file *); |
39 | static int nfs_file_release(struct inode *, struct file *); | 39 | static int nfs_file_release(struct inode *, struct file *); |
40 | static loff_t nfs_file_llseek(struct file *file, loff_t offset, int origin); | ||
40 | static int nfs_file_mmap(struct file *, struct vm_area_struct *); | 41 | static int nfs_file_mmap(struct file *, struct vm_area_struct *); |
41 | static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *); | 42 | static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *); |
42 | static ssize_t nfs_file_read(struct kiocb *, char __user *, size_t, loff_t); | 43 | static 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); | |||
48 | static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl); | 49 | static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl); |
49 | 50 | ||
50 | struct file_operations nfs_file_operations = { | 51 | struct 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 | ||
75 | struct 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 | */ | ||
135 | static 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 | */ | ||
156 | static 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; | ||
169 | force_reval: | ||
170 | return __nfs_revalidate_inode(server, inode); | ||
171 | } | ||
172 | |||
173 | static 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) |