aboutsummaryrefslogtreecommitdiffstats
path: root/fs/afs/cell.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/afs/cell.c')
-rw-r--r--fs/afs/cell.c98
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
16DECLARE_RWSEM(afs_proc_cells_sem); 19DECLARE_RWSEM(afs_proc_cells_sem);
@@ -23,45 +26,43 @@ static DECLARE_WAIT_QUEUE_HEAD(afs_cells_freeable_wq);
23static struct afs_cell *afs_cell_root; 26static 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 */
30struct afs_cell *afs_cell_create(const char *name, char *vllist) 32static 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
112bad_address:
113 printk(KERN_ERR "kAFS: bad VL server IP address\n");
114 ret = -EINVAL;
115error:
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 */
127struct 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
112badaddr:
113 printk(KERN_ERR "kAFS: bad VL server IP address\n");
114error: 168error:
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]");