diff options
Diffstat (limited to 'fs/afs/fsclient.c')
-rw-r--r-- | fs/afs/fsclient.c | 298 |
1 files changed, 298 insertions, 0 deletions
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c index 56cc0efa2a0c..5dff1308b6f0 100644 --- a/fs/afs/fsclient.c +++ b/fs/afs/fsclient.c | |||
@@ -202,6 +202,29 @@ static void xdr_encode_AFS_StoreStatus(__be32 **_bp, struct iattr *attr) | |||
202 | } | 202 | } |
203 | 203 | ||
204 | /* | 204 | /* |
205 | * decode an AFSFetchVolumeStatus block | ||
206 | */ | ||
207 | static void xdr_decode_AFSFetchVolumeStatus(const __be32 **_bp, | ||
208 | struct afs_volume_status *vs) | ||
209 | { | ||
210 | const __be32 *bp = *_bp; | ||
211 | |||
212 | vs->vid = ntohl(*bp++); | ||
213 | vs->parent_id = ntohl(*bp++); | ||
214 | vs->online = ntohl(*bp++); | ||
215 | vs->in_service = ntohl(*bp++); | ||
216 | vs->blessed = ntohl(*bp++); | ||
217 | vs->needs_salvage = ntohl(*bp++); | ||
218 | vs->type = ntohl(*bp++); | ||
219 | vs->min_quota = ntohl(*bp++); | ||
220 | vs->max_quota = ntohl(*bp++); | ||
221 | vs->blocks_in_use = ntohl(*bp++); | ||
222 | vs->part_blocks_avail = ntohl(*bp++); | ||
223 | vs->part_max_blocks = ntohl(*bp++); | ||
224 | *_bp = bp; | ||
225 | } | ||
226 | |||
227 | /* | ||
205 | * deliver reply data to an FS.FetchStatus | 228 | * deliver reply data to an FS.FetchStatus |
206 | */ | 229 | */ |
207 | static int afs_deliver_fs_fetch_status(struct afs_call *call, | 230 | static int afs_deliver_fs_fetch_status(struct afs_call *call, |
@@ -1450,3 +1473,278 @@ int afs_fs_setattr(struct afs_server *server, struct key *key, | |||
1450 | 1473 | ||
1451 | return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode); | 1474 | return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode); |
1452 | } | 1475 | } |
1476 | |||
1477 | /* | ||
1478 | * deliver reply data to an FS.GetVolumeStatus | ||
1479 | */ | ||
1480 | static int afs_deliver_fs_get_volume_status(struct afs_call *call, | ||
1481 | struct sk_buff *skb, bool last) | ||
1482 | { | ||
1483 | const __be32 *bp; | ||
1484 | char *p; | ||
1485 | int ret; | ||
1486 | |||
1487 | _enter("{%u},{%u},%d", call->unmarshall, skb->len, last); | ||
1488 | |||
1489 | switch (call->unmarshall) { | ||
1490 | case 0: | ||
1491 | call->offset = 0; | ||
1492 | call->unmarshall++; | ||
1493 | |||
1494 | /* extract the returned status record */ | ||
1495 | case 1: | ||
1496 | _debug("extract status"); | ||
1497 | ret = afs_extract_data(call, skb, last, call->buffer, | ||
1498 | 12 * 4); | ||
1499 | switch (ret) { | ||
1500 | case 0: break; | ||
1501 | case -EAGAIN: return 0; | ||
1502 | default: return ret; | ||
1503 | } | ||
1504 | |||
1505 | bp = call->buffer; | ||
1506 | xdr_decode_AFSFetchVolumeStatus(&bp, call->reply2); | ||
1507 | call->offset = 0; | ||
1508 | call->unmarshall++; | ||
1509 | |||
1510 | /* extract the volume name length */ | ||
1511 | case 2: | ||
1512 | ret = afs_extract_data(call, skb, last, &call->tmp, 4); | ||
1513 | switch (ret) { | ||
1514 | case 0: break; | ||
1515 | case -EAGAIN: return 0; | ||
1516 | default: return ret; | ||
1517 | } | ||
1518 | |||
1519 | call->count = ntohl(call->tmp); | ||
1520 | _debug("volname length: %u", call->count); | ||
1521 | if (call->count >= AFSNAMEMAX) | ||
1522 | return -EBADMSG; | ||
1523 | call->offset = 0; | ||
1524 | call->unmarshall++; | ||
1525 | |||
1526 | /* extract the volume name */ | ||
1527 | case 3: | ||
1528 | _debug("extract volname"); | ||
1529 | if (call->count > 0) { | ||
1530 | ret = afs_extract_data(call, skb, last, call->reply3, | ||
1531 | call->count); | ||
1532 | switch (ret) { | ||
1533 | case 0: break; | ||
1534 | case -EAGAIN: return 0; | ||
1535 | default: return ret; | ||
1536 | } | ||
1537 | } | ||
1538 | |||
1539 | p = call->reply3; | ||
1540 | p[call->count] = 0; | ||
1541 | _debug("volname '%s'", p); | ||
1542 | |||
1543 | call->offset = 0; | ||
1544 | call->unmarshall++; | ||
1545 | |||
1546 | /* extract the volume name padding */ | ||
1547 | if ((call->count & 3) == 0) { | ||
1548 | call->unmarshall++; | ||
1549 | goto no_volname_padding; | ||
1550 | } | ||
1551 | call->count = 4 - (call->count & 3); | ||
1552 | |||
1553 | case 4: | ||
1554 | ret = afs_extract_data(call, skb, last, call->buffer, | ||
1555 | call->count); | ||
1556 | switch (ret) { | ||
1557 | case 0: break; | ||
1558 | case -EAGAIN: return 0; | ||
1559 | default: return ret; | ||
1560 | } | ||
1561 | |||
1562 | call->offset = 0; | ||
1563 | call->unmarshall++; | ||
1564 | no_volname_padding: | ||
1565 | |||
1566 | /* extract the offline message length */ | ||
1567 | case 5: | ||
1568 | ret = afs_extract_data(call, skb, last, &call->tmp, 4); | ||
1569 | switch (ret) { | ||
1570 | case 0: break; | ||
1571 | case -EAGAIN: return 0; | ||
1572 | default: return ret; | ||
1573 | } | ||
1574 | |||
1575 | call->count = ntohl(call->tmp); | ||
1576 | _debug("offline msg length: %u", call->count); | ||
1577 | if (call->count >= AFSNAMEMAX) | ||
1578 | return -EBADMSG; | ||
1579 | call->offset = 0; | ||
1580 | call->unmarshall++; | ||
1581 | |||
1582 | /* extract the offline message */ | ||
1583 | case 6: | ||
1584 | _debug("extract offline"); | ||
1585 | if (call->count > 0) { | ||
1586 | ret = afs_extract_data(call, skb, last, call->reply3, | ||
1587 | call->count); | ||
1588 | switch (ret) { | ||
1589 | case 0: break; | ||
1590 | case -EAGAIN: return 0; | ||
1591 | default: return ret; | ||
1592 | } | ||
1593 | } | ||
1594 | |||
1595 | p = call->reply3; | ||
1596 | p[call->count] = 0; | ||
1597 | _debug("offline '%s'", p); | ||
1598 | |||
1599 | call->offset = 0; | ||
1600 | call->unmarshall++; | ||
1601 | |||
1602 | /* extract the offline message padding */ | ||
1603 | if ((call->count & 3) == 0) { | ||
1604 | call->unmarshall++; | ||
1605 | goto no_offline_padding; | ||
1606 | } | ||
1607 | call->count = 4 - (call->count & 3); | ||
1608 | |||
1609 | case 7: | ||
1610 | ret = afs_extract_data(call, skb, last, call->buffer, | ||
1611 | call->count); | ||
1612 | switch (ret) { | ||
1613 | case 0: break; | ||
1614 | case -EAGAIN: return 0; | ||
1615 | default: return ret; | ||
1616 | } | ||
1617 | |||
1618 | call->offset = 0; | ||
1619 | call->unmarshall++; | ||
1620 | no_offline_padding: | ||
1621 | |||
1622 | /* extract the message of the day length */ | ||
1623 | case 8: | ||
1624 | ret = afs_extract_data(call, skb, last, &call->tmp, 4); | ||
1625 | switch (ret) { | ||
1626 | case 0: break; | ||
1627 | case -EAGAIN: return 0; | ||
1628 | default: return ret; | ||
1629 | } | ||
1630 | |||
1631 | call->count = ntohl(call->tmp); | ||
1632 | _debug("motd length: %u", call->count); | ||
1633 | if (call->count >= AFSNAMEMAX) | ||
1634 | return -EBADMSG; | ||
1635 | call->offset = 0; | ||
1636 | call->unmarshall++; | ||
1637 | |||
1638 | /* extract the message of the day */ | ||
1639 | case 9: | ||
1640 | _debug("extract motd"); | ||
1641 | if (call->count > 0) { | ||
1642 | ret = afs_extract_data(call, skb, last, call->reply3, | ||
1643 | call->count); | ||
1644 | switch (ret) { | ||
1645 | case 0: break; | ||
1646 | case -EAGAIN: return 0; | ||
1647 | default: return ret; | ||
1648 | } | ||
1649 | } | ||
1650 | |||
1651 | p = call->reply3; | ||
1652 | p[call->count] = 0; | ||
1653 | _debug("motd '%s'", p); | ||
1654 | |||
1655 | call->offset = 0; | ||
1656 | call->unmarshall++; | ||
1657 | |||
1658 | /* extract the message of the day padding */ | ||
1659 | if ((call->count & 3) == 0) { | ||
1660 | call->unmarshall++; | ||
1661 | goto no_motd_padding; | ||
1662 | } | ||
1663 | call->count = 4 - (call->count & 3); | ||
1664 | |||
1665 | case 10: | ||
1666 | ret = afs_extract_data(call, skb, last, call->buffer, | ||
1667 | call->count); | ||
1668 | switch (ret) { | ||
1669 | case 0: break; | ||
1670 | case -EAGAIN: return 0; | ||
1671 | default: return ret; | ||
1672 | } | ||
1673 | |||
1674 | call->offset = 0; | ||
1675 | call->unmarshall++; | ||
1676 | no_motd_padding: | ||
1677 | |||
1678 | case 11: | ||
1679 | _debug("trailer %d", skb->len); | ||
1680 | if (skb->len != 0) | ||
1681 | return -EBADMSG; | ||
1682 | break; | ||
1683 | } | ||
1684 | |||
1685 | if (!last) | ||
1686 | return 0; | ||
1687 | |||
1688 | _leave(" = 0 [done]"); | ||
1689 | return 0; | ||
1690 | } | ||
1691 | |||
1692 | /* | ||
1693 | * destroy an FS.GetVolumeStatus call | ||
1694 | */ | ||
1695 | static void afs_get_volume_status_call_destructor(struct afs_call *call) | ||
1696 | { | ||
1697 | kfree(call->reply3); | ||
1698 | call->reply3 = NULL; | ||
1699 | afs_flat_call_destructor(call); | ||
1700 | } | ||
1701 | |||
1702 | /* | ||
1703 | * FS.GetVolumeStatus operation type | ||
1704 | */ | ||
1705 | static const struct afs_call_type afs_RXFSGetVolumeStatus = { | ||
1706 | .name = "FS.GetVolumeStatus", | ||
1707 | .deliver = afs_deliver_fs_get_volume_status, | ||
1708 | .abort_to_error = afs_abort_to_error, | ||
1709 | .destructor = afs_get_volume_status_call_destructor, | ||
1710 | }; | ||
1711 | |||
1712 | /* | ||
1713 | * fetch the status of a volume | ||
1714 | */ | ||
1715 | int afs_fs_get_volume_status(struct afs_server *server, | ||
1716 | struct key *key, | ||
1717 | struct afs_vnode *vnode, | ||
1718 | struct afs_volume_status *vs, | ||
1719 | const struct afs_wait_mode *wait_mode) | ||
1720 | { | ||
1721 | struct afs_call *call; | ||
1722 | __be32 *bp; | ||
1723 | void *tmpbuf; | ||
1724 | |||
1725 | _enter(""); | ||
1726 | |||
1727 | tmpbuf = kmalloc(AFSOPAQUEMAX, GFP_KERNEL); | ||
1728 | if (!tmpbuf) | ||
1729 | return -ENOMEM; | ||
1730 | |||
1731 | call = afs_alloc_flat_call(&afs_RXFSGetVolumeStatus, 2 * 4, 12 * 4); | ||
1732 | if (!call) { | ||
1733 | kfree(tmpbuf); | ||
1734 | return -ENOMEM; | ||
1735 | } | ||
1736 | |||
1737 | call->key = key; | ||
1738 | call->reply = vnode; | ||
1739 | call->reply2 = vs; | ||
1740 | call->reply3 = tmpbuf; | ||
1741 | call->service_id = FS_SERVICE; | ||
1742 | call->port = htons(AFS_FS_PORT); | ||
1743 | |||
1744 | /* marshall the parameters */ | ||
1745 | bp = call->request; | ||
1746 | bp[0] = htonl(FSGETVOLUMESTATUS); | ||
1747 | bp[1] = htonl(vnode->fid.vid); | ||
1748 | |||
1749 | return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode); | ||
1750 | } | ||