diff options
Diffstat (limited to 'fs/nfsd/vfs.c')
-rw-r--r-- | fs/nfsd/vfs.c | 79 |
1 files changed, 40 insertions, 39 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 4700a0a929d7..dccd396a1bb7 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -1276,6 +1276,10 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1276 | * If it has, the parent directory should already be locked. | 1276 | * If it has, the parent directory should already be locked. |
1277 | */ | 1277 | */ |
1278 | if (!resfhp->fh_dentry) { | 1278 | if (!resfhp->fh_dentry) { |
1279 | host_err = fh_want_write(fhp); | ||
1280 | if (host_err) | ||
1281 | goto out_nfserr; | ||
1282 | |||
1279 | /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */ | 1283 | /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */ |
1280 | fh_lock_nested(fhp, I_MUTEX_PARENT); | 1284 | fh_lock_nested(fhp, I_MUTEX_PARENT); |
1281 | dchild = lookup_one_len(fname, dentry, flen); | 1285 | dchild = lookup_one_len(fname, dentry, flen); |
@@ -1319,14 +1323,11 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1319 | goto out; | 1323 | goto out; |
1320 | } | 1324 | } |
1321 | 1325 | ||
1322 | host_err = fh_want_write(fhp); | ||
1323 | if (host_err) | ||
1324 | goto out_nfserr; | ||
1325 | |||
1326 | /* | 1326 | /* |
1327 | * Get the dir op function pointer. | 1327 | * Get the dir op function pointer. |
1328 | */ | 1328 | */ |
1329 | err = 0; | 1329 | err = 0; |
1330 | host_err = 0; | ||
1330 | switch (type) { | 1331 | switch (type) { |
1331 | case S_IFREG: | 1332 | case S_IFREG: |
1332 | host_err = vfs_create(dirp, dchild, iap->ia_mode, true); | 1333 | host_err = vfs_create(dirp, dchild, iap->ia_mode, true); |
@@ -1343,10 +1344,8 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1343 | host_err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); | 1344 | host_err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); |
1344 | break; | 1345 | break; |
1345 | } | 1346 | } |
1346 | if (host_err < 0) { | 1347 | if (host_err < 0) |
1347 | fh_drop_write(fhp); | ||
1348 | goto out_nfserr; | 1348 | goto out_nfserr; |
1349 | } | ||
1350 | 1349 | ||
1351 | err = nfsd_create_setattr(rqstp, resfhp, iap); | 1350 | err = nfsd_create_setattr(rqstp, resfhp, iap); |
1352 | 1351 | ||
@@ -1358,7 +1357,6 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1358 | err2 = nfserrno(commit_metadata(fhp)); | 1357 | err2 = nfserrno(commit_metadata(fhp)); |
1359 | if (err2) | 1358 | if (err2) |
1360 | err = err2; | 1359 | err = err2; |
1361 | fh_drop_write(fhp); | ||
1362 | /* | 1360 | /* |
1363 | * Update the file handle to get the new inode info. | 1361 | * Update the file handle to get the new inode info. |
1364 | */ | 1362 | */ |
@@ -1417,6 +1415,11 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1417 | err = nfserr_notdir; | 1415 | err = nfserr_notdir; |
1418 | if (!dirp->i_op->lookup) | 1416 | if (!dirp->i_op->lookup) |
1419 | goto out; | 1417 | goto out; |
1418 | |||
1419 | host_err = fh_want_write(fhp); | ||
1420 | if (host_err) | ||
1421 | goto out_nfserr; | ||
1422 | |||
1420 | fh_lock_nested(fhp, I_MUTEX_PARENT); | 1423 | fh_lock_nested(fhp, I_MUTEX_PARENT); |
1421 | 1424 | ||
1422 | /* | 1425 | /* |
@@ -1449,9 +1452,6 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1449 | v_atime = verifier[1]&0x7fffffff; | 1452 | v_atime = verifier[1]&0x7fffffff; |
1450 | } | 1453 | } |
1451 | 1454 | ||
1452 | host_err = fh_want_write(fhp); | ||
1453 | if (host_err) | ||
1454 | goto out_nfserr; | ||
1455 | if (dchild->d_inode) { | 1455 | if (dchild->d_inode) { |
1456 | err = 0; | 1456 | err = 0; |
1457 | 1457 | ||
@@ -1522,7 +1522,6 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1522 | if (!err) | 1522 | if (!err) |
1523 | err = nfserrno(commit_metadata(fhp)); | 1523 | err = nfserrno(commit_metadata(fhp)); |
1524 | 1524 | ||
1525 | fh_drop_write(fhp); | ||
1526 | /* | 1525 | /* |
1527 | * Update the filehandle to get the new inode info. | 1526 | * Update the filehandle to get the new inode info. |
1528 | */ | 1527 | */ |
@@ -1533,6 +1532,7 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1533 | fh_unlock(fhp); | 1532 | fh_unlock(fhp); |
1534 | if (dchild && !IS_ERR(dchild)) | 1533 | if (dchild && !IS_ERR(dchild)) |
1535 | dput(dchild); | 1534 | dput(dchild); |
1535 | fh_drop_write(fhp); | ||
1536 | return err; | 1536 | return err; |
1537 | 1537 | ||
1538 | out_nfserr: | 1538 | out_nfserr: |
@@ -1613,6 +1613,11 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1613 | err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE); | 1613 | err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE); |
1614 | if (err) | 1614 | if (err) |
1615 | goto out; | 1615 | goto out; |
1616 | |||
1617 | host_err = fh_want_write(fhp); | ||
1618 | if (host_err) | ||
1619 | goto out_nfserr; | ||
1620 | |||
1616 | fh_lock(fhp); | 1621 | fh_lock(fhp); |
1617 | dentry = fhp->fh_dentry; | 1622 | dentry = fhp->fh_dentry; |
1618 | dnew = lookup_one_len(fname, dentry, flen); | 1623 | dnew = lookup_one_len(fname, dentry, flen); |
@@ -1620,10 +1625,6 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1620 | if (IS_ERR(dnew)) | 1625 | if (IS_ERR(dnew)) |
1621 | goto out_nfserr; | 1626 | goto out_nfserr; |
1622 | 1627 | ||
1623 | host_err = fh_want_write(fhp); | ||
1624 | if (host_err) | ||
1625 | goto out_nfserr; | ||
1626 | |||
1627 | if (unlikely(path[plen] != 0)) { | 1628 | if (unlikely(path[plen] != 0)) { |
1628 | char *path_alloced = kmalloc(plen+1, GFP_KERNEL); | 1629 | char *path_alloced = kmalloc(plen+1, GFP_KERNEL); |
1629 | if (path_alloced == NULL) | 1630 | if (path_alloced == NULL) |
@@ -1683,6 +1684,12 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, | |||
1683 | if (isdotent(name, len)) | 1684 | if (isdotent(name, len)) |
1684 | goto out; | 1685 | goto out; |
1685 | 1686 | ||
1687 | host_err = fh_want_write(tfhp); | ||
1688 | if (host_err) { | ||
1689 | err = nfserrno(host_err); | ||
1690 | goto out; | ||
1691 | } | ||
1692 | |||
1686 | fh_lock_nested(ffhp, I_MUTEX_PARENT); | 1693 | fh_lock_nested(ffhp, I_MUTEX_PARENT); |
1687 | ddir = ffhp->fh_dentry; | 1694 | ddir = ffhp->fh_dentry; |
1688 | dirp = ddir->d_inode; | 1695 | dirp = ddir->d_inode; |
@@ -1694,18 +1701,13 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, | |||
1694 | 1701 | ||
1695 | dold = tfhp->fh_dentry; | 1702 | dold = tfhp->fh_dentry; |
1696 | 1703 | ||
1697 | host_err = fh_want_write(tfhp); | ||
1698 | if (host_err) { | ||
1699 | err = nfserrno(host_err); | ||
1700 | goto out_dput; | ||
1701 | } | ||
1702 | err = nfserr_noent; | 1704 | err = nfserr_noent; |
1703 | if (!dold->d_inode) | 1705 | if (!dold->d_inode) |
1704 | goto out_drop_write; | 1706 | goto out_dput; |
1705 | host_err = nfsd_break_lease(dold->d_inode); | 1707 | host_err = nfsd_break_lease(dold->d_inode); |
1706 | if (host_err) { | 1708 | if (host_err) { |
1707 | err = nfserrno(host_err); | 1709 | err = nfserrno(host_err); |
1708 | goto out_drop_write; | 1710 | goto out_dput; |
1709 | } | 1711 | } |
1710 | host_err = vfs_link(dold, dirp, dnew); | 1712 | host_err = vfs_link(dold, dirp, dnew); |
1711 | if (!host_err) { | 1713 | if (!host_err) { |
@@ -1718,12 +1720,11 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, | |||
1718 | else | 1720 | else |
1719 | err = nfserrno(host_err); | 1721 | err = nfserrno(host_err); |
1720 | } | 1722 | } |
1721 | out_drop_write: | ||
1722 | fh_drop_write(tfhp); | ||
1723 | out_dput: | 1723 | out_dput: |
1724 | dput(dnew); | 1724 | dput(dnew); |
1725 | out_unlock: | 1725 | out_unlock: |
1726 | fh_unlock(ffhp); | 1726 | fh_unlock(ffhp); |
1727 | fh_drop_write(tfhp); | ||
1727 | out: | 1728 | out: |
1728 | return err; | 1729 | return err; |
1729 | 1730 | ||
@@ -1766,6 +1767,12 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, | |||
1766 | if (!flen || isdotent(fname, flen) || !tlen || isdotent(tname, tlen)) | 1767 | if (!flen || isdotent(fname, flen) || !tlen || isdotent(tname, tlen)) |
1767 | goto out; | 1768 | goto out; |
1768 | 1769 | ||
1770 | host_err = fh_want_write(ffhp); | ||
1771 | if (host_err) { | ||
1772 | err = nfserrno(host_err); | ||
1773 | goto out; | ||
1774 | } | ||
1775 | |||
1769 | /* cannot use fh_lock as we need deadlock protective ordering | 1776 | /* cannot use fh_lock as we need deadlock protective ordering |
1770 | * so do it by hand */ | 1777 | * so do it by hand */ |
1771 | trap = lock_rename(tdentry, fdentry); | 1778 | trap = lock_rename(tdentry, fdentry); |
@@ -1796,17 +1803,14 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, | |||
1796 | host_err = -EXDEV; | 1803 | host_err = -EXDEV; |
1797 | if (ffhp->fh_export->ex_path.mnt != tfhp->fh_export->ex_path.mnt) | 1804 | if (ffhp->fh_export->ex_path.mnt != tfhp->fh_export->ex_path.mnt) |
1798 | goto out_dput_new; | 1805 | goto out_dput_new; |
1799 | host_err = fh_want_write(ffhp); | ||
1800 | if (host_err) | ||
1801 | goto out_dput_new; | ||
1802 | 1806 | ||
1803 | host_err = nfsd_break_lease(odentry->d_inode); | 1807 | host_err = nfsd_break_lease(odentry->d_inode); |
1804 | if (host_err) | 1808 | if (host_err) |
1805 | goto out_drop_write; | 1809 | goto out_dput_new; |
1806 | if (ndentry->d_inode) { | 1810 | if (ndentry->d_inode) { |
1807 | host_err = nfsd_break_lease(ndentry->d_inode); | 1811 | host_err = nfsd_break_lease(ndentry->d_inode); |
1808 | if (host_err) | 1812 | if (host_err) |
1809 | goto out_drop_write; | 1813 | goto out_dput_new; |
1810 | } | 1814 | } |
1811 | host_err = vfs_rename(fdir, odentry, tdir, ndentry); | 1815 | host_err = vfs_rename(fdir, odentry, tdir, ndentry); |
1812 | if (!host_err) { | 1816 | if (!host_err) { |
@@ -1814,8 +1818,6 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, | |||
1814 | if (!host_err) | 1818 | if (!host_err) |
1815 | host_err = commit_metadata(ffhp); | 1819 | host_err = commit_metadata(ffhp); |
1816 | } | 1820 | } |
1817 | out_drop_write: | ||
1818 | fh_drop_write(ffhp); | ||
1819 | out_dput_new: | 1821 | out_dput_new: |
1820 | dput(ndentry); | 1822 | dput(ndentry); |
1821 | out_dput_old: | 1823 | out_dput_old: |
@@ -1831,6 +1833,7 @@ out_drop_write: | |||
1831 | fill_post_wcc(tfhp); | 1833 | fill_post_wcc(tfhp); |
1832 | unlock_rename(tdentry, fdentry); | 1834 | unlock_rename(tdentry, fdentry); |
1833 | ffhp->fh_locked = tfhp->fh_locked = 0; | 1835 | ffhp->fh_locked = tfhp->fh_locked = 0; |
1836 | fh_drop_write(ffhp); | ||
1834 | 1837 | ||
1835 | out: | 1838 | out: |
1836 | return err; | 1839 | return err; |
@@ -1856,6 +1859,10 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, | |||
1856 | if (err) | 1859 | if (err) |
1857 | goto out; | 1860 | goto out; |
1858 | 1861 | ||
1862 | host_err = fh_want_write(fhp); | ||
1863 | if (host_err) | ||
1864 | goto out_nfserr; | ||
1865 | |||
1859 | fh_lock_nested(fhp, I_MUTEX_PARENT); | 1866 | fh_lock_nested(fhp, I_MUTEX_PARENT); |
1860 | dentry = fhp->fh_dentry; | 1867 | dentry = fhp->fh_dentry; |
1861 | dirp = dentry->d_inode; | 1868 | dirp = dentry->d_inode; |
@@ -1874,21 +1881,15 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, | |||
1874 | if (!type) | 1881 | if (!type) |
1875 | type = rdentry->d_inode->i_mode & S_IFMT; | 1882 | type = rdentry->d_inode->i_mode & S_IFMT; |
1876 | 1883 | ||
1877 | host_err = fh_want_write(fhp); | ||
1878 | if (host_err) | ||
1879 | goto out_put; | ||
1880 | |||
1881 | host_err = nfsd_break_lease(rdentry->d_inode); | 1884 | host_err = nfsd_break_lease(rdentry->d_inode); |
1882 | if (host_err) | 1885 | if (host_err) |
1883 | goto out_drop_write; | 1886 | goto out_put; |
1884 | if (type != S_IFDIR) | 1887 | if (type != S_IFDIR) |
1885 | host_err = vfs_unlink(dirp, rdentry); | 1888 | host_err = vfs_unlink(dirp, rdentry); |
1886 | else | 1889 | else |
1887 | host_err = vfs_rmdir(dirp, rdentry); | 1890 | host_err = vfs_rmdir(dirp, rdentry); |
1888 | if (!host_err) | 1891 | if (!host_err) |
1889 | host_err = commit_metadata(fhp); | 1892 | host_err = commit_metadata(fhp); |
1890 | out_drop_write: | ||
1891 | fh_drop_write(fhp); | ||
1892 | out_put: | 1893 | out_put: |
1893 | dput(rdentry); | 1894 | dput(rdentry); |
1894 | 1895 | ||