aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/export.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/export.c')
-rw-r--r--fs/nfsd/export.c418
1 files changed, 0 insertions, 418 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index b9566e46219f..f4cc1e2bfc54 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -797,58 +797,6 @@ exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp)
797 return ek; 797 return ek;
798} 798}
799 799
800#ifdef CONFIG_NFSD_DEPRECATED
801static int exp_set_key(svc_client *clp, int fsid_type, u32 *fsidv,
802 struct svc_export *exp)
803{
804 struct svc_expkey key, *ek;
805
806 key.ek_client = clp;
807 key.ek_fsidtype = fsid_type;
808 memcpy(key.ek_fsid, fsidv, key_len(fsid_type));
809 key.ek_path = exp->ex_path;
810 key.h.expiry_time = NEVER;
811 key.h.flags = 0;
812
813 ek = svc_expkey_lookup(&key);
814 if (ek)
815 ek = svc_expkey_update(&key,ek);
816 if (ek) {
817 cache_put(&ek->h, &svc_expkey_cache);
818 return 0;
819 }
820 return -ENOMEM;
821}
822
823/*
824 * Find the client's export entry matching xdev/xino.
825 */
826static inline struct svc_expkey *
827exp_get_key(svc_client *clp, dev_t dev, ino_t ino)
828{
829 u32 fsidv[3];
830
831 if (old_valid_dev(dev)) {
832 mk_fsid(FSID_DEV, fsidv, dev, ino, 0, NULL);
833 return exp_find_key(clp, FSID_DEV, fsidv, NULL);
834 }
835 mk_fsid(FSID_ENCODE_DEV, fsidv, dev, ino, 0, NULL);
836 return exp_find_key(clp, FSID_ENCODE_DEV, fsidv, NULL);
837}
838
839/*
840 * Find the client's export entry matching fsid
841 */
842static inline struct svc_expkey *
843exp_get_fsid_key(svc_client *clp, int fsid)
844{
845 u32 fsidv[2];
846
847 mk_fsid(FSID_NUM, fsidv, 0, 0, fsid, NULL);
848
849 return exp_find_key(clp, FSID_NUM, fsidv, NULL);
850}
851#endif
852 800
853static svc_export *exp_get_by_name(svc_client *clp, const struct path *path, 801static svc_export *exp_get_by_name(svc_client *clp, const struct path *path,
854 struct cache_req *reqp) 802 struct cache_req *reqp)
@@ -890,275 +838,7 @@ static struct svc_export *exp_parent(svc_client *clp, struct path *path)
890 return exp; 838 return exp;
891} 839}
892 840
893#ifdef CONFIG_NFSD_DEPRECATED
894/*
895 * Hashtable locking. Write locks are placed only by user processes
896 * wanting to modify export information.
897 * Write locking only done in this file. Read locking
898 * needed externally.
899 */
900
901static DECLARE_RWSEM(hash_sem);
902
903void
904exp_readlock(void)
905{
906 down_read(&hash_sem);
907}
908
909static inline void
910exp_writelock(void)
911{
912 down_write(&hash_sem);
913}
914
915void
916exp_readunlock(void)
917{
918 up_read(&hash_sem);
919}
920
921static inline void
922exp_writeunlock(void)
923{
924 up_write(&hash_sem);
925}
926#else
927
928/* hash_sem not needed once deprecated interface is removed */
929void exp_readlock(void) {}
930static inline void exp_writelock(void){}
931void exp_readunlock(void) {}
932static inline void exp_writeunlock(void){}
933
934#endif
935
936#ifdef CONFIG_NFSD_DEPRECATED
937static void exp_do_unexport(svc_export *unexp);
938static int exp_verify_string(char *cp, int max);
939
940static void exp_fsid_unhash(struct svc_export *exp)
941{
942 struct svc_expkey *ek;
943
944 if ((exp->ex_flags & NFSEXP_FSID) == 0)
945 return;
946
947 ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid);
948 if (!IS_ERR(ek)) {
949 sunrpc_invalidate(&ek->h, &svc_expkey_cache);
950 cache_put(&ek->h, &svc_expkey_cache);
951 }
952}
953
954static int exp_fsid_hash(svc_client *clp, struct svc_export *exp)
955{
956 u32 fsid[2];
957
958 if ((exp->ex_flags & NFSEXP_FSID) == 0)
959 return 0;
960
961 mk_fsid(FSID_NUM, fsid, 0, 0, exp->ex_fsid, NULL);
962 return exp_set_key(clp, FSID_NUM, fsid, exp);
963}
964
965static int exp_hash(struct auth_domain *clp, struct svc_export *exp)
966{
967 u32 fsid[2];
968 struct inode *inode = exp->ex_path.dentry->d_inode;
969 dev_t dev = inode->i_sb->s_dev;
970
971 if (old_valid_dev(dev)) {
972 mk_fsid(FSID_DEV, fsid, dev, inode->i_ino, 0, NULL);
973 return exp_set_key(clp, FSID_DEV, fsid, exp);
974 }
975 mk_fsid(FSID_ENCODE_DEV, fsid, dev, inode->i_ino, 0, NULL);
976 return exp_set_key(clp, FSID_ENCODE_DEV, fsid, exp);
977}
978 841
979static void exp_unhash(struct svc_export *exp)
980{
981 struct svc_expkey *ek;
982 struct inode *inode = exp->ex_path.dentry->d_inode;
983
984 ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino);
985 if (!IS_ERR(ek)) {
986 sunrpc_invalidate(&ek->h, &svc_expkey_cache);
987 cache_put(&ek->h, &svc_expkey_cache);
988 }
989}
990
991/*
992 * Export a file system.
993 */
994int
995exp_export(struct nfsctl_export *nxp)
996{
997 svc_client *clp;
998 struct svc_export *exp = NULL;
999 struct svc_export new;
1000 struct svc_expkey *fsid_key = NULL;
1001 struct path path;
1002 int err;
1003
1004 /* Consistency check */
1005 err = -EINVAL;
1006 if (!exp_verify_string(nxp->ex_path, NFS_MAXPATHLEN) ||
1007 !exp_verify_string(nxp->ex_client, NFSCLNT_IDMAX))
1008 goto out;
1009
1010 dprintk("exp_export called for %s:%s (%x/%ld fl %x).\n",
1011 nxp->ex_client, nxp->ex_path,
1012 (unsigned)nxp->ex_dev, (long)nxp->ex_ino,
1013 nxp->ex_flags);
1014
1015 /* Try to lock the export table for update */
1016 exp_writelock();
1017
1018 /* Look up client info */
1019 if (!(clp = auth_domain_find(nxp->ex_client)))
1020 goto out_unlock;
1021
1022
1023 /* Look up the dentry */
1024 err = kern_path(nxp->ex_path, 0, &path);
1025 if (err)
1026 goto out_put_clp;
1027 err = -EINVAL;
1028
1029 exp = exp_get_by_name(clp, &path, NULL);
1030
1031 memset(&new, 0, sizeof(new));
1032
1033 /* must make sure there won't be an ex_fsid clash */
1034 if ((nxp->ex_flags & NFSEXP_FSID) &&
1035 (!IS_ERR(fsid_key = exp_get_fsid_key(clp, nxp->ex_dev))) &&
1036 fsid_key->ek_path.mnt &&
1037 (fsid_key->ek_path.mnt != path.mnt ||
1038 fsid_key->ek_path.dentry != path.dentry))
1039 goto finish;
1040
1041 if (!IS_ERR(exp)) {
1042 /* just a flags/id/fsid update */
1043
1044 exp_fsid_unhash(exp);
1045 exp->ex_flags = nxp->ex_flags;
1046 exp->ex_anon_uid = nxp->ex_anon_uid;
1047 exp->ex_anon_gid = nxp->ex_anon_gid;
1048 exp->ex_fsid = nxp->ex_dev;
1049
1050 err = exp_fsid_hash(clp, exp);
1051 goto finish;
1052 }
1053
1054 err = check_export(path.dentry->d_inode, &nxp->ex_flags, NULL);
1055 if (err) goto finish;
1056
1057 err = -ENOMEM;
1058
1059 dprintk("nfsd: creating export entry %p for client %p\n", exp, clp);
1060
1061 new.h.expiry_time = NEVER;
1062 new.h.flags = 0;
1063 new.ex_pathname = kstrdup(nxp->ex_path, GFP_KERNEL);
1064 if (!new.ex_pathname)
1065 goto finish;
1066 new.ex_client = clp;
1067 new.ex_path = path;
1068 new.ex_flags = nxp->ex_flags;
1069 new.ex_anon_uid = nxp->ex_anon_uid;
1070 new.ex_anon_gid = nxp->ex_anon_gid;
1071 new.ex_fsid = nxp->ex_dev;
1072
1073 exp = svc_export_lookup(&new);
1074 if (exp)
1075 exp = svc_export_update(&new, exp);
1076
1077 if (!exp)
1078 goto finish;
1079
1080 if (exp_hash(clp, exp) ||
1081 exp_fsid_hash(clp, exp)) {
1082 /* failed to create at least one index */
1083 exp_do_unexport(exp);
1084 cache_flush();
1085 } else
1086 err = 0;
1087finish:
1088 kfree(new.ex_pathname);
1089 if (!IS_ERR_OR_NULL(exp))
1090 exp_put(exp);
1091 if (!IS_ERR_OR_NULL(fsid_key))
1092 cache_put(&fsid_key->h, &svc_expkey_cache);
1093 path_put(&path);
1094out_put_clp:
1095 auth_domain_put(clp);
1096out_unlock:
1097 exp_writeunlock();
1098out:
1099 return err;
1100}
1101
1102/*
1103 * Unexport a file system. The export entry has already
1104 * been removed from the client's list of exported fs's.
1105 */
1106static void
1107exp_do_unexport(svc_export *unexp)
1108{
1109 sunrpc_invalidate(&unexp->h, &svc_export_cache);
1110 exp_unhash(unexp);
1111 exp_fsid_unhash(unexp);
1112}
1113
1114
1115/*
1116 * unexport syscall.
1117 */
1118int
1119exp_unexport(struct nfsctl_export *nxp)
1120{
1121 struct auth_domain *dom;
1122 svc_export *exp;
1123 struct path path;
1124 int err;
1125
1126 /* Consistency check */
1127 if (!exp_verify_string(nxp->ex_path, NFS_MAXPATHLEN) ||
1128 !exp_verify_string(nxp->ex_client, NFSCLNT_IDMAX))
1129 return -EINVAL;
1130
1131 exp_writelock();
1132
1133 err = -EINVAL;
1134 dom = auth_domain_find(nxp->ex_client);
1135 if (!dom) {
1136 dprintk("nfsd: unexport couldn't find %s\n", nxp->ex_client);
1137 goto out_unlock;
1138 }
1139
1140 err = kern_path(nxp->ex_path, 0, &path);
1141 if (err)
1142 goto out_domain;
1143
1144 err = -EINVAL;
1145 exp = exp_get_by_name(dom, &path, NULL);
1146 path_put(&path);
1147 if (IS_ERR(exp))
1148 goto out_domain;
1149
1150 exp_do_unexport(exp);
1151 exp_put(exp);
1152 err = 0;
1153
1154out_domain:
1155 auth_domain_put(dom);
1156 cache_flush();
1157out_unlock:
1158 exp_writeunlock();
1159 return err;
1160}
1161#endif /* CONFIG_NFSD_DEPRECATED */
1162 842
1163/* 843/*
1164 * Obtain the root fh on behalf of a client. 844 * Obtain the root fh on behalf of a client.
@@ -1367,7 +1047,6 @@ static void *e_start(struct seq_file *m, loff_t *pos)
1367 unsigned hash, export; 1047 unsigned hash, export;
1368 struct cache_head *ch; 1048 struct cache_head *ch;
1369 1049
1370 exp_readlock();
1371 read_lock(&svc_export_cache.hash_lock); 1050 read_lock(&svc_export_cache.hash_lock);
1372 if (!n--) 1051 if (!n--)
1373 return SEQ_START_TOKEN; 1052 return SEQ_START_TOKEN;
@@ -1418,7 +1097,6 @@ static void e_stop(struct seq_file *m, void *p)
1418 __releases(svc_export_cache.hash_lock) 1097 __releases(svc_export_cache.hash_lock)
1419{ 1098{
1420 read_unlock(&svc_export_cache.hash_lock); 1099 read_unlock(&svc_export_cache.hash_lock);
1421 exp_readunlock();
1422} 1100}
1423 1101
1424static struct flags { 1102static struct flags {
@@ -1550,97 +1228,6 @@ const struct seq_operations nfs_exports_op = {
1550 .show = e_show, 1228 .show = e_show,
1551}; 1229};
1552 1230
1553#ifdef CONFIG_NFSD_DEPRECATED
1554/*
1555 * Add or modify a client.
1556 * Change requests may involve the list of host addresses. The list of
1557 * exports and possibly existing uid maps are left untouched.
1558 */
1559int
1560exp_addclient(struct nfsctl_client *ncp)
1561{
1562 struct auth_domain *dom;
1563 int i, err;
1564 struct in6_addr addr6;
1565
1566 /* First, consistency check. */
1567 err = -EINVAL;
1568 if (! exp_verify_string(ncp->cl_ident, NFSCLNT_IDMAX))
1569 goto out;
1570 if (ncp->cl_naddr > NFSCLNT_ADDRMAX)
1571 goto out;
1572
1573 /* Lock the hashtable */
1574 exp_writelock();
1575
1576 dom = unix_domain_find(ncp->cl_ident);
1577
1578 err = -ENOMEM;
1579 if (!dom)
1580 goto out_unlock;
1581
1582 /* Insert client into hashtable. */
1583 for (i = 0; i < ncp->cl_naddr; i++) {
1584 ipv6_addr_set_v4mapped(ncp->cl_addrlist[i].s_addr, &addr6);
1585 auth_unix_add_addr(&init_net, &addr6, dom);
1586 }
1587 auth_unix_forget_old(dom);
1588 auth_domain_put(dom);
1589
1590 err = 0;
1591
1592out_unlock:
1593 exp_writeunlock();
1594out:
1595 return err;
1596}
1597
1598/*
1599 * Delete a client given an identifier.
1600 */
1601int
1602exp_delclient(struct nfsctl_client *ncp)
1603{
1604 int err;
1605 struct auth_domain *dom;
1606
1607 err = -EINVAL;
1608 if (!exp_verify_string(ncp->cl_ident, NFSCLNT_IDMAX))
1609 goto out;
1610
1611 /* Lock the hashtable */
1612 exp_writelock();
1613
1614 dom = auth_domain_find(ncp->cl_ident);
1615 /* just make sure that no addresses work
1616 * and that it will expire soon
1617 */
1618 if (dom) {
1619 err = auth_unix_forget_old(dom);
1620 auth_domain_put(dom);
1621 }
1622
1623 exp_writeunlock();
1624out:
1625 return err;
1626}
1627
1628/*
1629 * Verify that string is non-empty and does not exceed max length.
1630 */
1631static int
1632exp_verify_string(char *cp, int max)
1633{
1634 int i;
1635
1636 for (i = 0; i < max; i++)
1637 if (!cp[i])
1638 return i;
1639 cp[i] = 0;
1640 printk(KERN_NOTICE "nfsd: couldn't validate string %s\n", cp);
1641 return 0;
1642}
1643#endif /* CONFIG_NFSD_DEPRECATED */
1644 1231
1645/* 1232/*
1646 * Initialize the exports module. 1233 * Initialize the exports module.
@@ -1667,10 +1254,8 @@ nfsd_export_init(void)
1667void 1254void
1668nfsd_export_flush(void) 1255nfsd_export_flush(void)
1669{ 1256{
1670 exp_writelock();
1671 cache_purge(&svc_expkey_cache); 1257 cache_purge(&svc_expkey_cache);
1672 cache_purge(&svc_export_cache); 1258 cache_purge(&svc_export_cache);
1673 exp_writeunlock();
1674} 1259}
1675 1260
1676/* 1261/*
@@ -1682,12 +1267,9 @@ nfsd_export_shutdown(void)
1682 1267
1683 dprintk("nfsd: shutting down export module.\n"); 1268 dprintk("nfsd: shutting down export module.\n");
1684 1269
1685 exp_writelock();
1686
1687 cache_unregister(&svc_expkey_cache); 1270 cache_unregister(&svc_expkey_cache);
1688 cache_unregister(&svc_export_cache); 1271 cache_unregister(&svc_export_cache);
1689 svcauth_unix_purge(); 1272 svcauth_unix_purge();
1690 1273
1691 exp_writeunlock();
1692 dprintk("nfsd: export shutdown complete.\n"); 1274 dprintk("nfsd: export shutdown complete.\n");
1693} 1275}