diff options
author | Steve French <sfrench@us.ibm.com> | 2010-05-13 18:19:32 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2010-05-13 18:19:32 -0400 |
commit | baa456331738b4e76a92318b62b354377a30ad80 (patch) | |
tree | 75c828a7c8a9f1b5f7f41b2e53271eafb7e561ef /fs/nfs | |
parent | aa3e5572c538d753dce11bf93532a75f95d22b40 (diff) | |
parent | 4462dc02842698f173f518c1f5ce79c0fb89395a (diff) |
Merge branch 'master' of /pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts:
fs/cifs/inode.c
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/client.c | 2 | ||||
-rw-r--r-- | fs/nfs/delegation.c | 86 | ||||
-rw-r--r-- | fs/nfs/dir.c | 4 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 5 | ||||
-rw-r--r-- | fs/nfs/super.c | 3 | ||||
-rw-r--r-- | fs/nfs/write.c | 55 |
6 files changed, 98 insertions, 57 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index a8766c4ef2e0..acc9c4943b84 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -966,6 +966,8 @@ out_error: | |||
966 | static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *source) | 966 | static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *source) |
967 | { | 967 | { |
968 | target->flags = source->flags; | 968 | target->flags = source->flags; |
969 | target->rsize = source->rsize; | ||
970 | target->wsize = source->wsize; | ||
969 | target->acregmin = source->acregmin; | 971 | target->acregmin = source->acregmin; |
970 | target->acregmax = source->acregmax; | 972 | target->acregmax = source->acregmax; |
971 | target->acdirmin = source->acdirmin; | 973 | target->acdirmin = source->acdirmin; |
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index 15671245c6ee..ea61d26e7871 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c | |||
@@ -24,6 +24,8 @@ | |||
24 | 24 | ||
25 | static void nfs_do_free_delegation(struct nfs_delegation *delegation) | 25 | static void nfs_do_free_delegation(struct nfs_delegation *delegation) |
26 | { | 26 | { |
27 | if (delegation->cred) | ||
28 | put_rpccred(delegation->cred); | ||
27 | kfree(delegation); | 29 | kfree(delegation); |
28 | } | 30 | } |
29 | 31 | ||
@@ -36,13 +38,7 @@ static void nfs_free_delegation_callback(struct rcu_head *head) | |||
36 | 38 | ||
37 | static void nfs_free_delegation(struct nfs_delegation *delegation) | 39 | static void nfs_free_delegation(struct nfs_delegation *delegation) |
38 | { | 40 | { |
39 | struct rpc_cred *cred; | ||
40 | |||
41 | cred = rcu_dereference(delegation->cred); | ||
42 | rcu_assign_pointer(delegation->cred, NULL); | ||
43 | call_rcu(&delegation->rcu, nfs_free_delegation_callback); | 41 | call_rcu(&delegation->rcu, nfs_free_delegation_callback); |
44 | if (cred) | ||
45 | put_rpccred(cred); | ||
46 | } | 42 | } |
47 | 43 | ||
48 | void nfs_mark_delegation_referenced(struct nfs_delegation *delegation) | 44 | void nfs_mark_delegation_referenced(struct nfs_delegation *delegation) |
@@ -129,21 +125,35 @@ again: | |||
129 | */ | 125 | */ |
130 | void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res) | 126 | void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res) |
131 | { | 127 | { |
132 | struct nfs_delegation *delegation = NFS_I(inode)->delegation; | 128 | struct nfs_delegation *delegation; |
133 | struct rpc_cred *oldcred; | 129 | struct rpc_cred *oldcred = NULL; |
134 | 130 | ||
135 | if (delegation == NULL) | 131 | rcu_read_lock(); |
136 | return; | 132 | delegation = rcu_dereference(NFS_I(inode)->delegation); |
137 | memcpy(delegation->stateid.data, res->delegation.data, | 133 | if (delegation != NULL) { |
138 | sizeof(delegation->stateid.data)); | 134 | spin_lock(&delegation->lock); |
139 | delegation->type = res->delegation_type; | 135 | if (delegation->inode != NULL) { |
140 | delegation->maxsize = res->maxsize; | 136 | memcpy(delegation->stateid.data, res->delegation.data, |
141 | oldcred = delegation->cred; | 137 | sizeof(delegation->stateid.data)); |
142 | delegation->cred = get_rpccred(cred); | 138 | delegation->type = res->delegation_type; |
143 | clear_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags); | 139 | delegation->maxsize = res->maxsize; |
144 | NFS_I(inode)->delegation_state = delegation->type; | 140 | oldcred = delegation->cred; |
145 | smp_wmb(); | 141 | delegation->cred = get_rpccred(cred); |
146 | put_rpccred(oldcred); | 142 | clear_bit(NFS_DELEGATION_NEED_RECLAIM, |
143 | &delegation->flags); | ||
144 | NFS_I(inode)->delegation_state = delegation->type; | ||
145 | spin_unlock(&delegation->lock); | ||
146 | put_rpccred(oldcred); | ||
147 | rcu_read_unlock(); | ||
148 | } else { | ||
149 | /* We appear to have raced with a delegation return. */ | ||
150 | spin_unlock(&delegation->lock); | ||
151 | rcu_read_unlock(); | ||
152 | nfs_inode_set_delegation(inode, cred, res); | ||
153 | } | ||
154 | } else { | ||
155 | rcu_read_unlock(); | ||
156 | } | ||
147 | } | 157 | } |
148 | 158 | ||
149 | static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *delegation, int issync) | 159 | static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *delegation, int issync) |
@@ -166,9 +176,13 @@ static struct inode *nfs_delegation_grab_inode(struct nfs_delegation *delegation | |||
166 | return inode; | 176 | return inode; |
167 | } | 177 | } |
168 | 178 | ||
169 | static struct nfs_delegation *nfs_detach_delegation_locked(struct nfs_inode *nfsi, const nfs4_stateid *stateid) | 179 | static struct nfs_delegation *nfs_detach_delegation_locked(struct nfs_inode *nfsi, |
180 | const nfs4_stateid *stateid, | ||
181 | struct nfs_client *clp) | ||
170 | { | 182 | { |
171 | struct nfs_delegation *delegation = rcu_dereference(nfsi->delegation); | 183 | struct nfs_delegation *delegation = |
184 | rcu_dereference_protected(nfsi->delegation, | ||
185 | lockdep_is_held(&clp->cl_lock)); | ||
172 | 186 | ||
173 | if (delegation == NULL) | 187 | if (delegation == NULL) |
174 | goto nomatch; | 188 | goto nomatch; |
@@ -195,7 +209,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct | |||
195 | { | 209 | { |
196 | struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; | 210 | struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; |
197 | struct nfs_inode *nfsi = NFS_I(inode); | 211 | struct nfs_inode *nfsi = NFS_I(inode); |
198 | struct nfs_delegation *delegation; | 212 | struct nfs_delegation *delegation, *old_delegation; |
199 | struct nfs_delegation *freeme = NULL; | 213 | struct nfs_delegation *freeme = NULL; |
200 | int status = 0; | 214 | int status = 0; |
201 | 215 | ||
@@ -213,10 +227,12 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct | |||
213 | spin_lock_init(&delegation->lock); | 227 | spin_lock_init(&delegation->lock); |
214 | 228 | ||
215 | spin_lock(&clp->cl_lock); | 229 | spin_lock(&clp->cl_lock); |
216 | if (rcu_dereference(nfsi->delegation) != NULL) { | 230 | old_delegation = rcu_dereference_protected(nfsi->delegation, |
217 | if (memcmp(&delegation->stateid, &nfsi->delegation->stateid, | 231 | lockdep_is_held(&clp->cl_lock)); |
218 | sizeof(delegation->stateid)) == 0 && | 232 | if (old_delegation != NULL) { |
219 | delegation->type == nfsi->delegation->type) { | 233 | if (memcmp(&delegation->stateid, &old_delegation->stateid, |
234 | sizeof(old_delegation->stateid)) == 0 && | ||
235 | delegation->type == old_delegation->type) { | ||
220 | goto out; | 236 | goto out; |
221 | } | 237 | } |
222 | /* | 238 | /* |
@@ -226,12 +242,12 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct | |||
226 | dfprintk(FILE, "%s: server %s handed out " | 242 | dfprintk(FILE, "%s: server %s handed out " |
227 | "a duplicate delegation!\n", | 243 | "a duplicate delegation!\n", |
228 | __func__, clp->cl_hostname); | 244 | __func__, clp->cl_hostname); |
229 | if (delegation->type <= nfsi->delegation->type) { | 245 | if (delegation->type <= old_delegation->type) { |
230 | freeme = delegation; | 246 | freeme = delegation; |
231 | delegation = NULL; | 247 | delegation = NULL; |
232 | goto out; | 248 | goto out; |
233 | } | 249 | } |
234 | freeme = nfs_detach_delegation_locked(nfsi, NULL); | 250 | freeme = nfs_detach_delegation_locked(nfsi, NULL, clp); |
235 | } | 251 | } |
236 | list_add_rcu(&delegation->super_list, &clp->cl_delegations); | 252 | list_add_rcu(&delegation->super_list, &clp->cl_delegations); |
237 | nfsi->delegation_state = delegation->type; | 253 | nfsi->delegation_state = delegation->type; |
@@ -301,7 +317,7 @@ restart: | |||
301 | if (inode == NULL) | 317 | if (inode == NULL) |
302 | continue; | 318 | continue; |
303 | spin_lock(&clp->cl_lock); | 319 | spin_lock(&clp->cl_lock); |
304 | delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL); | 320 | delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL, clp); |
305 | spin_unlock(&clp->cl_lock); | 321 | spin_unlock(&clp->cl_lock); |
306 | rcu_read_unlock(); | 322 | rcu_read_unlock(); |
307 | if (delegation != NULL) { | 323 | if (delegation != NULL) { |
@@ -330,9 +346,9 @@ void nfs_inode_return_delegation_noreclaim(struct inode *inode) | |||
330 | struct nfs_inode *nfsi = NFS_I(inode); | 346 | struct nfs_inode *nfsi = NFS_I(inode); |
331 | struct nfs_delegation *delegation; | 347 | struct nfs_delegation *delegation; |
332 | 348 | ||
333 | if (rcu_dereference(nfsi->delegation) != NULL) { | 349 | if (rcu_access_pointer(nfsi->delegation) != NULL) { |
334 | spin_lock(&clp->cl_lock); | 350 | spin_lock(&clp->cl_lock); |
335 | delegation = nfs_detach_delegation_locked(nfsi, NULL); | 351 | delegation = nfs_detach_delegation_locked(nfsi, NULL, clp); |
336 | spin_unlock(&clp->cl_lock); | 352 | spin_unlock(&clp->cl_lock); |
337 | if (delegation != NULL) | 353 | if (delegation != NULL) |
338 | nfs_do_return_delegation(inode, delegation, 0); | 354 | nfs_do_return_delegation(inode, delegation, 0); |
@@ -346,9 +362,9 @@ int nfs_inode_return_delegation(struct inode *inode) | |||
346 | struct nfs_delegation *delegation; | 362 | struct nfs_delegation *delegation; |
347 | int err = 0; | 363 | int err = 0; |
348 | 364 | ||
349 | if (rcu_dereference(nfsi->delegation) != NULL) { | 365 | if (rcu_access_pointer(nfsi->delegation) != NULL) { |
350 | spin_lock(&clp->cl_lock); | 366 | spin_lock(&clp->cl_lock); |
351 | delegation = nfs_detach_delegation_locked(nfsi, NULL); | 367 | delegation = nfs_detach_delegation_locked(nfsi, NULL, clp); |
352 | spin_unlock(&clp->cl_lock); | 368 | spin_unlock(&clp->cl_lock); |
353 | if (delegation != NULL) { | 369 | if (delegation != NULL) { |
354 | nfs_msync_inode(inode); | 370 | nfs_msync_inode(inode); |
@@ -526,7 +542,7 @@ restart: | |||
526 | if (inode == NULL) | 542 | if (inode == NULL) |
527 | continue; | 543 | continue; |
528 | spin_lock(&clp->cl_lock); | 544 | spin_lock(&clp->cl_lock); |
529 | delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL); | 545 | delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL, clp); |
530 | spin_unlock(&clp->cl_lock); | 546 | spin_unlock(&clp->cl_lock); |
531 | rcu_read_unlock(); | 547 | rcu_read_unlock(); |
532 | if (delegation != NULL) | 548 | if (delegation != NULL) |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index be46f26c9a56..a7bb5c694aa3 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -837,6 +837,8 @@ out_zap_parent: | |||
837 | /* If we have submounts, don't unhash ! */ | 837 | /* If we have submounts, don't unhash ! */ |
838 | if (have_submounts(dentry)) | 838 | if (have_submounts(dentry)) |
839 | goto out_valid; | 839 | goto out_valid; |
840 | if (dentry->d_flags & DCACHE_DISCONNECTED) | ||
841 | goto out_valid; | ||
840 | shrink_dcache_parent(dentry); | 842 | shrink_dcache_parent(dentry); |
841 | } | 843 | } |
842 | d_drop(dentry); | 844 | d_drop(dentry); |
@@ -1050,7 +1052,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1050 | struct inode *dir; | 1052 | struct inode *dir; |
1051 | int openflags, ret = 0; | 1053 | int openflags, ret = 0; |
1052 | 1054 | ||
1053 | if (!is_atomic_open(nd)) | 1055 | if (!is_atomic_open(nd) || d_mountpoint(dentry)) |
1054 | goto no_open; | 1056 | goto no_open; |
1055 | parent = dget_parent(dentry); | 1057 | parent = dget_parent(dentry); |
1056 | dir = parent->d_inode; | 1058 | dir = parent->d_inode; |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 638067007c65..071fcedd517c 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -5218,9 +5218,12 @@ static int nfs41_proc_reclaim_complete(struct nfs_client *clp) | |||
5218 | msg.rpc_resp = &calldata->res; | 5218 | msg.rpc_resp = &calldata->res; |
5219 | task_setup_data.callback_data = calldata; | 5219 | task_setup_data.callback_data = calldata; |
5220 | task = rpc_run_task(&task_setup_data); | 5220 | task = rpc_run_task(&task_setup_data); |
5221 | if (IS_ERR(task)) | 5221 | if (IS_ERR(task)) { |
5222 | status = PTR_ERR(task); | 5222 | status = PTR_ERR(task); |
5223 | goto out; | ||
5224 | } | ||
5223 | rpc_put_task(task); | 5225 | rpc_put_task(task); |
5226 | return 0; | ||
5224 | out: | 5227 | out: |
5225 | dprintk("<-- %s status=%d\n", __func__, status); | 5228 | dprintk("<-- %s status=%d\n", __func__, status); |
5226 | return status; | 5229 | return status; |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index e01637240eeb..b4148fc00f9f 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -2187,6 +2187,7 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
2187 | if (data->version == 4) { | 2187 | if (data->version == 4) { |
2188 | error = nfs4_try_mount(flags, dev_name, data, mnt); | 2188 | error = nfs4_try_mount(flags, dev_name, data, mnt); |
2189 | kfree(data->client_address); | 2189 | kfree(data->client_address); |
2190 | kfree(data->nfs_server.export_path); | ||
2190 | goto out; | 2191 | goto out; |
2191 | } | 2192 | } |
2192 | #endif /* CONFIG_NFS_V4 */ | 2193 | #endif /* CONFIG_NFS_V4 */ |
@@ -2657,7 +2658,7 @@ static void nfs_fix_devname(const struct path *path, struct vfsmount *mnt) | |||
2657 | devname = nfs_path(path->mnt->mnt_devname, | 2658 | devname = nfs_path(path->mnt->mnt_devname, |
2658 | path->mnt->mnt_root, path->dentry, | 2659 | path->mnt->mnt_root, path->dentry, |
2659 | page, PAGE_SIZE); | 2660 | page, PAGE_SIZE); |
2660 | if (devname == NULL) | 2661 | if (IS_ERR(devname)) |
2661 | goto out_freepage; | 2662 | goto out_freepage; |
2662 | tmp = kstrdup(devname, GFP_KERNEL); | 2663 | tmp = kstrdup(devname, GFP_KERNEL); |
2663 | if (tmp == NULL) | 2664 | if (tmp == NULL) |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index de38d63aa920..3aea3ca98ab7 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -1201,6 +1201,25 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) | |||
1201 | 1201 | ||
1202 | 1202 | ||
1203 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) | 1203 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) |
1204 | static int nfs_commit_set_lock(struct nfs_inode *nfsi, int may_wait) | ||
1205 | { | ||
1206 | if (!test_and_set_bit(NFS_INO_COMMIT, &nfsi->flags)) | ||
1207 | return 1; | ||
1208 | if (may_wait && !out_of_line_wait_on_bit_lock(&nfsi->flags, | ||
1209 | NFS_INO_COMMIT, nfs_wait_bit_killable, | ||
1210 | TASK_KILLABLE)) | ||
1211 | return 1; | ||
1212 | return 0; | ||
1213 | } | ||
1214 | |||
1215 | static void nfs_commit_clear_lock(struct nfs_inode *nfsi) | ||
1216 | { | ||
1217 | clear_bit(NFS_INO_COMMIT, &nfsi->flags); | ||
1218 | smp_mb__after_clear_bit(); | ||
1219 | wake_up_bit(&nfsi->flags, NFS_INO_COMMIT); | ||
1220 | } | ||
1221 | |||
1222 | |||
1204 | static void nfs_commitdata_release(void *data) | 1223 | static void nfs_commitdata_release(void *data) |
1205 | { | 1224 | { |
1206 | struct nfs_write_data *wdata = data; | 1225 | struct nfs_write_data *wdata = data; |
@@ -1262,8 +1281,6 @@ static int nfs_commit_rpcsetup(struct list_head *head, | |||
1262 | task = rpc_run_task(&task_setup_data); | 1281 | task = rpc_run_task(&task_setup_data); |
1263 | if (IS_ERR(task)) | 1282 | if (IS_ERR(task)) |
1264 | return PTR_ERR(task); | 1283 | return PTR_ERR(task); |
1265 | if (how & FLUSH_SYNC) | ||
1266 | rpc_wait_for_completion_task(task); | ||
1267 | rpc_put_task(task); | 1284 | rpc_put_task(task); |
1268 | return 0; | 1285 | return 0; |
1269 | } | 1286 | } |
@@ -1294,6 +1311,7 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how) | |||
1294 | BDI_RECLAIMABLE); | 1311 | BDI_RECLAIMABLE); |
1295 | nfs_clear_page_tag_locked(req); | 1312 | nfs_clear_page_tag_locked(req); |
1296 | } | 1313 | } |
1314 | nfs_commit_clear_lock(NFS_I(inode)); | ||
1297 | return -ENOMEM; | 1315 | return -ENOMEM; |
1298 | } | 1316 | } |
1299 | 1317 | ||
@@ -1349,6 +1367,7 @@ static void nfs_commit_release(void *calldata) | |||
1349 | next: | 1367 | next: |
1350 | nfs_clear_page_tag_locked(req); | 1368 | nfs_clear_page_tag_locked(req); |
1351 | } | 1369 | } |
1370 | nfs_commit_clear_lock(NFS_I(data->inode)); | ||
1352 | nfs_commitdata_release(calldata); | 1371 | nfs_commitdata_release(calldata); |
1353 | } | 1372 | } |
1354 | 1373 | ||
@@ -1363,8 +1382,11 @@ static const struct rpc_call_ops nfs_commit_ops = { | |||
1363 | static int nfs_commit_inode(struct inode *inode, int how) | 1382 | static int nfs_commit_inode(struct inode *inode, int how) |
1364 | { | 1383 | { |
1365 | LIST_HEAD(head); | 1384 | LIST_HEAD(head); |
1366 | int res; | 1385 | int may_wait = how & FLUSH_SYNC; |
1386 | int res = 0; | ||
1367 | 1387 | ||
1388 | if (!nfs_commit_set_lock(NFS_I(inode), may_wait)) | ||
1389 | goto out; | ||
1368 | spin_lock(&inode->i_lock); | 1390 | spin_lock(&inode->i_lock); |
1369 | res = nfs_scan_commit(inode, &head, 0, 0); | 1391 | res = nfs_scan_commit(inode, &head, 0, 0); |
1370 | spin_unlock(&inode->i_lock); | 1392 | spin_unlock(&inode->i_lock); |
@@ -1372,7 +1394,13 @@ static int nfs_commit_inode(struct inode *inode, int how) | |||
1372 | int error = nfs_commit_list(inode, &head, how); | 1394 | int error = nfs_commit_list(inode, &head, how); |
1373 | if (error < 0) | 1395 | if (error < 0) |
1374 | return error; | 1396 | return error; |
1375 | } | 1397 | if (may_wait) |
1398 | wait_on_bit(&NFS_I(inode)->flags, NFS_INO_COMMIT, | ||
1399 | nfs_wait_bit_killable, | ||
1400 | TASK_KILLABLE); | ||
1401 | } else | ||
1402 | nfs_commit_clear_lock(NFS_I(inode)); | ||
1403 | out: | ||
1376 | return res; | 1404 | return res; |
1377 | } | 1405 | } |
1378 | 1406 | ||
@@ -1444,6 +1472,7 @@ int nfs_wb_page_cancel(struct inode *inode, struct page *page) | |||
1444 | 1472 | ||
1445 | BUG_ON(!PageLocked(page)); | 1473 | BUG_ON(!PageLocked(page)); |
1446 | for (;;) { | 1474 | for (;;) { |
1475 | wait_on_page_writeback(page); | ||
1447 | req = nfs_page_find_request(page); | 1476 | req = nfs_page_find_request(page); |
1448 | if (req == NULL) | 1477 | if (req == NULL) |
1449 | break; | 1478 | break; |
@@ -1478,30 +1507,18 @@ int nfs_wb_page(struct inode *inode, struct page *page) | |||
1478 | .range_start = range_start, | 1507 | .range_start = range_start, |
1479 | .range_end = range_end, | 1508 | .range_end = range_end, |
1480 | }; | 1509 | }; |
1481 | struct nfs_page *req; | ||
1482 | int need_commit; | ||
1483 | int ret; | 1510 | int ret; |
1484 | 1511 | ||
1485 | while(PagePrivate(page)) { | 1512 | while(PagePrivate(page)) { |
1513 | wait_on_page_writeback(page); | ||
1486 | if (clear_page_dirty_for_io(page)) { | 1514 | if (clear_page_dirty_for_io(page)) { |
1487 | ret = nfs_writepage_locked(page, &wbc); | 1515 | ret = nfs_writepage_locked(page, &wbc); |
1488 | if (ret < 0) | 1516 | if (ret < 0) |
1489 | goto out_error; | 1517 | goto out_error; |
1490 | } | 1518 | } |
1491 | req = nfs_find_and_lock_request(page); | 1519 | ret = sync_inode(inode, &wbc); |
1492 | if (!req) | 1520 | if (ret < 0) |
1493 | break; | ||
1494 | if (IS_ERR(req)) { | ||
1495 | ret = PTR_ERR(req); | ||
1496 | goto out_error; | 1521 | goto out_error; |
1497 | } | ||
1498 | need_commit = test_bit(PG_CLEAN, &req->wb_flags); | ||
1499 | nfs_clear_page_tag_locked(req); | ||
1500 | if (need_commit) { | ||
1501 | ret = nfs_commit_inode(inode, FLUSH_SYNC); | ||
1502 | if (ret < 0) | ||
1503 | goto out_error; | ||
1504 | } | ||
1505 | } | 1522 | } |
1506 | return 0; | 1523 | return 0; |
1507 | out_error: | 1524 | out_error: |