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 | ||
