aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/vfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/vfs.c')
-rw-r--r--fs/nfsd/vfs.c79
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 }
1729out_drop_write:
1730 fh_drop_write(tfhp);
1731out_dput: 1731out_dput:
1732 dput(dnew); 1732 dput(dnew);
1733out_unlock: 1733out_unlock:
1734 fh_unlock(ffhp); 1734 fh_unlock(ffhp);
1735 fh_drop_write(tfhp);
1735out: 1736out:
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 }
1825out_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
1843out: 1846out:
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);
1898out_drop_write:
1899 fh_drop_write(fhp);
1900out_put: 1901out_put:
1901 dput(rdentry); 1902 dput(rdentry);
1902 1903