diff options
Diffstat (limited to 'fs/nfs/dir.c')
-rw-r--r-- | fs/nfs/dir.c | 81 |
1 files changed, 61 insertions, 20 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 7468735d299e..e79bc6ce828e 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -43,6 +43,8 @@ | |||
43 | #include "internal.h" | 43 | #include "internal.h" |
44 | #include "fscache.h" | 44 | #include "fscache.h" |
45 | 45 | ||
46 | #include "nfstrace.h" | ||
47 | |||
46 | /* #define NFS_DEBUG_VERBOSE 1 */ | 48 | /* #define NFS_DEBUG_VERBOSE 1 */ |
47 | 49 | ||
48 | static int nfs_opendir(struct inode *, struct file *); | 50 | static int nfs_opendir(struct inode *, struct file *); |
@@ -1100,7 +1102,9 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) | |||
1100 | if (IS_ERR(label)) | 1102 | if (IS_ERR(label)) |
1101 | goto out_error; | 1103 | goto out_error; |
1102 | 1104 | ||
1105 | trace_nfs_lookup_revalidate_enter(dir, dentry, flags); | ||
1103 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label); | 1106 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label); |
1107 | trace_nfs_lookup_revalidate_exit(dir, dentry, flags, error); | ||
1104 | if (error) | 1108 | if (error) |
1105 | goto out_bad; | 1109 | goto out_bad; |
1106 | if (nfs_compare_fh(NFS_FH(inode), fhandle)) | 1110 | if (nfs_compare_fh(NFS_FH(inode), fhandle)) |
@@ -1312,6 +1316,7 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned in | |||
1312 | 1316 | ||
1313 | parent = dentry->d_parent; | 1317 | parent = dentry->d_parent; |
1314 | /* Protect against concurrent sillydeletes */ | 1318 | /* Protect against concurrent sillydeletes */ |
1319 | trace_nfs_lookup_enter(dir, dentry, flags); | ||
1315 | nfs_block_sillyrename(parent); | 1320 | nfs_block_sillyrename(parent); |
1316 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label); | 1321 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label); |
1317 | if (error == -ENOENT) | 1322 | if (error == -ENOENT) |
@@ -1338,6 +1343,7 @@ no_entry: | |||
1338 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1343 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
1339 | out_unblock_sillyrename: | 1344 | out_unblock_sillyrename: |
1340 | nfs_unblock_sillyrename(parent); | 1345 | nfs_unblock_sillyrename(parent); |
1346 | trace_nfs_lookup_exit(dir, dentry, flags, error); | ||
1341 | nfs4_label_free(label); | 1347 | nfs4_label_free(label); |
1342 | out: | 1348 | out: |
1343 | nfs_free_fattr(fattr); | 1349 | nfs_free_fattr(fattr); |
@@ -1392,7 +1398,6 @@ static int nfs_finish_open(struct nfs_open_context *ctx, | |||
1392 | nfs_file_set_open_context(file, ctx); | 1398 | nfs_file_set_open_context(file, ctx); |
1393 | 1399 | ||
1394 | out: | 1400 | out: |
1395 | put_nfs_open_context(ctx); | ||
1396 | return err; | 1401 | return err; |
1397 | } | 1402 | } |
1398 | 1403 | ||
@@ -1404,6 +1409,7 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
1404 | struct dentry *res; | 1409 | struct dentry *res; |
1405 | struct iattr attr = { .ia_valid = ATTR_OPEN }; | 1410 | struct iattr attr = { .ia_valid = ATTR_OPEN }; |
1406 | struct inode *inode; | 1411 | struct inode *inode; |
1412 | unsigned int lookup_flags = 0; | ||
1407 | int err; | 1413 | int err; |
1408 | 1414 | ||
1409 | /* Expect a negative dentry */ | 1415 | /* Expect a negative dentry */ |
@@ -1412,6 +1418,10 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
1412 | dfprintk(VFS, "NFS: atomic_open(%s/%ld), %s\n", | 1418 | dfprintk(VFS, "NFS: atomic_open(%s/%ld), %s\n", |
1413 | dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); | 1419 | dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); |
1414 | 1420 | ||
1421 | err = nfs_check_flags(open_flags); | ||
1422 | if (err) | ||
1423 | return err; | ||
1424 | |||
1415 | /* NFS only supports OPEN on regular files */ | 1425 | /* NFS only supports OPEN on regular files */ |
1416 | if ((open_flags & O_DIRECTORY)) { | 1426 | if ((open_flags & O_DIRECTORY)) { |
1417 | if (!d_unhashed(dentry)) { | 1427 | if (!d_unhashed(dentry)) { |
@@ -1422,6 +1432,7 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
1422 | */ | 1432 | */ |
1423 | return -ENOENT; | 1433 | return -ENOENT; |
1424 | } | 1434 | } |
1435 | lookup_flags = LOOKUP_OPEN|LOOKUP_DIRECTORY; | ||
1425 | goto no_open; | 1436 | goto no_open; |
1426 | } | 1437 | } |
1427 | 1438 | ||
@@ -1442,12 +1453,14 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
1442 | if (IS_ERR(ctx)) | 1453 | if (IS_ERR(ctx)) |
1443 | goto out; | 1454 | goto out; |
1444 | 1455 | ||
1456 | trace_nfs_atomic_open_enter(dir, ctx, open_flags); | ||
1445 | nfs_block_sillyrename(dentry->d_parent); | 1457 | nfs_block_sillyrename(dentry->d_parent); |
1446 | inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr); | 1458 | inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr); |
1447 | nfs_unblock_sillyrename(dentry->d_parent); | 1459 | nfs_unblock_sillyrename(dentry->d_parent); |
1448 | if (IS_ERR(inode)) { | 1460 | if (IS_ERR(inode)) { |
1449 | put_nfs_open_context(ctx); | ||
1450 | err = PTR_ERR(inode); | 1461 | err = PTR_ERR(inode); |
1462 | trace_nfs_atomic_open_exit(dir, ctx, open_flags, err); | ||
1463 | put_nfs_open_context(ctx); | ||
1451 | switch (err) { | 1464 | switch (err) { |
1452 | case -ENOENT: | 1465 | case -ENOENT: |
1453 | d_drop(dentry); | 1466 | d_drop(dentry); |
@@ -1468,11 +1481,13 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
1468 | } | 1481 | } |
1469 | 1482 | ||
1470 | err = nfs_finish_open(ctx, ctx->dentry, file, open_flags, opened); | 1483 | err = nfs_finish_open(ctx, ctx->dentry, file, open_flags, opened); |
1484 | trace_nfs_atomic_open_exit(dir, ctx, open_flags, err); | ||
1485 | put_nfs_open_context(ctx); | ||
1471 | out: | 1486 | out: |
1472 | return err; | 1487 | return err; |
1473 | 1488 | ||
1474 | no_open: | 1489 | no_open: |
1475 | res = nfs_lookup(dir, dentry, 0); | 1490 | res = nfs_lookup(dir, dentry, lookup_flags); |
1476 | err = PTR_ERR(res); | 1491 | err = PTR_ERR(res); |
1477 | if (IS_ERR(res)) | 1492 | if (IS_ERR(res)) |
1478 | goto out; | 1493 | goto out; |
@@ -1596,7 +1611,9 @@ int nfs_create(struct inode *dir, struct dentry *dentry, | |||
1596 | attr.ia_mode = mode; | 1611 | attr.ia_mode = mode; |
1597 | attr.ia_valid = ATTR_MODE; | 1612 | attr.ia_valid = ATTR_MODE; |
1598 | 1613 | ||
1614 | trace_nfs_create_enter(dir, dentry, open_flags); | ||
1599 | error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags); | 1615 | error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags); |
1616 | trace_nfs_create_exit(dir, dentry, open_flags, error); | ||
1600 | if (error != 0) | 1617 | if (error != 0) |
1601 | goto out_err; | 1618 | goto out_err; |
1602 | return 0; | 1619 | return 0; |
@@ -1624,7 +1641,9 @@ nfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev) | |||
1624 | attr.ia_mode = mode; | 1641 | attr.ia_mode = mode; |
1625 | attr.ia_valid = ATTR_MODE; | 1642 | attr.ia_valid = ATTR_MODE; |
1626 | 1643 | ||
1644 | trace_nfs_mknod_enter(dir, dentry); | ||
1627 | status = NFS_PROTO(dir)->mknod(dir, dentry, &attr, rdev); | 1645 | status = NFS_PROTO(dir)->mknod(dir, dentry, &attr, rdev); |
1646 | trace_nfs_mknod_exit(dir, dentry, status); | ||
1628 | if (status != 0) | 1647 | if (status != 0) |
1629 | goto out_err; | 1648 | goto out_err; |
1630 | return 0; | 1649 | return 0; |
@@ -1648,7 +1667,9 @@ int nfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
1648 | attr.ia_valid = ATTR_MODE; | 1667 | attr.ia_valid = ATTR_MODE; |
1649 | attr.ia_mode = mode | S_IFDIR; | 1668 | attr.ia_mode = mode | S_IFDIR; |
1650 | 1669 | ||
1670 | trace_nfs_mkdir_enter(dir, dentry); | ||
1651 | error = NFS_PROTO(dir)->mkdir(dir, dentry, &attr); | 1671 | error = NFS_PROTO(dir)->mkdir(dir, dentry, &attr); |
1672 | trace_nfs_mkdir_exit(dir, dentry, error); | ||
1652 | if (error != 0) | 1673 | if (error != 0) |
1653 | goto out_err; | 1674 | goto out_err; |
1654 | return 0; | 1675 | return 0; |
@@ -1671,12 +1692,21 @@ int nfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
1671 | dfprintk(VFS, "NFS: rmdir(%s/%ld), %s\n", | 1692 | dfprintk(VFS, "NFS: rmdir(%s/%ld), %s\n", |
1672 | dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); | 1693 | dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); |
1673 | 1694 | ||
1674 | error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name); | 1695 | trace_nfs_rmdir_enter(dir, dentry); |
1675 | /* Ensure the VFS deletes this inode */ | 1696 | if (dentry->d_inode) { |
1676 | if (error == 0 && dentry->d_inode != NULL) | 1697 | nfs_wait_on_sillyrename(dentry); |
1677 | clear_nlink(dentry->d_inode); | 1698 | error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name); |
1678 | else if (error == -ENOENT) | 1699 | /* Ensure the VFS deletes this inode */ |
1679 | nfs_dentry_handle_enoent(dentry); | 1700 | switch (error) { |
1701 | case 0: | ||
1702 | clear_nlink(dentry->d_inode); | ||
1703 | break; | ||
1704 | case -ENOENT: | ||
1705 | nfs_dentry_handle_enoent(dentry); | ||
1706 | } | ||
1707 | } else | ||
1708 | error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name); | ||
1709 | trace_nfs_rmdir_exit(dir, dentry, error); | ||
1680 | 1710 | ||
1681 | return error; | 1711 | return error; |
1682 | } | 1712 | } |
@@ -1704,6 +1734,7 @@ static int nfs_safe_remove(struct dentry *dentry) | |||
1704 | goto out; | 1734 | goto out; |
1705 | } | 1735 | } |
1706 | 1736 | ||
1737 | trace_nfs_remove_enter(dir, dentry); | ||
1707 | if (inode != NULL) { | 1738 | if (inode != NULL) { |
1708 | NFS_PROTO(inode)->return_delegation(inode); | 1739 | NFS_PROTO(inode)->return_delegation(inode); |
1709 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); | 1740 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); |
@@ -1713,6 +1744,7 @@ static int nfs_safe_remove(struct dentry *dentry) | |||
1713 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); | 1744 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); |
1714 | if (error == -ENOENT) | 1745 | if (error == -ENOENT) |
1715 | nfs_dentry_handle_enoent(dentry); | 1746 | nfs_dentry_handle_enoent(dentry); |
1747 | trace_nfs_remove_exit(dir, dentry, error); | ||
1716 | out: | 1748 | out: |
1717 | return error; | 1749 | return error; |
1718 | } | 1750 | } |
@@ -1730,13 +1762,14 @@ int nfs_unlink(struct inode *dir, struct dentry *dentry) | |||
1730 | dfprintk(VFS, "NFS: unlink(%s/%ld, %s)\n", dir->i_sb->s_id, | 1762 | dfprintk(VFS, "NFS: unlink(%s/%ld, %s)\n", dir->i_sb->s_id, |
1731 | dir->i_ino, dentry->d_name.name); | 1763 | dir->i_ino, dentry->d_name.name); |
1732 | 1764 | ||
1765 | trace_nfs_unlink_enter(dir, dentry); | ||
1733 | spin_lock(&dentry->d_lock); | 1766 | spin_lock(&dentry->d_lock); |
1734 | if (d_count(dentry) > 1) { | 1767 | if (d_count(dentry) > 1) { |
1735 | spin_unlock(&dentry->d_lock); | 1768 | spin_unlock(&dentry->d_lock); |
1736 | /* Start asynchronous writeout of the inode */ | 1769 | /* Start asynchronous writeout of the inode */ |
1737 | write_inode_now(dentry->d_inode, 0); | 1770 | write_inode_now(dentry->d_inode, 0); |
1738 | error = nfs_sillyrename(dir, dentry); | 1771 | error = nfs_sillyrename(dir, dentry); |
1739 | return error; | 1772 | goto out; |
1740 | } | 1773 | } |
1741 | if (!d_unhashed(dentry)) { | 1774 | if (!d_unhashed(dentry)) { |
1742 | __d_drop(dentry); | 1775 | __d_drop(dentry); |
@@ -1748,6 +1781,8 @@ int nfs_unlink(struct inode *dir, struct dentry *dentry) | |||
1748 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1781 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
1749 | } else if (need_rehash) | 1782 | } else if (need_rehash) |
1750 | d_rehash(dentry); | 1783 | d_rehash(dentry); |
1784 | out: | ||
1785 | trace_nfs_unlink_exit(dir, dentry, error); | ||
1751 | return error; | 1786 | return error; |
1752 | } | 1787 | } |
1753 | EXPORT_SYMBOL_GPL(nfs_unlink); | 1788 | EXPORT_SYMBOL_GPL(nfs_unlink); |
@@ -1794,7 +1829,9 @@ int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) | |||
1794 | memset(kaddr + pathlen, 0, PAGE_SIZE - pathlen); | 1829 | memset(kaddr + pathlen, 0, PAGE_SIZE - pathlen); |
1795 | kunmap_atomic(kaddr); | 1830 | kunmap_atomic(kaddr); |
1796 | 1831 | ||
1832 | trace_nfs_symlink_enter(dir, dentry); | ||
1797 | error = NFS_PROTO(dir)->symlink(dir, dentry, page, pathlen, &attr); | 1833 | error = NFS_PROTO(dir)->symlink(dir, dentry, page, pathlen, &attr); |
1834 | trace_nfs_symlink_exit(dir, dentry, error); | ||
1798 | if (error != 0) { | 1835 | if (error != 0) { |
1799 | dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s) error %d\n", | 1836 | dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s) error %d\n", |
1800 | dir->i_sb->s_id, dir->i_ino, | 1837 | dir->i_sb->s_id, dir->i_ino, |
@@ -1829,6 +1866,7 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) | |||
1829 | old_dentry->d_parent->d_name.name, old_dentry->d_name.name, | 1866 | old_dentry->d_parent->d_name.name, old_dentry->d_name.name, |
1830 | dentry->d_parent->d_name.name, dentry->d_name.name); | 1867 | dentry->d_parent->d_name.name, dentry->d_name.name); |
1831 | 1868 | ||
1869 | trace_nfs_link_enter(inode, dir, dentry); | ||
1832 | NFS_PROTO(inode)->return_delegation(inode); | 1870 | NFS_PROTO(inode)->return_delegation(inode); |
1833 | 1871 | ||
1834 | d_drop(dentry); | 1872 | d_drop(dentry); |
@@ -1837,6 +1875,7 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) | |||
1837 | ihold(inode); | 1875 | ihold(inode); |
1838 | d_add(dentry, inode); | 1876 | d_add(dentry, inode); |
1839 | } | 1877 | } |
1878 | trace_nfs_link_exit(inode, dir, dentry, error); | ||
1840 | return error; | 1879 | return error; |
1841 | } | 1880 | } |
1842 | EXPORT_SYMBOL_GPL(nfs_link); | 1881 | EXPORT_SYMBOL_GPL(nfs_link); |
@@ -1878,6 +1917,7 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1878 | new_dentry->d_parent->d_name.name, new_dentry->d_name.name, | 1917 | new_dentry->d_parent->d_name.name, new_dentry->d_name.name, |
1879 | d_count(new_dentry)); | 1918 | d_count(new_dentry)); |
1880 | 1919 | ||
1920 | trace_nfs_rename_enter(old_dir, old_dentry, new_dir, new_dentry); | ||
1881 | /* | 1921 | /* |
1882 | * For non-directories, check whether the target is busy and if so, | 1922 | * For non-directories, check whether the target is busy and if so, |
1883 | * make a copy of the dentry and then do a silly-rename. If the | 1923 | * make a copy of the dentry and then do a silly-rename. If the |
@@ -1924,6 +1964,8 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1924 | out: | 1964 | out: |
1925 | if (rehash) | 1965 | if (rehash) |
1926 | d_rehash(rehash); | 1966 | d_rehash(rehash); |
1967 | trace_nfs_rename_exit(old_dir, old_dentry, | ||
1968 | new_dir, new_dentry, error); | ||
1927 | if (!error) { | 1969 | if (!error) { |
1928 | if (new_inode != NULL) | 1970 | if (new_inode != NULL) |
1929 | nfs_drop_nlink(new_inode); | 1971 | nfs_drop_nlink(new_inode); |
@@ -2173,9 +2215,11 @@ static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask) | |||
2173 | struct nfs_access_entry cache; | 2215 | struct nfs_access_entry cache; |
2174 | int status; | 2216 | int status; |
2175 | 2217 | ||
2218 | trace_nfs_access_enter(inode); | ||
2219 | |||
2176 | status = nfs_access_get_cached(inode, cred, &cache); | 2220 | status = nfs_access_get_cached(inode, cred, &cache); |
2177 | if (status == 0) | 2221 | if (status == 0) |
2178 | goto out; | 2222 | goto out_cached; |
2179 | 2223 | ||
2180 | /* Be clever: ask server to check for all possible rights */ | 2224 | /* Be clever: ask server to check for all possible rights */ |
2181 | cache.mask = MAY_EXEC | MAY_WRITE | MAY_READ; | 2225 | cache.mask = MAY_EXEC | MAY_WRITE | MAY_READ; |
@@ -2188,13 +2232,15 @@ static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask) | |||
2188 | if (!S_ISDIR(inode->i_mode)) | 2232 | if (!S_ISDIR(inode->i_mode)) |
2189 | set_bit(NFS_INO_STALE, &NFS_I(inode)->flags); | 2233 | set_bit(NFS_INO_STALE, &NFS_I(inode)->flags); |
2190 | } | 2234 | } |
2191 | return status; | 2235 | goto out; |
2192 | } | 2236 | } |
2193 | nfs_access_add_cache(inode, &cache); | 2237 | nfs_access_add_cache(inode, &cache); |
2238 | out_cached: | ||
2239 | if ((mask & ~cache.mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) != 0) | ||
2240 | status = -EACCES; | ||
2194 | out: | 2241 | out: |
2195 | if ((mask & ~cache.mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0) | 2242 | trace_nfs_access_exit(inode, status); |
2196 | return 0; | 2243 | return status; |
2197 | return -EACCES; | ||
2198 | } | 2244 | } |
2199 | 2245 | ||
2200 | static int nfs_open_permission_mask(int openflags) | 2246 | static int nfs_open_permission_mask(int openflags) |
@@ -2240,11 +2286,6 @@ int nfs_permission(struct inode *inode, int mask) | |||
2240 | case S_IFLNK: | 2286 | case S_IFLNK: |
2241 | goto out; | 2287 | goto out; |
2242 | case S_IFREG: | 2288 | case S_IFREG: |
2243 | /* NFSv4 has atomic_open... */ | ||
2244 | if (nfs_server_capable(inode, NFS_CAP_ATOMIC_OPEN) | ||
2245 | && (mask & MAY_OPEN) | ||
2246 | && !(mask & MAY_EXEC)) | ||
2247 | goto out; | ||
2248 | break; | 2289 | break; |
2249 | case S_IFDIR: | 2290 | case S_IFDIR: |
2250 | /* | 2291 | /* |