aboutsummaryrefslogtreecommitdiffstats
path: root/fs/afs/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/afs/dir.c')
-rw-r--r--fs/afs/dir.c54
1 files changed, 26 insertions, 28 deletions
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 5889f70d4d27..7d623008157f 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -180,6 +180,7 @@ static int afs_dir_open(struct inode *inode, struct file *file)
180 * get reclaimed during the iteration. 180 * get reclaimed during the iteration.
181 */ 181 */
182static struct afs_read *afs_read_dir(struct afs_vnode *dvnode, struct key *key) 182static struct afs_read *afs_read_dir(struct afs_vnode *dvnode, struct key *key)
183 __acquires(&dvnode->validate_lock)
183{ 184{
184 struct afs_read *req; 185 struct afs_read *req;
185 loff_t i_size; 186 loff_t i_size;
@@ -261,18 +262,21 @@ retry:
261 /* If we're going to reload, we need to lock all the pages to prevent 262 /* If we're going to reload, we need to lock all the pages to prevent
262 * races. 263 * races.
263 */ 264 */
264 if (!test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) { 265 ret = -ERESTARTSYS;
265 ret = -ERESTARTSYS; 266 if (down_read_killable(&dvnode->validate_lock) < 0)
266 for (i = 0; i < req->nr_pages; i++) 267 goto error;
267 if (lock_page_killable(req->pages[i]) < 0)
268 goto error_unlock;
269 268
270 if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) 269 if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
271 goto success; 270 goto success;
271
272 up_read(&dvnode->validate_lock);
273 if (down_write_killable(&dvnode->validate_lock) < 0)
274 goto error;
272 275
276 if (!test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) {
273 ret = afs_fetch_data(dvnode, key, req); 277 ret = afs_fetch_data(dvnode, key, req);
274 if (ret < 0) 278 if (ret < 0)
275 goto error_unlock_all; 279 goto error_unlock;
276 280
277 task_io_account_read(PAGE_SIZE * req->nr_pages); 281 task_io_account_read(PAGE_SIZE * req->nr_pages);
278 282
@@ -284,33 +288,26 @@ retry:
284 for (i = 0; i < req->nr_pages; i++) 288 for (i = 0; i < req->nr_pages; i++)
285 if (!afs_dir_check_page(dvnode, req->pages[i], 289 if (!afs_dir_check_page(dvnode, req->pages[i],
286 req->actual_len)) 290 req->actual_len))
287 goto error_unlock_all; 291 goto error_unlock;
288 292
289 // TODO: Trim excess pages 293 // TODO: Trim excess pages
290 294
291 set_bit(AFS_VNODE_DIR_VALID, &dvnode->flags); 295 set_bit(AFS_VNODE_DIR_VALID, &dvnode->flags);
292 } 296 }
293 297
298 downgrade_write(&dvnode->validate_lock);
294success: 299success:
295 i = req->nr_pages;
296 while (i > 0)
297 unlock_page(req->pages[--i]);
298 return req; 300 return req;
299 301
300error_unlock_all:
301 i = req->nr_pages;
302error_unlock: 302error_unlock:
303 while (i > 0) 303 up_write(&dvnode->validate_lock);
304 unlock_page(req->pages[--i]);
305error: 304error:
306 afs_put_read(req); 305 afs_put_read(req);
307 _leave(" = %d", ret); 306 _leave(" = %d", ret);
308 return ERR_PTR(ret); 307 return ERR_PTR(ret);
309 308
310content_has_grown: 309content_has_grown:
311 i = req->nr_pages; 310 up_write(&dvnode->validate_lock);
312 while (i > 0)
313 unlock_page(req->pages[--i]);
314 afs_put_read(req); 311 afs_put_read(req);
315 goto retry; 312 goto retry;
316} 313}
@@ -473,6 +470,7 @@ static int afs_dir_iterate(struct inode *dir, struct dir_context *ctx,
473 } 470 }
474 471
475out: 472out:
473 up_read(&dvnode->validate_lock);
476 afs_put_read(req); 474 afs_put_read(req);
477 _leave(" = %d", ret); 475 _leave(" = %d", ret);
478 return ret; 476 return ret;
@@ -1143,7 +1141,7 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
1143 ret = -ERESTARTSYS; 1141 ret = -ERESTARTSYS;
1144 if (afs_begin_vnode_operation(&fc, dvnode, key)) { 1142 if (afs_begin_vnode_operation(&fc, dvnode, key)) {
1145 while (afs_select_fileserver(&fc)) { 1143 while (afs_select_fileserver(&fc)) {
1146 fc.cb_break = dvnode->cb_break + dvnode->cb_s_break; 1144 fc.cb_break = afs_calc_vnode_cb_break(dvnode);
1147 afs_fs_create(&fc, dentry->d_name.name, mode, data_version, 1145 afs_fs_create(&fc, dentry->d_name.name, mode, data_version,
1148 &newfid, &newstatus, &newcb); 1146 &newfid, &newstatus, &newcb);
1149 } 1147 }
@@ -1213,7 +1211,7 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
1213 ret = -ERESTARTSYS; 1211 ret = -ERESTARTSYS;
1214 if (afs_begin_vnode_operation(&fc, dvnode, key)) { 1212 if (afs_begin_vnode_operation(&fc, dvnode, key)) {
1215 while (afs_select_fileserver(&fc)) { 1213 while (afs_select_fileserver(&fc)) {
1216 fc.cb_break = dvnode->cb_break + dvnode->cb_s_break; 1214 fc.cb_break = afs_calc_vnode_cb_break(dvnode);
1217 afs_fs_remove(&fc, dentry->d_name.name, true, 1215 afs_fs_remove(&fc, dentry->d_name.name, true,
1218 data_version); 1216 data_version);
1219 } 1217 }
@@ -1316,7 +1314,7 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)
1316 ret = -ERESTARTSYS; 1314 ret = -ERESTARTSYS;
1317 if (afs_begin_vnode_operation(&fc, dvnode, key)) { 1315 if (afs_begin_vnode_operation(&fc, dvnode, key)) {
1318 while (afs_select_fileserver(&fc)) { 1316 while (afs_select_fileserver(&fc)) {
1319 fc.cb_break = dvnode->cb_break + dvnode->cb_s_break; 1317 fc.cb_break = afs_calc_vnode_cb_break(dvnode);
1320 afs_fs_remove(&fc, dentry->d_name.name, false, 1318 afs_fs_remove(&fc, dentry->d_name.name, false,
1321 data_version); 1319 data_version);
1322 } 1320 }
@@ -1373,7 +1371,7 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
1373 ret = -ERESTARTSYS; 1371 ret = -ERESTARTSYS;
1374 if (afs_begin_vnode_operation(&fc, dvnode, key)) { 1372 if (afs_begin_vnode_operation(&fc, dvnode, key)) {
1375 while (afs_select_fileserver(&fc)) { 1373 while (afs_select_fileserver(&fc)) {
1376 fc.cb_break = dvnode->cb_break + dvnode->cb_s_break; 1374 fc.cb_break = afs_calc_vnode_cb_break(dvnode);
1377 afs_fs_create(&fc, dentry->d_name.name, mode, data_version, 1375 afs_fs_create(&fc, dentry->d_name.name, mode, data_version,
1378 &newfid, &newstatus, &newcb); 1376 &newfid, &newstatus, &newcb);
1379 } 1377 }
@@ -1443,8 +1441,8 @@ static int afs_link(struct dentry *from, struct inode *dir,
1443 } 1441 }
1444 1442
1445 while (afs_select_fileserver(&fc)) { 1443 while (afs_select_fileserver(&fc)) {
1446 fc.cb_break = dvnode->cb_break + dvnode->cb_s_break; 1444 fc.cb_break = afs_calc_vnode_cb_break(dvnode);
1447 fc.cb_break_2 = vnode->cb_break + vnode->cb_s_break; 1445 fc.cb_break_2 = afs_calc_vnode_cb_break(vnode);
1448 afs_fs_link(&fc, vnode, dentry->d_name.name, data_version); 1446 afs_fs_link(&fc, vnode, dentry->d_name.name, data_version);
1449 } 1447 }
1450 1448
@@ -1512,7 +1510,7 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry,
1512 ret = -ERESTARTSYS; 1510 ret = -ERESTARTSYS;
1513 if (afs_begin_vnode_operation(&fc, dvnode, key)) { 1511 if (afs_begin_vnode_operation(&fc, dvnode, key)) {
1514 while (afs_select_fileserver(&fc)) { 1512 while (afs_select_fileserver(&fc)) {
1515 fc.cb_break = dvnode->cb_break + dvnode->cb_s_break; 1513 fc.cb_break = afs_calc_vnode_cb_break(dvnode);
1516 afs_fs_symlink(&fc, dentry->d_name.name, 1514 afs_fs_symlink(&fc, dentry->d_name.name,
1517 content, data_version, 1515 content, data_version,
1518 &newfid, &newstatus); 1516 &newfid, &newstatus);
@@ -1588,8 +1586,8 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
1588 } 1586 }
1589 } 1587 }
1590 while (afs_select_fileserver(&fc)) { 1588 while (afs_select_fileserver(&fc)) {
1591 fc.cb_break = orig_dvnode->cb_break + orig_dvnode->cb_s_break; 1589 fc.cb_break = afs_calc_vnode_cb_break(orig_dvnode);
1592 fc.cb_break_2 = new_dvnode->cb_break + new_dvnode->cb_s_break; 1590 fc.cb_break_2 = afs_calc_vnode_cb_break(new_dvnode);
1593 afs_fs_rename(&fc, old_dentry->d_name.name, 1591 afs_fs_rename(&fc, old_dentry->d_name.name,
1594 new_dvnode, new_dentry->d_name.name, 1592 new_dvnode, new_dentry->d_name.name,
1595 orig_data_version, new_data_version); 1593 orig_data_version, new_data_version);