diff options
Diffstat (limited to 'fs/afs/cell.c')
-rw-r--r-- | fs/afs/cell.c | 98 |
1 files changed, 77 insertions, 21 deletions
diff --git a/fs/afs/cell.c b/fs/afs/cell.c index 733c60246ab0..9b1311a1df51 100644 --- a/fs/afs/cell.c +++ b/fs/afs/cell.c | |||
@@ -11,6 +11,9 @@ | |||
11 | 11 | ||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | #include <linux/key.h> | ||
15 | #include <linux/ctype.h> | ||
16 | #include <keys/rxrpc-type.h> | ||
14 | #include "internal.h" | 17 | #include "internal.h" |
15 | 18 | ||
16 | DECLARE_RWSEM(afs_proc_cells_sem); | 19 | DECLARE_RWSEM(afs_proc_cells_sem); |
@@ -23,45 +26,43 @@ static DECLARE_WAIT_QUEUE_HEAD(afs_cells_freeable_wq); | |||
23 | static struct afs_cell *afs_cell_root; | 26 | static struct afs_cell *afs_cell_root; |
24 | 27 | ||
25 | /* | 28 | /* |
26 | * create a cell record | 29 | * allocate a cell record and fill in its name, VL server address list and |
27 | * - "name" is the name of the cell | 30 | * allocate an anonymous key |
28 | * - "vllist" is a colon separated list of IP addresses in "a.b.c.d" format | ||
29 | */ | 31 | */ |
30 | struct afs_cell *afs_cell_create(const char *name, char *vllist) | 32 | static struct afs_cell *afs_cell_alloc(const char *name, char *vllist) |
31 | { | 33 | { |
32 | struct afs_cell *cell; | 34 | struct afs_cell *cell; |
33 | char *next; | 35 | size_t namelen; |
36 | char keyname[4 + AFS_MAXCELLNAME + 1], *cp, *dp, *next; | ||
34 | int ret; | 37 | int ret; |
35 | 38 | ||
36 | _enter("%s,%s", name, vllist); | 39 | _enter("%s,%s", name, vllist); |
37 | 40 | ||
38 | BUG_ON(!name); /* TODO: want to look up "this cell" in the cache */ | 41 | BUG_ON(!name); /* TODO: want to look up "this cell" in the cache */ |
39 | 42 | ||
43 | namelen = strlen(name); | ||
44 | if (namelen > AFS_MAXCELLNAME) | ||
45 | return ERR_PTR(-ENAMETOOLONG); | ||
46 | |||
40 | /* allocate and initialise a cell record */ | 47 | /* allocate and initialise a cell record */ |
41 | cell = kmalloc(sizeof(struct afs_cell) + strlen(name) + 1, GFP_KERNEL); | 48 | cell = kzalloc(sizeof(struct afs_cell) + namelen + 1, GFP_KERNEL); |
42 | if (!cell) { | 49 | if (!cell) { |
43 | _leave(" = -ENOMEM"); | 50 | _leave(" = -ENOMEM"); |
44 | return ERR_PTR(-ENOMEM); | 51 | return ERR_PTR(-ENOMEM); |
45 | } | 52 | } |
46 | 53 | ||
47 | down_write(&afs_cells_sem); | 54 | memcpy(cell->name, name, namelen); |
55 | cell->name[namelen] = 0; | ||
48 | 56 | ||
49 | memset(cell, 0, sizeof(struct afs_cell)); | ||
50 | atomic_set(&cell->usage, 1); | 57 | atomic_set(&cell->usage, 1); |
51 | |||
52 | INIT_LIST_HEAD(&cell->link); | 58 | INIT_LIST_HEAD(&cell->link); |
53 | |||
54 | rwlock_init(&cell->servers_lock); | 59 | rwlock_init(&cell->servers_lock); |
55 | INIT_LIST_HEAD(&cell->servers); | 60 | INIT_LIST_HEAD(&cell->servers); |
56 | |||
57 | init_rwsem(&cell->vl_sem); | 61 | init_rwsem(&cell->vl_sem); |
58 | INIT_LIST_HEAD(&cell->vl_list); | 62 | INIT_LIST_HEAD(&cell->vl_list); |
59 | spin_lock_init(&cell->vl_lock); | 63 | spin_lock_init(&cell->vl_lock); |
60 | 64 | ||
61 | strcpy(cell->name, name); | ||
62 | |||
63 | /* fill in the VL server list from the rest of the string */ | 65 | /* fill in the VL server list from the rest of the string */ |
64 | ret = -EINVAL; | ||
65 | do { | 66 | do { |
66 | unsigned a, b, c, d; | 67 | unsigned a, b, c, d; |
67 | 68 | ||
@@ -70,18 +71,73 @@ struct afs_cell *afs_cell_create(const char *name, char *vllist) | |||
70 | *next++ = 0; | 71 | *next++ = 0; |
71 | 72 | ||
72 | if (sscanf(vllist, "%u.%u.%u.%u", &a, &b, &c, &d) != 4) | 73 | if (sscanf(vllist, "%u.%u.%u.%u", &a, &b, &c, &d) != 4) |
73 | goto badaddr; | 74 | goto bad_address; |
74 | 75 | ||
75 | if (a > 255 || b > 255 || c > 255 || d > 255) | 76 | if (a > 255 || b > 255 || c > 255 || d > 255) |
76 | goto badaddr; | 77 | goto bad_address; |
77 | 78 | ||
78 | cell->vl_addrs[cell->vl_naddrs++].s_addr = | 79 | cell->vl_addrs[cell->vl_naddrs++].s_addr = |
79 | htonl((a << 24) | (b << 16) | (c << 8) | d); | 80 | htonl((a << 24) | (b << 16) | (c << 8) | d); |
80 | 81 | ||
81 | if (cell->vl_naddrs >= AFS_CELL_MAX_ADDRS) | 82 | } while (cell->vl_naddrs < AFS_CELL_MAX_ADDRS && (vllist = next)); |
82 | break; | 83 | |
84 | /* create a key to represent an anonymous user */ | ||
85 | memcpy(keyname, "afs@", 4); | ||
86 | dp = keyname + 4; | ||
87 | cp = cell->name; | ||
88 | do { | ||
89 | *dp++ = toupper(*cp); | ||
90 | } while (*cp++); | ||
91 | cell->anonymous_key = key_alloc(&key_type_rxrpc, keyname, 0, 0, current, | ||
92 | KEY_POS_SEARCH, KEY_ALLOC_NOT_IN_QUOTA); | ||
93 | if (IS_ERR(cell->anonymous_key)) { | ||
94 | _debug("no key"); | ||
95 | ret = PTR_ERR(cell->anonymous_key); | ||
96 | goto error; | ||
97 | } | ||
98 | |||
99 | ret = key_instantiate_and_link(cell->anonymous_key, NULL, 0, | ||
100 | NULL, NULL); | ||
101 | if (ret < 0) { | ||
102 | _debug("instantiate failed"); | ||
103 | goto error; | ||
104 | } | ||
105 | |||
106 | _debug("anon key %p{%x}", | ||
107 | cell->anonymous_key, key_serial(cell->anonymous_key)); | ||
108 | |||
109 | _leave(" = %p", cell); | ||
110 | return cell; | ||
111 | |||
112 | bad_address: | ||
113 | printk(KERN_ERR "kAFS: bad VL server IP address\n"); | ||
114 | ret = -EINVAL; | ||
115 | error: | ||
116 | key_put(cell->anonymous_key); | ||
117 | kfree(cell); | ||
118 | _leave(" = %d", ret); | ||
119 | return ERR_PTR(ret); | ||
120 | } | ||
83 | 121 | ||
84 | } while ((vllist = next)); | 122 | /* |
123 | * create a cell record | ||
124 | * - "name" is the name of the cell | ||
125 | * - "vllist" is a colon separated list of IP addresses in "a.b.c.d" format | ||
126 | */ | ||
127 | struct afs_cell *afs_cell_create(const char *name, char *vllist) | ||
128 | { | ||
129 | struct afs_cell *cell; | ||
130 | int ret; | ||
131 | |||
132 | _enter("%s,%s", name, vllist); | ||
133 | |||
134 | cell = afs_cell_alloc(name, vllist); | ||
135 | if (IS_ERR(cell)) { | ||
136 | _leave(" = %ld", PTR_ERR(cell)); | ||
137 | return cell; | ||
138 | } | ||
139 | |||
140 | down_write(&afs_cells_sem); | ||
85 | 141 | ||
86 | /* add a proc directory for this cell */ | 142 | /* add a proc directory for this cell */ |
87 | ret = afs_proc_cell_setup(cell); | 143 | ret = afs_proc_cell_setup(cell); |
@@ -109,10 +165,9 @@ struct afs_cell *afs_cell_create(const char *name, char *vllist) | |||
109 | _leave(" = %p", cell); | 165 | _leave(" = %p", cell); |
110 | return cell; | 166 | return cell; |
111 | 167 | ||
112 | badaddr: | ||
113 | printk(KERN_ERR "kAFS: bad VL server IP address\n"); | ||
114 | error: | 168 | error: |
115 | up_write(&afs_cells_sem); | 169 | up_write(&afs_cells_sem); |
170 | key_put(cell->anonymous_key); | ||
116 | kfree(cell); | 171 | kfree(cell); |
117 | _leave(" = %d", ret); | 172 | _leave(" = %d", ret); |
118 | return ERR_PTR(ret); | 173 | return ERR_PTR(ret); |
@@ -301,6 +356,7 @@ static void afs_cell_destroy(struct afs_cell *cell) | |||
301 | cachefs_relinquish_cookie(cell->cache, 0); | 356 | cachefs_relinquish_cookie(cell->cache, 0); |
302 | #endif | 357 | #endif |
303 | 358 | ||
359 | key_put(cell->anonymous_key); | ||
304 | kfree(cell); | 360 | kfree(cell); |
305 | 361 | ||
306 | _leave(" [destroyed]"); | 362 | _leave(" [destroyed]"); |