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 702f64e820c3..a9269f142cc4 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -1284,6 +1284,10 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1284 | * If it has, the parent directory should already be locked. | 1284 | * If it has, the parent directory should already be locked. |
1285 | */ | 1285 | */ |
1286 | if (!resfhp->fh_dentry) { | 1286 | if (!resfhp->fh_dentry) { |
1287 | host_err = fh_want_write(fhp); | ||
1288 | if (host_err) | ||
1289 | goto out_nfserr; | ||
1290 | |||
1287 | /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */ | 1291 | /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */ |
1288 | fh_lock_nested(fhp, I_MUTEX_PARENT); | 1292 | fh_lock_nested(fhp, I_MUTEX_PARENT); |
1289 | dchild = lookup_one_len(fname, dentry, flen); | 1293 | dchild = lookup_one_len(fname, dentry, flen); |
@@ -1327,14 +1331,11 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1327 | goto out; | 1331 | goto out; |
1328 | } | 1332 | } |
1329 | 1333 | ||
1330 | host_err = fh_want_write(fhp); | ||
1331 | if (host_err) | ||
1332 | goto out_nfserr; | ||
1333 | |||
1334 | /* | 1334 | /* |
1335 | * Get the dir op function pointer. | 1335 | * Get the dir op function pointer. |
1336 | */ | 1336 | */ |
1337 | err = 0; | 1337 | err = 0; |
1338 | host_err = 0; | ||
1338 | switch (type) { | 1339 | switch (type) { |
1339 | case S_IFREG: | 1340 | case S_IFREG: |
1340 | host_err = vfs_create(dirp, dchild, iap->ia_mode, true); | 1341 | host_err = vfs_create(dirp, dchild, iap->ia_mode, true); |
@@ -1351,10 +1352,8 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1351 | host_err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); | 1352 | host_err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); |
1352 | break; | 1353 | break; |
1353 | } | 1354 | } |
1354 | if (host_err < 0) { | 1355 | if (host_err < 0) |
1355 | fh_drop_write(fhp); | ||
1356 | goto out_nfserr; | 1356 | goto out_nfserr; |
1357 | } | ||
1358 | 1357 | ||
1359 | err = nfsd_create_setattr(rqstp, resfhp, iap); | 1358 | err = nfsd_create_setattr(rqstp, resfhp, iap); |
1360 | 1359 | ||
@@ -1366,7 +1365,6 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1366 | err2 = nfserrno(commit_metadata(fhp)); | 1365 | err2 = nfserrno(commit_metadata(fhp)); |
1367 | if (err2) | 1366 | if (err2) |
1368 | err = err2; | 1367 | err = err2; |
1369 | fh_drop_write(fhp); | ||
1370 | /* | 1368 | /* |
1371 | * Update the file handle to get the new inode info. | 1369 | * Update the file handle to get the new inode info. |
1372 | */ | 1370 | */ |
@@ -1425,6 +1423,11 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1425 | err = nfserr_notdir; | 1423 | err = nfserr_notdir; |
1426 | if (!dirp->i_op->lookup) | 1424 | if (!dirp->i_op->lookup) |
1427 | goto out; | 1425 | goto out; |
1426 | |||
1427 | host_err = fh_want_write(fhp); | ||
1428 | if (host_err) | ||
1429 | goto out_nfserr; | ||
1430 | |||
1428 | fh_lock_nested(fhp, I_MUTEX_PARENT); | 1431 | fh_lock_nested(fhp, I_MUTEX_PARENT); |
1429 | 1432 | ||
1430 | /* | 1433 | /* |
@@ -1457,9 +1460,6 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1457 | v_atime = verifier[1]&0x7fffffff; | 1460 | v_atime = verifier[1]&0x7fffffff; |
1458 | } | 1461 | } |
1459 | 1462 | ||
1460 | host_err = fh_want_write(fhp); | ||
1461 | if (host_err) | ||
1462 | goto out_nfserr; | ||
1463 | if (dchild->d_inode) { | 1463 | if (dchild->d_inode) { |
1464 | err = 0; | 1464 | err = 0; |
1465 | 1465 | ||
@@ -1530,7 +1530,6 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1530 | if (!err) | 1530 | if (!err) |
1531 | err = nfserrno(commit_metadata(fhp)); | 1531 | err = nfserrno(commit_metadata(fhp)); |
1532 | 1532 | ||
1533 | fh_drop_write(fhp); | ||
1534 | /* | 1533 | /* |
1535 | * Update the filehandle to get the new inode info. | 1534 | * Update the filehandle to get the new inode info. |
1536 | */ | 1535 | */ |
@@ -1541,6 +1540,7 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1541 | fh_unlock(fhp); | 1540 | fh_unlock(fhp); |
1542 | if (dchild && !IS_ERR(dchild)) | 1541 | if (dchild && !IS_ERR(dchild)) |
1543 | dput(dchild); | 1542 | dput(dchild); |
1543 | fh_drop_write(fhp); | ||
1544 | return err; | 1544 | return err; |
1545 | 1545 | ||
1546 | out_nfserr: | 1546 | out_nfserr: |
@@ -1621,6 +1621,11 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1621 | err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE); | 1621 | err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE); |
1622 | if (err) | 1622 | if (err) |
1623 | goto out; | 1623 | goto out; |
1624 | |||
1625 | host_err = fh_want_write(fhp); | ||
1626 | if (host_err) | ||
1627 | goto out_nfserr; | ||
1628 | |||
1624 | fh_lock(fhp); | 1629 | fh_lock(fhp); |
1625 | dentry = fhp->fh_dentry; | 1630 | dentry = fhp->fh_dentry; |
1626 | dnew = lookup_one_len(fname, dentry, flen); | 1631 | dnew = lookup_one_len(fname, dentry, flen); |
@@ -1628,10 +1633,6 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1628 | if (IS_ERR(dnew)) | 1633 | if (IS_ERR(dnew)) |
1629 | goto out_nfserr; | 1634 | goto out_nfserr; |
1630 | 1635 | ||
1631 | host_err = fh_want_write(fhp); | ||
1632 | if (host_err) | ||
1633 | goto out_nfserr; | ||
1634 | |||
1635 | if (unlikely(path[plen] != 0)) { | 1636 | if (unlikely(path[plen] != 0)) { |
1636 | char *path_alloced = kmalloc(plen+1, GFP_KERNEL); | 1637 | char *path_alloced = kmalloc(plen+1, GFP_KERNEL); |
1637 | if (path_alloced == NULL) | 1638 | if (path_alloced == NULL) |
@@ -1691,6 +1692,12 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, | |||
1691 | if (isdotent(name, len)) | 1692 | if (isdotent(name, len)) |
1692 | goto out; | 1693 | goto out; |
1693 | 1694 | ||
1695 | host_err = fh_want_write(tfhp); | ||
1696 | if (host_err) { | ||
1697 | err = nfserrno(host_err); | ||
1698 | goto out; | ||
1699 | } | ||
1700 | |||
1694 | fh_lock_nested(ffhp, I_MUTEX_PARENT); | 1701 | fh_lock_nested(ffhp, I_MUTEX_PARENT); |
1695 | ddir = ffhp->fh_dentry; | 1702 | ddir = ffhp->fh_dentry; |
1696 | dirp = ddir->d_inode; | 1703 | dirp = ddir->d_inode; |
@@ -1702,18 +1709,13 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, | |||
1702 | 1709 | ||
1703 | dold = tfhp->fh_dentry; | 1710 | dold = tfhp->fh_dentry; |
1704 | 1711 | ||
1705 | host_err = fh_want_write(tfhp); | ||
1706 | if (host_err) { | ||
1707 | err = nfserrno(host_err); | ||
1708 | goto out_dput; | ||
1709 | } | ||
1710 | err = nfserr_noent; | 1712 | err = nfserr_noent; |
1711 | if (!dold->d_inode) | 1713 | if (!dold->d_inode) |
1712 | goto out_drop_write; | 1714 | goto out_dput; |
1713 | host_err = nfsd_break_lease(dold->d_inode); | 1715 | host_err = nfsd_break_lease(dold->d_inode); |
1714 | if (host_err) { | 1716 | if (host_err) { |
1715 | err = nfserrno(host_err); | 1717 | err = nfserrno(host_err); |
1716 | goto out_drop_write; | 1718 | goto out_dput; |
1717 | } | 1719 | } |
1718 | host_err = vfs_link(dold, dirp, dnew); | 1720 | host_err = vfs_link(dold, dirp, dnew); |
1719 | if (!host_err) { | 1721 | if (!host_err) { |
@@ -1726,12 +1728,11 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, | |||
1726 | else | 1728 | else |
1727 | err = nfserrno(host_err); | 1729 | err = nfserrno(host_err); |
1728 | } | 1730 | } |
1729 | out_drop_write: | ||
1730 | fh_drop_write(tfhp); | ||
1731 | out_dput: | 1731 | out_dput: |
1732 | dput(dnew); | 1732 | dput(dnew); |
1733 | out_unlock: | 1733 | out_unlock: |
1734 | fh_unlock(ffhp); | 1734 | fh_unlock(ffhp); |
1735 | fh_drop_write(tfhp); | ||
1735 | out: | 1736 | out: |
1736 | return err; | 1737 | return err; |
1737 | 1738 | ||
@@ -1774,6 +1775,12 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, | |||
1774 | if (!flen || isdotent(fname, flen) || !tlen || isdotent(tname, tlen)) | 1775 | if (!flen || isdotent(fname, flen) || !tlen || isdotent(tname, tlen)) |
1775 | goto out; | 1776 | goto out; |
1776 | 1777 | ||
1778 | host_err = fh_want_write(ffhp); | ||
1779 | if (host_err) { | ||
1780 | err = nfserrno(host_err); | ||
1781 | goto out; | ||
1782 | } | ||
1783 | |||
1777 | /* cannot use fh_lock as we need deadlock protective ordering | 1784 | /* cannot use fh_lock as we need deadlock protective ordering |
1778 | * so do it by hand */ | 1785 | * so do it by hand */ |
1779 | trap = lock_rename(tdentry, fdentry); | 1786 | trap = lock_rename(tdentry, fdentry); |
@@ -1804,17 +1811,14 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, | |||
1804 | host_err = -EXDEV; | 1811 | host_err = -EXDEV; |
1805 | if (ffhp->fh_export->ex_path.mnt != tfhp->fh_export->ex_path.mnt) | 1812 | if (ffhp->fh_export->ex_path.mnt != tfhp->fh_export->ex_path.mnt) |
1806 | goto out_dput_new; | 1813 | goto out_dput_new; |
1807 | host_err = fh_want_write(ffhp); | ||
1808 | if (host_err) | ||
1809 | goto out_dput_new; | ||
1810 | 1814 | ||
1811 | host_err = nfsd_break_lease(odentry->d_inode); | 1815 | host_err = nfsd_break_lease(odentry->d_inode); |
1812 | if (host_err) | 1816 | if (host_err) |
1813 | goto out_drop_write; | 1817 | goto out_dput_new; |
1814 | if (ndentry->d_inode) { | 1818 | if (ndentry->d_inode) { |
1815 | host_err = nfsd_break_lease(ndentry->d_inode); | 1819 | host_err = nfsd_break_lease(ndentry->d_inode); |
1816 | if (host_err) | 1820 | if (host_err) |
1817 | goto out_drop_write; | 1821 | goto out_dput_new; |
1818 | } | 1822 | } |
1819 | host_err = vfs_rename(fdir, odentry, tdir, ndentry); | 1823 | host_err = vfs_rename(fdir, odentry, tdir, ndentry); |
1820 | if (!host_err) { | 1824 | if (!host_err) { |
@@ -1822,8 +1826,6 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, | |||
1822 | if (!host_err) | 1826 | if (!host_err) |
1823 | host_err = commit_metadata(ffhp); | 1827 | host_err = commit_metadata(ffhp); |
1824 | } | 1828 | } |
1825 | out_drop_write: | ||
1826 | fh_drop_write(ffhp); | ||
1827 | out_dput_new: | 1829 | out_dput_new: |
1828 | dput(ndentry); | 1830 | dput(ndentry); |
1829 | out_dput_old: | 1831 | out_dput_old: |
@@ -1839,6 +1841,7 @@ out_drop_write: | |||
1839 | fill_post_wcc(tfhp); | 1841 | fill_post_wcc(tfhp); |
1840 | unlock_rename(tdentry, fdentry); | 1842 | unlock_rename(tdentry, fdentry); |
1841 | ffhp->fh_locked = tfhp->fh_locked = 0; | 1843 | ffhp->fh_locked = tfhp->fh_locked = 0; |
1844 | fh_drop_write(ffhp); | ||
1842 | 1845 | ||
1843 | out: | 1846 | out: |
1844 | return err; | 1847 | return err; |
@@ -1864,6 +1867,10 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, | |||
1864 | if (err) | 1867 | if (err) |
1865 | goto out; | 1868 | goto out; |
1866 | 1869 | ||
1870 | host_err = fh_want_write(fhp); | ||
1871 | if (host_err) | ||
1872 | goto out_nfserr; | ||
1873 | |||
1867 | fh_lock_nested(fhp, I_MUTEX_PARENT); | 1874 | fh_lock_nested(fhp, I_MUTEX_PARENT); |
1868 | dentry = fhp->fh_dentry; | 1875 | dentry = fhp->fh_dentry; |
1869 | dirp = dentry->d_inode; | 1876 | dirp = dentry->d_inode; |
@@ -1882,21 +1889,15 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, | |||
1882 | if (!type) | 1889 | if (!type) |
1883 | type = rdentry->d_inode->i_mode & S_IFMT; | 1890 | type = rdentry->d_inode->i_mode & S_IFMT; |
1884 | 1891 | ||
1885 | host_err = fh_want_write(fhp); | ||
1886 | if (host_err) | ||
1887 | goto out_put; | ||
1888 | |||
1889 | host_err = nfsd_break_lease(rdentry->d_inode); | 1892 | host_err = nfsd_break_lease(rdentry->d_inode); |
1890 | if (host_err) | 1893 | if (host_err) |
1891 | goto out_drop_write; | 1894 | goto out_put; |
1892 | if (type != S_IFDIR) | 1895 | if (type != S_IFDIR) |
1893 | host_err = vfs_unlink(dirp, rdentry); | 1896 | host_err = vfs_unlink(dirp, rdentry); |
1894 | else | 1897 | else |
1895 | host_err = vfs_rmdir(dirp, rdentry); | 1898 | host_err = vfs_rmdir(dirp, rdentry); |
1896 | if (!host_err) | 1899 | if (!host_err) |
1897 | host_err = commit_metadata(fhp); | 1900 | host_err = commit_metadata(fhp); |
1898 | out_drop_write: | ||
1899 | fh_drop_write(fhp); | ||
1900 | out_put: | 1901 | out_put: |
1901 | dput(rdentry); | 1902 | dput(rdentry); |
1902 | 1903 | ||