diff options
Diffstat (limited to 'fs/nfs/dir.c')
-rw-r--r-- | fs/nfs/dir.c | 75 |
1 files changed, 42 insertions, 33 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index c933bdfbcb1f..0fac2cb1ea18 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -437,6 +437,7 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) | |||
437 | struct dentry *alias; | 437 | struct dentry *alias; |
438 | struct inode *dir = parent->d_inode; | 438 | struct inode *dir = parent->d_inode; |
439 | struct inode *inode; | 439 | struct inode *inode; |
440 | int status; | ||
440 | 441 | ||
441 | if (filename.name[0] == '.') { | 442 | if (filename.name[0] == '.') { |
442 | if (filename.len == 1) | 443 | if (filename.len == 1) |
@@ -449,7 +450,9 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) | |||
449 | dentry = d_lookup(parent, &filename); | 450 | dentry = d_lookup(parent, &filename); |
450 | if (dentry != NULL) { | 451 | if (dentry != NULL) { |
451 | if (nfs_same_file(dentry, entry)) { | 452 | if (nfs_same_file(dentry, entry)) { |
452 | nfs_refresh_inode(dentry->d_inode, entry->fattr); | 453 | status = nfs_refresh_inode(dentry->d_inode, entry->fattr); |
454 | if (!status) | ||
455 | nfs_setsecurity(dentry->d_inode, entry->fattr, entry->label); | ||
453 | goto out; | 456 | goto out; |
454 | } else { | 457 | } else { |
455 | if (d_invalidate(dentry) != 0) | 458 | if (d_invalidate(dentry) != 0) |
@@ -462,7 +465,7 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) | |||
462 | if (dentry == NULL) | 465 | if (dentry == NULL) |
463 | return; | 466 | return; |
464 | 467 | ||
465 | inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr); | 468 | inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr, entry->label); |
466 | if (IS_ERR(inode)) | 469 | if (IS_ERR(inode)) |
467 | goto out; | 470 | goto out; |
468 | 471 | ||
@@ -587,10 +590,16 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, | |||
587 | if (entry.fh == NULL || entry.fattr == NULL) | 590 | if (entry.fh == NULL || entry.fattr == NULL) |
588 | goto out; | 591 | goto out; |
589 | 592 | ||
593 | entry.label = nfs4_label_alloc(NFS_SERVER(inode), GFP_NOWAIT); | ||
594 | if (IS_ERR(entry.label)) { | ||
595 | status = PTR_ERR(entry.label); | ||
596 | goto out; | ||
597 | } | ||
598 | |||
590 | array = nfs_readdir_get_array(page); | 599 | array = nfs_readdir_get_array(page); |
591 | if (IS_ERR(array)) { | 600 | if (IS_ERR(array)) { |
592 | status = PTR_ERR(array); | 601 | status = PTR_ERR(array); |
593 | goto out; | 602 | goto out_label_free; |
594 | } | 603 | } |
595 | memset(array, 0, sizeof(struct nfs_cache_array)); | 604 | memset(array, 0, sizeof(struct nfs_cache_array)); |
596 | array->eof_index = -1; | 605 | array->eof_index = -1; |
@@ -616,6 +625,8 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, | |||
616 | nfs_readdir_free_large_page(pages_ptr, pages, array_size); | 625 | nfs_readdir_free_large_page(pages_ptr, pages, array_size); |
617 | out_release_array: | 626 | out_release_array: |
618 | nfs_readdir_release_array(page); | 627 | nfs_readdir_release_array(page); |
628 | out_label_free: | ||
629 | nfs4_label_free(entry.label); | ||
619 | out: | 630 | out: |
620 | nfs_free_fattr(entry.fattr); | 631 | nfs_free_fattr(entry.fattr); |
621 | nfs_free_fhandle(entry.fh); | 632 | nfs_free_fhandle(entry.fh); |
@@ -1040,6 +1051,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) | |||
1040 | struct dentry *parent; | 1051 | struct dentry *parent; |
1041 | struct nfs_fh *fhandle = NULL; | 1052 | struct nfs_fh *fhandle = NULL; |
1042 | struct nfs_fattr *fattr = NULL; | 1053 | struct nfs_fattr *fattr = NULL; |
1054 | struct nfs4_label *label = NULL; | ||
1043 | int error; | 1055 | int error; |
1044 | 1056 | ||
1045 | if (flags & LOOKUP_RCU) | 1057 | if (flags & LOOKUP_RCU) |
@@ -1082,7 +1094,11 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) | |||
1082 | if (fhandle == NULL || fattr == NULL) | 1094 | if (fhandle == NULL || fattr == NULL) |
1083 | goto out_error; | 1095 | goto out_error; |
1084 | 1096 | ||
1085 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); | 1097 | label = nfs4_label_alloc(NFS_SERVER(inode), GFP_NOWAIT); |
1098 | if (IS_ERR(label)) | ||
1099 | goto out_error; | ||
1100 | |||
1101 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label); | ||
1086 | if (error) | 1102 | if (error) |
1087 | goto out_bad; | 1103 | goto out_bad; |
1088 | if (nfs_compare_fh(NFS_FH(inode), fhandle)) | 1104 | if (nfs_compare_fh(NFS_FH(inode), fhandle)) |
@@ -1090,8 +1106,12 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) | |||
1090 | if ((error = nfs_refresh_inode(inode, fattr)) != 0) | 1106 | if ((error = nfs_refresh_inode(inode, fattr)) != 0) |
1091 | goto out_bad; | 1107 | goto out_bad; |
1092 | 1108 | ||
1109 | nfs_setsecurity(inode, fattr, label); | ||
1110 | |||
1093 | nfs_free_fattr(fattr); | 1111 | nfs_free_fattr(fattr); |
1094 | nfs_free_fhandle(fhandle); | 1112 | nfs_free_fhandle(fhandle); |
1113 | nfs4_label_free(label); | ||
1114 | |||
1095 | out_set_verifier: | 1115 | out_set_verifier: |
1096 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1116 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
1097 | out_valid: | 1117 | out_valid: |
@@ -1108,6 +1128,7 @@ out_zap_parent: | |||
1108 | out_bad: | 1128 | out_bad: |
1109 | nfs_free_fattr(fattr); | 1129 | nfs_free_fattr(fattr); |
1110 | nfs_free_fhandle(fhandle); | 1130 | nfs_free_fhandle(fhandle); |
1131 | nfs4_label_free(label); | ||
1111 | nfs_mark_for_revalidate(dir); | 1132 | nfs_mark_for_revalidate(dir); |
1112 | if (inode && S_ISDIR(inode->i_mode)) { | 1133 | if (inode && S_ISDIR(inode->i_mode)) { |
1113 | /* Purge readdir caches. */ | 1134 | /* Purge readdir caches. */ |
@@ -1128,6 +1149,7 @@ out_zap_parent: | |||
1128 | out_error: | 1149 | out_error: |
1129 | nfs_free_fattr(fattr); | 1150 | nfs_free_fattr(fattr); |
1130 | nfs_free_fhandle(fhandle); | 1151 | nfs_free_fhandle(fhandle); |
1152 | nfs4_label_free(label); | ||
1131 | dput(parent); | 1153 | dput(parent); |
1132 | dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) lookup returned error %d\n", | 1154 | dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) lookup returned error %d\n", |
1133 | __func__, dentry->d_parent->d_name.name, | 1155 | __func__, dentry->d_parent->d_name.name, |
@@ -1256,6 +1278,7 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned in | |||
1256 | struct inode *inode = NULL; | 1278 | struct inode *inode = NULL; |
1257 | struct nfs_fh *fhandle = NULL; | 1279 | struct nfs_fh *fhandle = NULL; |
1258 | struct nfs_fattr *fattr = NULL; | 1280 | struct nfs_fattr *fattr = NULL; |
1281 | struct nfs4_label *label = NULL; | ||
1259 | int error; | 1282 | int error; |
1260 | 1283 | ||
1261 | dfprintk(VFS, "NFS: lookup(%s/%s)\n", | 1284 | dfprintk(VFS, "NFS: lookup(%s/%s)\n", |
@@ -1282,17 +1305,21 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned in | |||
1282 | if (fhandle == NULL || fattr == NULL) | 1305 | if (fhandle == NULL || fattr == NULL) |
1283 | goto out; | 1306 | goto out; |
1284 | 1307 | ||
1308 | label = nfs4_label_alloc(NFS_SERVER(dir), GFP_NOWAIT); | ||
1309 | if (IS_ERR(label)) | ||
1310 | goto out; | ||
1311 | |||
1285 | parent = dentry->d_parent; | 1312 | parent = dentry->d_parent; |
1286 | /* Protect against concurrent sillydeletes */ | 1313 | /* Protect against concurrent sillydeletes */ |
1287 | nfs_block_sillyrename(parent); | 1314 | nfs_block_sillyrename(parent); |
1288 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); | 1315 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label); |
1289 | if (error == -ENOENT) | 1316 | if (error == -ENOENT) |
1290 | goto no_entry; | 1317 | goto no_entry; |
1291 | if (error < 0) { | 1318 | if (error < 0) { |
1292 | res = ERR_PTR(error); | 1319 | res = ERR_PTR(error); |
1293 | goto out_unblock_sillyrename; | 1320 | goto out_unblock_sillyrename; |
1294 | } | 1321 | } |
1295 | inode = nfs_fhget(dentry->d_sb, fhandle, fattr); | 1322 | inode = nfs_fhget(dentry->d_sb, fhandle, fattr, label); |
1296 | res = ERR_CAST(inode); | 1323 | res = ERR_CAST(inode); |
1297 | if (IS_ERR(res)) | 1324 | if (IS_ERR(res)) |
1298 | goto out_unblock_sillyrename; | 1325 | goto out_unblock_sillyrename; |
@@ -1310,6 +1337,7 @@ no_entry: | |||
1310 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1337 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
1311 | out_unblock_sillyrename: | 1338 | out_unblock_sillyrename: |
1312 | nfs_unblock_sillyrename(parent); | 1339 | nfs_unblock_sillyrename(parent); |
1340 | nfs4_label_free(label); | ||
1313 | out: | 1341 | out: |
1314 | nfs_free_fattr(fattr); | 1342 | nfs_free_fattr(fattr); |
1315 | nfs_free_fhandle(fhandle); | 1343 | nfs_free_fhandle(fhandle); |
@@ -1357,18 +1385,6 @@ static int nfs_finish_open(struct nfs_open_context *ctx, | |||
1357 | { | 1385 | { |
1358 | int err; | 1386 | int err; |
1359 | 1387 | ||
1360 | if (ctx->dentry != dentry) { | ||
1361 | dput(ctx->dentry); | ||
1362 | ctx->dentry = dget(dentry); | ||
1363 | } | ||
1364 | |||
1365 | /* If the open_intent is for execute, we have an extra check to make */ | ||
1366 | if (ctx->mode & FMODE_EXEC) { | ||
1367 | err = nfs_may_open(dentry->d_inode, ctx->cred, open_flags); | ||
1368 | if (err < 0) | ||
1369 | goto out; | ||
1370 | } | ||
1371 | |||
1372 | err = finish_open(file, dentry, do_open, opened); | 1388 | err = finish_open(file, dentry, do_open, opened); |
1373 | if (err) | 1389 | if (err) |
1374 | goto out; | 1390 | goto out; |
@@ -1427,13 +1443,13 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
1427 | 1443 | ||
1428 | nfs_block_sillyrename(dentry->d_parent); | 1444 | nfs_block_sillyrename(dentry->d_parent); |
1429 | inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr); | 1445 | inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr); |
1430 | d_drop(dentry); | 1446 | nfs_unblock_sillyrename(dentry->d_parent); |
1431 | if (IS_ERR(inode)) { | 1447 | if (IS_ERR(inode)) { |
1432 | nfs_unblock_sillyrename(dentry->d_parent); | ||
1433 | put_nfs_open_context(ctx); | 1448 | put_nfs_open_context(ctx); |
1434 | err = PTR_ERR(inode); | 1449 | err = PTR_ERR(inode); |
1435 | switch (err) { | 1450 | switch (err) { |
1436 | case -ENOENT: | 1451 | case -ENOENT: |
1452 | d_drop(dentry); | ||
1437 | d_add(dentry, NULL); | 1453 | d_add(dentry, NULL); |
1438 | break; | 1454 | break; |
1439 | case -EISDIR: | 1455 | case -EISDIR: |
@@ -1449,16 +1465,8 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
1449 | } | 1465 | } |
1450 | goto out; | 1466 | goto out; |
1451 | } | 1467 | } |
1452 | res = d_add_unique(dentry, inode); | ||
1453 | if (res != NULL) | ||
1454 | dentry = res; | ||
1455 | |||
1456 | nfs_unblock_sillyrename(dentry->d_parent); | ||
1457 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
1458 | |||
1459 | err = nfs_finish_open(ctx, dentry, file, open_flags, opened); | ||
1460 | 1468 | ||
1461 | dput(res); | 1469 | err = nfs_finish_open(ctx, ctx->dentry, file, open_flags, opened); |
1462 | out: | 1470 | out: |
1463 | return err; | 1471 | return err; |
1464 | 1472 | ||
@@ -1528,7 +1536,8 @@ no_open: | |||
1528 | * Code common to create, mkdir, and mknod. | 1536 | * Code common to create, mkdir, and mknod. |
1529 | */ | 1537 | */ |
1530 | int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle, | 1538 | int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle, |
1531 | struct nfs_fattr *fattr) | 1539 | struct nfs_fattr *fattr, |
1540 | struct nfs4_label *label) | ||
1532 | { | 1541 | { |
1533 | struct dentry *parent = dget_parent(dentry); | 1542 | struct dentry *parent = dget_parent(dentry); |
1534 | struct inode *dir = parent->d_inode; | 1543 | struct inode *dir = parent->d_inode; |
@@ -1541,18 +1550,18 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle, | |||
1541 | if (dentry->d_inode) | 1550 | if (dentry->d_inode) |
1542 | goto out; | 1551 | goto out; |
1543 | if (fhandle->size == 0) { | 1552 | if (fhandle->size == 0) { |
1544 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); | 1553 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, NULL); |
1545 | if (error) | 1554 | if (error) |
1546 | goto out_error; | 1555 | goto out_error; |
1547 | } | 1556 | } |
1548 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1557 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
1549 | if (!(fattr->valid & NFS_ATTR_FATTR)) { | 1558 | if (!(fattr->valid & NFS_ATTR_FATTR)) { |
1550 | struct nfs_server *server = NFS_SB(dentry->d_sb); | 1559 | struct nfs_server *server = NFS_SB(dentry->d_sb); |
1551 | error = server->nfs_client->rpc_ops->getattr(server, fhandle, fattr); | 1560 | error = server->nfs_client->rpc_ops->getattr(server, fhandle, fattr, NULL); |
1552 | if (error < 0) | 1561 | if (error < 0) |
1553 | goto out_error; | 1562 | goto out_error; |
1554 | } | 1563 | } |
1555 | inode = nfs_fhget(dentry->d_sb, fhandle, fattr); | 1564 | inode = nfs_fhget(dentry->d_sb, fhandle, fattr, label); |
1556 | error = PTR_ERR(inode); | 1565 | error = PTR_ERR(inode); |
1557 | if (IS_ERR(inode)) | 1566 | if (IS_ERR(inode)) |
1558 | goto out_error; | 1567 | goto out_error; |