aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/vfs.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-08-01 13:26:23 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-08-01 13:26:23 -0400
commita0e881b7c189fa2bd76c024dbff91e79511c971d (patch)
tree0c801918565b08921d21aceee5b326f64d998f5f /fs/nfsd/vfs.c
parenteff0d13f3823f35d70228cd151d2a2c89288ff32 (diff)
parentdbc6e0222d79e78925fe20733844a796a4b72cf9 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull second vfs pile from Al Viro: "The stuff in there: fsfreeze deadlock fixes by Jan (essentially, the deadlock reproduced by xfstests 068), symlink and hardlink restriction patches, plus assorted cleanups and fixes. Note that another fsfreeze deadlock (emergency thaw one) is *not* dealt with - the series by Fernando conflicts a lot with Jan's, breaks userland ABI (FIFREEZE semantics gets changed) and trades the deadlock for massive vfsmount leak; this is going to be handled next cycle. There probably will be another pull request, but that stuff won't be in it." Fix up trivial conflicts due to unrelated changes next to each other in drivers/{staging/gdm72xx/usb_boot.c, usb/gadget/storage_common.c} * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (54 commits) delousing target_core_file a bit Documentation: Correct s_umount state for freeze_fs/unfreeze_fs fs: Remove old freezing mechanism ext2: Implement freezing btrfs: Convert to new freezing mechanism nilfs2: Convert to new freezing mechanism ntfs: Convert to new freezing mechanism fuse: Convert to new freezing mechanism gfs2: Convert to new freezing mechanism ocfs2: Convert to new freezing mechanism xfs: Convert to new freezing code ext4: Convert to new freezing mechanism fs: Protect write paths by sb_start_write - sb_end_write fs: Skip atime update on frozen filesystem fs: Add freezing handling to mnt_want_write() / mnt_drop_write() fs: Improve filesystem freezing handling switch the protection of percpu_counter list to spinlock nfsd: Push mnt_want_write() outside of i_mutex btrfs: Push mnt_want_write() outside of i_mutex fat: Push mnt_want_write() outside of i_mutex ...
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