diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2009-04-01 13:28:15 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2009-04-01 13:28:15 -0400 |
commit | cc85906110e26fe8537c3bdbc08a74ae8110030b (patch) | |
tree | 891813098ede3dba4d5ff3b83b1f7b491367ad2f /fs/nfs | |
parent | c09bca786ff941ed17c5f381c4eca5b106808c51 (diff) | |
parent | c69da774b28e01e062e0a3aba7509f2dcfd2a11a (diff) |
Merge branch 'devel' into for-linus
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/callback.c | 31 | ||||
-rw-r--r-- | fs/nfs/callback.h | 1 | ||||
-rw-r--r-- | fs/nfs/client.c | 116 | ||||
-rw-r--r-- | fs/nfs/dir.c | 9 | ||||
-rw-r--r-- | fs/nfs/file.c | 32 | ||||
-rw-r--r-- | fs/nfs/getroot.c | 4 | ||||
-rw-r--r-- | fs/nfs/inode.c | 309 | ||||
-rw-r--r-- | fs/nfs/internal.h | 4 | ||||
-rw-r--r-- | fs/nfs/nfs2xdr.c | 9 | ||||
-rw-r--r-- | fs/nfs/nfs3proc.c | 1 | ||||
-rw-r--r-- | fs/nfs/nfs3xdr.c | 37 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 47 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 10 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 213 | ||||
-rw-r--r-- | fs/nfs/pagelist.c | 11 | ||||
-rw-r--r-- | fs/nfs/proc.c | 1 | ||||
-rw-r--r-- | fs/nfs/super.c | 4 | ||||
-rw-r--r-- | fs/nfs/write.c | 53 |
18 files changed, 549 insertions, 343 deletions
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index 3e634f2a1083..a886e692ddd0 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c | |||
@@ -38,19 +38,10 @@ static struct svc_program nfs4_callback_program; | |||
38 | 38 | ||
39 | unsigned int nfs_callback_set_tcpport; | 39 | unsigned int nfs_callback_set_tcpport; |
40 | unsigned short nfs_callback_tcpport; | 40 | unsigned short nfs_callback_tcpport; |
41 | unsigned short nfs_callback_tcpport6; | ||
41 | static const int nfs_set_port_min = 0; | 42 | static const int nfs_set_port_min = 0; |
42 | static const int nfs_set_port_max = 65535; | 43 | static const int nfs_set_port_max = 65535; |
43 | 44 | ||
44 | /* | ||
45 | * If the kernel has IPv6 support available, always listen for | ||
46 | * both AF_INET and AF_INET6 requests. | ||
47 | */ | ||
48 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
49 | static const sa_family_t nfs_callback_family = AF_INET6; | ||
50 | #else | ||
51 | static const sa_family_t nfs_callback_family = AF_INET; | ||
52 | #endif | ||
53 | |||
54 | static int param_set_port(const char *val, struct kernel_param *kp) | 45 | static int param_set_port(const char *val, struct kernel_param *kp) |
55 | { | 46 | { |
56 | char *endp; | 47 | char *endp; |
@@ -116,19 +107,29 @@ int nfs_callback_up(void) | |||
116 | mutex_lock(&nfs_callback_mutex); | 107 | mutex_lock(&nfs_callback_mutex); |
117 | if (nfs_callback_info.users++ || nfs_callback_info.task != NULL) | 108 | if (nfs_callback_info.users++ || nfs_callback_info.task != NULL) |
118 | goto out; | 109 | goto out; |
119 | serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, | 110 | serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, NULL); |
120 | nfs_callback_family, NULL); | ||
121 | ret = -ENOMEM; | 111 | ret = -ENOMEM; |
122 | if (!serv) | 112 | if (!serv) |
123 | goto out_err; | 113 | goto out_err; |
124 | 114 | ||
125 | ret = svc_create_xprt(serv, "tcp", nfs_callback_set_tcpport, | 115 | ret = svc_create_xprt(serv, "tcp", PF_INET, |
126 | SVC_SOCK_ANONYMOUS); | 116 | nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); |
127 | if (ret <= 0) | 117 | if (ret <= 0) |
128 | goto out_err; | 118 | goto out_err; |
129 | nfs_callback_tcpport = ret; | 119 | nfs_callback_tcpport = ret; |
130 | dprintk("NFS: Callback listener port = %u (af %u)\n", | 120 | dprintk("NFS: Callback listener port = %u (af %u)\n", |
131 | nfs_callback_tcpport, nfs_callback_family); | 121 | nfs_callback_tcpport, PF_INET); |
122 | |||
123 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
124 | ret = svc_create_xprt(serv, "tcp", PF_INET6, | ||
125 | nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); | ||
126 | if (ret > 0) { | ||
127 | nfs_callback_tcpport6 = ret; | ||
128 | dprintk("NFS: Callback listener port = %u (af %u)\n", | ||
129 | nfs_callback_tcpport6, PF_INET6); | ||
130 | } else if (ret != -EAFNOSUPPORT) | ||
131 | goto out_err; | ||
132 | #endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ | ||
132 | 133 | ||
133 | nfs_callback_info.rqst = svc_prepare_thread(serv, &serv->sv_pools[0]); | 134 | nfs_callback_info.rqst = svc_prepare_thread(serv, &serv->sv_pools[0]); |
134 | if (IS_ERR(nfs_callback_info.rqst)) { | 135 | if (IS_ERR(nfs_callback_info.rqst)) { |
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h index bb25d2135ff1..e110e286a262 100644 --- a/fs/nfs/callback.h +++ b/fs/nfs/callback.h | |||
@@ -72,5 +72,6 @@ extern void nfs_callback_down(void); | |||
72 | 72 | ||
73 | extern unsigned int nfs_callback_set_tcpport; | 73 | extern unsigned int nfs_callback_set_tcpport; |
74 | extern unsigned short nfs_callback_tcpport; | 74 | extern unsigned short nfs_callback_tcpport; |
75 | extern unsigned short nfs_callback_tcpport6; | ||
75 | 76 | ||
76 | #endif /* __LINUX_FS_NFS_CALLBACK_H */ | 77 | #endif /* __LINUX_FS_NFS_CALLBACK_H */ |
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 2277421656e7..aba38017bdef 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -224,38 +224,6 @@ void nfs_put_client(struct nfs_client *clp) | |||
224 | } | 224 | } |
225 | 225 | ||
226 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 226 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
227 | static const struct in6_addr *nfs_map_ipv4_addr(const struct sockaddr *sa, struct in6_addr *addr_mapped) | ||
228 | { | ||
229 | switch (sa->sa_family) { | ||
230 | default: | ||
231 | return NULL; | ||
232 | case AF_INET6: | ||
233 | return &((const struct sockaddr_in6 *)sa)->sin6_addr; | ||
234 | break; | ||
235 | case AF_INET: | ||
236 | ipv6_addr_set_v4mapped(((const struct sockaddr_in *)sa)->sin_addr.s_addr, | ||
237 | addr_mapped); | ||
238 | return addr_mapped; | ||
239 | } | ||
240 | } | ||
241 | |||
242 | static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1, | ||
243 | const struct sockaddr *sa2) | ||
244 | { | ||
245 | const struct in6_addr *addr1; | ||
246 | const struct in6_addr *addr2; | ||
247 | struct in6_addr addr1_mapped; | ||
248 | struct in6_addr addr2_mapped; | ||
249 | |||
250 | addr1 = nfs_map_ipv4_addr(sa1, &addr1_mapped); | ||
251 | if (likely(addr1 != NULL)) { | ||
252 | addr2 = nfs_map_ipv4_addr(sa2, &addr2_mapped); | ||
253 | if (likely(addr2 != NULL)) | ||
254 | return ipv6_addr_equal(addr1, addr2); | ||
255 | } | ||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | /* | 227 | /* |
260 | * Test if two ip6 socket addresses refer to the same socket by | 228 | * Test if two ip6 socket addresses refer to the same socket by |
261 | * comparing relevant fields. The padding bytes specifically, are not | 229 | * comparing relevant fields. The padding bytes specifically, are not |
@@ -267,38 +235,21 @@ static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1, | |||
267 | * | 235 | * |
268 | * The caller should ensure both socket addresses are AF_INET6. | 236 | * The caller should ensure both socket addresses are AF_INET6. |
269 | */ | 237 | */ |
270 | static int nfs_sockaddr_cmp_ip6(const struct sockaddr *sa1, | 238 | static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1, |
271 | const struct sockaddr *sa2) | 239 | const struct sockaddr *sa2) |
272 | { | 240 | { |
273 | const struct sockaddr_in6 *saddr1 = (const struct sockaddr_in6 *)sa1; | 241 | const struct sockaddr_in6 *sin1 = (const struct sockaddr_in6 *)sa1; |
274 | const struct sockaddr_in6 *saddr2 = (const struct sockaddr_in6 *)sa2; | 242 | const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sa2; |
275 | 243 | ||
276 | if (!ipv6_addr_equal(&saddr1->sin6_addr, | 244 | if (ipv6_addr_scope(&sin1->sin6_addr) == IPV6_ADDR_SCOPE_LINKLOCAL && |
277 | &saddr1->sin6_addr)) | 245 | sin1->sin6_scope_id != sin2->sin6_scope_id) |
278 | return 0; | 246 | return 0; |
279 | if (ipv6_addr_scope(&saddr1->sin6_addr) == IPV6_ADDR_SCOPE_LINKLOCAL && | ||
280 | saddr1->sin6_scope_id != saddr2->sin6_scope_id) | ||
281 | return 0; | ||
282 | return saddr1->sin6_port == saddr2->sin6_port; | ||
283 | } | ||
284 | #else | ||
285 | static int nfs_sockaddr_match_ipaddr4(const struct sockaddr_in *sa1, | ||
286 | const struct sockaddr_in *sa2) | ||
287 | { | ||
288 | return sa1->sin_addr.s_addr == sa2->sin_addr.s_addr; | ||
289 | } | ||
290 | 247 | ||
291 | static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1, | 248 | return ipv6_addr_equal(&sin1->sin6_addr, &sin1->sin6_addr); |
292 | const struct sockaddr *sa2) | ||
293 | { | ||
294 | if (unlikely(sa1->sa_family != AF_INET || sa2->sa_family != AF_INET)) | ||
295 | return 0; | ||
296 | return nfs_sockaddr_match_ipaddr4((const struct sockaddr_in *)sa1, | ||
297 | (const struct sockaddr_in *)sa2); | ||
298 | } | 249 | } |
299 | 250 | #else /* !defined(CONFIG_IPV6) && !defined(CONFIG_IPV6_MODULE) */ | |
300 | static int nfs_sockaddr_cmp_ip6(const struct sockaddr * sa1, | 251 | static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1, |
301 | const struct sockaddr * sa2) | 252 | const struct sockaddr *sa2) |
302 | { | 253 | { |
303 | return 0; | 254 | return 0; |
304 | } | 255 | } |
@@ -311,20 +262,57 @@ static int nfs_sockaddr_cmp_ip6(const struct sockaddr * sa1, | |||
311 | * | 262 | * |
312 | * The caller should ensure both socket addresses are AF_INET. | 263 | * The caller should ensure both socket addresses are AF_INET. |
313 | */ | 264 | */ |
265 | static int nfs_sockaddr_match_ipaddr4(const struct sockaddr *sa1, | ||
266 | const struct sockaddr *sa2) | ||
267 | { | ||
268 | const struct sockaddr_in *sin1 = (const struct sockaddr_in *)sa1; | ||
269 | const struct sockaddr_in *sin2 = (const struct sockaddr_in *)sa2; | ||
270 | |||
271 | return sin1->sin_addr.s_addr == sin2->sin_addr.s_addr; | ||
272 | } | ||
273 | |||
274 | static int nfs_sockaddr_cmp_ip6(const struct sockaddr *sa1, | ||
275 | const struct sockaddr *sa2) | ||
276 | { | ||
277 | const struct sockaddr_in6 *sin1 = (const struct sockaddr_in6 *)sa1; | ||
278 | const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sa2; | ||
279 | |||
280 | return nfs_sockaddr_match_ipaddr6(sa1, sa2) && | ||
281 | (sin1->sin6_port == sin2->sin6_port); | ||
282 | } | ||
283 | |||
314 | static int nfs_sockaddr_cmp_ip4(const struct sockaddr *sa1, | 284 | static int nfs_sockaddr_cmp_ip4(const struct sockaddr *sa1, |
315 | const struct sockaddr *sa2) | 285 | const struct sockaddr *sa2) |
316 | { | 286 | { |
317 | const struct sockaddr_in *saddr1 = (const struct sockaddr_in *)sa1; | 287 | const struct sockaddr_in *sin1 = (const struct sockaddr_in *)sa1; |
318 | const struct sockaddr_in *saddr2 = (const struct sockaddr_in *)sa2; | 288 | const struct sockaddr_in *sin2 = (const struct sockaddr_in *)sa2; |
319 | 289 | ||
320 | if (saddr1->sin_addr.s_addr != saddr2->sin_addr.s_addr) | 290 | return nfs_sockaddr_match_ipaddr4(sa1, sa2) && |
291 | (sin1->sin_port == sin2->sin_port); | ||
292 | } | ||
293 | |||
294 | /* | ||
295 | * Test if two socket addresses represent the same actual socket, | ||
296 | * by comparing (only) relevant fields, excluding the port number. | ||
297 | */ | ||
298 | static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1, | ||
299 | const struct sockaddr *sa2) | ||
300 | { | ||
301 | if (sa1->sa_family != sa2->sa_family) | ||
321 | return 0; | 302 | return 0; |
322 | return saddr1->sin_port == saddr2->sin_port; | 303 | |
304 | switch (sa1->sa_family) { | ||
305 | case AF_INET: | ||
306 | return nfs_sockaddr_match_ipaddr4(sa1, sa2); | ||
307 | case AF_INET6: | ||
308 | return nfs_sockaddr_match_ipaddr6(sa1, sa2); | ||
309 | } | ||
310 | return 0; | ||
323 | } | 311 | } |
324 | 312 | ||
325 | /* | 313 | /* |
326 | * Test if two socket addresses represent the same actual socket, | 314 | * Test if two socket addresses represent the same actual socket, |
327 | * by comparing (only) relevant fields. | 315 | * by comparing (only) relevant fields, including the port number. |
328 | */ | 316 | */ |
329 | static int nfs_sockaddr_cmp(const struct sockaddr *sa1, | 317 | static int nfs_sockaddr_cmp(const struct sockaddr *sa1, |
330 | const struct sockaddr *sa2) | 318 | const struct sockaddr *sa2) |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 78bf72fc1db3..370b190a09d1 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -1624,8 +1624,7 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1624 | } else if (atomic_read(&new_dentry->d_count) > 1) | 1624 | } else if (atomic_read(&new_dentry->d_count) > 1) |
1625 | /* dentry still busy? */ | 1625 | /* dentry still busy? */ |
1626 | goto out; | 1626 | goto out; |
1627 | } else | 1627 | } |
1628 | nfs_drop_nlink(new_inode); | ||
1629 | 1628 | ||
1630 | go_ahead: | 1629 | go_ahead: |
1631 | /* | 1630 | /* |
@@ -1638,10 +1637,8 @@ go_ahead: | |||
1638 | } | 1637 | } |
1639 | nfs_inode_return_delegation(old_inode); | 1638 | nfs_inode_return_delegation(old_inode); |
1640 | 1639 | ||
1641 | if (new_inode != NULL) { | 1640 | if (new_inode != NULL) |
1642 | nfs_inode_return_delegation(new_inode); | 1641 | nfs_inode_return_delegation(new_inode); |
1643 | d_delete(new_dentry); | ||
1644 | } | ||
1645 | 1642 | ||
1646 | error = NFS_PROTO(old_dir)->rename(old_dir, &old_dentry->d_name, | 1643 | error = NFS_PROTO(old_dir)->rename(old_dir, &old_dentry->d_name, |
1647 | new_dir, &new_dentry->d_name); | 1644 | new_dir, &new_dentry->d_name); |
@@ -1650,6 +1647,8 @@ out: | |||
1650 | if (rehash) | 1647 | if (rehash) |
1651 | d_rehash(rehash); | 1648 | d_rehash(rehash); |
1652 | if (!error) { | 1649 | if (!error) { |
1650 | if (new_inode != NULL) | ||
1651 | nfs_drop_nlink(new_inode); | ||
1653 | d_move(old_dentry, new_dentry); | 1652 | d_move(old_dentry, new_dentry); |
1654 | nfs_set_verifier(new_dentry, | 1653 | nfs_set_verifier(new_dentry, |
1655 | nfs_save_change_attribute(new_dir)); | 1654 | nfs_save_change_attribute(new_dir)); |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index cec79392e4ba..0abf3f331f56 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -64,11 +64,7 @@ const struct file_operations nfs_file_operations = { | |||
64 | .write = do_sync_write, | 64 | .write = do_sync_write, |
65 | .aio_read = nfs_file_read, | 65 | .aio_read = nfs_file_read, |
66 | .aio_write = nfs_file_write, | 66 | .aio_write = nfs_file_write, |
67 | #ifdef CONFIG_MMU | ||
68 | .mmap = nfs_file_mmap, | 67 | .mmap = nfs_file_mmap, |
69 | #else | ||
70 | .mmap = generic_file_mmap, | ||
71 | #endif | ||
72 | .open = nfs_file_open, | 68 | .open = nfs_file_open, |
73 | .flush = nfs_file_flush, | 69 | .flush = nfs_file_flush, |
74 | .release = nfs_file_release, | 70 | .release = nfs_file_release, |
@@ -141,9 +137,6 @@ nfs_file_release(struct inode *inode, struct file *filp) | |||
141 | dentry->d_parent->d_name.name, | 137 | dentry->d_parent->d_name.name, |
142 | dentry->d_name.name); | 138 | dentry->d_name.name); |
143 | 139 | ||
144 | /* Ensure that dirty pages are flushed out with the right creds */ | ||
145 | if (filp->f_mode & FMODE_WRITE) | ||
146 | nfs_wb_all(dentry->d_inode); | ||
147 | nfs_inc_stats(inode, NFSIOS_VFSRELEASE); | 140 | nfs_inc_stats(inode, NFSIOS_VFSRELEASE); |
148 | return nfs_release(inode, filp); | 141 | return nfs_release(inode, filp); |
149 | } | 142 | } |
@@ -235,7 +228,6 @@ nfs_file_flush(struct file *file, fl_owner_t id) | |||
235 | struct nfs_open_context *ctx = nfs_file_open_context(file); | 228 | struct nfs_open_context *ctx = nfs_file_open_context(file); |
236 | struct dentry *dentry = file->f_path.dentry; | 229 | struct dentry *dentry = file->f_path.dentry; |
237 | struct inode *inode = dentry->d_inode; | 230 | struct inode *inode = dentry->d_inode; |
238 | int status; | ||
239 | 231 | ||
240 | dprintk("NFS: flush(%s/%s)\n", | 232 | dprintk("NFS: flush(%s/%s)\n", |
241 | dentry->d_parent->d_name.name, | 233 | dentry->d_parent->d_name.name, |
@@ -245,11 +237,8 @@ nfs_file_flush(struct file *file, fl_owner_t id) | |||
245 | return 0; | 237 | return 0; |
246 | nfs_inc_stats(inode, NFSIOS_VFSFLUSH); | 238 | nfs_inc_stats(inode, NFSIOS_VFSFLUSH); |
247 | 239 | ||
248 | /* Ensure that data+attribute caches are up to date after close() */ | 240 | /* Flush writes to the server and return any errors */ |
249 | status = nfs_do_fsync(ctx, inode); | 241 | return nfs_do_fsync(ctx, inode); |
250 | if (!status) | ||
251 | nfs_revalidate_inode(NFS_SERVER(inode), inode); | ||
252 | return status; | ||
253 | } | 242 | } |
254 | 243 | ||
255 | static ssize_t | 244 | static ssize_t |
@@ -304,11 +293,13 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma) | |||
304 | dprintk("NFS: mmap(%s/%s)\n", | 293 | dprintk("NFS: mmap(%s/%s)\n", |
305 | dentry->d_parent->d_name.name, dentry->d_name.name); | 294 | dentry->d_parent->d_name.name, dentry->d_name.name); |
306 | 295 | ||
307 | status = nfs_revalidate_mapping(inode, file->f_mapping); | 296 | /* Note: generic_file_mmap() returns ENOSYS on nommu systems |
297 | * so we call that before revalidating the mapping | ||
298 | */ | ||
299 | status = generic_file_mmap(file, vma); | ||
308 | if (!status) { | 300 | if (!status) { |
309 | vma->vm_ops = &nfs_file_vm_ops; | 301 | vma->vm_ops = &nfs_file_vm_ops; |
310 | vma->vm_flags |= VM_CAN_NONLINEAR; | 302 | status = nfs_revalidate_mapping(inode, file->f_mapping); |
311 | file_accessed(file); | ||
312 | } | 303 | } |
313 | return status; | 304 | return status; |
314 | } | 305 | } |
@@ -354,6 +345,15 @@ static int nfs_write_begin(struct file *file, struct address_space *mapping, | |||
354 | file->f_path.dentry->d_name.name, | 345 | file->f_path.dentry->d_name.name, |
355 | mapping->host->i_ino, len, (long long) pos); | 346 | mapping->host->i_ino, len, (long long) pos); |
356 | 347 | ||
348 | /* | ||
349 | * Prevent starvation issues if someone is doing a consistency | ||
350 | * sync-to-disk | ||
351 | */ | ||
352 | ret = wait_on_bit(&NFS_I(mapping->host)->flags, NFS_INO_FLUSHING, | ||
353 | nfs_wait_bit_killable, TASK_KILLABLE); | ||
354 | if (ret) | ||
355 | return ret; | ||
356 | |||
357 | page = grab_cache_page_write_begin(mapping, index, flags); | 357 | page = grab_cache_page_write_begin(mapping, index, flags); |
358 | if (!page) | 358 | if (!page) |
359 | return -ENOMEM; | 359 | return -ENOMEM; |
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c index b7c9b2df1f29..46177cb87064 100644 --- a/fs/nfs/getroot.c +++ b/fs/nfs/getroot.c | |||
@@ -156,7 +156,7 @@ int nfs4_path_walk(struct nfs_server *server, | |||
156 | return ret; | 156 | return ret; |
157 | } | 157 | } |
158 | 158 | ||
159 | if (fattr.type != NFDIR) { | 159 | if (!S_ISDIR(fattr.mode)) { |
160 | printk(KERN_ERR "nfs4_get_root:" | 160 | printk(KERN_ERR "nfs4_get_root:" |
161 | " getroot encountered non-directory\n"); | 161 | " getroot encountered non-directory\n"); |
162 | return -ENOTDIR; | 162 | return -ENOTDIR; |
@@ -213,7 +213,7 @@ eat_dot_dir: | |||
213 | return ret; | 213 | return ret; |
214 | } | 214 | } |
215 | 215 | ||
216 | if (fattr.type != NFDIR) { | 216 | if (!S_ISDIR(fattr.mode)) { |
217 | printk(KERN_ERR "nfs4_get_root:" | 217 | printk(KERN_ERR "nfs4_get_root:" |
218 | " lookupfh encountered non-directory\n"); | 218 | " lookupfh encountered non-directory\n"); |
219 | return -ENOTDIR; | 219 | return -ENOTDIR; |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 0c381686171e..a834d1d850b7 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -66,6 +66,18 @@ nfs_fattr_to_ino_t(struct nfs_fattr *fattr) | |||
66 | } | 66 | } |
67 | 67 | ||
68 | /** | 68 | /** |
69 | * nfs_wait_bit_killable - helper for functions that are sleeping on bit locks | ||
70 | * @word: long word containing the bit lock | ||
71 | */ | ||
72 | int nfs_wait_bit_killable(void *word) | ||
73 | { | ||
74 | if (fatal_signal_pending(current)) | ||
75 | return -ERESTARTSYS; | ||
76 | schedule(); | ||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | /** | ||
69 | * nfs_compat_user_ino64 - returns the user-visible inode number | 81 | * nfs_compat_user_ino64 - returns the user-visible inode number |
70 | * @fileid: 64-bit fileid | 82 | * @fileid: 64-bit fileid |
71 | * | 83 | * |
@@ -249,13 +261,10 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
249 | struct inode *inode = ERR_PTR(-ENOENT); | 261 | struct inode *inode = ERR_PTR(-ENOENT); |
250 | unsigned long hash; | 262 | unsigned long hash; |
251 | 263 | ||
252 | if ((fattr->valid & NFS_ATTR_FATTR) == 0) | 264 | if ((fattr->valid & NFS_ATTR_FATTR_FILEID) == 0) |
253 | goto out_no_inode; | 265 | goto out_no_inode; |
254 | 266 | if ((fattr->valid & NFS_ATTR_FATTR_TYPE) == 0) | |
255 | if (!fattr->nlink) { | ||
256 | printk("NFS: Buggy server - nlink == 0!\n"); | ||
257 | goto out_no_inode; | 267 | goto out_no_inode; |
258 | } | ||
259 | 268 | ||
260 | hash = nfs_fattr_to_ino_t(fattr); | 269 | hash = nfs_fattr_to_ino_t(fattr); |
261 | 270 | ||
@@ -291,7 +300,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
291 | && fattr->size <= NFS_LIMIT_READDIRPLUS) | 300 | && fattr->size <= NFS_LIMIT_READDIRPLUS) |
292 | set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); | 301 | set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); |
293 | /* Deal with crossing mountpoints */ | 302 | /* Deal with crossing mountpoints */ |
294 | if (!nfs_fsid_equal(&NFS_SB(sb)->fsid, &fattr->fsid)) { | 303 | if ((fattr->valid & NFS_ATTR_FATTR_FSID) |
304 | && !nfs_fsid_equal(&NFS_SB(sb)->fsid, &fattr->fsid)) { | ||
295 | if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) | 305 | if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) |
296 | inode->i_op = &nfs_referral_inode_operations; | 306 | inode->i_op = &nfs_referral_inode_operations; |
297 | else | 307 | else |
@@ -304,28 +314,45 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
304 | else | 314 | else |
305 | init_special_inode(inode, inode->i_mode, fattr->rdev); | 315 | init_special_inode(inode, inode->i_mode, fattr->rdev); |
306 | 316 | ||
317 | memset(&inode->i_atime, 0, sizeof(inode->i_atime)); | ||
318 | memset(&inode->i_mtime, 0, sizeof(inode->i_mtime)); | ||
319 | memset(&inode->i_ctime, 0, sizeof(inode->i_ctime)); | ||
320 | nfsi->change_attr = 0; | ||
321 | inode->i_size = 0; | ||
322 | inode->i_nlink = 0; | ||
323 | inode->i_uid = -2; | ||
324 | inode->i_gid = -2; | ||
325 | inode->i_blocks = 0; | ||
326 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); | ||
327 | |||
307 | nfsi->read_cache_jiffies = fattr->time_start; | 328 | nfsi->read_cache_jiffies = fattr->time_start; |
308 | nfsi->attr_gencount = fattr->gencount; | 329 | nfsi->attr_gencount = fattr->gencount; |
309 | inode->i_atime = fattr->atime; | 330 | if (fattr->valid & NFS_ATTR_FATTR_ATIME) |
310 | inode->i_mtime = fattr->mtime; | 331 | inode->i_atime = fattr->atime; |
311 | inode->i_ctime = fattr->ctime; | 332 | if (fattr->valid & NFS_ATTR_FATTR_MTIME) |
312 | if (fattr->valid & NFS_ATTR_FATTR_V4) | 333 | inode->i_mtime = fattr->mtime; |
334 | if (fattr->valid & NFS_ATTR_FATTR_CTIME) | ||
335 | inode->i_ctime = fattr->ctime; | ||
336 | if (fattr->valid & NFS_ATTR_FATTR_CHANGE) | ||
313 | nfsi->change_attr = fattr->change_attr; | 337 | nfsi->change_attr = fattr->change_attr; |
314 | inode->i_size = nfs_size_to_loff_t(fattr->size); | 338 | if (fattr->valid & NFS_ATTR_FATTR_SIZE) |
315 | inode->i_nlink = fattr->nlink; | 339 | inode->i_size = nfs_size_to_loff_t(fattr->size); |
316 | inode->i_uid = fattr->uid; | 340 | if (fattr->valid & NFS_ATTR_FATTR_NLINK) |
317 | inode->i_gid = fattr->gid; | 341 | inode->i_nlink = fattr->nlink; |
318 | if (fattr->valid & (NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4)) { | 342 | if (fattr->valid & NFS_ATTR_FATTR_OWNER) |
343 | inode->i_uid = fattr->uid; | ||
344 | if (fattr->valid & NFS_ATTR_FATTR_GROUP) | ||
345 | inode->i_gid = fattr->gid; | ||
346 | if (fattr->valid & NFS_ATTR_FATTR_BLOCKS_USED) | ||
347 | inode->i_blocks = fattr->du.nfs2.blocks; | ||
348 | if (fattr->valid & NFS_ATTR_FATTR_SPACE_USED) { | ||
319 | /* | 349 | /* |
320 | * report the blocks in 512byte units | 350 | * report the blocks in 512byte units |
321 | */ | 351 | */ |
322 | inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used); | 352 | inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used); |
323 | } else { | ||
324 | inode->i_blocks = fattr->du.nfs2.blocks; | ||
325 | } | 353 | } |
326 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); | 354 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
327 | nfsi->attrtimeo_timestamp = now; | 355 | nfsi->attrtimeo_timestamp = now; |
328 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); | ||
329 | nfsi->access_cache = RB_ROOT; | 356 | nfsi->access_cache = RB_ROOT; |
330 | 357 | ||
331 | unlock_new_inode(inode); | 358 | unlock_new_inode(inode); |
@@ -514,6 +541,32 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | |||
514 | return err; | 541 | return err; |
515 | } | 542 | } |
516 | 543 | ||
544 | /** | ||
545 | * nfs_close_context - Common close_context() routine NFSv2/v3 | ||
546 | * @ctx: pointer to context | ||
547 | * @is_sync: is this a synchronous close | ||
548 | * | ||
549 | * always ensure that the attributes are up to date if we're mounted | ||
550 | * with close-to-open semantics | ||
551 | */ | ||
552 | void nfs_close_context(struct nfs_open_context *ctx, int is_sync) | ||
553 | { | ||
554 | struct inode *inode; | ||
555 | struct nfs_server *server; | ||
556 | |||
557 | if (!(ctx->mode & FMODE_WRITE)) | ||
558 | return; | ||
559 | if (!is_sync) | ||
560 | return; | ||
561 | inode = ctx->path.dentry->d_inode; | ||
562 | if (!list_empty(&NFS_I(inode)->open_files)) | ||
563 | return; | ||
564 | server = NFS_SERVER(inode); | ||
565 | if (server->flags & NFS_MOUNT_NOCTO) | ||
566 | return; | ||
567 | nfs_revalidate_inode(server, inode); | ||
568 | } | ||
569 | |||
517 | static struct nfs_open_context *alloc_nfs_open_context(struct vfsmount *mnt, struct dentry *dentry, struct rpc_cred *cred) | 570 | static struct nfs_open_context *alloc_nfs_open_context(struct vfsmount *mnt, struct dentry *dentry, struct rpc_cred *cred) |
518 | { | 571 | { |
519 | struct nfs_open_context *ctx; | 572 | struct nfs_open_context *ctx; |
@@ -540,24 +593,15 @@ struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx) | |||
540 | return ctx; | 593 | return ctx; |
541 | } | 594 | } |
542 | 595 | ||
543 | static void __put_nfs_open_context(struct nfs_open_context *ctx, int wait) | 596 | static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync) |
544 | { | 597 | { |
545 | struct inode *inode; | 598 | struct inode *inode = ctx->path.dentry->d_inode; |
546 | |||
547 | if (ctx == NULL) | ||
548 | return; | ||
549 | 599 | ||
550 | inode = ctx->path.dentry->d_inode; | ||
551 | if (!atomic_dec_and_lock(&ctx->count, &inode->i_lock)) | 600 | if (!atomic_dec_and_lock(&ctx->count, &inode->i_lock)) |
552 | return; | 601 | return; |
553 | list_del(&ctx->list); | 602 | list_del(&ctx->list); |
554 | spin_unlock(&inode->i_lock); | 603 | spin_unlock(&inode->i_lock); |
555 | if (ctx->state != NULL) { | 604 | NFS_PROTO(inode)->close_context(ctx, is_sync); |
556 | if (wait) | ||
557 | nfs4_close_sync(&ctx->path, ctx->state, ctx->mode); | ||
558 | else | ||
559 | nfs4_close_state(&ctx->path, ctx->state, ctx->mode); | ||
560 | } | ||
561 | if (ctx->cred != NULL) | 605 | if (ctx->cred != NULL) |
562 | put_rpccred(ctx->cred); | 606 | put_rpccred(ctx->cred); |
563 | path_put(&ctx->path); | 607 | path_put(&ctx->path); |
@@ -670,9 +714,6 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
670 | if (NFS_STALE(inode)) | 714 | if (NFS_STALE(inode)) |
671 | goto out; | 715 | goto out; |
672 | 716 | ||
673 | if (NFS_STALE(inode)) | ||
674 | goto out; | ||
675 | |||
676 | nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE); | 717 | nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE); |
677 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr); | 718 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr); |
678 | if (status != 0) { | 719 | if (status != 0) { |
@@ -815,25 +856,31 @@ static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
815 | { | 856 | { |
816 | struct nfs_inode *nfsi = NFS_I(inode); | 857 | struct nfs_inode *nfsi = NFS_I(inode); |
817 | 858 | ||
818 | if ((fattr->valid & NFS_ATTR_WCC_V4) != 0 && | 859 | if ((fattr->valid & NFS_ATTR_FATTR_PRECHANGE) |
819 | nfsi->change_attr == fattr->pre_change_attr) { | 860 | && (fattr->valid & NFS_ATTR_FATTR_CHANGE) |
861 | && nfsi->change_attr == fattr->pre_change_attr) { | ||
820 | nfsi->change_attr = fattr->change_attr; | 862 | nfsi->change_attr = fattr->change_attr; |
821 | if (S_ISDIR(inode->i_mode)) | 863 | if (S_ISDIR(inode->i_mode)) |
822 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; | 864 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; |
823 | } | 865 | } |
824 | /* If we have atomic WCC data, we may update some attributes */ | 866 | /* If we have atomic WCC data, we may update some attributes */ |
825 | if ((fattr->valid & NFS_ATTR_WCC) != 0) { | 867 | if ((fattr->valid & NFS_ATTR_FATTR_PRECTIME) |
826 | if (timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) | 868 | && (fattr->valid & NFS_ATTR_FATTR_CTIME) |
869 | && timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) | ||
827 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); | 870 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); |
828 | if (timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) { | 871 | |
872 | if ((fattr->valid & NFS_ATTR_FATTR_PREMTIME) | ||
873 | && (fattr->valid & NFS_ATTR_FATTR_MTIME) | ||
874 | && timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) { | ||
829 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); | 875 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); |
830 | if (S_ISDIR(inode->i_mode)) | 876 | if (S_ISDIR(inode->i_mode)) |
831 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; | 877 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; |
832 | } | ||
833 | if (i_size_read(inode) == nfs_size_to_loff_t(fattr->pre_size) && | ||
834 | nfsi->npages == 0) | ||
835 | i_size_write(inode, nfs_size_to_loff_t(fattr->size)); | ||
836 | } | 878 | } |
879 | if ((fattr->valid & NFS_ATTR_FATTR_PRESIZE) | ||
880 | && (fattr->valid & NFS_ATTR_FATTR_SIZE) | ||
881 | && i_size_read(inode) == nfs_size_to_loff_t(fattr->pre_size) | ||
882 | && nfsi->npages == 0) | ||
883 | i_size_write(inode, nfs_size_to_loff_t(fattr->size)); | ||
837 | } | 884 | } |
838 | 885 | ||
839 | /** | 886 | /** |
@@ -853,35 +900,39 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat | |||
853 | 900 | ||
854 | 901 | ||
855 | /* Has the inode gone and changed behind our back? */ | 902 | /* Has the inode gone and changed behind our back? */ |
856 | if (nfsi->fileid != fattr->fileid | 903 | if ((fattr->valid & NFS_ATTR_FATTR_FILEID) && nfsi->fileid != fattr->fileid) |
857 | || (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) { | 904 | return -EIO; |
905 | if ((fattr->valid & NFS_ATTR_FATTR_TYPE) && (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) | ||
858 | return -EIO; | 906 | return -EIO; |
859 | } | ||
860 | 907 | ||
861 | if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 && | 908 | if ((fattr->valid & NFS_ATTR_FATTR_CHANGE) != 0 && |
862 | nfsi->change_attr != fattr->change_attr) | 909 | nfsi->change_attr != fattr->change_attr) |
863 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | 910 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; |
864 | 911 | ||
865 | /* Verify a few of the more important attributes */ | 912 | /* Verify a few of the more important attributes */ |
866 | if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) | 913 | if ((fattr->valid & NFS_ATTR_FATTR_MTIME) && !timespec_equal(&inode->i_mtime, &fattr->mtime)) |
867 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | 914 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; |
868 | 915 | ||
869 | cur_size = i_size_read(inode); | 916 | if (fattr->valid & NFS_ATTR_FATTR_SIZE) { |
870 | new_isize = nfs_size_to_loff_t(fattr->size); | 917 | cur_size = i_size_read(inode); |
871 | if (cur_size != new_isize && nfsi->npages == 0) | 918 | new_isize = nfs_size_to_loff_t(fattr->size); |
872 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | 919 | if (cur_size != new_isize && nfsi->npages == 0) |
920 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | ||
921 | } | ||
873 | 922 | ||
874 | /* Have any file permissions changed? */ | 923 | /* Have any file permissions changed? */ |
875 | if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) | 924 | if ((fattr->valid & NFS_ATTR_FATTR_MODE) && (inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)) |
876 | || inode->i_uid != fattr->uid | 925 | invalid |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL; |
877 | || inode->i_gid != fattr->gid) | 926 | if ((fattr->valid & NFS_ATTR_FATTR_OWNER) && inode->i_uid != fattr->uid) |
927 | invalid |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL; | ||
928 | if ((fattr->valid & NFS_ATTR_FATTR_GROUP) && inode->i_gid != fattr->gid) | ||
878 | invalid |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL; | 929 | invalid |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL; |
879 | 930 | ||
880 | /* Has the link count changed? */ | 931 | /* Has the link count changed? */ |
881 | if (inode->i_nlink != fattr->nlink) | 932 | if ((fattr->valid & NFS_ATTR_FATTR_NLINK) && inode->i_nlink != fattr->nlink) |
882 | invalid |= NFS_INO_INVALID_ATTR; | 933 | invalid |= NFS_INO_INVALID_ATTR; |
883 | 934 | ||
884 | if (!timespec_equal(&inode->i_atime, &fattr->atime)) | 935 | if ((fattr->valid & NFS_ATTR_FATTR_ATIME) && !timespec_equal(&inode->i_atime, &fattr->atime)) |
885 | invalid |= NFS_INO_INVALID_ATIME; | 936 | invalid |= NFS_INO_INVALID_ATIME; |
886 | 937 | ||
887 | if (invalid != 0) | 938 | if (invalid != 0) |
@@ -893,11 +944,15 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat | |||
893 | 944 | ||
894 | static int nfs_ctime_need_update(const struct inode *inode, const struct nfs_fattr *fattr) | 945 | static int nfs_ctime_need_update(const struct inode *inode, const struct nfs_fattr *fattr) |
895 | { | 946 | { |
947 | if (!(fattr->valid & NFS_ATTR_FATTR_CTIME)) | ||
948 | return 0; | ||
896 | return timespec_compare(&fattr->ctime, &inode->i_ctime) > 0; | 949 | return timespec_compare(&fattr->ctime, &inode->i_ctime) > 0; |
897 | } | 950 | } |
898 | 951 | ||
899 | static int nfs_size_need_update(const struct inode *inode, const struct nfs_fattr *fattr) | 952 | static int nfs_size_need_update(const struct inode *inode, const struct nfs_fattr *fattr) |
900 | { | 953 | { |
954 | if (!(fattr->valid & NFS_ATTR_FATTR_SIZE)) | ||
955 | return 0; | ||
901 | return nfs_size_to_loff_t(fattr->size) > i_size_read(inode); | 956 | return nfs_size_to_loff_t(fattr->size) > i_size_read(inode); |
902 | } | 957 | } |
903 | 958 | ||
@@ -1033,20 +1088,31 @@ int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fa | |||
1033 | /* Don't do a WCC update if these attributes are already stale */ | 1088 | /* Don't do a WCC update if these attributes are already stale */ |
1034 | if ((fattr->valid & NFS_ATTR_FATTR) == 0 || | 1089 | if ((fattr->valid & NFS_ATTR_FATTR) == 0 || |
1035 | !nfs_inode_attrs_need_update(inode, fattr)) { | 1090 | !nfs_inode_attrs_need_update(inode, fattr)) { |
1036 | fattr->valid &= ~(NFS_ATTR_WCC_V4|NFS_ATTR_WCC); | 1091 | fattr->valid &= ~(NFS_ATTR_FATTR_PRECHANGE |
1092 | | NFS_ATTR_FATTR_PRESIZE | ||
1093 | | NFS_ATTR_FATTR_PREMTIME | ||
1094 | | NFS_ATTR_FATTR_PRECTIME); | ||
1037 | goto out_noforce; | 1095 | goto out_noforce; |
1038 | } | 1096 | } |
1039 | if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 && | 1097 | if ((fattr->valid & NFS_ATTR_FATTR_CHANGE) != 0 && |
1040 | (fattr->valid & NFS_ATTR_WCC_V4) == 0) { | 1098 | (fattr->valid & NFS_ATTR_FATTR_PRECHANGE) == 0) { |
1041 | fattr->pre_change_attr = NFS_I(inode)->change_attr; | 1099 | fattr->pre_change_attr = NFS_I(inode)->change_attr; |
1042 | fattr->valid |= NFS_ATTR_WCC_V4; | 1100 | fattr->valid |= NFS_ATTR_FATTR_PRECHANGE; |
1043 | } | 1101 | } |
1044 | if ((fattr->valid & NFS_ATTR_FATTR) != 0 && | 1102 | if ((fattr->valid & NFS_ATTR_FATTR_CTIME) != 0 && |
1045 | (fattr->valid & NFS_ATTR_WCC) == 0) { | 1103 | (fattr->valid & NFS_ATTR_FATTR_PRECTIME) == 0) { |
1046 | memcpy(&fattr->pre_ctime, &inode->i_ctime, sizeof(fattr->pre_ctime)); | 1104 | memcpy(&fattr->pre_ctime, &inode->i_ctime, sizeof(fattr->pre_ctime)); |
1105 | fattr->valid |= NFS_ATTR_FATTR_PRECTIME; | ||
1106 | } | ||
1107 | if ((fattr->valid & NFS_ATTR_FATTR_MTIME) != 0 && | ||
1108 | (fattr->valid & NFS_ATTR_FATTR_PREMTIME) == 0) { | ||
1047 | memcpy(&fattr->pre_mtime, &inode->i_mtime, sizeof(fattr->pre_mtime)); | 1109 | memcpy(&fattr->pre_mtime, &inode->i_mtime, sizeof(fattr->pre_mtime)); |
1110 | fattr->valid |= NFS_ATTR_FATTR_PREMTIME; | ||
1111 | } | ||
1112 | if ((fattr->valid & NFS_ATTR_FATTR_SIZE) != 0 && | ||
1113 | (fattr->valid & NFS_ATTR_FATTR_PRESIZE) == 0) { | ||
1048 | fattr->pre_size = i_size_read(inode); | 1114 | fattr->pre_size = i_size_read(inode); |
1049 | fattr->valid |= NFS_ATTR_WCC; | 1115 | fattr->valid |= NFS_ATTR_FATTR_PRESIZE; |
1050 | } | 1116 | } |
1051 | out_noforce: | 1117 | out_noforce: |
1052 | status = nfs_post_op_update_inode_locked(inode, fattr); | 1118 | status = nfs_post_op_update_inode_locked(inode, fattr); |
@@ -1078,18 +1144,18 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1078 | __func__, inode->i_sb->s_id, inode->i_ino, | 1144 | __func__, inode->i_sb->s_id, inode->i_ino, |
1079 | atomic_read(&inode->i_count), fattr->valid); | 1145 | atomic_read(&inode->i_count), fattr->valid); |
1080 | 1146 | ||
1081 | if (nfsi->fileid != fattr->fileid) | 1147 | if ((fattr->valid & NFS_ATTR_FATTR_FILEID) && nfsi->fileid != fattr->fileid) |
1082 | goto out_fileid; | 1148 | goto out_fileid; |
1083 | 1149 | ||
1084 | /* | 1150 | /* |
1085 | * Make sure the inode's type hasn't changed. | 1151 | * Make sure the inode's type hasn't changed. |
1086 | */ | 1152 | */ |
1087 | if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) | 1153 | if ((fattr->valid & NFS_ATTR_FATTR_TYPE) && (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) |
1088 | goto out_changed; | 1154 | goto out_changed; |
1089 | 1155 | ||
1090 | server = NFS_SERVER(inode); | 1156 | server = NFS_SERVER(inode); |
1091 | /* Update the fsid? */ | 1157 | /* Update the fsid? */ |
1092 | if (S_ISDIR(inode->i_mode) && | 1158 | if (S_ISDIR(inode->i_mode) && (fattr->valid & NFS_ATTR_FATTR_FSID) && |
1093 | !nfs_fsid_equal(&server->fsid, &fattr->fsid) && | 1159 | !nfs_fsid_equal(&server->fsid, &fattr->fsid) && |
1094 | !test_bit(NFS_INO_MOUNTPOINT, &nfsi->flags)) | 1160 | !test_bit(NFS_INO_MOUNTPOINT, &nfsi->flags)) |
1095 | server->fsid = fattr->fsid; | 1161 | server->fsid = fattr->fsid; |
@@ -1099,14 +1165,27 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1099 | */ | 1165 | */ |
1100 | nfsi->read_cache_jiffies = fattr->time_start; | 1166 | nfsi->read_cache_jiffies = fattr->time_start; |
1101 | 1167 | ||
1102 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ATIME | 1168 | if ((fattr->valid & NFS_ATTR_FATTR_CHANGE) || (fattr->valid & (NFS_ATTR_FATTR_MTIME|NFS_ATTR_FATTR_CTIME))) |
1103 | | NFS_INO_REVAL_PAGECACHE); | 1169 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR |
1170 | | NFS_INO_INVALID_ATIME | ||
1171 | | NFS_INO_REVAL_PAGECACHE); | ||
1104 | 1172 | ||
1105 | /* Do atomic weak cache consistency updates */ | 1173 | /* Do atomic weak cache consistency updates */ |
1106 | nfs_wcc_update_inode(inode, fattr); | 1174 | nfs_wcc_update_inode(inode, fattr); |
1107 | 1175 | ||
1108 | /* More cache consistency checks */ | 1176 | /* More cache consistency checks */ |
1109 | if (!(fattr->valid & NFS_ATTR_FATTR_V4)) { | 1177 | if (fattr->valid & NFS_ATTR_FATTR_CHANGE) { |
1178 | if (nfsi->change_attr != fattr->change_attr) { | ||
1179 | dprintk("NFS: change_attr change on server for file %s/%ld\n", | ||
1180 | inode->i_sb->s_id, inode->i_ino); | ||
1181 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | ||
1182 | if (S_ISDIR(inode->i_mode)) | ||
1183 | nfs_force_lookup_revalidate(inode); | ||
1184 | nfsi->change_attr = fattr->change_attr; | ||
1185 | } | ||
1186 | } | ||
1187 | |||
1188 | if (fattr->valid & NFS_ATTR_FATTR_MTIME) { | ||
1110 | /* NFSv2/v3: Check if the mtime agrees */ | 1189 | /* NFSv2/v3: Check if the mtime agrees */ |
1111 | if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) { | 1190 | if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) { |
1112 | dprintk("NFS: mtime change on server for file %s/%ld\n", | 1191 | dprintk("NFS: mtime change on server for file %s/%ld\n", |
@@ -1114,59 +1193,80 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1114 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1193 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
1115 | if (S_ISDIR(inode->i_mode)) | 1194 | if (S_ISDIR(inode->i_mode)) |
1116 | nfs_force_lookup_revalidate(inode); | 1195 | nfs_force_lookup_revalidate(inode); |
1196 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); | ||
1117 | } | 1197 | } |
1198 | } | ||
1199 | if (fattr->valid & NFS_ATTR_FATTR_CTIME) { | ||
1118 | /* If ctime has changed we should definitely clear access+acl caches */ | 1200 | /* If ctime has changed we should definitely clear access+acl caches */ |
1119 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) | 1201 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) { |
1120 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 1202 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |
1121 | } else if (nfsi->change_attr != fattr->change_attr) { | 1203 | /* and probably clear data for a directory too as utimes can cause |
1122 | dprintk("NFS: change_attr change on server for file %s/%ld\n", | 1204 | * havoc with our cache. |
1123 | inode->i_sb->s_id, inode->i_ino); | 1205 | */ |
1124 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 1206 | if (S_ISDIR(inode->i_mode)) { |
1125 | if (S_ISDIR(inode->i_mode)) | 1207 | invalid |= NFS_INO_INVALID_DATA; |
1126 | nfs_force_lookup_revalidate(inode); | 1208 | nfs_force_lookup_revalidate(inode); |
1209 | } | ||
1210 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); | ||
1211 | } | ||
1127 | } | 1212 | } |
1128 | 1213 | ||
1129 | /* Check if our cached file size is stale */ | 1214 | /* Check if our cached file size is stale */ |
1130 | new_isize = nfs_size_to_loff_t(fattr->size); | 1215 | if (fattr->valid & NFS_ATTR_FATTR_SIZE) { |
1131 | cur_isize = i_size_read(inode); | 1216 | new_isize = nfs_size_to_loff_t(fattr->size); |
1132 | if (new_isize != cur_isize) { | 1217 | cur_isize = i_size_read(inode); |
1133 | /* Do we perhaps have any outstanding writes, or has | 1218 | if (new_isize != cur_isize) { |
1134 | * the file grown beyond our last write? */ | 1219 | /* Do we perhaps have any outstanding writes, or has |
1135 | if (nfsi->npages == 0 || new_isize > cur_isize) { | 1220 | * the file grown beyond our last write? */ |
1136 | i_size_write(inode, new_isize); | 1221 | if (nfsi->npages == 0 || new_isize > cur_isize) { |
1137 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1222 | i_size_write(inode, new_isize); |
1223 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | ||
1224 | } | ||
1225 | dprintk("NFS: isize change on server for file %s/%ld\n", | ||
1226 | inode->i_sb->s_id, inode->i_ino); | ||
1138 | } | 1227 | } |
1139 | dprintk("NFS: isize change on server for file %s/%ld\n", | ||
1140 | inode->i_sb->s_id, inode->i_ino); | ||
1141 | } | 1228 | } |
1142 | 1229 | ||
1143 | 1230 | ||
1144 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); | 1231 | if (fattr->valid & NFS_ATTR_FATTR_ATIME) |
1145 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); | 1232 | memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime)); |
1146 | memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime)); | ||
1147 | nfsi->change_attr = fattr->change_attr; | ||
1148 | |||
1149 | if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) || | ||
1150 | inode->i_uid != fattr->uid || | ||
1151 | inode->i_gid != fattr->gid) | ||
1152 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | ||
1153 | 1233 | ||
1154 | if (inode->i_nlink != fattr->nlink) | 1234 | if (fattr->valid & NFS_ATTR_FATTR_MODE) { |
1155 | invalid |= NFS_INO_INVALID_ATTR; | 1235 | if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)) { |
1236 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | ||
1237 | inode->i_mode = fattr->mode; | ||
1238 | } | ||
1239 | } | ||
1240 | if (fattr->valid & NFS_ATTR_FATTR_OWNER) { | ||
1241 | if (inode->i_uid != fattr->uid) { | ||
1242 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | ||
1243 | inode->i_uid = fattr->uid; | ||
1244 | } | ||
1245 | } | ||
1246 | if (fattr->valid & NFS_ATTR_FATTR_GROUP) { | ||
1247 | if (inode->i_gid != fattr->gid) { | ||
1248 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | ||
1249 | inode->i_gid = fattr->gid; | ||
1250 | } | ||
1251 | } | ||
1156 | 1252 | ||
1157 | inode->i_mode = fattr->mode; | 1253 | if (fattr->valid & NFS_ATTR_FATTR_NLINK) { |
1158 | inode->i_nlink = fattr->nlink; | 1254 | if (inode->i_nlink != fattr->nlink) { |
1159 | inode->i_uid = fattr->uid; | 1255 | invalid |= NFS_INO_INVALID_ATTR; |
1160 | inode->i_gid = fattr->gid; | 1256 | if (S_ISDIR(inode->i_mode)) |
1257 | invalid |= NFS_INO_INVALID_DATA; | ||
1258 | inode->i_nlink = fattr->nlink; | ||
1259 | } | ||
1260 | } | ||
1161 | 1261 | ||
1162 | if (fattr->valid & (NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4)) { | 1262 | if (fattr->valid & NFS_ATTR_FATTR_SPACE_USED) { |
1163 | /* | 1263 | /* |
1164 | * report the blocks in 512byte units | 1264 | * report the blocks in 512byte units |
1165 | */ | 1265 | */ |
1166 | inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used); | 1266 | inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used); |
1167 | } else { | ||
1168 | inode->i_blocks = fattr->du.nfs2.blocks; | ||
1169 | } | 1267 | } |
1268 | if (fattr->valid & NFS_ATTR_FATTR_BLOCKS_USED) | ||
1269 | inode->i_blocks = fattr->du.nfs2.blocks; | ||
1170 | 1270 | ||
1171 | /* Update attrtimeo value if we're out of the unstable period */ | 1271 | /* Update attrtimeo value if we're out of the unstable period */ |
1172 | if (invalid & NFS_INO_INVALID_ATTR) { | 1272 | if (invalid & NFS_INO_INVALID_ATTR) { |
@@ -1274,7 +1374,6 @@ static void init_once(void *foo) | |||
1274 | INIT_LIST_HEAD(&nfsi->access_cache_entry_lru); | 1374 | INIT_LIST_HEAD(&nfsi->access_cache_entry_lru); |
1275 | INIT_LIST_HEAD(&nfsi->access_cache_inode_lru); | 1375 | INIT_LIST_HEAD(&nfsi->access_cache_inode_lru); |
1276 | INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC); | 1376 | INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC); |
1277 | nfsi->ncommit = 0; | ||
1278 | nfsi->npages = 0; | 1377 | nfsi->npages = 0; |
1279 | atomic_set(&nfsi->silly_count, 1); | 1378 | atomic_set(&nfsi->silly_count, 1); |
1280 | INIT_HLIST_HEAD(&nfsi->silly_list); | 1379 | INIT_HLIST_HEAD(&nfsi->silly_list); |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 340ede8f608f..2041f68ff1cc 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -152,6 +152,9 @@ extern __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus); | |||
152 | extern struct rpc_procinfo nfs4_procedures[]; | 152 | extern struct rpc_procinfo nfs4_procedures[]; |
153 | #endif | 153 | #endif |
154 | 154 | ||
155 | /* proc.c */ | ||
156 | void nfs_close_context(struct nfs_open_context *ctx, int is_sync); | ||
157 | |||
155 | /* dir.c */ | 158 | /* dir.c */ |
156 | extern int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask); | 159 | extern int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask); |
157 | 160 | ||
@@ -165,6 +168,7 @@ extern void nfs_clear_inode(struct inode *); | |||
165 | extern void nfs4_clear_inode(struct inode *); | 168 | extern void nfs4_clear_inode(struct inode *); |
166 | #endif | 169 | #endif |
167 | void nfs_zap_acl_cache(struct inode *inode); | 170 | void nfs_zap_acl_cache(struct inode *inode); |
171 | extern int nfs_wait_bit_killable(void *word); | ||
168 | 172 | ||
169 | /* super.c */ | 173 | /* super.c */ |
170 | void nfs_parse_ip_address(char *, size_t, struct sockaddr *, size_t *); | 174 | void nfs_parse_ip_address(char *, size_t, struct sockaddr *, size_t *); |
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c index 28bab67d1519..c862c9340f9a 100644 --- a/fs/nfs/nfs2xdr.c +++ b/fs/nfs/nfs2xdr.c | |||
@@ -120,8 +120,8 @@ xdr_decode_time(__be32 *p, struct timespec *timep) | |||
120 | static __be32 * | 120 | static __be32 * |
121 | xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr) | 121 | xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr) |
122 | { | 122 | { |
123 | u32 rdev; | 123 | u32 rdev, type; |
124 | fattr->type = (enum nfs_ftype) ntohl(*p++); | 124 | type = ntohl(*p++); |
125 | fattr->mode = ntohl(*p++); | 125 | fattr->mode = ntohl(*p++); |
126 | fattr->nlink = ntohl(*p++); | 126 | fattr->nlink = ntohl(*p++); |
127 | fattr->uid = ntohl(*p++); | 127 | fattr->uid = ntohl(*p++); |
@@ -136,10 +136,9 @@ xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr) | |||
136 | p = xdr_decode_time(p, &fattr->atime); | 136 | p = xdr_decode_time(p, &fattr->atime); |
137 | p = xdr_decode_time(p, &fattr->mtime); | 137 | p = xdr_decode_time(p, &fattr->mtime); |
138 | p = xdr_decode_time(p, &fattr->ctime); | 138 | p = xdr_decode_time(p, &fattr->ctime); |
139 | fattr->valid |= NFS_ATTR_FATTR; | 139 | fattr->valid |= NFS_ATTR_FATTR_V2; |
140 | fattr->rdev = new_decode_dev(rdev); | 140 | fattr->rdev = new_decode_dev(rdev); |
141 | if (fattr->type == NFCHR && rdev == NFS2_FIFO_DEV) { | 141 | if (type == NFCHR && rdev == NFS2_FIFO_DEV) { |
142 | fattr->type = NFFIFO; | ||
143 | fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO; | 142 | fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO; |
144 | fattr->rdev = 0; | 143 | fattr->rdev = 0; |
145 | } | 144 | } |
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index c55be7a7679e..b82fe6847f14 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c | |||
@@ -834,4 +834,5 @@ const struct nfs_rpc_ops nfs_v3_clientops = { | |||
834 | .commit_done = nfs3_commit_done, | 834 | .commit_done = nfs3_commit_done, |
835 | .lock = nfs3_proc_lock, | 835 | .lock = nfs3_proc_lock, |
836 | .clear_acl_cache = nfs3_forget_cached_acls, | 836 | .clear_acl_cache = nfs3_forget_cached_acls, |
837 | .close_context = nfs_close_context, | ||
837 | }; | 838 | }; |
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c index 6cdeacffde46..e6a1932c7110 100644 --- a/fs/nfs/nfs3xdr.c +++ b/fs/nfs/nfs3xdr.c | |||
@@ -91,19 +91,15 @@ | |||
91 | /* | 91 | /* |
92 | * Map file type to S_IFMT bits | 92 | * Map file type to S_IFMT bits |
93 | */ | 93 | */ |
94 | static struct { | 94 | static const umode_t nfs_type2fmt[] = { |
95 | unsigned int mode; | 95 | [NF3BAD] = 0, |
96 | unsigned int nfs2type; | 96 | [NF3REG] = S_IFREG, |
97 | } nfs_type2fmt[] = { | 97 | [NF3DIR] = S_IFDIR, |
98 | { 0, NFNON }, | 98 | [NF3BLK] = S_IFBLK, |
99 | { S_IFREG, NFREG }, | 99 | [NF3CHR] = S_IFCHR, |
100 | { S_IFDIR, NFDIR }, | 100 | [NF3LNK] = S_IFLNK, |
101 | { S_IFBLK, NFBLK }, | 101 | [NF3SOCK] = S_IFSOCK, |
102 | { S_IFCHR, NFCHR }, | 102 | [NF3FIFO] = S_IFIFO, |
103 | { S_IFLNK, NFLNK }, | ||
104 | { S_IFSOCK, NFSOCK }, | ||
105 | { S_IFIFO, NFFIFO }, | ||
106 | { 0, NFBAD } | ||
107 | }; | 103 | }; |
108 | 104 | ||
109 | /* | 105 | /* |
@@ -148,13 +144,12 @@ static __be32 * | |||
148 | xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr) | 144 | xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr) |
149 | { | 145 | { |
150 | unsigned int type, major, minor; | 146 | unsigned int type, major, minor; |
151 | int fmode; | 147 | umode_t fmode; |
152 | 148 | ||
153 | type = ntohl(*p++); | 149 | type = ntohl(*p++); |
154 | if (type >= NF3BAD) | 150 | if (type > NF3FIFO) |
155 | type = NF3BAD; | 151 | type = NF3NON; |
156 | fmode = nfs_type2fmt[type].mode; | 152 | fmode = nfs_type2fmt[type]; |
157 | fattr->type = nfs_type2fmt[type].nfs2type; | ||
158 | fattr->mode = (ntohl(*p++) & ~S_IFMT) | fmode; | 153 | fattr->mode = (ntohl(*p++) & ~S_IFMT) | fmode; |
159 | fattr->nlink = ntohl(*p++); | 154 | fattr->nlink = ntohl(*p++); |
160 | fattr->uid = ntohl(*p++); | 155 | fattr->uid = ntohl(*p++); |
@@ -177,7 +172,7 @@ xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr) | |||
177 | p = xdr_decode_time3(p, &fattr->ctime); | 172 | p = xdr_decode_time3(p, &fattr->ctime); |
178 | 173 | ||
179 | /* Update the mode bits */ | 174 | /* Update the mode bits */ |
180 | fattr->valid |= (NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3); | 175 | fattr->valid |= NFS_ATTR_FATTR_V3; |
181 | return p; | 176 | return p; |
182 | } | 177 | } |
183 | 178 | ||
@@ -233,7 +228,9 @@ xdr_decode_wcc_attr(__be32 *p, struct nfs_fattr *fattr) | |||
233 | p = xdr_decode_hyper(p, &fattr->pre_size); | 228 | p = xdr_decode_hyper(p, &fattr->pre_size); |
234 | p = xdr_decode_time3(p, &fattr->pre_mtime); | 229 | p = xdr_decode_time3(p, &fattr->pre_mtime); |
235 | p = xdr_decode_time3(p, &fattr->pre_ctime); | 230 | p = xdr_decode_time3(p, &fattr->pre_ctime); |
236 | fattr->valid |= NFS_ATTR_WCC; | 231 | fattr->valid |= NFS_ATTR_FATTR_PRESIZE |
232 | | NFS_ATTR_FATTR_PREMTIME | ||
233 | | NFS_ATTR_FATTR_PRECTIME; | ||
237 | return p; | 234 | return p; |
238 | } | 235 | } |
239 | 236 | ||
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 8dde84b988d9..97bacccff579 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -193,14 +193,6 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent | |||
193 | kunmap_atomic(start, KM_USER0); | 193 | kunmap_atomic(start, KM_USER0); |
194 | } | 194 | } |
195 | 195 | ||
196 | static int nfs4_wait_bit_killable(void *word) | ||
197 | { | ||
198 | if (fatal_signal_pending(current)) | ||
199 | return -ERESTARTSYS; | ||
200 | schedule(); | ||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | static int nfs4_wait_clnt_recover(struct nfs_client *clp) | 196 | static int nfs4_wait_clnt_recover(struct nfs_client *clp) |
205 | { | 197 | { |
206 | int res; | 198 | int res; |
@@ -208,7 +200,7 @@ static int nfs4_wait_clnt_recover(struct nfs_client *clp) | |||
208 | might_sleep(); | 200 | might_sleep(); |
209 | 201 | ||
210 | res = wait_on_bit(&clp->cl_state, NFS4CLNT_MANAGER_RUNNING, | 202 | res = wait_on_bit(&clp->cl_state, NFS4CLNT_MANAGER_RUNNING, |
211 | nfs4_wait_bit_killable, TASK_KILLABLE); | 203 | nfs_wait_bit_killable, TASK_KILLABLE); |
212 | return res; | 204 | return res; |
213 | } | 205 | } |
214 | 206 | ||
@@ -1439,7 +1431,7 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait) | |||
1439 | if (calldata->arg.seqid == NULL) | 1431 | if (calldata->arg.seqid == NULL) |
1440 | goto out_free_calldata; | 1432 | goto out_free_calldata; |
1441 | calldata->arg.fmode = 0; | 1433 | calldata->arg.fmode = 0; |
1442 | calldata->arg.bitmask = server->attr_bitmask; | 1434 | calldata->arg.bitmask = server->cache_consistency_bitmask; |
1443 | calldata->res.fattr = &calldata->fattr; | 1435 | calldata->res.fattr = &calldata->fattr; |
1444 | calldata->res.seqid = calldata->arg.seqid; | 1436 | calldata->res.seqid = calldata->arg.seqid; |
1445 | calldata->res.server = server; | 1437 | calldata->res.server = server; |
@@ -1580,6 +1572,15 @@ out_drop: | |||
1580 | return 0; | 1572 | return 0; |
1581 | } | 1573 | } |
1582 | 1574 | ||
1575 | void nfs4_close_context(struct nfs_open_context *ctx, int is_sync) | ||
1576 | { | ||
1577 | if (ctx->state == NULL) | ||
1578 | return; | ||
1579 | if (is_sync) | ||
1580 | nfs4_close_sync(&ctx->path, ctx->state, ctx->mode); | ||
1581 | else | ||
1582 | nfs4_close_state(&ctx->path, ctx->state, ctx->mode); | ||
1583 | } | ||
1583 | 1584 | ||
1584 | static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle) | 1585 | static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle) |
1585 | { | 1586 | { |
@@ -1600,6 +1601,9 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f | |||
1600 | server->caps |= NFS_CAP_HARDLINKS; | 1601 | server->caps |= NFS_CAP_HARDLINKS; |
1601 | if (res.has_symlinks != 0) | 1602 | if (res.has_symlinks != 0) |
1602 | server->caps |= NFS_CAP_SYMLINKS; | 1603 | server->caps |= NFS_CAP_SYMLINKS; |
1604 | memcpy(server->cache_consistency_bitmask, res.attr_bitmask, sizeof(server->cache_consistency_bitmask)); | ||
1605 | server->cache_consistency_bitmask[0] &= FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE; | ||
1606 | server->cache_consistency_bitmask[1] &= FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY; | ||
1603 | server->acl_bitmask = res.acl_bitmask; | 1607 | server->acl_bitmask = res.acl_bitmask; |
1604 | } | 1608 | } |
1605 | return status; | 1609 | return status; |
@@ -2079,7 +2083,7 @@ static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct inode *dir) | |||
2079 | struct nfs_removeargs *args = msg->rpc_argp; | 2083 | struct nfs_removeargs *args = msg->rpc_argp; |
2080 | struct nfs_removeres *res = msg->rpc_resp; | 2084 | struct nfs_removeres *res = msg->rpc_resp; |
2081 | 2085 | ||
2082 | args->bitmask = server->attr_bitmask; | 2086 | args->bitmask = server->cache_consistency_bitmask; |
2083 | res->server = server; | 2087 | res->server = server; |
2084 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE]; | 2088 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE]; |
2085 | } | 2089 | } |
@@ -2323,7 +2327,7 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, | |||
2323 | .pages = &page, | 2327 | .pages = &page, |
2324 | .pgbase = 0, | 2328 | .pgbase = 0, |
2325 | .count = count, | 2329 | .count = count, |
2326 | .bitmask = NFS_SERVER(dentry->d_inode)->attr_bitmask, | 2330 | .bitmask = NFS_SERVER(dentry->d_inode)->cache_consistency_bitmask, |
2327 | }; | 2331 | }; |
2328 | struct nfs4_readdir_res res; | 2332 | struct nfs4_readdir_res res; |
2329 | struct rpc_message msg = { | 2333 | struct rpc_message msg = { |
@@ -2552,7 +2556,7 @@ static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_messag | |||
2552 | { | 2556 | { |
2553 | struct nfs_server *server = NFS_SERVER(data->inode); | 2557 | struct nfs_server *server = NFS_SERVER(data->inode); |
2554 | 2558 | ||
2555 | data->args.bitmask = server->attr_bitmask; | 2559 | data->args.bitmask = server->cache_consistency_bitmask; |
2556 | data->res.server = server; | 2560 | data->res.server = server; |
2557 | data->timestamp = jiffies; | 2561 | data->timestamp = jiffies; |
2558 | 2562 | ||
@@ -2575,7 +2579,7 @@ static void nfs4_proc_commit_setup(struct nfs_write_data *data, struct rpc_messa | |||
2575 | { | 2579 | { |
2576 | struct nfs_server *server = NFS_SERVER(data->inode); | 2580 | struct nfs_server *server = NFS_SERVER(data->inode); |
2577 | 2581 | ||
2578 | data->args.bitmask = server->attr_bitmask; | 2582 | data->args.bitmask = server->cache_consistency_bitmask; |
2579 | data->res.server = server; | 2583 | data->res.server = server; |
2580 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT]; | 2584 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT]; |
2581 | } | 2585 | } |
@@ -3678,6 +3682,19 @@ ssize_t nfs4_listxattr(struct dentry *dentry, char *buf, size_t buflen) | |||
3678 | return len; | 3682 | return len; |
3679 | } | 3683 | } |
3680 | 3684 | ||
3685 | static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr) | ||
3686 | { | ||
3687 | if (!((fattr->valid & NFS_ATTR_FATTR_FILEID) && | ||
3688 | (fattr->valid & NFS_ATTR_FATTR_FSID) && | ||
3689 | (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL))) | ||
3690 | return; | ||
3691 | |||
3692 | fattr->valid |= NFS_ATTR_FATTR_TYPE | NFS_ATTR_FATTR_MODE | | ||
3693 | NFS_ATTR_FATTR_NLINK; | ||
3694 | fattr->mode = S_IFDIR | S_IRUGO | S_IXUGO; | ||
3695 | fattr->nlink = 2; | ||
3696 | } | ||
3697 | |||
3681 | int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, | 3698 | int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, |
3682 | struct nfs4_fs_locations *fs_locations, struct page *page) | 3699 | struct nfs4_fs_locations *fs_locations, struct page *page) |
3683 | { | 3700 | { |
@@ -3704,6 +3721,7 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, | |||
3704 | fs_locations->server = server; | 3721 | fs_locations->server = server; |
3705 | fs_locations->nlocations = 0; | 3722 | fs_locations->nlocations = 0; |
3706 | status = rpc_call_sync(server->client, &msg, 0); | 3723 | status = rpc_call_sync(server->client, &msg, 0); |
3724 | nfs_fixup_referral_attributes(&fs_locations->fattr); | ||
3707 | dprintk("%s: returned status = %d\n", __func__, status); | 3725 | dprintk("%s: returned status = %d\n", __func__, status); |
3708 | return status; | 3726 | return status; |
3709 | } | 3727 | } |
@@ -3767,6 +3785,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = { | |||
3767 | .commit_done = nfs4_commit_done, | 3785 | .commit_done = nfs4_commit_done, |
3768 | .lock = nfs4_proc_lock, | 3786 | .lock = nfs4_proc_lock, |
3769 | .clear_acl_cache = nfs4_zap_acl_attr, | 3787 | .clear_acl_cache = nfs4_zap_acl_attr, |
3788 | .close_context = nfs4_close_context, | ||
3770 | }; | 3789 | }; |
3771 | 3790 | ||
3772 | /* | 3791 | /* |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 2022fe47966f..0298e909559f 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -62,8 +62,14 @@ static LIST_HEAD(nfs4_clientid_list); | |||
62 | 62 | ||
63 | static int nfs4_init_client(struct nfs_client *clp, struct rpc_cred *cred) | 63 | static int nfs4_init_client(struct nfs_client *clp, struct rpc_cred *cred) |
64 | { | 64 | { |
65 | int status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, | 65 | unsigned short port; |
66 | nfs_callback_tcpport, cred); | 66 | int status; |
67 | |||
68 | port = nfs_callback_tcpport; | ||
69 | if (clp->cl_addr.ss_family == AF_INET6) | ||
70 | port = nfs_callback_tcpport6; | ||
71 | |||
72 | status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, port, cred); | ||
67 | if (status == 0) | 73 | if (status == 0) |
68 | status = nfs4_proc_setclientid_confirm(clp, cred); | 74 | status = nfs4_proc_setclientid_confirm(clp, cred); |
69 | if (status == 0) | 75 | if (status == 0) |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index d1e4c8f8a0a9..1690f0e44b91 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -522,20 +522,17 @@ static int nfs4_stat_to_errno(int); | |||
522 | decode_lookup_maxsz + \ | 522 | decode_lookup_maxsz + \ |
523 | decode_fs_locations_maxsz) | 523 | decode_fs_locations_maxsz) |
524 | 524 | ||
525 | static struct { | 525 | static const umode_t nfs_type2fmt[] = { |
526 | unsigned int mode; | 526 | [NF4BAD] = 0, |
527 | unsigned int nfs2type; | 527 | [NF4REG] = S_IFREG, |
528 | } nfs_type2fmt[] = { | 528 | [NF4DIR] = S_IFDIR, |
529 | { 0, NFNON }, | 529 | [NF4BLK] = S_IFBLK, |
530 | { S_IFREG, NFREG }, | 530 | [NF4CHR] = S_IFCHR, |
531 | { S_IFDIR, NFDIR }, | 531 | [NF4LNK] = S_IFLNK, |
532 | { S_IFBLK, NFBLK }, | 532 | [NF4SOCK] = S_IFSOCK, |
533 | { S_IFCHR, NFCHR }, | 533 | [NF4FIFO] = S_IFIFO, |
534 | { S_IFLNK, NFLNK }, | 534 | [NF4ATTRDIR] = 0, |
535 | { S_IFSOCK, NFSOCK }, | 535 | [NF4NAMEDATTR] = 0, |
536 | { S_IFIFO, NFFIFO }, | ||
537 | { 0, NFNON }, | ||
538 | { 0, NFNON }, | ||
539 | }; | 536 | }; |
540 | 537 | ||
541 | struct compound_hdr { | 538 | struct compound_hdr { |
@@ -2160,6 +2157,7 @@ static int decode_attr_supported(struct xdr_stream *xdr, uint32_t *bitmap, uint3 | |||
2160 | static int decode_attr_type(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *type) | 2157 | static int decode_attr_type(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *type) |
2161 | { | 2158 | { |
2162 | __be32 *p; | 2159 | __be32 *p; |
2160 | int ret = 0; | ||
2163 | 2161 | ||
2164 | *type = 0; | 2162 | *type = 0; |
2165 | if (unlikely(bitmap[0] & (FATTR4_WORD0_TYPE - 1U))) | 2163 | if (unlikely(bitmap[0] & (FATTR4_WORD0_TYPE - 1U))) |
@@ -2172,14 +2170,16 @@ static int decode_attr_type(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t * | |||
2172 | return -EIO; | 2170 | return -EIO; |
2173 | } | 2171 | } |
2174 | bitmap[0] &= ~FATTR4_WORD0_TYPE; | 2172 | bitmap[0] &= ~FATTR4_WORD0_TYPE; |
2173 | ret = NFS_ATTR_FATTR_TYPE; | ||
2175 | } | 2174 | } |
2176 | dprintk("%s: type=0%o\n", __func__, nfs_type2fmt[*type].nfs2type); | 2175 | dprintk("%s: type=0%o\n", __func__, nfs_type2fmt[*type]); |
2177 | return 0; | 2176 | return ret; |
2178 | } | 2177 | } |
2179 | 2178 | ||
2180 | static int decode_attr_change(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *change) | 2179 | static int decode_attr_change(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *change) |
2181 | { | 2180 | { |
2182 | __be32 *p; | 2181 | __be32 *p; |
2182 | int ret = 0; | ||
2183 | 2183 | ||
2184 | *change = 0; | 2184 | *change = 0; |
2185 | if (unlikely(bitmap[0] & (FATTR4_WORD0_CHANGE - 1U))) | 2185 | if (unlikely(bitmap[0] & (FATTR4_WORD0_CHANGE - 1U))) |
@@ -2188,15 +2188,17 @@ static int decode_attr_change(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t | |||
2188 | READ_BUF(8); | 2188 | READ_BUF(8); |
2189 | READ64(*change); | 2189 | READ64(*change); |
2190 | bitmap[0] &= ~FATTR4_WORD0_CHANGE; | 2190 | bitmap[0] &= ~FATTR4_WORD0_CHANGE; |
2191 | ret = NFS_ATTR_FATTR_CHANGE; | ||
2191 | } | 2192 | } |
2192 | dprintk("%s: change attribute=%Lu\n", __func__, | 2193 | dprintk("%s: change attribute=%Lu\n", __func__, |
2193 | (unsigned long long)*change); | 2194 | (unsigned long long)*change); |
2194 | return 0; | 2195 | return ret; |
2195 | } | 2196 | } |
2196 | 2197 | ||
2197 | static int decode_attr_size(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *size) | 2198 | static int decode_attr_size(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *size) |
2198 | { | 2199 | { |
2199 | __be32 *p; | 2200 | __be32 *p; |
2201 | int ret = 0; | ||
2200 | 2202 | ||
2201 | *size = 0; | 2203 | *size = 0; |
2202 | if (unlikely(bitmap[0] & (FATTR4_WORD0_SIZE - 1U))) | 2204 | if (unlikely(bitmap[0] & (FATTR4_WORD0_SIZE - 1U))) |
@@ -2205,9 +2207,10 @@ static int decode_attr_size(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t * | |||
2205 | READ_BUF(8); | 2207 | READ_BUF(8); |
2206 | READ64(*size); | 2208 | READ64(*size); |
2207 | bitmap[0] &= ~FATTR4_WORD0_SIZE; | 2209 | bitmap[0] &= ~FATTR4_WORD0_SIZE; |
2210 | ret = NFS_ATTR_FATTR_SIZE; | ||
2208 | } | 2211 | } |
2209 | dprintk("%s: file size=%Lu\n", __func__, (unsigned long long)*size); | 2212 | dprintk("%s: file size=%Lu\n", __func__, (unsigned long long)*size); |
2210 | return 0; | 2213 | return ret; |
2211 | } | 2214 | } |
2212 | 2215 | ||
2213 | static int decode_attr_link_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) | 2216 | static int decode_attr_link_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) |
@@ -2245,6 +2248,7 @@ static int decode_attr_symlink_support(struct xdr_stream *xdr, uint32_t *bitmap, | |||
2245 | static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fsid *fsid) | 2248 | static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fsid *fsid) |
2246 | { | 2249 | { |
2247 | __be32 *p; | 2250 | __be32 *p; |
2251 | int ret = 0; | ||
2248 | 2252 | ||
2249 | fsid->major = 0; | 2253 | fsid->major = 0; |
2250 | fsid->minor = 0; | 2254 | fsid->minor = 0; |
@@ -2255,11 +2259,12 @@ static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs | |||
2255 | READ64(fsid->major); | 2259 | READ64(fsid->major); |
2256 | READ64(fsid->minor); | 2260 | READ64(fsid->minor); |
2257 | bitmap[0] &= ~FATTR4_WORD0_FSID; | 2261 | bitmap[0] &= ~FATTR4_WORD0_FSID; |
2262 | ret = NFS_ATTR_FATTR_FSID; | ||
2258 | } | 2263 | } |
2259 | dprintk("%s: fsid=(0x%Lx/0x%Lx)\n", __func__, | 2264 | dprintk("%s: fsid=(0x%Lx/0x%Lx)\n", __func__, |
2260 | (unsigned long long)fsid->major, | 2265 | (unsigned long long)fsid->major, |
2261 | (unsigned long long)fsid->minor); | 2266 | (unsigned long long)fsid->minor); |
2262 | return 0; | 2267 | return ret; |
2263 | } | 2268 | } |
2264 | 2269 | ||
2265 | static int decode_attr_lease_time(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) | 2270 | static int decode_attr_lease_time(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) |
@@ -2297,6 +2302,7 @@ static int decode_attr_aclsupport(struct xdr_stream *xdr, uint32_t *bitmap, uint | |||
2297 | static int decode_attr_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid) | 2302 | static int decode_attr_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid) |
2298 | { | 2303 | { |
2299 | __be32 *p; | 2304 | __be32 *p; |
2305 | int ret = 0; | ||
2300 | 2306 | ||
2301 | *fileid = 0; | 2307 | *fileid = 0; |
2302 | if (unlikely(bitmap[0] & (FATTR4_WORD0_FILEID - 1U))) | 2308 | if (unlikely(bitmap[0] & (FATTR4_WORD0_FILEID - 1U))) |
@@ -2305,14 +2311,16 @@ static int decode_attr_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t | |||
2305 | READ_BUF(8); | 2311 | READ_BUF(8); |
2306 | READ64(*fileid); | 2312 | READ64(*fileid); |
2307 | bitmap[0] &= ~FATTR4_WORD0_FILEID; | 2313 | bitmap[0] &= ~FATTR4_WORD0_FILEID; |
2314 | ret = NFS_ATTR_FATTR_FILEID; | ||
2308 | } | 2315 | } |
2309 | dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid); | 2316 | dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid); |
2310 | return 0; | 2317 | return ret; |
2311 | } | 2318 | } |
2312 | 2319 | ||
2313 | static int decode_attr_mounted_on_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid) | 2320 | static int decode_attr_mounted_on_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid) |
2314 | { | 2321 | { |
2315 | __be32 *p; | 2322 | __be32 *p; |
2323 | int ret = 0; | ||
2316 | 2324 | ||
2317 | *fileid = 0; | 2325 | *fileid = 0; |
2318 | if (unlikely(bitmap[1] & (FATTR4_WORD1_MOUNTED_ON_FILEID - 1U))) | 2326 | if (unlikely(bitmap[1] & (FATTR4_WORD1_MOUNTED_ON_FILEID - 1U))) |
@@ -2321,9 +2329,10 @@ static int decode_attr_mounted_on_fileid(struct xdr_stream *xdr, uint32_t *bitma | |||
2321 | READ_BUF(8); | 2329 | READ_BUF(8); |
2322 | READ64(*fileid); | 2330 | READ64(*fileid); |
2323 | bitmap[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID; | 2331 | bitmap[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID; |
2332 | ret = NFS_ATTR_FATTR_FILEID; | ||
2324 | } | 2333 | } |
2325 | dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid); | 2334 | dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid); |
2326 | return 0; | 2335 | return ret; |
2327 | } | 2336 | } |
2328 | 2337 | ||
2329 | static int decode_attr_files_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) | 2338 | static int decode_attr_files_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) |
@@ -2479,6 +2488,8 @@ static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, st | |||
2479 | if (res->nlocations < NFS4_FS_LOCATIONS_MAXENTRIES) | 2488 | if (res->nlocations < NFS4_FS_LOCATIONS_MAXENTRIES) |
2480 | res->nlocations++; | 2489 | res->nlocations++; |
2481 | } | 2490 | } |
2491 | if (res->nlocations != 0) | ||
2492 | status = NFS_ATTR_FATTR_V4_REFERRAL; | ||
2482 | out: | 2493 | out: |
2483 | dprintk("%s: fs_locations done, error = %d\n", __func__, status); | 2494 | dprintk("%s: fs_locations done, error = %d\n", __func__, status); |
2484 | return status; | 2495 | return status; |
@@ -2580,26 +2591,30 @@ static int decode_attr_maxwrite(struct xdr_stream *xdr, uint32_t *bitmap, uint32 | |||
2580 | return status; | 2591 | return status; |
2581 | } | 2592 | } |
2582 | 2593 | ||
2583 | static int decode_attr_mode(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *mode) | 2594 | static int decode_attr_mode(struct xdr_stream *xdr, uint32_t *bitmap, umode_t *mode) |
2584 | { | 2595 | { |
2596 | uint32_t tmp; | ||
2585 | __be32 *p; | 2597 | __be32 *p; |
2598 | int ret = 0; | ||
2586 | 2599 | ||
2587 | *mode = 0; | 2600 | *mode = 0; |
2588 | if (unlikely(bitmap[1] & (FATTR4_WORD1_MODE - 1U))) | 2601 | if (unlikely(bitmap[1] & (FATTR4_WORD1_MODE - 1U))) |
2589 | return -EIO; | 2602 | return -EIO; |
2590 | if (likely(bitmap[1] & FATTR4_WORD1_MODE)) { | 2603 | if (likely(bitmap[1] & FATTR4_WORD1_MODE)) { |
2591 | READ_BUF(4); | 2604 | READ_BUF(4); |
2592 | READ32(*mode); | 2605 | READ32(tmp); |
2593 | *mode &= ~S_IFMT; | 2606 | *mode = tmp & ~S_IFMT; |
2594 | bitmap[1] &= ~FATTR4_WORD1_MODE; | 2607 | bitmap[1] &= ~FATTR4_WORD1_MODE; |
2608 | ret = NFS_ATTR_FATTR_MODE; | ||
2595 | } | 2609 | } |
2596 | dprintk("%s: file mode=0%o\n", __func__, (unsigned int)*mode); | 2610 | dprintk("%s: file mode=0%o\n", __func__, (unsigned int)*mode); |
2597 | return 0; | 2611 | return ret; |
2598 | } | 2612 | } |
2599 | 2613 | ||
2600 | static int decode_attr_nlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *nlink) | 2614 | static int decode_attr_nlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *nlink) |
2601 | { | 2615 | { |
2602 | __be32 *p; | 2616 | __be32 *p; |
2617 | int ret = 0; | ||
2603 | 2618 | ||
2604 | *nlink = 1; | 2619 | *nlink = 1; |
2605 | if (unlikely(bitmap[1] & (FATTR4_WORD1_NUMLINKS - 1U))) | 2620 | if (unlikely(bitmap[1] & (FATTR4_WORD1_NUMLINKS - 1U))) |
@@ -2608,15 +2623,17 @@ static int decode_attr_nlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t | |||
2608 | READ_BUF(4); | 2623 | READ_BUF(4); |
2609 | READ32(*nlink); | 2624 | READ32(*nlink); |
2610 | bitmap[1] &= ~FATTR4_WORD1_NUMLINKS; | 2625 | bitmap[1] &= ~FATTR4_WORD1_NUMLINKS; |
2626 | ret = NFS_ATTR_FATTR_NLINK; | ||
2611 | } | 2627 | } |
2612 | dprintk("%s: nlink=%u\n", __func__, (unsigned int)*nlink); | 2628 | dprintk("%s: nlink=%u\n", __func__, (unsigned int)*nlink); |
2613 | return 0; | 2629 | return ret; |
2614 | } | 2630 | } |
2615 | 2631 | ||
2616 | static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_client *clp, uint32_t *uid) | 2632 | static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_client *clp, uint32_t *uid) |
2617 | { | 2633 | { |
2618 | uint32_t len; | 2634 | uint32_t len; |
2619 | __be32 *p; | 2635 | __be32 *p; |
2636 | int ret = 0; | ||
2620 | 2637 | ||
2621 | *uid = -2; | 2638 | *uid = -2; |
2622 | if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER - 1U))) | 2639 | if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER - 1U))) |
@@ -2626,7 +2643,9 @@ static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, struct nf | |||
2626 | READ32(len); | 2643 | READ32(len); |
2627 | READ_BUF(len); | 2644 | READ_BUF(len); |
2628 | if (len < XDR_MAX_NETOBJ) { | 2645 | if (len < XDR_MAX_NETOBJ) { |
2629 | if (nfs_map_name_to_uid(clp, (char *)p, len, uid) != 0) | 2646 | if (nfs_map_name_to_uid(clp, (char *)p, len, uid) == 0) |
2647 | ret = NFS_ATTR_FATTR_OWNER; | ||
2648 | else | ||
2630 | dprintk("%s: nfs_map_name_to_uid failed!\n", | 2649 | dprintk("%s: nfs_map_name_to_uid failed!\n", |
2631 | __func__); | 2650 | __func__); |
2632 | } else | 2651 | } else |
@@ -2635,13 +2654,14 @@ static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, struct nf | |||
2635 | bitmap[1] &= ~FATTR4_WORD1_OWNER; | 2654 | bitmap[1] &= ~FATTR4_WORD1_OWNER; |
2636 | } | 2655 | } |
2637 | dprintk("%s: uid=%d\n", __func__, (int)*uid); | 2656 | dprintk("%s: uid=%d\n", __func__, (int)*uid); |
2638 | return 0; | 2657 | return ret; |
2639 | } | 2658 | } |
2640 | 2659 | ||
2641 | static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_client *clp, uint32_t *gid) | 2660 | static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_client *clp, uint32_t *gid) |
2642 | { | 2661 | { |
2643 | uint32_t len; | 2662 | uint32_t len; |
2644 | __be32 *p; | 2663 | __be32 *p; |
2664 | int ret = 0; | ||
2645 | 2665 | ||
2646 | *gid = -2; | 2666 | *gid = -2; |
2647 | if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER_GROUP - 1U))) | 2667 | if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER_GROUP - 1U))) |
@@ -2651,7 +2671,9 @@ static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, struct nf | |||
2651 | READ32(len); | 2671 | READ32(len); |
2652 | READ_BUF(len); | 2672 | READ_BUF(len); |
2653 | if (len < XDR_MAX_NETOBJ) { | 2673 | if (len < XDR_MAX_NETOBJ) { |
2654 | if (nfs_map_group_to_gid(clp, (char *)p, len, gid) != 0) | 2674 | if (nfs_map_group_to_gid(clp, (char *)p, len, gid) == 0) |
2675 | ret = NFS_ATTR_FATTR_GROUP; | ||
2676 | else | ||
2655 | dprintk("%s: nfs_map_group_to_gid failed!\n", | 2677 | dprintk("%s: nfs_map_group_to_gid failed!\n", |
2656 | __func__); | 2678 | __func__); |
2657 | } else | 2679 | } else |
@@ -2660,13 +2682,14 @@ static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, struct nf | |||
2660 | bitmap[1] &= ~FATTR4_WORD1_OWNER_GROUP; | 2682 | bitmap[1] &= ~FATTR4_WORD1_OWNER_GROUP; |
2661 | } | 2683 | } |
2662 | dprintk("%s: gid=%d\n", __func__, (int)*gid); | 2684 | dprintk("%s: gid=%d\n", __func__, (int)*gid); |
2663 | return 0; | 2685 | return ret; |
2664 | } | 2686 | } |
2665 | 2687 | ||
2666 | static int decode_attr_rdev(struct xdr_stream *xdr, uint32_t *bitmap, dev_t *rdev) | 2688 | static int decode_attr_rdev(struct xdr_stream *xdr, uint32_t *bitmap, dev_t *rdev) |
2667 | { | 2689 | { |
2668 | uint32_t major = 0, minor = 0; | 2690 | uint32_t major = 0, minor = 0; |
2669 | __be32 *p; | 2691 | __be32 *p; |
2692 | int ret = 0; | ||
2670 | 2693 | ||
2671 | *rdev = MKDEV(0,0); | 2694 | *rdev = MKDEV(0,0); |
2672 | if (unlikely(bitmap[1] & (FATTR4_WORD1_RAWDEV - 1U))) | 2695 | if (unlikely(bitmap[1] & (FATTR4_WORD1_RAWDEV - 1U))) |
@@ -2681,9 +2704,10 @@ static int decode_attr_rdev(struct xdr_stream *xdr, uint32_t *bitmap, dev_t *rde | |||
2681 | if (MAJOR(tmp) == major && MINOR(tmp) == minor) | 2704 | if (MAJOR(tmp) == major && MINOR(tmp) == minor) |
2682 | *rdev = tmp; | 2705 | *rdev = tmp; |
2683 | bitmap[1] &= ~ FATTR4_WORD1_RAWDEV; | 2706 | bitmap[1] &= ~ FATTR4_WORD1_RAWDEV; |
2707 | ret = NFS_ATTR_FATTR_RDEV; | ||
2684 | } | 2708 | } |
2685 | dprintk("%s: rdev=(0x%x:0x%x)\n", __func__, major, minor); | 2709 | dprintk("%s: rdev=(0x%x:0x%x)\n", __func__, major, minor); |
2686 | return 0; | 2710 | return ret; |
2687 | } | 2711 | } |
2688 | 2712 | ||
2689 | static int decode_attr_space_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) | 2713 | static int decode_attr_space_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) |
@@ -2740,6 +2764,7 @@ static int decode_attr_space_total(struct xdr_stream *xdr, uint32_t *bitmap, uin | |||
2740 | static int decode_attr_space_used(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *used) | 2764 | static int decode_attr_space_used(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *used) |
2741 | { | 2765 | { |
2742 | __be32 *p; | 2766 | __be32 *p; |
2767 | int ret = 0; | ||
2743 | 2768 | ||
2744 | *used = 0; | 2769 | *used = 0; |
2745 | if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_USED - 1U))) | 2770 | if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_USED - 1U))) |
@@ -2748,10 +2773,11 @@ static int decode_attr_space_used(struct xdr_stream *xdr, uint32_t *bitmap, uint | |||
2748 | READ_BUF(8); | 2773 | READ_BUF(8); |
2749 | READ64(*used); | 2774 | READ64(*used); |
2750 | bitmap[1] &= ~FATTR4_WORD1_SPACE_USED; | 2775 | bitmap[1] &= ~FATTR4_WORD1_SPACE_USED; |
2776 | ret = NFS_ATTR_FATTR_SPACE_USED; | ||
2751 | } | 2777 | } |
2752 | dprintk("%s: space used=%Lu\n", __func__, | 2778 | dprintk("%s: space used=%Lu\n", __func__, |
2753 | (unsigned long long)*used); | 2779 | (unsigned long long)*used); |
2754 | return 0; | 2780 | return ret; |
2755 | } | 2781 | } |
2756 | 2782 | ||
2757 | static int decode_attr_time(struct xdr_stream *xdr, struct timespec *time) | 2783 | static int decode_attr_time(struct xdr_stream *xdr, struct timespec *time) |
@@ -2778,6 +2804,8 @@ static int decode_attr_time_access(struct xdr_stream *xdr, uint32_t *bitmap, str | |||
2778 | return -EIO; | 2804 | return -EIO; |
2779 | if (likely(bitmap[1] & FATTR4_WORD1_TIME_ACCESS)) { | 2805 | if (likely(bitmap[1] & FATTR4_WORD1_TIME_ACCESS)) { |
2780 | status = decode_attr_time(xdr, time); | 2806 | status = decode_attr_time(xdr, time); |
2807 | if (status == 0) | ||
2808 | status = NFS_ATTR_FATTR_ATIME; | ||
2781 | bitmap[1] &= ~FATTR4_WORD1_TIME_ACCESS; | 2809 | bitmap[1] &= ~FATTR4_WORD1_TIME_ACCESS; |
2782 | } | 2810 | } |
2783 | dprintk("%s: atime=%ld\n", __func__, (long)time->tv_sec); | 2811 | dprintk("%s: atime=%ld\n", __func__, (long)time->tv_sec); |
@@ -2794,6 +2822,8 @@ static int decode_attr_time_metadata(struct xdr_stream *xdr, uint32_t *bitmap, s | |||
2794 | return -EIO; | 2822 | return -EIO; |
2795 | if (likely(bitmap[1] & FATTR4_WORD1_TIME_METADATA)) { | 2823 | if (likely(bitmap[1] & FATTR4_WORD1_TIME_METADATA)) { |
2796 | status = decode_attr_time(xdr, time); | 2824 | status = decode_attr_time(xdr, time); |
2825 | if (status == 0) | ||
2826 | status = NFS_ATTR_FATTR_CTIME; | ||
2797 | bitmap[1] &= ~FATTR4_WORD1_TIME_METADATA; | 2827 | bitmap[1] &= ~FATTR4_WORD1_TIME_METADATA; |
2798 | } | 2828 | } |
2799 | dprintk("%s: ctime=%ld\n", __func__, (long)time->tv_sec); | 2829 | dprintk("%s: ctime=%ld\n", __func__, (long)time->tv_sec); |
@@ -2810,6 +2840,8 @@ static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, str | |||
2810 | return -EIO; | 2840 | return -EIO; |
2811 | if (likely(bitmap[1] & FATTR4_WORD1_TIME_MODIFY)) { | 2841 | if (likely(bitmap[1] & FATTR4_WORD1_TIME_MODIFY)) { |
2812 | status = decode_attr_time(xdr, time); | 2842 | status = decode_attr_time(xdr, time); |
2843 | if (status == 0) | ||
2844 | status = NFS_ATTR_FATTR_MTIME; | ||
2813 | bitmap[1] &= ~FATTR4_WORD1_TIME_MODIFY; | 2845 | bitmap[1] &= ~FATTR4_WORD1_TIME_MODIFY; |
2814 | } | 2846 | } |
2815 | dprintk("%s: mtime=%ld\n", __func__, (long)time->tv_sec); | 2847 | dprintk("%s: mtime=%ld\n", __func__, (long)time->tv_sec); |
@@ -2994,63 +3026,116 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, cons | |||
2994 | uint32_t attrlen, | 3026 | uint32_t attrlen, |
2995 | bitmap[2] = {0}, | 3027 | bitmap[2] = {0}, |
2996 | type; | 3028 | type; |
2997 | int status, fmode = 0; | 3029 | int status; |
3030 | umode_t fmode = 0; | ||
2998 | uint64_t fileid; | 3031 | uint64_t fileid; |
2999 | 3032 | ||
3000 | if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) | 3033 | status = decode_op_hdr(xdr, OP_GETATTR); |
3001 | goto xdr_error; | 3034 | if (status < 0) |
3002 | if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) | ||
3003 | goto xdr_error; | 3035 | goto xdr_error; |
3004 | 3036 | ||
3005 | fattr->bitmap[0] = bitmap[0]; | 3037 | status = decode_attr_bitmap(xdr, bitmap); |
3006 | fattr->bitmap[1] = bitmap[1]; | 3038 | if (status < 0) |
3039 | goto xdr_error; | ||
3007 | 3040 | ||
3008 | if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) | 3041 | status = decode_attr_length(xdr, &attrlen, &savep); |
3042 | if (status < 0) | ||
3009 | goto xdr_error; | 3043 | goto xdr_error; |
3010 | 3044 | ||
3011 | 3045 | ||
3012 | if ((status = decode_attr_type(xdr, bitmap, &type)) != 0) | 3046 | status = decode_attr_type(xdr, bitmap, &type); |
3047 | if (status < 0) | ||
3013 | goto xdr_error; | 3048 | goto xdr_error; |
3014 | fattr->type = nfs_type2fmt[type].nfs2type; | 3049 | fattr->mode = 0; |
3015 | fmode = nfs_type2fmt[type].mode; | 3050 | if (status != 0) { |
3051 | fattr->mode |= nfs_type2fmt[type]; | ||
3052 | fattr->valid |= status; | ||
3053 | } | ||
3016 | 3054 | ||
3017 | if ((status = decode_attr_change(xdr, bitmap, &fattr->change_attr)) != 0) | 3055 | status = decode_attr_change(xdr, bitmap, &fattr->change_attr); |
3056 | if (status < 0) | ||
3018 | goto xdr_error; | 3057 | goto xdr_error; |
3019 | if ((status = decode_attr_size(xdr, bitmap, &fattr->size)) != 0) | 3058 | fattr->valid |= status; |
3059 | |||
3060 | status = decode_attr_size(xdr, bitmap, &fattr->size); | ||
3061 | if (status < 0) | ||
3020 | goto xdr_error; | 3062 | goto xdr_error; |
3021 | if ((status = decode_attr_fsid(xdr, bitmap, &fattr->fsid)) != 0) | 3063 | fattr->valid |= status; |
3064 | |||
3065 | status = decode_attr_fsid(xdr, bitmap, &fattr->fsid); | ||
3066 | if (status < 0) | ||
3022 | goto xdr_error; | 3067 | goto xdr_error; |
3023 | if ((status = decode_attr_fileid(xdr, bitmap, &fattr->fileid)) != 0) | 3068 | fattr->valid |= status; |
3069 | |||
3070 | status = decode_attr_fileid(xdr, bitmap, &fattr->fileid); | ||
3071 | if (status < 0) | ||
3024 | goto xdr_error; | 3072 | goto xdr_error; |
3025 | if ((status = decode_attr_fs_locations(xdr, bitmap, container_of(fattr, | 3073 | fattr->valid |= status; |
3074 | |||
3075 | status = decode_attr_fs_locations(xdr, bitmap, container_of(fattr, | ||
3026 | struct nfs4_fs_locations, | 3076 | struct nfs4_fs_locations, |
3027 | fattr))) != 0) | 3077 | fattr)); |
3078 | if (status < 0) | ||
3028 | goto xdr_error; | 3079 | goto xdr_error; |
3029 | if ((status = decode_attr_mode(xdr, bitmap, &fattr->mode)) != 0) | 3080 | fattr->valid |= status; |
3081 | |||
3082 | status = decode_attr_mode(xdr, bitmap, &fmode); | ||
3083 | if (status < 0) | ||
3030 | goto xdr_error; | 3084 | goto xdr_error; |
3031 | fattr->mode |= fmode; | 3085 | if (status != 0) { |
3032 | if ((status = decode_attr_nlink(xdr, bitmap, &fattr->nlink)) != 0) | 3086 | fattr->mode |= fmode; |
3087 | fattr->valid |= status; | ||
3088 | } | ||
3089 | |||
3090 | status = decode_attr_nlink(xdr, bitmap, &fattr->nlink); | ||
3091 | if (status < 0) | ||
3033 | goto xdr_error; | 3092 | goto xdr_error; |
3034 | if ((status = decode_attr_owner(xdr, bitmap, server->nfs_client, &fattr->uid)) != 0) | 3093 | fattr->valid |= status; |
3094 | |||
3095 | status = decode_attr_owner(xdr, bitmap, server->nfs_client, &fattr->uid); | ||
3096 | if (status < 0) | ||
3035 | goto xdr_error; | 3097 | goto xdr_error; |
3036 | if ((status = decode_attr_group(xdr, bitmap, server->nfs_client, &fattr->gid)) != 0) | 3098 | fattr->valid |= status; |
3099 | |||
3100 | status = decode_attr_group(xdr, bitmap, server->nfs_client, &fattr->gid); | ||
3101 | if (status < 0) | ||
3037 | goto xdr_error; | 3102 | goto xdr_error; |
3038 | if ((status = decode_attr_rdev(xdr, bitmap, &fattr->rdev)) != 0) | 3103 | fattr->valid |= status; |
3104 | |||
3105 | status = decode_attr_rdev(xdr, bitmap, &fattr->rdev); | ||
3106 | if (status < 0) | ||
3039 | goto xdr_error; | 3107 | goto xdr_error; |
3040 | if ((status = decode_attr_space_used(xdr, bitmap, &fattr->du.nfs3.used)) != 0) | 3108 | fattr->valid |= status; |
3109 | |||
3110 | status = decode_attr_space_used(xdr, bitmap, &fattr->du.nfs3.used); | ||
3111 | if (status < 0) | ||
3041 | goto xdr_error; | 3112 | goto xdr_error; |
3042 | if ((status = decode_attr_time_access(xdr, bitmap, &fattr->atime)) != 0) | 3113 | fattr->valid |= status; |
3114 | |||
3115 | status = decode_attr_time_access(xdr, bitmap, &fattr->atime); | ||
3116 | if (status < 0) | ||
3043 | goto xdr_error; | 3117 | goto xdr_error; |
3044 | if ((status = decode_attr_time_metadata(xdr, bitmap, &fattr->ctime)) != 0) | 3118 | fattr->valid |= status; |
3119 | |||
3120 | status = decode_attr_time_metadata(xdr, bitmap, &fattr->ctime); | ||
3121 | if (status < 0) | ||
3045 | goto xdr_error; | 3122 | goto xdr_error; |
3046 | if ((status = decode_attr_time_modify(xdr, bitmap, &fattr->mtime)) != 0) | 3123 | fattr->valid |= status; |
3124 | |||
3125 | status = decode_attr_time_modify(xdr, bitmap, &fattr->mtime); | ||
3126 | if (status < 0) | ||
3047 | goto xdr_error; | 3127 | goto xdr_error; |
3048 | if ((status = decode_attr_mounted_on_fileid(xdr, bitmap, &fileid)) != 0) | 3128 | fattr->valid |= status; |
3129 | |||
3130 | status = decode_attr_mounted_on_fileid(xdr, bitmap, &fileid); | ||
3131 | if (status < 0) | ||
3049 | goto xdr_error; | 3132 | goto xdr_error; |
3050 | if (fattr->fileid == 0 && fileid != 0) | 3133 | if (status != 0 && !(fattr->valid & status)) { |
3051 | fattr->fileid = fileid; | 3134 | fattr->fileid = fileid; |
3052 | if ((status = verify_attr_len(xdr, savep, attrlen)) == 0) | 3135 | fattr->valid |= status; |
3053 | fattr->valid = NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4; | 3136 | } |
3137 | |||
3138 | status = verify_attr_len(xdr, savep, attrlen); | ||
3054 | xdr_error: | 3139 | xdr_error: |
3055 | dprintk("%s: xdr returned %d\n", __func__, -status); | 3140 | dprintk("%s: xdr returned %d\n", __func__, -status); |
3056 | return status; | 3141 | return status; |
@@ -4078,9 +4163,7 @@ static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs_se | |||
4078 | status = decode_setattr(&xdr, res); | 4163 | status = decode_setattr(&xdr, res); |
4079 | if (status) | 4164 | if (status) |
4080 | goto out; | 4165 | goto out; |
4081 | status = decode_getfattr(&xdr, res->fattr, res->server); | 4166 | decode_getfattr(&xdr, res->fattr, res->server); |
4082 | if (status == NFS4ERR_DELAY) | ||
4083 | status = 0; | ||
4084 | out: | 4167 | out: |
4085 | return status; | 4168 | return status; |
4086 | } | 4169 | } |
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 7f079209d70a..e2975939126a 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
@@ -176,17 +176,6 @@ void nfs_release_request(struct nfs_page *req) | |||
176 | kref_put(&req->wb_kref, nfs_free_request); | 176 | kref_put(&req->wb_kref, nfs_free_request); |
177 | } | 177 | } |
178 | 178 | ||
179 | static int nfs_wait_bit_killable(void *word) | ||
180 | { | ||
181 | int ret = 0; | ||
182 | |||
183 | if (fatal_signal_pending(current)) | ||
184 | ret = -ERESTARTSYS; | ||
185 | else | ||
186 | schedule(); | ||
187 | return ret; | ||
188 | } | ||
189 | |||
190 | /** | 179 | /** |
191 | * nfs_wait_on_request - Wait for a request to complete. | 180 | * nfs_wait_on_request - Wait for a request to complete. |
192 | * @req: request to wait upon. | 181 | * @req: request to wait upon. |
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index 193465210d7c..7be72d90d49d 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c | |||
@@ -663,4 +663,5 @@ const struct nfs_rpc_ops nfs_v2_clientops = { | |||
663 | .commit_setup = nfs_proc_commit_setup, | 663 | .commit_setup = nfs_proc_commit_setup, |
664 | .lock = nfs_proc_lock, | 664 | .lock = nfs_proc_lock, |
665 | .lock_check_bounds = nfs_lock_check_bounds, | 665 | .lock_check_bounds = nfs_lock_check_bounds, |
666 | .close_context = nfs_close_context, | ||
666 | }; | 667 | }; |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index d6686f4786dc..0942fcbbad3c 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -1018,6 +1018,7 @@ static int nfs_parse_mount_options(char *raw, | |||
1018 | case Opt_rdma: | 1018 | case Opt_rdma: |
1019 | mnt->flags |= NFS_MOUNT_TCP; /* for side protocols */ | 1019 | mnt->flags |= NFS_MOUNT_TCP; /* for side protocols */ |
1020 | mnt->nfs_server.protocol = XPRT_TRANSPORT_RDMA; | 1020 | mnt->nfs_server.protocol = XPRT_TRANSPORT_RDMA; |
1021 | xprt_load_transport(p); | ||
1021 | break; | 1022 | break; |
1022 | case Opt_acl: | 1023 | case Opt_acl: |
1023 | mnt->flags &= ~NFS_MOUNT_NOACL; | 1024 | mnt->flags &= ~NFS_MOUNT_NOACL; |
@@ -1205,12 +1206,14 @@ static int nfs_parse_mount_options(char *raw, | |||
1205 | /* vector side protocols to TCP */ | 1206 | /* vector side protocols to TCP */ |
1206 | mnt->flags |= NFS_MOUNT_TCP; | 1207 | mnt->flags |= NFS_MOUNT_TCP; |
1207 | mnt->nfs_server.protocol = XPRT_TRANSPORT_RDMA; | 1208 | mnt->nfs_server.protocol = XPRT_TRANSPORT_RDMA; |
1209 | xprt_load_transport(string); | ||
1208 | break; | 1210 | break; |
1209 | default: | 1211 | default: |
1210 | errors++; | 1212 | errors++; |
1211 | dfprintk(MOUNT, "NFS: unrecognized " | 1213 | dfprintk(MOUNT, "NFS: unrecognized " |
1212 | "transport protocol\n"); | 1214 | "transport protocol\n"); |
1213 | } | 1215 | } |
1216 | kfree(string); | ||
1214 | break; | 1217 | break; |
1215 | case Opt_mountproto: | 1218 | case Opt_mountproto: |
1216 | string = match_strdup(args); | 1219 | string = match_strdup(args); |
@@ -1218,7 +1221,6 @@ static int nfs_parse_mount_options(char *raw, | |||
1218 | goto out_nomem; | 1221 | goto out_nomem; |
1219 | token = match_token(string, | 1222 | token = match_token(string, |
1220 | nfs_xprt_protocol_tokens, args); | 1223 | nfs_xprt_protocol_tokens, args); |
1221 | kfree(string); | ||
1222 | 1224 | ||
1223 | switch (token) { | 1225 | switch (token) { |
1224 | case Opt_xprt_udp: | 1226 | case Opt_xprt_udp: |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 9f9845859fc1..e560a78995a3 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -313,19 +313,34 @@ static int nfs_writepages_callback(struct page *page, struct writeback_control * | |||
313 | int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc) | 313 | int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc) |
314 | { | 314 | { |
315 | struct inode *inode = mapping->host; | 315 | struct inode *inode = mapping->host; |
316 | unsigned long *bitlock = &NFS_I(inode)->flags; | ||
316 | struct nfs_pageio_descriptor pgio; | 317 | struct nfs_pageio_descriptor pgio; |
317 | int err; | 318 | int err; |
318 | 319 | ||
320 | /* Stop dirtying of new pages while we sync */ | ||
321 | err = wait_on_bit_lock(bitlock, NFS_INO_FLUSHING, | ||
322 | nfs_wait_bit_killable, TASK_KILLABLE); | ||
323 | if (err) | ||
324 | goto out_err; | ||
325 | |||
319 | nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGES); | 326 | nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGES); |
320 | 327 | ||
321 | nfs_pageio_init_write(&pgio, inode, wb_priority(wbc)); | 328 | nfs_pageio_init_write(&pgio, inode, wb_priority(wbc)); |
322 | err = write_cache_pages(mapping, wbc, nfs_writepages_callback, &pgio); | 329 | err = write_cache_pages(mapping, wbc, nfs_writepages_callback, &pgio); |
323 | nfs_pageio_complete(&pgio); | 330 | nfs_pageio_complete(&pgio); |
331 | |||
332 | clear_bit_unlock(NFS_INO_FLUSHING, bitlock); | ||
333 | smp_mb__after_clear_bit(); | ||
334 | wake_up_bit(bitlock, NFS_INO_FLUSHING); | ||
335 | |||
324 | if (err < 0) | 336 | if (err < 0) |
325 | return err; | 337 | goto out_err; |
326 | if (pgio.pg_error < 0) | 338 | err = pgio.pg_error; |
327 | return pgio.pg_error; | 339 | if (err < 0) |
340 | goto out_err; | ||
328 | return 0; | 341 | return 0; |
342 | out_err: | ||
343 | return err; | ||
329 | } | 344 | } |
330 | 345 | ||
331 | /* | 346 | /* |
@@ -404,7 +419,6 @@ nfs_mark_request_commit(struct nfs_page *req) | |||
404 | struct nfs_inode *nfsi = NFS_I(inode); | 419 | struct nfs_inode *nfsi = NFS_I(inode); |
405 | 420 | ||
406 | spin_lock(&inode->i_lock); | 421 | spin_lock(&inode->i_lock); |
407 | nfsi->ncommit++; | ||
408 | set_bit(PG_CLEAN, &(req)->wb_flags); | 422 | set_bit(PG_CLEAN, &(req)->wb_flags); |
409 | radix_tree_tag_set(&nfsi->nfs_page_tree, | 423 | radix_tree_tag_set(&nfsi->nfs_page_tree, |
410 | req->wb_index, | 424 | req->wb_index, |
@@ -524,6 +538,12 @@ static void nfs_cancel_commit_list(struct list_head *head) | |||
524 | } | 538 | } |
525 | 539 | ||
526 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) | 540 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) |
541 | static int | ||
542 | nfs_need_commit(struct nfs_inode *nfsi) | ||
543 | { | ||
544 | return radix_tree_tagged(&nfsi->nfs_page_tree, NFS_PAGE_TAG_COMMIT); | ||
545 | } | ||
546 | |||
527 | /* | 547 | /* |
528 | * nfs_scan_commit - Scan an inode for commit requests | 548 | * nfs_scan_commit - Scan an inode for commit requests |
529 | * @inode: NFS inode to scan | 549 | * @inode: NFS inode to scan |
@@ -538,16 +558,18 @@ static int | |||
538 | nfs_scan_commit(struct inode *inode, struct list_head *dst, pgoff_t idx_start, unsigned int npages) | 558 | nfs_scan_commit(struct inode *inode, struct list_head *dst, pgoff_t idx_start, unsigned int npages) |
539 | { | 559 | { |
540 | struct nfs_inode *nfsi = NFS_I(inode); | 560 | struct nfs_inode *nfsi = NFS_I(inode); |
541 | int res = 0; | ||
542 | 561 | ||
543 | if (nfsi->ncommit != 0) { | 562 | if (!nfs_need_commit(nfsi)) |
544 | res = nfs_scan_list(nfsi, dst, idx_start, npages, | 563 | return 0; |
545 | NFS_PAGE_TAG_COMMIT); | 564 | |
546 | nfsi->ncommit -= res; | 565 | return nfs_scan_list(nfsi, dst, idx_start, npages, NFS_PAGE_TAG_COMMIT); |
547 | } | ||
548 | return res; | ||
549 | } | 566 | } |
550 | #else | 567 | #else |
568 | static inline int nfs_need_commit(struct nfs_inode *nfsi) | ||
569 | { | ||
570 | return 0; | ||
571 | } | ||
572 | |||
551 | static inline int nfs_scan_commit(struct inode *inode, struct list_head *dst, pgoff_t idx_start, unsigned int npages) | 573 | static inline int nfs_scan_commit(struct inode *inode, struct list_head *dst, pgoff_t idx_start, unsigned int npages) |
552 | { | 574 | { |
553 | return 0; | 575 | return 0; |
@@ -820,7 +842,7 @@ static int nfs_write_rpcsetup(struct nfs_page *req, | |||
820 | data->args.stable = NFS_UNSTABLE; | 842 | data->args.stable = NFS_UNSTABLE; |
821 | if (how & FLUSH_STABLE) { | 843 | if (how & FLUSH_STABLE) { |
822 | data->args.stable = NFS_DATA_SYNC; | 844 | data->args.stable = NFS_DATA_SYNC; |
823 | if (!NFS_I(inode)->ncommit) | 845 | if (!nfs_need_commit(NFS_I(inode))) |
824 | data->args.stable = NFS_FILE_SYNC; | 846 | data->args.stable = NFS_FILE_SYNC; |
825 | } | 847 | } |
826 | 848 | ||
@@ -1425,18 +1447,13 @@ static int nfs_write_mapping(struct address_space *mapping, int how) | |||
1425 | { | 1447 | { |
1426 | struct writeback_control wbc = { | 1448 | struct writeback_control wbc = { |
1427 | .bdi = mapping->backing_dev_info, | 1449 | .bdi = mapping->backing_dev_info, |
1428 | .sync_mode = WB_SYNC_NONE, | 1450 | .sync_mode = WB_SYNC_ALL, |
1429 | .nr_to_write = LONG_MAX, | 1451 | .nr_to_write = LONG_MAX, |
1430 | .range_start = 0, | 1452 | .range_start = 0, |
1431 | .range_end = LLONG_MAX, | 1453 | .range_end = LLONG_MAX, |
1432 | .for_writepages = 1, | 1454 | .for_writepages = 1, |
1433 | }; | 1455 | }; |
1434 | int ret; | ||
1435 | 1456 | ||
1436 | ret = __nfs_write_mapping(mapping, &wbc, how); | ||
1437 | if (ret < 0) | ||
1438 | return ret; | ||
1439 | wbc.sync_mode = WB_SYNC_ALL; | ||
1440 | return __nfs_write_mapping(mapping, &wbc, how); | 1457 | return __nfs_write_mapping(mapping, &wbc, how); |
1441 | } | 1458 | } |
1442 | 1459 | ||