diff options
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/inode.c | 179 |
1 files changed, 105 insertions, 74 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index ea784969fb85..32ddcf69e9ac 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -366,13 +366,15 @@ nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data) | |||
366 | xprt = xprt_create_proto(tcp ? IPPROTO_TCP : IPPROTO_UDP, | 366 | xprt = xprt_create_proto(tcp ? IPPROTO_TCP : IPPROTO_UDP, |
367 | &server->addr, &timeparms); | 367 | &server->addr, &timeparms); |
368 | if (IS_ERR(xprt)) { | 368 | if (IS_ERR(xprt)) { |
369 | printk(KERN_WARNING "NFS: cannot create RPC transport.\n"); | 369 | dprintk("%s: cannot create RPC transport. Error = %ld\n", |
370 | __FUNCTION__, PTR_ERR(xprt)); | ||
370 | return (struct rpc_clnt *)xprt; | 371 | return (struct rpc_clnt *)xprt; |
371 | } | 372 | } |
372 | clnt = rpc_create_client(xprt, server->hostname, &nfs_program, | 373 | clnt = rpc_create_client(xprt, server->hostname, &nfs_program, |
373 | server->rpc_ops->version, data->pseudoflavor); | 374 | server->rpc_ops->version, data->pseudoflavor); |
374 | if (IS_ERR(clnt)) { | 375 | if (IS_ERR(clnt)) { |
375 | printk(KERN_WARNING "NFS: cannot create RPC client.\n"); | 376 | dprintk("%s: cannot create RPC client. Error = %ld\n", |
377 | __FUNCTION__, PTR_ERR(xprt)); | ||
376 | goto out_fail; | 378 | goto out_fail; |
377 | } | 379 | } |
378 | 380 | ||
@@ -426,21 +428,16 @@ nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent) | |||
426 | 428 | ||
427 | /* Check NFS protocol revision and initialize RPC op vector | 429 | /* Check NFS protocol revision and initialize RPC op vector |
428 | * and file handle pool. */ | 430 | * and file handle pool. */ |
429 | if (server->flags & NFS_MOUNT_VER3) { | ||
430 | #ifdef CONFIG_NFS_V3 | 431 | #ifdef CONFIG_NFS_V3 |
432 | if (server->flags & NFS_MOUNT_VER3) { | ||
431 | server->rpc_ops = &nfs_v3_clientops; | 433 | server->rpc_ops = &nfs_v3_clientops; |
432 | server->caps |= NFS_CAP_READDIRPLUS; | 434 | server->caps |= NFS_CAP_READDIRPLUS; |
433 | if (data->version < 4) { | ||
434 | printk(KERN_NOTICE "NFS: NFSv3 not supported by mount program.\n"); | ||
435 | return -EIO; | ||
436 | } | ||
437 | #else | ||
438 | printk(KERN_NOTICE "NFS: NFSv3 not supported.\n"); | ||
439 | return -EIO; | ||
440 | #endif | ||
441 | } else { | 435 | } else { |
442 | server->rpc_ops = &nfs_v2_clientops; | 436 | server->rpc_ops = &nfs_v2_clientops; |
443 | } | 437 | } |
438 | #else | ||
439 | server->rpc_ops = &nfs_v2_clientops; | ||
440 | #endif | ||
444 | 441 | ||
445 | /* Fill in pseudoflavor for mount version < 5 */ | 442 | /* Fill in pseudoflavor for mount version < 5 */ |
446 | if (!(data->flags & NFS_MOUNT_SECFLAVOUR)) | 443 | if (!(data->flags & NFS_MOUNT_SECFLAVOUR)) |
@@ -1384,74 +1381,94 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type, | |||
1384 | int flags, const char *dev_name, void *raw_data) | 1381 | int flags, const char *dev_name, void *raw_data) |
1385 | { | 1382 | { |
1386 | int error; | 1383 | int error; |
1387 | struct nfs_server *server; | 1384 | struct nfs_server *server = NULL; |
1388 | struct super_block *s; | 1385 | struct super_block *s; |
1389 | struct nfs_fh *root; | 1386 | struct nfs_fh *root; |
1390 | struct nfs_mount_data *data = raw_data; | 1387 | struct nfs_mount_data *data = raw_data; |
1391 | 1388 | ||
1392 | if (!data) { | 1389 | s = ERR_PTR(-EINVAL); |
1393 | printk("nfs_read_super: missing data argument\n"); | 1390 | if (data == NULL) { |
1394 | return ERR_PTR(-EINVAL); | 1391 | dprintk("%s: missing data argument\n", __FUNCTION__); |
1392 | goto out_err; | ||
1393 | } | ||
1394 | if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) { | ||
1395 | dprintk("%s: bad mount version\n", __FUNCTION__); | ||
1396 | goto out_err; | ||
1395 | } | 1397 | } |
1398 | switch (data->version) { | ||
1399 | case 1: | ||
1400 | data->namlen = 0; | ||
1401 | case 2: | ||
1402 | data->bsize = 0; | ||
1403 | case 3: | ||
1404 | if (data->flags & NFS_MOUNT_VER3) { | ||
1405 | dprintk("%s: mount structure version %d does not support NFSv3\n", | ||
1406 | __FUNCTION__, | ||
1407 | data->version); | ||
1408 | goto out_err; | ||
1409 | } | ||
1410 | data->root.size = NFS2_FHSIZE; | ||
1411 | memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE); | ||
1412 | case 4: | ||
1413 | if (data->flags & NFS_MOUNT_SECFLAVOUR) { | ||
1414 | dprintk("%s: mount structure version %d does not support strong security\n", | ||
1415 | __FUNCTION__, | ||
1416 | data->version); | ||
1417 | goto out_err; | ||
1418 | } | ||
1419 | case 5: | ||
1420 | memset(data->context, 0, sizeof(data->context)); | ||
1421 | } | ||
1422 | #ifndef CONFIG_NFS_V3 | ||
1423 | /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */ | ||
1424 | s = ERR_PTR(-EPROTONOSUPPORT); | ||
1425 | if (data->flags & NFS_MOUNT_VER3) { | ||
1426 | dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__); | ||
1427 | goto out_err; | ||
1428 | } | ||
1429 | #endif /* CONFIG_NFS_V3 */ | ||
1396 | 1430 | ||
1431 | s = ERR_PTR(-ENOMEM); | ||
1397 | server = kmalloc(sizeof(struct nfs_server), GFP_KERNEL); | 1432 | server = kmalloc(sizeof(struct nfs_server), GFP_KERNEL); |
1398 | if (!server) | 1433 | if (!server) |
1399 | return ERR_PTR(-ENOMEM); | 1434 | goto out_err; |
1400 | memset(server, 0, sizeof(struct nfs_server)); | 1435 | memset(server, 0, sizeof(struct nfs_server)); |
1401 | /* Zero out the NFS state stuff */ | 1436 | /* Zero out the NFS state stuff */ |
1402 | init_nfsv4_state(server); | 1437 | init_nfsv4_state(server); |
1403 | 1438 | ||
1404 | if (data->version != NFS_MOUNT_VERSION) { | ||
1405 | printk("nfs warning: mount version %s than kernel\n", | ||
1406 | data->version < NFS_MOUNT_VERSION ? "older" : "newer"); | ||
1407 | if (data->version < 2) | ||
1408 | data->namlen = 0; | ||
1409 | if (data->version < 3) | ||
1410 | data->bsize = 0; | ||
1411 | if (data->version < 4) { | ||
1412 | data->flags &= ~NFS_MOUNT_VER3; | ||
1413 | data->root.size = NFS2_FHSIZE; | ||
1414 | memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE); | ||
1415 | } | ||
1416 | if (data->version < 5) | ||
1417 | data->flags &= ~NFS_MOUNT_SECFLAVOUR; | ||
1418 | } | ||
1419 | |||
1420 | root = &server->fh; | 1439 | root = &server->fh; |
1421 | if (data->flags & NFS_MOUNT_VER3) | 1440 | if (data->flags & NFS_MOUNT_VER3) |
1422 | root->size = data->root.size; | 1441 | root->size = data->root.size; |
1423 | else | 1442 | else |
1424 | root->size = NFS2_FHSIZE; | 1443 | root->size = NFS2_FHSIZE; |
1444 | s = ERR_PTR(-EINVAL); | ||
1425 | if (root->size > sizeof(root->data)) { | 1445 | if (root->size > sizeof(root->data)) { |
1426 | printk("nfs_get_sb: invalid root filehandle\n"); | 1446 | dprintk("%s: invalid root filehandle\n", __FUNCTION__); |
1427 | kfree(server); | 1447 | goto out_err; |
1428 | return ERR_PTR(-EINVAL); | ||
1429 | } | 1448 | } |
1430 | memcpy(root->data, data->root.data, root->size); | 1449 | memcpy(root->data, data->root.data, root->size); |
1431 | 1450 | ||
1432 | /* We now require that the mount process passes the remote address */ | 1451 | /* We now require that the mount process passes the remote address */ |
1433 | memcpy(&server->addr, &data->addr, sizeof(server->addr)); | 1452 | memcpy(&server->addr, &data->addr, sizeof(server->addr)); |
1434 | if (server->addr.sin_addr.s_addr == INADDR_ANY) { | 1453 | if (server->addr.sin_addr.s_addr == INADDR_ANY) { |
1435 | printk("NFS: mount program didn't pass remote address!\n"); | 1454 | dprintk("%s: mount program didn't pass remote address!\n", |
1436 | kfree(server); | 1455 | __FUNCTION__); |
1437 | return ERR_PTR(-EINVAL); | 1456 | goto out_err; |
1438 | } | 1457 | } |
1439 | 1458 | ||
1440 | s = sget(fs_type, nfs_compare_super, nfs_set_super, server); | 1459 | /* Fire up rpciod if not yet running */ |
1441 | 1460 | s = ERR_PTR(rpciod_up()); | |
1442 | if (IS_ERR(s) || s->s_root) { | 1461 | if (IS_ERR(s)) { |
1443 | kfree(server); | 1462 | dprintk("%s: couldn't start rpciod! Error = %ld\n", |
1444 | return s; | 1463 | __FUNCTION__, PTR_ERR(s)); |
1464 | goto out_err; | ||
1445 | } | 1465 | } |
1446 | 1466 | ||
1447 | s->s_flags = flags; | 1467 | s = sget(fs_type, nfs_compare_super, nfs_set_super, server); |
1468 | if (IS_ERR(s) || s->s_root) | ||
1469 | goto out_rpciod_down; | ||
1448 | 1470 | ||
1449 | /* Fire up rpciod if not yet running */ | 1471 | s->s_flags = flags; |
1450 | if (rpciod_up() != 0) { | ||
1451 | printk(KERN_WARNING "NFS: couldn't start rpciod!\n"); | ||
1452 | kfree(server); | ||
1453 | return ERR_PTR(-EIO); | ||
1454 | } | ||
1455 | 1472 | ||
1456 | error = nfs_fill_super(s, data, flags & MS_VERBOSE ? 1 : 0); | 1473 | error = nfs_fill_super(s, data, flags & MS_VERBOSE ? 1 : 0); |
1457 | if (error) { | 1474 | if (error) { |
@@ -1461,6 +1478,11 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type, | |||
1461 | } | 1478 | } |
1462 | s->s_flags |= MS_ACTIVE; | 1479 | s->s_flags |= MS_ACTIVE; |
1463 | return s; | 1480 | return s; |
1481 | out_rpciod_down: | ||
1482 | rpciod_down(); | ||
1483 | out_err: | ||
1484 | kfree(server); | ||
1485 | return s; | ||
1464 | } | 1486 | } |
1465 | 1487 | ||
1466 | static void nfs_kill_super(struct super_block *s) | 1488 | static void nfs_kill_super(struct super_block *s) |
@@ -1593,15 +1615,19 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, | |||
1593 | 1615 | ||
1594 | clp = nfs4_get_client(&server->addr.sin_addr); | 1616 | clp = nfs4_get_client(&server->addr.sin_addr); |
1595 | if (!clp) { | 1617 | if (!clp) { |
1596 | printk(KERN_WARNING "NFS: failed to create NFS4 client.\n"); | 1618 | dprintk("%s: failed to create NFS4 client.\n", __FUNCTION__); |
1597 | return -EIO; | 1619 | return -EIO; |
1598 | } | 1620 | } |
1599 | 1621 | ||
1600 | /* Now create transport and client */ | 1622 | /* Now create transport and client */ |
1601 | authflavour = RPC_AUTH_UNIX; | 1623 | authflavour = RPC_AUTH_UNIX; |
1602 | if (data->auth_flavourlen != 0) { | 1624 | if (data->auth_flavourlen != 0) { |
1603 | if (data->auth_flavourlen > 1) | 1625 | if (data->auth_flavourlen != 1) { |
1604 | printk(KERN_INFO "NFS: cannot yet deal with multiple auth flavours.\n"); | 1626 | dprintk("%s: Invalid number of RPC auth flavours %d.\n", |
1627 | __FUNCTION__, data->auth_flavourlen); | ||
1628 | err = -EINVAL; | ||
1629 | goto out_fail; | ||
1630 | } | ||
1605 | if (copy_from_user(&authflavour, data->auth_flavours, sizeof(authflavour))) { | 1631 | if (copy_from_user(&authflavour, data->auth_flavours, sizeof(authflavour))) { |
1606 | err = -EFAULT; | 1632 | err = -EFAULT; |
1607 | goto out_fail; | 1633 | goto out_fail; |
@@ -1613,16 +1639,18 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, | |||
1613 | xprt = xprt_create_proto(proto, &server->addr, &timeparms); | 1639 | xprt = xprt_create_proto(proto, &server->addr, &timeparms); |
1614 | if (IS_ERR(xprt)) { | 1640 | if (IS_ERR(xprt)) { |
1615 | up_write(&clp->cl_sem); | 1641 | up_write(&clp->cl_sem); |
1616 | printk(KERN_WARNING "NFS: cannot create RPC transport.\n"); | ||
1617 | err = PTR_ERR(xprt); | 1642 | err = PTR_ERR(xprt); |
1643 | dprintk("%s: cannot create RPC transport. Error = %d\n", | ||
1644 | __FUNCTION__, err); | ||
1618 | goto out_fail; | 1645 | goto out_fail; |
1619 | } | 1646 | } |
1620 | clnt = rpc_create_client(xprt, server->hostname, &nfs_program, | 1647 | clnt = rpc_create_client(xprt, server->hostname, &nfs_program, |
1621 | server->rpc_ops->version, authflavour); | 1648 | server->rpc_ops->version, authflavour); |
1622 | if (IS_ERR(clnt)) { | 1649 | if (IS_ERR(clnt)) { |
1623 | up_write(&clp->cl_sem); | 1650 | up_write(&clp->cl_sem); |
1624 | printk(KERN_WARNING "NFS: cannot create RPC client.\n"); | ||
1625 | err = PTR_ERR(clnt); | 1651 | err = PTR_ERR(clnt); |
1652 | dprintk("%s: cannot create RPC client. Error = %d\n", | ||
1653 | __FUNCTION__, err); | ||
1626 | goto out_fail; | 1654 | goto out_fail; |
1627 | } | 1655 | } |
1628 | clnt->cl_intr = 1; | 1656 | clnt->cl_intr = 1; |
@@ -1654,20 +1682,22 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, | |||
1654 | clp = NULL; | 1682 | clp = NULL; |
1655 | 1683 | ||
1656 | if (IS_ERR(clnt)) { | 1684 | if (IS_ERR(clnt)) { |
1657 | printk(KERN_WARNING "NFS: cannot create RPC client.\n"); | 1685 | err = PTR_ERR(clnt); |
1658 | return PTR_ERR(clnt); | 1686 | dprintk("%s: cannot create RPC client. Error = %d\n", |
1687 | __FUNCTION__, err); | ||
1688 | return err; | ||
1659 | } | 1689 | } |
1660 | 1690 | ||
1661 | server->client = clnt; | 1691 | server->client = clnt; |
1662 | 1692 | ||
1663 | if (server->nfs4_state->cl_idmap == NULL) { | 1693 | if (server->nfs4_state->cl_idmap == NULL) { |
1664 | printk(KERN_WARNING "NFS: failed to create idmapper.\n"); | 1694 | dprintk("%s: failed to create idmapper.\n", __FUNCTION__); |
1665 | return -ENOMEM; | 1695 | return -ENOMEM; |
1666 | } | 1696 | } |
1667 | 1697 | ||
1668 | if (clnt->cl_auth->au_flavor != authflavour) { | 1698 | if (clnt->cl_auth->au_flavor != authflavour) { |
1669 | if (rpcauth_create(authflavour, clnt) == NULL) { | 1699 | if (rpcauth_create(authflavour, clnt) == NULL) { |
1670 | printk(KERN_WARNING "NFS: couldn't create credcache!\n"); | 1700 | dprintk("%s: couldn't create credcache!\n", __FUNCTION__); |
1671 | return -ENOMEM; | 1701 | return -ENOMEM; |
1672 | } | 1702 | } |
1673 | } | 1703 | } |
@@ -1728,8 +1758,12 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type, | |||
1728 | struct nfs4_mount_data *data = raw_data; | 1758 | struct nfs4_mount_data *data = raw_data; |
1729 | void *p; | 1759 | void *p; |
1730 | 1760 | ||
1731 | if (!data) { | 1761 | if (data == NULL) { |
1732 | printk("nfs_read_super: missing data argument\n"); | 1762 | dprintk("%s: missing data argument\n", __FUNCTION__); |
1763 | return ERR_PTR(-EINVAL); | ||
1764 | } | ||
1765 | if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) { | ||
1766 | dprintk("%s: bad mount version\n", __FUNCTION__); | ||
1733 | return ERR_PTR(-EINVAL); | 1767 | return ERR_PTR(-EINVAL); |
1734 | } | 1768 | } |
1735 | 1769 | ||
@@ -1740,11 +1774,6 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type, | |||
1740 | /* Zero out the NFS state stuff */ | 1774 | /* Zero out the NFS state stuff */ |
1741 | init_nfsv4_state(server); | 1775 | init_nfsv4_state(server); |
1742 | 1776 | ||
1743 | if (data->version != NFS4_MOUNT_VERSION) { | ||
1744 | printk("nfs warning: mount version %s than kernel\n", | ||
1745 | data->version < NFS4_MOUNT_VERSION ? "older" : "newer"); | ||
1746 | } | ||
1747 | |||
1748 | p = nfs_copy_user_string(NULL, &data->hostname, 256); | 1777 | p = nfs_copy_user_string(NULL, &data->hostname, 256); |
1749 | if (IS_ERR(p)) | 1778 | if (IS_ERR(p)) |
1750 | goto out_err; | 1779 | goto out_err; |
@@ -1771,11 +1800,20 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type, | |||
1771 | } | 1800 | } |
1772 | if (server->addr.sin_family != AF_INET || | 1801 | if (server->addr.sin_family != AF_INET || |
1773 | server->addr.sin_addr.s_addr == INADDR_ANY) { | 1802 | server->addr.sin_addr.s_addr == INADDR_ANY) { |
1774 | printk("NFS: mount program didn't pass remote IP address!\n"); | 1803 | dprintk("%s: mount program didn't pass remote IP address!\n", |
1804 | __FUNCTION__); | ||
1775 | s = ERR_PTR(-EINVAL); | 1805 | s = ERR_PTR(-EINVAL); |
1776 | goto out_free; | 1806 | goto out_free; |
1777 | } | 1807 | } |
1778 | 1808 | ||
1809 | /* Fire up rpciod if not yet running */ | ||
1810 | s = ERR_PTR(rpciod_up()); | ||
1811 | if (IS_ERR(s)) { | ||
1812 | dprintk("%s: couldn't start rpciod! Error = %ld\n", | ||
1813 | __FUNCTION__, PTR_ERR(s)); | ||
1814 | goto out_free; | ||
1815 | } | ||
1816 | |||
1779 | s = sget(fs_type, nfs4_compare_super, nfs_set_super, server); | 1817 | s = sget(fs_type, nfs4_compare_super, nfs_set_super, server); |
1780 | 1818 | ||
1781 | if (IS_ERR(s) || s->s_root) | 1819 | if (IS_ERR(s) || s->s_root) |
@@ -1783,13 +1821,6 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type, | |||
1783 | 1821 | ||
1784 | s->s_flags = flags; | 1822 | s->s_flags = flags; |
1785 | 1823 | ||
1786 | /* Fire up rpciod if not yet running */ | ||
1787 | if (rpciod_up() != 0) { | ||
1788 | printk(KERN_WARNING "NFS: couldn't start rpciod!\n"); | ||
1789 | s = ERR_PTR(-EIO); | ||
1790 | goto out_free; | ||
1791 | } | ||
1792 | |||
1793 | error = nfs4_fill_super(s, data, flags & MS_VERBOSE ? 1 : 0); | 1824 | error = nfs4_fill_super(s, data, flags & MS_VERBOSE ? 1 : 0); |
1794 | if (error) { | 1825 | if (error) { |
1795 | up_write(&s->s_umount); | 1826 | up_write(&s->s_umount); |