aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/afs/Makefile1
-rw-r--r--fs/afs/afs.h27
-rw-r--r--fs/afs/callback.c5
-rw-r--r--fs/afs/cell.c98
-rw-r--r--fs/afs/cmservice.c3
-rw-r--r--fs/afs/dir.c51
-rw-r--r--fs/afs/file.c60
-rw-r--r--fs/afs/fsclient.c9
-rw-r--r--fs/afs/inode.c21
-rw-r--r--fs/afs/internal.h106
-rw-r--r--fs/afs/mntpt.c12
-rw-r--r--fs/afs/rxrpc.c137
-rw-r--r--fs/afs/security.c345
-rw-r--r--fs/afs/super.c142
-rw-r--r--fs/afs/vlclient.c6
-rw-r--r--fs/afs/vlocation.c26
-rw-r--r--fs/afs/vnode.c25
-rw-r--r--fs/afs/volume.c109
18 files changed, 945 insertions, 238 deletions
diff --git a/fs/afs/Makefile b/fs/afs/Makefile
index 66bdc219ccde..cca198b2caed 100644
--- a/fs/afs/Makefile
+++ b/fs/afs/Makefile
@@ -15,6 +15,7 @@ kafs-objs := \
15 mntpt.o \ 15 mntpt.o \
16 proc.o \ 16 proc.o \
17 rxrpc.o \ 17 rxrpc.o \
18 security.o \
18 server.o \ 19 server.o \
19 super.o \ 20 super.o \
20 vlclient.o \ 21 vlclient.o \
diff --git a/fs/afs/afs.h b/fs/afs/afs.h
index b9d2d2ceaf43..d959092aaf4b 100644
--- a/fs/afs/afs.h
+++ b/fs/afs/afs.h
@@ -14,6 +14,9 @@
14 14
15#include <linux/in.h> 15#include <linux/in.h>
16 16
17#define AFS_MAXCELLNAME 64 /* maximum length of a cell name */
18#define AFS_MAXVOLNAME 64 /* maximum length of a volume name */
19
17typedef unsigned afs_volid_t; 20typedef unsigned afs_volid_t;
18typedef unsigned afs_vnodeid_t; 21typedef unsigned afs_vnodeid_t;
19typedef unsigned long long afs_dataversion_t; 22typedef unsigned long long afs_dataversion_t;
@@ -75,6 +78,26 @@ struct afs_volume_info {
75}; 78};
76 79
77/* 80/*
81 * AFS security ACE access mask
82 */
83typedef u32 afs_access_t;
84#define AFS_ACE_READ 0x00000001U /* - permission to read a file/dir */
85#define AFS_ACE_WRITE 0x00000002U /* - permission to write/chmod a file */
86#define AFS_ACE_INSERT 0x00000004U /* - permission to create dirent in a dir */
87#define AFS_ACE_LOOKUP 0x00000008U /* - permission to lookup a file/dir in a dir */
88#define AFS_ACE_DELETE 0x00000010U /* - permission to delete a dirent from a dir */
89#define AFS_ACE_LOCK 0x00000020U /* - permission to lock a file */
90#define AFS_ACE_ADMINISTER 0x00000040U /* - permission to change ACL */
91#define AFS_ACE_USER_A 0x01000000U /* - 'A' user-defined permission */
92#define AFS_ACE_USER_B 0x02000000U /* - 'B' user-defined permission */
93#define AFS_ACE_USER_C 0x04000000U /* - 'C' user-defined permission */
94#define AFS_ACE_USER_D 0x08000000U /* - 'D' user-defined permission */
95#define AFS_ACE_USER_E 0x10000000U /* - 'E' user-defined permission */
96#define AFS_ACE_USER_F 0x20000000U /* - 'F' user-defined permission */
97#define AFS_ACE_USER_G 0x40000000U /* - 'G' user-defined permission */
98#define AFS_ACE_USER_H 0x80000000U /* - 'H' user-defined permission */
99
100/*
78 * AFS file status information 101 * AFS file status information
79 */ 102 */
80struct afs_file_status { 103struct afs_file_status {
@@ -87,8 +110,8 @@ struct afs_file_status {
87 afs_dataversion_t data_version; /* current data version */ 110 afs_dataversion_t data_version; /* current data version */
88 unsigned author; /* author ID */ 111 unsigned author; /* author ID */
89 unsigned owner; /* owner ID */ 112 unsigned owner; /* owner ID */
90 unsigned caller_access; /* access rights for authenticated caller */ 113 afs_access_t caller_access; /* access rights for authenticated caller */
91 unsigned anon_access; /* access rights for unauthenticated caller */ 114 afs_access_t anon_access; /* access rights for unauthenticated caller */
92 umode_t mode; /* UNIX mode */ 115 umode_t mode; /* UNIX mode */
93 struct afs_fid parent; /* parent file ID */ 116 struct afs_fid parent; /* parent file ID */
94 time_t mtime_client; /* last time client changed data */ 117 time_t mtime_client; /* last time client changed data */
diff --git a/fs/afs/callback.c b/fs/afs/callback.c
index 611215547142..e674bebbb8b1 100644
--- a/fs/afs/callback.c
+++ b/fs/afs/callback.c
@@ -72,7 +72,10 @@ void afs_broken_callback_work(struct work_struct *work)
72 return; /* someone else is dealing with it */ 72 return; /* someone else is dealing with it */
73 73
74 if (test_bit(AFS_VNODE_CB_BROKEN, &vnode->flags)) { 74 if (test_bit(AFS_VNODE_CB_BROKEN, &vnode->flags)) {
75 if (afs_vnode_fetch_status(vnode) < 0) 75 if (S_ISDIR(vnode->vfs_inode.i_mode))
76 afs_clear_permits(vnode);
77
78 if (afs_vnode_fetch_status(vnode, NULL, NULL) < 0)
76 goto out; 79 goto out;
77 80
78 if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) 81 if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
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]");
diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c
index c7141175391b..c3ec57a237bf 100644
--- a/fs/afs/cmservice.c
+++ b/fs/afs/cmservice.c
@@ -28,6 +28,7 @@ static void afs_cm_destructor(struct afs_call *);
28 * CB.CallBack operation type 28 * CB.CallBack operation type
29 */ 29 */
30static const struct afs_call_type afs_SRXCBCallBack = { 30static const struct afs_call_type afs_SRXCBCallBack = {
31 .name = "CB.CallBack",
31 .deliver = afs_deliver_cb_callback, 32 .deliver = afs_deliver_cb_callback,
32 .abort_to_error = afs_abort_to_error, 33 .abort_to_error = afs_abort_to_error,
33 .destructor = afs_cm_destructor, 34 .destructor = afs_cm_destructor,
@@ -37,6 +38,7 @@ static const struct afs_call_type afs_SRXCBCallBack = {
37 * CB.InitCallBackState operation type 38 * CB.InitCallBackState operation type
38 */ 39 */
39static const struct afs_call_type afs_SRXCBInitCallBackState = { 40static const struct afs_call_type afs_SRXCBInitCallBackState = {
41 .name = "CB.InitCallBackState",
40 .deliver = afs_deliver_cb_init_call_back_state, 42 .deliver = afs_deliver_cb_init_call_back_state,
41 .abort_to_error = afs_abort_to_error, 43 .abort_to_error = afs_abort_to_error,
42 .destructor = afs_cm_destructor, 44 .destructor = afs_cm_destructor,
@@ -46,6 +48,7 @@ static const struct afs_call_type afs_SRXCBInitCallBackState = {
46 * CB.Probe operation type 48 * CB.Probe operation type
47 */ 49 */
48static const struct afs_call_type afs_SRXCBProbe = { 50static const struct afs_call_type afs_SRXCBProbe = {
51 .name = "CB.Probe",
49 .deliver = afs_deliver_cb_probe, 52 .deliver = afs_deliver_cb_probe,
50 .abort_to_error = afs_abort_to_error, 53 .abort_to_error = afs_abort_to_error,
51 .destructor = afs_cm_destructor, 54 .destructor = afs_cm_destructor,
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index d7697f6f3b7f..87368417e4d3 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -15,6 +15,7 @@
15#include <linux/slab.h> 15#include <linux/slab.h>
16#include <linux/fs.h> 16#include <linux/fs.h>
17#include <linux/pagemap.h> 17#include <linux/pagemap.h>
18#include <linux/ctype.h>
18#include "internal.h" 19#include "internal.h"
19 20
20static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry, 21static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry,
@@ -28,11 +29,13 @@ static int afs_dir_lookup_filldir(void *_cookie, const char *name, int nlen,
28 29
29const struct file_operations afs_dir_file_operations = { 30const struct file_operations afs_dir_file_operations = {
30 .open = afs_dir_open, 31 .open = afs_dir_open,
32 .release = afs_release,
31 .readdir = afs_dir_readdir, 33 .readdir = afs_dir_readdir,
32}; 34};
33 35
34const struct inode_operations afs_dir_inode_operations = { 36const struct inode_operations afs_dir_inode_operations = {
35 .lookup = afs_dir_lookup, 37 .lookup = afs_dir_lookup,
38 .permission = afs_permission,
36 .getattr = afs_inode_getattr, 39 .getattr = afs_inode_getattr,
37#if 0 /* TODO */ 40#if 0 /* TODO */
38 .create = afs_dir_create, 41 .create = afs_dir_create,
@@ -169,13 +172,17 @@ static inline void afs_dir_put_page(struct page *page)
169/* 172/*
170 * get a page into the pagecache 173 * get a page into the pagecache
171 */ 174 */
172static struct page *afs_dir_get_page(struct inode *dir, unsigned long index) 175static struct page *afs_dir_get_page(struct inode *dir, unsigned long index,
176 struct key *key)
173{ 177{
174 struct page *page; 178 struct page *page;
179 struct file file = {
180 .private_data = key,
181 };
175 182
176 _enter("{%lu},%lu", dir->i_ino, index); 183 _enter("{%lu},%lu", dir->i_ino, index);
177 184
178 page = read_mapping_page(dir->i_mapping, index, NULL); 185 page = read_mapping_page(dir->i_mapping, index, &file);
179 if (!IS_ERR(page)) { 186 if (!IS_ERR(page)) {
180 wait_on_page_locked(page); 187 wait_on_page_locked(page);
181 kmap(page); 188 kmap(page);
@@ -207,8 +214,7 @@ static int afs_dir_open(struct inode *inode, struct file *file)
207 if (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(inode)->flags)) 214 if (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(inode)->flags))
208 return -ENOENT; 215 return -ENOENT;
209 216
210 _leave(" = 0"); 217 return afs_open(inode, file);
211 return 0;
212} 218}
213 219
214/* 220/*
@@ -311,7 +317,7 @@ static int afs_dir_iterate_block(unsigned *fpos,
311 * iterate through the data blob that lists the contents of an AFS directory 317 * iterate through the data blob that lists the contents of an AFS directory
312 */ 318 */
313static int afs_dir_iterate(struct inode *dir, unsigned *fpos, void *cookie, 319static int afs_dir_iterate(struct inode *dir, unsigned *fpos, void *cookie,
314 filldir_t filldir) 320 filldir_t filldir, struct key *key)
315{ 321{
316 union afs_dir_block *dblock; 322 union afs_dir_block *dblock;
317 struct afs_dir_page *dbuf; 323 struct afs_dir_page *dbuf;
@@ -336,7 +342,7 @@ static int afs_dir_iterate(struct inode *dir, unsigned *fpos, void *cookie,
336 blkoff = *fpos & ~(sizeof(union afs_dir_block) - 1); 342 blkoff = *fpos & ~(sizeof(union afs_dir_block) - 1);
337 343
338 /* fetch the appropriate page from the directory */ 344 /* fetch the appropriate page from the directory */
339 page = afs_dir_get_page(dir, blkoff / PAGE_SIZE); 345 page = afs_dir_get_page(dir, blkoff / PAGE_SIZE, key);
340 if (IS_ERR(page)) { 346 if (IS_ERR(page)) {
341 ret = PTR_ERR(page); 347 ret = PTR_ERR(page);
342 break; 348 break;
@@ -381,9 +387,11 @@ static int afs_dir_readdir(struct file *file, void *cookie, filldir_t filldir)
381 _enter("{%Ld,{%lu}}", 387 _enter("{%Ld,{%lu}}",
382 file->f_pos, file->f_path.dentry->d_inode->i_ino); 388 file->f_pos, file->f_path.dentry->d_inode->i_ino);
383 389
390 ASSERT(file->private_data != NULL);
391
384 fpos = file->f_pos; 392 fpos = file->f_pos;
385 ret = afs_dir_iterate(file->f_path.dentry->d_inode, &fpos, 393 ret = afs_dir_iterate(file->f_path.dentry->d_inode, &fpos,
386 cookie, filldir); 394 cookie, filldir, file->private_data);
387 file->f_pos = fpos; 395 file->f_pos = fpos;
388 396
389 _leave(" = %d", ret); 397 _leave(" = %d", ret);
@@ -424,7 +432,7 @@ static int afs_dir_lookup_filldir(void *_cookie, const char *name, int nlen,
424 * do a lookup in a directory 432 * do a lookup in a directory
425 */ 433 */
426static int afs_do_lookup(struct inode *dir, struct dentry *dentry, 434static int afs_do_lookup(struct inode *dir, struct dentry *dentry,
427 struct afs_fid *fid) 435 struct afs_fid *fid, struct key *key)
428{ 436{
429 struct afs_dir_lookup_cookie cookie; 437 struct afs_dir_lookup_cookie cookie;
430 struct afs_super_info *as; 438 struct afs_super_info *as;
@@ -442,7 +450,8 @@ static int afs_do_lookup(struct inode *dir, struct dentry *dentry,
442 cookie.found = 0; 450 cookie.found = 0;
443 451
444 fpos = 0; 452 fpos = 0;
445 ret = afs_dir_iterate(dir, &fpos, &cookie, afs_dir_lookup_filldir); 453 ret = afs_dir_iterate(dir, &fpos, &cookie, afs_dir_lookup_filldir,
454 key);
446 if (ret < 0) { 455 if (ret < 0) {
447 _leave(" = %d [iter]", ret); 456 _leave(" = %d [iter]", ret);
448 return ret; 457 return ret;
@@ -468,6 +477,7 @@ static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry,
468 struct afs_vnode *vnode; 477 struct afs_vnode *vnode;
469 struct afs_fid fid; 478 struct afs_fid fid;
470 struct inode *inode; 479 struct inode *inode;
480 struct key *key;
471 int ret; 481 int ret;
472 482
473 _enter("{%lu},%p{%s}", dir->i_ino, dentry, dentry->d_name.name); 483 _enter("{%lu},%p{%s}", dir->i_ino, dentry, dentry->d_name.name);
@@ -483,14 +493,22 @@ static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry,
483 return ERR_PTR(-ESTALE); 493 return ERR_PTR(-ESTALE);
484 } 494 }
485 495
486 ret = afs_do_lookup(dir, dentry, &fid); 496 key = afs_request_key(vnode->volume->cell);
497 if (IS_ERR(key)) {
498 _leave(" = %ld [key]", PTR_ERR(key));
499 return ERR_PTR(PTR_ERR(key));
500 }
501
502 ret = afs_do_lookup(dir, dentry, &fid, key);
487 if (ret < 0) { 503 if (ret < 0) {
504 key_put(key);
488 _leave(" = %d [do]", ret); 505 _leave(" = %d [do]", ret);
489 return ERR_PTR(ret); 506 return ERR_PTR(ret);
490 } 507 }
491 508
492 /* instantiate the dentry */ 509 /* instantiate the dentry */
493 inode = afs_iget(dir->i_sb, &fid); 510 inode = afs_iget(dir->i_sb, key, &fid);
511 key_put(key);
494 if (IS_ERR(inode)) { 512 if (IS_ERR(inode)) {
495 _leave(" = %ld", PTR_ERR(inode)); 513 _leave(" = %ld", PTR_ERR(inode));
496 return ERR_PTR(PTR_ERR(inode)); 514 return ERR_PTR(PTR_ERR(inode));
@@ -559,6 +577,7 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
559 struct afs_fid fid; 577 struct afs_fid fid;
560 struct dentry *parent; 578 struct dentry *parent;
561 struct inode *inode, *dir; 579 struct inode *inode, *dir;
580 struct key *key;
562 int ret; 581 int ret;
563 582
564 vnode = AFS_FS_I(dentry->d_inode); 583 vnode = AFS_FS_I(dentry->d_inode);
@@ -566,6 +585,10 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
566 _enter("{sb=%p n=%s fl=%lx},", 585 _enter("{sb=%p n=%s fl=%lx},",
567 dentry->d_sb, dentry->d_name.name, vnode->flags); 586 dentry->d_sb, dentry->d_name.name, vnode->flags);
568 587
588 key = afs_request_key(vnode->volume->cell);
589 if (IS_ERR(key))
590 key = NULL;
591
569 /* lock down the parent dentry so we can peer at it */ 592 /* lock down the parent dentry so we can peer at it */
570 parent = dget_parent(dentry); 593 parent = dget_parent(dentry);
571 594
@@ -595,7 +618,7 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
595 _debug("dir modified"); 618 _debug("dir modified");
596 619
597 /* search the directory for this vnode */ 620 /* search the directory for this vnode */
598 ret = afs_do_lookup(dir, dentry, &fid); 621 ret = afs_do_lookup(dir, dentry, &fid, key);
599 if (ret == -ENOENT) { 622 if (ret == -ENOENT) {
600 _debug("%s: dirent not found", dentry->d_name.name); 623 _debug("%s: dirent not found", dentry->d_name.name);
601 goto not_found; 624 goto not_found;
@@ -637,7 +660,7 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
637 test_bit(AFS_VNODE_CB_BROKEN, &vnode->flags)) { 660 test_bit(AFS_VNODE_CB_BROKEN, &vnode->flags)) {
638 _debug("%s: changed", dentry->d_name.name); 661 _debug("%s: changed", dentry->d_name.name);
639 set_bit(AFS_VNODE_CB_BROKEN, &vnode->flags); 662 set_bit(AFS_VNODE_CB_BROKEN, &vnode->flags);
640 if (afs_vnode_fetch_status(vnode) < 0) { 663 if (afs_vnode_fetch_status(vnode, NULL, key) < 0) {
641 mutex_unlock(&vnode->cb_broken_lock); 664 mutex_unlock(&vnode->cb_broken_lock);
642 goto out_bad; 665 goto out_bad;
643 } 666 }
@@ -667,6 +690,7 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
667 690
668out_valid: 691out_valid:
669 dput(parent); 692 dput(parent);
693 key_put(key);
670 _leave(" = 1 [valid]"); 694 _leave(" = 1 [valid]");
671 return 1; 695 return 1;
672 696
@@ -688,6 +712,7 @@ out_bad:
688 shrink_dcache_parent(dentry); 712 shrink_dcache_parent(dentry);
689 d_drop(dentry); 713 d_drop(dentry);
690 dput(parent); 714 dput(parent);
715 key_put(key);
691 716
692 _leave(" = 0 [bad]"); 717 _leave(" = 0 [bad]");
693 return 0; 718 return 0;
diff --git a/fs/afs/file.c b/fs/afs/file.c
index 6990327e75dd..101bbb8c0d8b 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -17,17 +17,23 @@
17#include <linux/pagemap.h> 17#include <linux/pagemap.h>
18#include "internal.h" 18#include "internal.h"
19 19
20#if 0
21static int afs_file_open(struct inode *inode, struct file *file);
22static int afs_file_release(struct inode *inode, struct file *file);
23#endif
24
25static int afs_file_readpage(struct file *file, struct page *page); 20static int afs_file_readpage(struct file *file, struct page *page);
26static void afs_file_invalidatepage(struct page *page, unsigned long offset); 21static void afs_file_invalidatepage(struct page *page, unsigned long offset);
27static int afs_file_releasepage(struct page *page, gfp_t gfp_flags); 22static int afs_file_releasepage(struct page *page, gfp_t gfp_flags);
28 23
24const struct file_operations afs_file_operations = {
25 .open = afs_open,
26 .release = afs_release,
27 .llseek = generic_file_llseek,
28 .read = do_sync_read,
29 .aio_read = generic_file_aio_read,
30 .mmap = generic_file_readonly_mmap,
31 .sendfile = generic_file_sendfile,
32};
33
29const struct inode_operations afs_file_inode_operations = { 34const struct inode_operations afs_file_inode_operations = {
30 .getattr = afs_inode_getattr, 35 .getattr = afs_inode_getattr,
36 .permission = afs_permission,
31}; 37};
32 38
33const struct address_space_operations afs_fs_aops = { 39const struct address_space_operations afs_fs_aops = {
@@ -38,6 +44,41 @@ const struct address_space_operations afs_fs_aops = {
38}; 44};
39 45
40/* 46/*
47 * open an AFS file or directory and attach a key to it
48 */
49int afs_open(struct inode *inode, struct file *file)
50{
51 struct afs_vnode *vnode = AFS_FS_I(inode);
52 struct key *key;
53
54 _enter("{%x:%x},", vnode->fid.vid, vnode->fid.vnode);
55
56 key = afs_request_key(vnode->volume->cell);
57 if (IS_ERR(key)) {
58 _leave(" = %ld [key]", PTR_ERR(key));
59 return PTR_ERR(key);
60 }
61
62 file->private_data = key;
63 _leave(" = 0");
64 return 0;
65}
66
67/*
68 * release an AFS file or directory and discard its key
69 */
70int afs_release(struct inode *inode, struct file *file)
71{
72 struct afs_vnode *vnode = AFS_FS_I(inode);
73
74 _enter("{%x:%x},", vnode->fid.vid, vnode->fid.vnode);
75
76 key_put(file->private_data);
77 _leave(" = 0");
78 return 0;
79}
80
81/*
41 * deal with notification that a page was read from the cache 82 * deal with notification that a page was read from the cache
42 */ 83 */
43#ifdef AFS_CACHING_SUPPORT 84#ifdef AFS_CACHING_SUPPORT
@@ -79,13 +120,18 @@ static int afs_file_readpage(struct file *file, struct page *page)
79{ 120{
80 struct afs_vnode *vnode; 121 struct afs_vnode *vnode;
81 struct inode *inode; 122 struct inode *inode;
123 struct key *key;
82 size_t len; 124 size_t len;
83 off_t offset; 125 off_t offset;
84 int ret; 126 int ret;
85 127
86 inode = page->mapping->host; 128 inode = page->mapping->host;
87 129
88 _enter("{%lu},{%lu}", inode->i_ino, page->index); 130 ASSERT(file != NULL);
131 key = file->private_data;
132 ASSERT(key != NULL);
133
134 _enter("{%x},{%lu},{%lu}", key_serial(key), inode->i_ino, page->index);
89 135
90 vnode = AFS_FS_I(inode); 136 vnode = AFS_FS_I(inode);
91 137
@@ -124,7 +170,7 @@ static int afs_file_readpage(struct file *file, struct page *page)
124 170
125 /* read the contents of the file from the server into the 171 /* read the contents of the file from the server into the
126 * page */ 172 * page */
127 ret = afs_vnode_fetch_data(vnode, offset, len, page); 173 ret = afs_vnode_fetch_data(vnode, key, offset, len, page);
128 if (ret < 0) { 174 if (ret < 0) {
129 if (ret == -ENOENT) { 175 if (ret == -ENOENT) {
130 _debug("got NOENT from server" 176 _debug("got NOENT from server"
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c
index 167ca615c2e6..321b489aa90f 100644
--- a/fs/afs/fsclient.c
+++ b/fs/afs/fsclient.c
@@ -148,6 +148,7 @@ static int afs_deliver_fs_fetch_status(struct afs_call *call,
148 * FS.FetchStatus operation type 148 * FS.FetchStatus operation type
149 */ 149 */
150static const struct afs_call_type afs_RXFSFetchStatus = { 150static const struct afs_call_type afs_RXFSFetchStatus = {
151 .name = "FS.FetchStatus",
151 .deliver = afs_deliver_fs_fetch_status, 152 .deliver = afs_deliver_fs_fetch_status,
152 .abort_to_error = afs_abort_to_error, 153 .abort_to_error = afs_abort_to_error,
153 .destructor = afs_flat_call_destructor, 154 .destructor = afs_flat_call_destructor,
@@ -157,6 +158,7 @@ static const struct afs_call_type afs_RXFSFetchStatus = {
157 * fetch the status information for a file 158 * fetch the status information for a file
158 */ 159 */
159int afs_fs_fetch_file_status(struct afs_server *server, 160int afs_fs_fetch_file_status(struct afs_server *server,
161 struct key *key,
160 struct afs_vnode *vnode, 162 struct afs_vnode *vnode,
161 struct afs_volsync *volsync, 163 struct afs_volsync *volsync,
162 const struct afs_wait_mode *wait_mode) 164 const struct afs_wait_mode *wait_mode)
@@ -164,12 +166,13 @@ int afs_fs_fetch_file_status(struct afs_server *server,
164 struct afs_call *call; 166 struct afs_call *call;
165 __be32 *bp; 167 __be32 *bp;
166 168
167 _enter(""); 169 _enter(",%x,,,", key_serial(key));
168 170
169 call = afs_alloc_flat_call(&afs_RXFSFetchStatus, 16, 120); 171 call = afs_alloc_flat_call(&afs_RXFSFetchStatus, 16, 120);
170 if (!call) 172 if (!call)
171 return -ENOMEM; 173 return -ENOMEM;
172 174
175 call->key = key;
173 call->reply = vnode; 176 call->reply = vnode;
174 call->reply2 = volsync; 177 call->reply2 = volsync;
175 call->service_id = FS_SERVICE; 178 call->service_id = FS_SERVICE;
@@ -279,6 +282,7 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call,
279 * FS.FetchData operation type 282 * FS.FetchData operation type
280 */ 283 */
281static const struct afs_call_type afs_RXFSFetchData = { 284static const struct afs_call_type afs_RXFSFetchData = {
285 .name = "FS.FetchData",
282 .deliver = afs_deliver_fs_fetch_data, 286 .deliver = afs_deliver_fs_fetch_data,
283 .abort_to_error = afs_abort_to_error, 287 .abort_to_error = afs_abort_to_error,
284 .destructor = afs_flat_call_destructor, 288 .destructor = afs_flat_call_destructor,
@@ -288,6 +292,7 @@ static const struct afs_call_type afs_RXFSFetchData = {
288 * fetch data from a file 292 * fetch data from a file
289 */ 293 */
290int afs_fs_fetch_data(struct afs_server *server, 294int afs_fs_fetch_data(struct afs_server *server,
295 struct key *key,
291 struct afs_vnode *vnode, 296 struct afs_vnode *vnode,
292 off_t offset, size_t length, 297 off_t offset, size_t length,
293 struct page *buffer, 298 struct page *buffer,
@@ -303,6 +308,7 @@ int afs_fs_fetch_data(struct afs_server *server,
303 if (!call) 308 if (!call)
304 return -ENOMEM; 309 return -ENOMEM;
305 310
311 call->key = key;
306 call->reply = vnode; 312 call->reply = vnode;
307 call->reply2 = volsync; 313 call->reply2 = volsync;
308 call->reply3 = buffer; 314 call->reply3 = buffer;
@@ -338,6 +344,7 @@ static int afs_deliver_fs_give_up_callbacks(struct afs_call *call,
338 * FS.GiveUpCallBacks operation type 344 * FS.GiveUpCallBacks operation type
339 */ 345 */
340static const struct afs_call_type afs_RXFSGiveUpCallBacks = { 346static const struct afs_call_type afs_RXFSGiveUpCallBacks = {
347 .name = "FS.GiveUpCallBacks",
341 .deliver = afs_deliver_fs_give_up_callbacks, 348 .deliver = afs_deliver_fs_give_up_callbacks,
342 .abort_to_error = afs_abort_to_error, 349 .abort_to_error = afs_abort_to_error,
343 .destructor = afs_flat_call_destructor, 350 .destructor = afs_flat_call_destructor,
diff --git a/fs/afs/inode.c b/fs/afs/inode.c
index 18863315211f..227336228299 100644
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -29,7 +29,7 @@ struct afs_iget_data {
29/* 29/*
30 * map the AFS file status to the inode member variables 30 * map the AFS file status to the inode member variables
31 */ 31 */
32static int afs_inode_map_status(struct afs_vnode *vnode) 32static int afs_inode_map_status(struct afs_vnode *vnode, struct key *key)
33{ 33{
34 struct inode *inode = AFS_VNODE_TO_I(vnode); 34 struct inode *inode = AFS_VNODE_TO_I(vnode);
35 35
@@ -44,7 +44,7 @@ static int afs_inode_map_status(struct afs_vnode *vnode)
44 case AFS_FTYPE_FILE: 44 case AFS_FTYPE_FILE:
45 inode->i_mode = S_IFREG | vnode->status.mode; 45 inode->i_mode = S_IFREG | vnode->status.mode;
46 inode->i_op = &afs_file_inode_operations; 46 inode->i_op = &afs_file_inode_operations;
47 inode->i_fop = &generic_ro_fops; 47 inode->i_fop = &afs_file_operations;
48 break; 48 break;
49 case AFS_FTYPE_DIR: 49 case AFS_FTYPE_DIR:
50 inode->i_mode = S_IFDIR | vnode->status.mode; 50 inode->i_mode = S_IFDIR | vnode->status.mode;
@@ -73,7 +73,7 @@ static int afs_inode_map_status(struct afs_vnode *vnode)
73 73
74 /* check to see whether a symbolic link is really a mountpoint */ 74 /* check to see whether a symbolic link is really a mountpoint */
75 if (vnode->status.type == AFS_FTYPE_SYMLINK) { 75 if (vnode->status.type == AFS_FTYPE_SYMLINK) {
76 afs_mntpt_check_symlink(vnode); 76 afs_mntpt_check_symlink(vnode, key);
77 77
78 if (test_bit(AFS_VNODE_MOUNTPOINT, &vnode->flags)) { 78 if (test_bit(AFS_VNODE_MOUNTPOINT, &vnode->flags)) {
79 inode->i_mode = S_IFDIR | vnode->status.mode; 79 inode->i_mode = S_IFDIR | vnode->status.mode;
@@ -115,7 +115,8 @@ static int afs_iget5_set(struct inode *inode, void *opaque)
115/* 115/*
116 * inode retrieval 116 * inode retrieval
117 */ 117 */
118inline struct inode *afs_iget(struct super_block *sb, struct afs_fid *fid) 118inline struct inode *afs_iget(struct super_block *sb, struct key *key,
119 struct afs_fid *fid)
119{ 120{
120 struct afs_iget_data data = { .fid = *fid }; 121 struct afs_iget_data data = { .fid = *fid };
121 struct afs_super_info *as; 122 struct afs_super_info *as;
@@ -157,10 +158,10 @@ inline struct inode *afs_iget(struct super_block *sb, struct afs_fid *fid)
157 158
158 /* okay... it's a new inode */ 159 /* okay... it's a new inode */
159 set_bit(AFS_VNODE_CB_BROKEN, &vnode->flags); 160 set_bit(AFS_VNODE_CB_BROKEN, &vnode->flags);
160 ret = afs_vnode_fetch_status(vnode); 161 ret = afs_vnode_fetch_status(vnode, NULL, key);
161 if (ret < 0) 162 if (ret < 0)
162 goto bad_inode; 163 goto bad_inode;
163 ret = afs_inode_map_status(vnode); 164 ret = afs_inode_map_status(vnode, key);
164 if (ret < 0) 165 if (ret < 0)
165 goto bad_inode; 166 goto bad_inode;
166 167
@@ -201,6 +202,7 @@ int afs_inode_getattr(struct vfsmount *mnt, struct dentry *dentry,
201 */ 202 */
202void afs_clear_inode(struct inode *inode) 203void afs_clear_inode(struct inode *inode)
203{ 204{
205 struct afs_permits *permits;
204 struct afs_vnode *vnode; 206 struct afs_vnode *vnode;
205 207
206 vnode = AFS_FS_I(inode); 208 vnode = AFS_FS_I(inode);
@@ -233,5 +235,12 @@ void afs_clear_inode(struct inode *inode)
233 vnode->cache = NULL; 235 vnode->cache = NULL;
234#endif 236#endif
235 237
238 mutex_lock(&vnode->permits_lock);
239 permits = vnode->permits;
240 rcu_assign_pointer(vnode->permits, NULL);
241 mutex_unlock(&vnode->permits_lock);
242 if (permits)
243 call_rcu(&permits->rcu, afs_zap_permits);
244
236 _leave(""); 245 _leave("");
237} 246}
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index afc6f0f30259..8bed2429d01f 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -15,6 +15,7 @@
15#include <linux/pagemap.h> 15#include <linux/pagemap.h>
16#include <linux/skbuff.h> 16#include <linux/skbuff.h>
17#include <linux/rxrpc.h> 17#include <linux/rxrpc.h>
18#include <linux/key.h>
18#include "afs.h" 19#include "afs.h"
19#include "afs_vl.h" 20#include "afs_vl.h"
20 21
@@ -32,6 +33,17 @@ typedef enum {
32 AFS_VL_UNCERTAIN, /* uncertain state (update failed) */ 33 AFS_VL_UNCERTAIN, /* uncertain state (update failed) */
33} __attribute__((packed)) afs_vlocation_state_t; 34} __attribute__((packed)) afs_vlocation_state_t;
34 35
36struct afs_mount_params {
37 bool rwpath; /* T if the parent should be considered R/W */
38 bool force; /* T to force cell type */
39 afs_voltype_t type; /* type of volume requested */
40 int volnamesz; /* size of volume name */
41 const char *volname; /* name of volume to mount */
42 struct afs_cell *cell; /* cell in which to find volume */
43 struct afs_volume *volume; /* volume record */
44 struct key *key; /* key to use for secure mounting */
45};
46
35/* 47/*
36 * definition of how to wait for the completion of an operation 48 * definition of how to wait for the completion of an operation
37 */ 49 */
@@ -95,6 +107,8 @@ struct afs_call {
95}; 107};
96 108
97struct afs_call_type { 109struct afs_call_type {
110 const char *name;
111
98 /* deliver request or reply data to an call 112 /* deliver request or reply data to an call
99 * - returning an error will cause the call to be aborted 113 * - returning an error will cause the call to be aborted
100 */ 114 */
@@ -128,8 +142,8 @@ extern struct file_system_type afs_fs_type;
128 * entry in the cached cell catalogue 142 * entry in the cached cell catalogue
129 */ 143 */
130struct afs_cache_cell { 144struct afs_cache_cell {
131 char name[64]; /* cell name (padded with NULs) */ 145 char name[AFS_MAXCELLNAME]; /* cell name (padded with NULs) */
132 struct in_addr vl_servers[15]; /* cached cell VL servers */ 146 struct in_addr vl_servers[15]; /* cached cell VL servers */
133}; 147};
134 148
135/* 149/*
@@ -138,6 +152,7 @@ struct afs_cache_cell {
138struct afs_cell { 152struct afs_cell {
139 atomic_t usage; 153 atomic_t usage;
140 struct list_head link; /* main cell list link */ 154 struct list_head link; /* main cell list link */
155 struct key *anonymous_key; /* anonymous user key for this cell */
141 struct list_head proc_link; /* /proc cell list link */ 156 struct list_head proc_link; /* /proc cell list link */
142 struct proc_dir_entry *proc_dir; /* /proc dir for this cell */ 157 struct proc_dir_entry *proc_dir; /* /proc dir for this cell */
143#ifdef AFS_CACHING_SUPPORT 158#ifdef AFS_CACHING_SUPPORT
@@ -163,7 +178,9 @@ struct afs_cell {
163 * entry in the cached volume location catalogue 178 * entry in the cached volume location catalogue
164 */ 179 */
165struct afs_cache_vlocation { 180struct afs_cache_vlocation {
166 uint8_t name[64 + 1]; /* volume name (lowercase, padded with NULs) */ 181 /* volume name (lowercase, padded with NULs) */
182 uint8_t name[AFS_MAXVOLNAME + 1];
183
167 uint8_t nservers; /* number of entries used in servers[] */ 184 uint8_t nservers; /* number of entries used in servers[] */
168 uint8_t vidmask; /* voltype mask for vid[] */ 185 uint8_t vidmask; /* voltype mask for vid[] */
169 uint8_t srvtmask[8]; /* voltype masks for servers[] */ 186 uint8_t srvtmask[8]; /* voltype masks for servers[] */
@@ -281,7 +298,8 @@ struct afs_vnode {
281#ifdef AFS_CACHING_SUPPORT 298#ifdef AFS_CACHING_SUPPORT
282 struct cachefs_cookie *cache; /* caching cookie */ 299 struct cachefs_cookie *cache; /* caching cookie */
283#endif 300#endif
284 301 struct afs_permits *permits; /* cache of permits so far obtained */
302 struct mutex permits_lock; /* lock for altering permits list */
285 wait_queue_head_t update_waitq; /* status fetch waitqueue */ 303 wait_queue_head_t update_waitq; /* status fetch waitqueue */
286 unsigned update_cnt; /* number of outstanding ops that will update the 304 unsigned update_cnt; /* number of outstanding ops that will update the
287 * status */ 305 * status */
@@ -296,12 +314,13 @@ struct afs_vnode {
296#define AFS_VNODE_DIR_CHANGED 6 /* set if vnode's parent dir metadata changed */ 314#define AFS_VNODE_DIR_CHANGED 6 /* set if vnode's parent dir metadata changed */
297#define AFS_VNODE_DIR_MODIFIED 7 /* set if vnode's parent dir data modified */ 315#define AFS_VNODE_DIR_MODIFIED 7 /* set if vnode's parent dir data modified */
298 316
317 long acl_order; /* ACL check count (callback break count) */
318
299 /* outstanding callback notification on this file */ 319 /* outstanding callback notification on this file */
300 struct rb_node server_rb; /* link in server->fs_vnodes */ 320 struct rb_node server_rb; /* link in server->fs_vnodes */
301 struct rb_node cb_promise; /* link in server->cb_promises */ 321 struct rb_node cb_promise; /* link in server->cb_promises */
302 struct work_struct cb_broken_work; /* work to be done on callback break */ 322 struct work_struct cb_broken_work; /* work to be done on callback break */
303 struct mutex cb_broken_lock; /* lock against multiple attempts to fix break */ 323 struct mutex cb_broken_lock; /* lock against multiple attempts to fix break */
304// struct list_head cb_hash_link; /* link in master callback hash */
305 time_t cb_expires; /* time at which callback expires */ 324 time_t cb_expires; /* time at which callback expires */
306 time_t cb_expires_at; /* time used to order cb_promise */ 325 time_t cb_expires_at; /* time used to order cb_promise */
307 unsigned cb_version; /* callback version */ 326 unsigned cb_version; /* callback version */
@@ -310,6 +329,23 @@ struct afs_vnode {
310 bool cb_promised; /* true if promise still holds */ 329 bool cb_promised; /* true if promise still holds */
311}; 330};
312 331
332/*
333 * cached security record for one user's attempt to access a vnode
334 */
335struct afs_permit {
336 struct key *key; /* RxRPC ticket holding a security context */
337 afs_access_t access_mask; /* access mask for this key */
338};
339
340/*
341 * cache of security records from attempts to access a vnode
342 */
343struct afs_permits {
344 struct rcu_head rcu; /* disposal procedure */
345 int count; /* number of records */
346 struct afs_permit permits[0]; /* the permits so far examined */
347};
348
313/*****************************************************************************/ 349/*****************************************************************************/
314/* 350/*
315 * callback.c 351 * callback.c
@@ -352,11 +388,17 @@ extern bool afs_cm_incoming_call(struct afs_call *);
352extern const struct inode_operations afs_dir_inode_operations; 388extern const struct inode_operations afs_dir_inode_operations;
353extern const struct file_operations afs_dir_file_operations; 389extern const struct file_operations afs_dir_file_operations;
354 390
391extern int afs_permission(struct inode *, int, struct nameidata *);
392
355/* 393/*
356 * file.c 394 * file.c
357 */ 395 */
358extern const struct address_space_operations afs_fs_aops; 396extern const struct address_space_operations afs_fs_aops;
359extern const struct inode_operations afs_file_inode_operations; 397extern const struct inode_operations afs_file_inode_operations;
398extern const struct file_operations afs_file_operations;
399
400extern int afs_open(struct inode *, struct file *);
401extern int afs_release(struct inode *, struct file *);
360 402
361#ifdef AFS_CACHING_SUPPORT 403#ifdef AFS_CACHING_SUPPORT
362extern int afs_cache_get_page_cookie(struct page *, struct cachefs_page **); 404extern int afs_cache_get_page_cookie(struct page *, struct cachefs_page **);
@@ -365,22 +407,24 @@ extern int afs_cache_get_page_cookie(struct page *, struct cachefs_page **);
365/* 407/*
366 * fsclient.c 408 * fsclient.c
367 */ 409 */
368extern int afs_fs_fetch_file_status(struct afs_server *, 410extern int afs_fs_fetch_file_status(struct afs_server *, struct key *,
369 struct afs_vnode *, 411 struct afs_vnode *, struct afs_volsync *,
370 struct afs_volsync *,
371 const struct afs_wait_mode *); 412 const struct afs_wait_mode *);
372extern int afs_fs_give_up_callbacks(struct afs_server *, 413extern int afs_fs_give_up_callbacks(struct afs_server *,
373 const struct afs_wait_mode *); 414 const struct afs_wait_mode *);
374extern int afs_fs_fetch_data(struct afs_server *, struct afs_vnode *, off_t, 415extern int afs_fs_fetch_data(struct afs_server *, struct key *,
375 size_t, struct page *, struct afs_volsync *, 416 struct afs_vnode *, off_t, size_t, struct page *,
417 struct afs_volsync *,
376 const struct afs_wait_mode *); 418 const struct afs_wait_mode *);
377 419
378/* 420/*
379 * inode.c 421 * inode.c
380 */ 422 */
381extern struct inode *afs_iget(struct super_block *, struct afs_fid *); 423extern struct inode *afs_iget(struct super_block *, struct key *,
424 struct afs_fid *);
382extern int afs_inode_getattr(struct vfsmount *, struct dentry *, 425extern int afs_inode_getattr(struct vfsmount *, struct dentry *,
383 struct kstat *); 426 struct kstat *);
427extern void afs_zap_permits(struct rcu_head *);
384extern void afs_clear_inode(struct inode *); 428extern void afs_clear_inode(struct inode *);
385 429
386/* 430/*
@@ -402,17 +446,11 @@ extern const struct inode_operations afs_mntpt_inode_operations;
402extern const struct file_operations afs_mntpt_file_operations; 446extern const struct file_operations afs_mntpt_file_operations;
403extern unsigned long afs_mntpt_expiry_timeout; 447extern unsigned long afs_mntpt_expiry_timeout;
404 448
405extern int afs_mntpt_check_symlink(struct afs_vnode *); 449extern int afs_mntpt_check_symlink(struct afs_vnode *, struct key *);
406extern void afs_mntpt_kill_timer(void); 450extern void afs_mntpt_kill_timer(void);
407extern void afs_umount_begin(struct vfsmount *, int); 451extern void afs_umount_begin(struct vfsmount *, int);
408 452
409/* 453/*
410 * super.c
411 */
412extern int afs_fs_init(void);
413extern void afs_fs_exit(void);
414
415/*
416 * proc.c 454 * proc.c
417 */ 455 */
418extern int afs_proc_init(void); 456extern int afs_proc_init(void);
@@ -436,6 +474,14 @@ extern int afs_extract_data(struct afs_call *, struct sk_buff *, bool, void *,
436 size_t); 474 size_t);
437 475
438/* 476/*
477 * security.c
478 */
479extern void afs_clear_permits(struct afs_vnode *);
480extern void afs_cache_permit(struct afs_vnode *, struct key *, long);
481extern struct key *afs_request_key(struct afs_cell *);
482extern int afs_permission(struct inode *, int, struct nameidata *);
483
484/*
439 * server.c 485 * server.c
440 */ 486 */
441extern spinlock_t afs_server_peer_lock; 487extern spinlock_t afs_server_peer_lock;
@@ -449,16 +495,23 @@ extern void afs_put_server(struct afs_server *);
449extern void __exit afs_purge_servers(void); 495extern void __exit afs_purge_servers(void);
450 496
451/* 497/*
498 * super.c
499 */
500extern int afs_fs_init(void);
501extern void afs_fs_exit(void);
502
503/*
452 * vlclient.c 504 * vlclient.c
453 */ 505 */
454#ifdef AFS_CACHING_SUPPORT 506#ifdef AFS_CACHING_SUPPORT
455extern struct cachefs_index_def afs_vlocation_cache_index_def; 507extern struct cachefs_index_def afs_vlocation_cache_index_def;
456#endif 508#endif
457 509
458extern int afs_vl_get_entry_by_name(struct in_addr *, const char *, 510extern int afs_vl_get_entry_by_name(struct in_addr *, struct key *,
459 struct afs_cache_vlocation *, 511 const char *, struct afs_cache_vlocation *,
460 const struct afs_wait_mode *); 512 const struct afs_wait_mode *);
461extern int afs_vl_get_entry_by_id(struct in_addr *, afs_volid_t, afs_voltype_t, 513extern int afs_vl_get_entry_by_id(struct in_addr *, struct key *,
514 afs_volid_t, afs_voltype_t,
462 struct afs_cache_vlocation *, 515 struct afs_cache_vlocation *,
463 const struct afs_wait_mode *); 516 const struct afs_wait_mode *);
464 517
@@ -469,6 +522,7 @@ extern int afs_vl_get_entry_by_id(struct in_addr *, afs_volid_t, afs_voltype_t,
469 522
470extern int __init afs_vlocation_update_init(void); 523extern int __init afs_vlocation_update_init(void);
471extern struct afs_vlocation *afs_vlocation_lookup(struct afs_cell *, 524extern struct afs_vlocation *afs_vlocation_lookup(struct afs_cell *,
525 struct key *,
472 const char *, size_t); 526 const char *, size_t);
473extern void afs_put_vlocation(struct afs_vlocation *); 527extern void afs_put_vlocation(struct afs_vlocation *);
474extern void __exit afs_vlocation_purge(void); 528extern void __exit afs_vlocation_purge(void);
@@ -492,9 +546,10 @@ static inline struct inode *AFS_VNODE_TO_I(struct afs_vnode *vnode)
492 return &vnode->vfs_inode; 546 return &vnode->vfs_inode;
493} 547}
494 548
495extern int afs_vnode_fetch_status(struct afs_vnode *); 549extern int afs_vnode_fetch_status(struct afs_vnode *, struct afs_vnode *,
496extern int afs_vnode_fetch_data(struct afs_vnode *vnode, off_t, size_t, 550 struct key *);
497 struct page *); 551extern int afs_vnode_fetch_data(struct afs_vnode *, struct key *,
552 off_t, size_t, struct page *);
498 553
499/* 554/*
500 * volume.c 555 * volume.c
@@ -506,8 +561,7 @@ extern struct cachefs_index_def afs_volume_cache_index_def;
506#define afs_get_volume(V) do { atomic_inc(&(V)->usage); } while(0) 561#define afs_get_volume(V) do { atomic_inc(&(V)->usage); } while(0)
507 562
508extern void afs_put_volume(struct afs_volume *); 563extern void afs_put_volume(struct afs_volume *);
509extern struct afs_volume *afs_volume_lookup(const char *, struct afs_cell *, 564extern struct afs_volume *afs_volume_lookup(struct afs_mount_params *);
510 int);
511extern struct afs_server *afs_volume_pick_fileserver(struct afs_vnode *); 565extern struct afs_server *afs_volume_pick_fileserver(struct afs_vnode *);
512extern int afs_volume_release_fileserver(struct afs_vnode *, 566extern int afs_volume_release_fileserver(struct afs_vnode *,
513 struct afs_server *, int); 567 struct afs_server *, int);
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c
index 08c11a0b66bd..b905ae37f912 100644
--- a/fs/afs/mntpt.c
+++ b/fs/afs/mntpt.c
@@ -48,8 +48,11 @@ unsigned long afs_mntpt_expiry_timeout = 10 * 60;
48 * check a symbolic link to see whether it actually encodes a mountpoint 48 * check a symbolic link to see whether it actually encodes a mountpoint
49 * - sets the AFS_VNODE_MOUNTPOINT flag on the vnode appropriately 49 * - sets the AFS_VNODE_MOUNTPOINT flag on the vnode appropriately
50 */ 50 */
51int afs_mntpt_check_symlink(struct afs_vnode *vnode) 51int afs_mntpt_check_symlink(struct afs_vnode *vnode, struct key *key)
52{ 52{
53 struct file file = {
54 .private_data = key,
55 };
53 struct page *page; 56 struct page *page;
54 size_t size; 57 size_t size;
55 char *buf; 58 char *buf;
@@ -58,7 +61,7 @@ int afs_mntpt_check_symlink(struct afs_vnode *vnode)
58 _enter("{%u,%u}", vnode->fid.vnode, vnode->fid.unique); 61 _enter("{%u,%u}", vnode->fid.vnode, vnode->fid.unique);
59 62
60 /* read the contents of the symlink into the pagecache */ 63 /* read the contents of the symlink into the pagecache */
61 page = read_mapping_page(AFS_VNODE_TO_I(vnode)->i_mapping, 0, NULL); 64 page = read_mapping_page(AFS_VNODE_TO_I(vnode)->i_mapping, 0, &file);
62 if (IS_ERR(page)) { 65 if (IS_ERR(page)) {
63 ret = PTR_ERR(page); 66 ret = PTR_ERR(page);
64 goto out; 67 goto out;
@@ -214,7 +217,7 @@ static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd)
214 struct vfsmount *newmnt; 217 struct vfsmount *newmnt;
215 int err; 218 int err;
216 219
217 _enter("%p{%s},{%s:%p{%s}}", 220 _enter("%p{%s},{%s:%p{%s},}",
218 dentry, 221 dentry,
219 dentry->d_name.name, 222 dentry->d_name.name,
220 nd->mnt->mnt_devname, 223 nd->mnt->mnt_devname,
@@ -234,7 +237,8 @@ static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd)
234 err = do_add_mount(newmnt, nd, MNT_SHRINKABLE, &afs_vfsmounts); 237 err = do_add_mount(newmnt, nd, MNT_SHRINKABLE, &afs_vfsmounts);
235 switch (err) { 238 switch (err) {
236 case 0: 239 case 0:
237 path_release(nd); 240 mntput(nd->mnt);
241 dput(nd->dentry);
238 nd->mnt = newmnt; 242 nd->mnt = newmnt;
239 nd->dentry = dget(newmnt->mnt_root); 243 nd->dentry = dget(newmnt->mnt_root);
240 schedule_delayed_work(&afs_mntpt_expiry_timer, 244 schedule_delayed_work(&afs_mntpt_expiry_timer,
diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c
index b92774231b3c..e86c527d87a1 100644
--- a/fs/afs/rxrpc.c
+++ b/fs/afs/rxrpc.c
@@ -17,6 +17,8 @@
17 17
18static struct socket *afs_socket; /* my RxRPC socket */ 18static struct socket *afs_socket; /* my RxRPC socket */
19static struct workqueue_struct *afs_async_calls; 19static struct workqueue_struct *afs_async_calls;
20static atomic_t afs_outstanding_calls;
21static atomic_t afs_outstanding_skbs;
20 22
21static void afs_wake_up_call_waiter(struct afs_call *); 23static void afs_wake_up_call_waiter(struct afs_call *);
22static int afs_wait_for_call_to_complete(struct afs_call *); 24static int afs_wait_for_call_to_complete(struct afs_call *);
@@ -45,6 +47,7 @@ static const struct afs_wait_mode afs_async_incoming_call = {
45 47
46/* asynchronous incoming call initial processing */ 48/* asynchronous incoming call initial processing */
47static const struct afs_call_type afs_RXCMxxxx = { 49static const struct afs_call_type afs_RXCMxxxx = {
50 .name = "CB.xxxx",
48 .deliver = afs_deliver_cm_op_id, 51 .deliver = afs_deliver_cm_op_id,
49 .abort_to_error = afs_abort_to_error, 52 .abort_to_error = afs_abort_to_error,
50}; 53};
@@ -118,10 +121,67 @@ void afs_close_socket(void)
118 121
119 _debug("dework"); 122 _debug("dework");
120 destroy_workqueue(afs_async_calls); 123 destroy_workqueue(afs_async_calls);
124
125 ASSERTCMP(atomic_read(&afs_outstanding_skbs), ==, 0);
126 ASSERTCMP(atomic_read(&afs_outstanding_calls), ==, 0);
121 _leave(""); 127 _leave("");
122} 128}
123 129
124/* 130/*
131 * note that the data in a socket buffer is now delivered and that the buffer
132 * should be freed
133 */
134static void afs_data_delivered(struct sk_buff *skb)
135{
136 if (!skb) {
137 _debug("DLVR NULL [%d]", atomic_read(&afs_outstanding_skbs));
138 dump_stack();
139 } else {
140 _debug("DLVR %p{%u} [%d]",
141 skb, skb->mark, atomic_read(&afs_outstanding_skbs));
142 if (atomic_dec_return(&afs_outstanding_skbs) == -1)
143 BUG();
144 rxrpc_kernel_data_delivered(skb);
145 }
146}
147
148/*
149 * free a socket buffer
150 */
151static void afs_free_skb(struct sk_buff *skb)
152{
153 if (!skb) {
154 _debug("FREE NULL [%d]", atomic_read(&afs_outstanding_skbs));
155 dump_stack();
156 } else {
157 _debug("FREE %p{%u} [%d]",
158 skb, skb->mark, atomic_read(&afs_outstanding_skbs));
159 if (atomic_dec_return(&afs_outstanding_skbs) == -1)
160 BUG();
161 rxrpc_kernel_free_skb(skb);
162 }
163}
164
165/*
166 * free a call
167 */
168static void afs_free_call(struct afs_call *call)
169{
170 _debug("DONE %p{%s} [%d]",
171 call, call->type->name, atomic_read(&afs_outstanding_calls));
172 if (atomic_dec_return(&afs_outstanding_calls) == -1)
173 BUG();
174
175 ASSERTCMP(call->rxcall, ==, NULL);
176 ASSERT(!work_pending(&call->async_work));
177 ASSERT(skb_queue_empty(&call->rx_queue));
178 ASSERT(call->type->name != NULL);
179
180 kfree(call->request);
181 kfree(call);
182}
183
184/*
125 * allocate a call with flat request and reply buffers 185 * allocate a call with flat request and reply buffers
126 */ 186 */
127struct afs_call *afs_alloc_flat_call(const struct afs_call_type *type, 187struct afs_call *afs_alloc_flat_call(const struct afs_call_type *type,
@@ -133,30 +193,32 @@ struct afs_call *afs_alloc_flat_call(const struct afs_call_type *type,
133 if (!call) 193 if (!call)
134 goto nomem_call; 194 goto nomem_call;
135 195
196 _debug("CALL %p{%s} [%d]",
197 call, type->name, atomic_read(&afs_outstanding_calls));
198 atomic_inc(&afs_outstanding_calls);
199
200 call->type = type;
201 call->request_size = request_size;
202 call->reply_max = reply_size;
203
136 if (request_size) { 204 if (request_size) {
137 call->request = kmalloc(request_size, GFP_NOFS); 205 call->request = kmalloc(request_size, GFP_NOFS);
138 if (!call->request) 206 if (!call->request)
139 goto nomem_request; 207 goto nomem_free;
140 } 208 }
141 209
142 if (reply_size) { 210 if (reply_size) {
143 call->buffer = kmalloc(reply_size, GFP_NOFS); 211 call->buffer = kmalloc(reply_size, GFP_NOFS);
144 if (!call->buffer) 212 if (!call->buffer)
145 goto nomem_buffer; 213 goto nomem_free;
146 } 214 }
147 215
148 call->type = type;
149 call->request_size = request_size;
150 call->reply_max = reply_size;
151
152 init_waitqueue_head(&call->waitq); 216 init_waitqueue_head(&call->waitq);
153 skb_queue_head_init(&call->rx_queue); 217 skb_queue_head_init(&call->rx_queue);
154 return call; 218 return call;
155 219
156nomem_buffer: 220nomem_free:
157 kfree(call->request); 221 afs_free_call(call);
158nomem_request:
159 kfree(call);
160nomem_call: 222nomem_call:
161 return NULL; 223 return NULL;
162} 224}
@@ -188,6 +250,12 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
188 250
189 _enter("%x,{%d},", addr->s_addr, ntohs(call->port)); 251 _enter("%x,{%d},", addr->s_addr, ntohs(call->port));
190 252
253 ASSERT(call->type != NULL);
254 ASSERT(call->type->name != NULL);
255
256 _debug("MAKE %p{%s} [%d]",
257 call, call->type->name, atomic_read(&afs_outstanding_calls));
258
191 call->wait_mode = wait_mode; 259 call->wait_mode = wait_mode;
192 INIT_WORK(&call->async_work, afs_process_async_call); 260 INIT_WORK(&call->async_work, afs_process_async_call);
193 261
@@ -203,6 +271,7 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
203 /* create a call */ 271 /* create a call */
204 rxcall = rxrpc_kernel_begin_call(afs_socket, &srx, call->key, 272 rxcall = rxrpc_kernel_begin_call(afs_socket, &srx, call->key,
205 (unsigned long) call, gfp); 273 (unsigned long) call, gfp);
274 call->key = NULL;
206 if (IS_ERR(rxcall)) { 275 if (IS_ERR(rxcall)) {
207 ret = PTR_ERR(rxcall); 276 ret = PTR_ERR(rxcall);
208 goto error_kill_call; 277 goto error_kill_call;
@@ -237,10 +306,10 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
237error_do_abort: 306error_do_abort:
238 rxrpc_kernel_abort_call(rxcall, RX_USER_ABORT); 307 rxrpc_kernel_abort_call(rxcall, RX_USER_ABORT);
239 rxrpc_kernel_end_call(rxcall); 308 rxrpc_kernel_end_call(rxcall);
309 call->rxcall = NULL;
240error_kill_call: 310error_kill_call:
241 call->type->destructor(call); 311 call->type->destructor(call);
242 ASSERT(skb_queue_empty(&call->rx_queue)); 312 afs_free_call(call);
243 kfree(call);
244 _leave(" = %d", ret); 313 _leave(" = %d", ret);
245 return ret; 314 return ret;
246} 315}
@@ -257,15 +326,19 @@ static void afs_rx_interceptor(struct sock *sk, unsigned long user_call_ID,
257 326
258 _enter("%p,,%u", call, skb->mark); 327 _enter("%p,,%u", call, skb->mark);
259 328
329 _debug("ICPT %p{%u} [%d]",
330 skb, skb->mark, atomic_read(&afs_outstanding_skbs));
331
260 ASSERTCMP(sk, ==, afs_socket->sk); 332 ASSERTCMP(sk, ==, afs_socket->sk);
333 atomic_inc(&afs_outstanding_skbs);
261 334
262 if (!call) { 335 if (!call) {
263 /* its an incoming call for our callback service */ 336 /* its an incoming call for our callback service */
264 __skb_queue_tail(&afs_incoming_calls, skb); 337 skb_queue_tail(&afs_incoming_calls, skb);
265 schedule_work(&afs_collect_incoming_call_work); 338 schedule_work(&afs_collect_incoming_call_work);
266 } else { 339 } else {
267 /* route the messages directly to the appropriate call */ 340 /* route the messages directly to the appropriate call */
268 __skb_queue_tail(&call->rx_queue, skb); 341 skb_queue_tail(&call->rx_queue, skb);
269 call->wait_mode->rx_wakeup(call); 342 call->wait_mode->rx_wakeup(call);
270 } 343 }
271 344
@@ -317,9 +390,9 @@ static void afs_deliver_to_call(struct afs_call *call)
317 call->state = AFS_CALL_ERROR; 390 call->state = AFS_CALL_ERROR;
318 break; 391 break;
319 } 392 }
320 rxrpc_kernel_data_delivered(skb); 393 afs_data_delivered(skb);
321 skb = NULL; 394 skb = NULL;
322 break; 395 continue;
323 case RXRPC_SKB_MARK_FINAL_ACK: 396 case RXRPC_SKB_MARK_FINAL_ACK:
324 _debug("Rcv ACK"); 397 _debug("Rcv ACK");
325 call->state = AFS_CALL_COMPLETE; 398 call->state = AFS_CALL_COMPLETE;
@@ -350,19 +423,19 @@ static void afs_deliver_to_call(struct afs_call *call)
350 break; 423 break;
351 } 424 }
352 425
353 rxrpc_kernel_free_skb(skb); 426 afs_free_skb(skb);
354 } 427 }
355 428
356 /* make sure the queue is empty if the call is done with (we might have 429 /* make sure the queue is empty if the call is done with (we might have
357 * aborted the call early because of an unmarshalling error) */ 430 * aborted the call early because of an unmarshalling error) */
358 if (call->state >= AFS_CALL_COMPLETE) { 431 if (call->state >= AFS_CALL_COMPLETE) {
359 while ((skb = skb_dequeue(&call->rx_queue))) 432 while ((skb = skb_dequeue(&call->rx_queue)))
360 rxrpc_kernel_free_skb(skb); 433 afs_free_skb(skb);
361 if (call->incoming) { 434 if (call->incoming) {
362 rxrpc_kernel_end_call(call->rxcall); 435 rxrpc_kernel_end_call(call->rxcall);
436 call->rxcall = NULL;
363 call->type->destructor(call); 437 call->type->destructor(call);
364 ASSERT(skb_queue_empty(&call->rx_queue)); 438 afs_free_call(call);
365 kfree(call);
366 } 439 }
367 } 440 }
368 441
@@ -409,14 +482,14 @@ static int afs_wait_for_call_to_complete(struct afs_call *call)
409 _debug("call incomplete"); 482 _debug("call incomplete");
410 rxrpc_kernel_abort_call(call->rxcall, RX_CALL_DEAD); 483 rxrpc_kernel_abort_call(call->rxcall, RX_CALL_DEAD);
411 while ((skb = skb_dequeue(&call->rx_queue))) 484 while ((skb = skb_dequeue(&call->rx_queue)))
412 rxrpc_kernel_free_skb(skb); 485 afs_free_skb(skb);
413 } 486 }
414 487
415 _debug("call complete"); 488 _debug("call complete");
416 rxrpc_kernel_end_call(call->rxcall); 489 rxrpc_kernel_end_call(call->rxcall);
490 call->rxcall = NULL;
417 call->type->destructor(call); 491 call->type->destructor(call);
418 ASSERT(skb_queue_empty(&call->rx_queue)); 492 afs_free_call(call);
419 kfree(call);
420 _leave(" = %d", ret); 493 _leave(" = %d", ret);
421 return ret; 494 return ret;
422} 495}
@@ -459,9 +532,7 @@ static void afs_delete_async_call(struct work_struct *work)
459 532
460 _enter(""); 533 _enter("");
461 534
462 ASSERT(skb_queue_empty(&call->rx_queue)); 535 afs_free_call(call);
463 ASSERT(!work_pending(&call->async_work));
464 kfree(call);
465 536
466 _leave(""); 537 _leave("");
467} 538}
@@ -489,6 +560,7 @@ static void afs_process_async_call(struct work_struct *work)
489 560
490 /* kill the call */ 561 /* kill the call */
491 rxrpc_kernel_end_call(call->rxcall); 562 rxrpc_kernel_end_call(call->rxcall);
563 call->rxcall = NULL;
492 if (call->type->destructor) 564 if (call->type->destructor)
493 call->type->destructor(call); 565 call->type->destructor(call);
494 566
@@ -526,7 +598,7 @@ static void afs_collect_incoming_call(struct work_struct *work)
526 _debug("new call"); 598 _debug("new call");
527 599
528 /* don't need the notification */ 600 /* don't need the notification */
529 rxrpc_kernel_free_skb(skb); 601 afs_free_skb(skb);
530 602
531 if (!call) { 603 if (!call) {
532 call = kzalloc(sizeof(struct afs_call), GFP_KERNEL); 604 call = kzalloc(sizeof(struct afs_call), GFP_KERNEL);
@@ -541,6 +613,11 @@ static void afs_collect_incoming_call(struct work_struct *work)
541 init_waitqueue_head(&call->waitq); 613 init_waitqueue_head(&call->waitq);
542 skb_queue_head_init(&call->rx_queue); 614 skb_queue_head_init(&call->rx_queue);
543 call->state = AFS_CALL_AWAIT_OP_ID; 615 call->state = AFS_CALL_AWAIT_OP_ID;
616
617 _debug("CALL %p{%s} [%d]",
618 call, call->type->name,
619 atomic_read(&afs_outstanding_calls));
620 atomic_inc(&afs_outstanding_calls);
544 } 621 }
545 622
546 rxcall = rxrpc_kernel_accept_call(afs_socket, 623 rxcall = rxrpc_kernel_accept_call(afs_socket,
@@ -551,7 +628,8 @@ static void afs_collect_incoming_call(struct work_struct *work)
551 } 628 }
552 } 629 }
553 630
554 kfree(call); 631 if (call)
632 afs_free_call(call);
555} 633}
556 634
557/* 635/*
@@ -629,8 +707,7 @@ void afs_send_empty_reply(struct afs_call *call)
629 rxrpc_kernel_end_call(call->rxcall); 707 rxrpc_kernel_end_call(call->rxcall);
630 call->rxcall = NULL; 708 call->rxcall = NULL;
631 call->type->destructor(call); 709 call->type->destructor(call);
632 ASSERT(skb_queue_empty(&call->rx_queue)); 710 afs_free_call(call);
633 kfree(call);
634 _leave(" [error]"); 711 _leave(" [error]");
635 return; 712 return;
636 } 713 }
diff --git a/fs/afs/security.c b/fs/afs/security.c
new file mode 100644
index 000000000000..cbdd7f7162fa
--- /dev/null
+++ b/fs/afs/security.c
@@ -0,0 +1,345 @@
1/* AFS security handling
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
12#include <linux/init.h>
13#include <linux/slab.h>
14#include <linux/fs.h>
15#include <linux/ctype.h>
16#include <keys/rxrpc-type.h>
17#include "internal.h"
18
19/*
20 * get a key
21 */
22struct key *afs_request_key(struct afs_cell *cell)
23{
24 struct key *key;
25
26 _enter("{%x}", key_serial(cell->anonymous_key));
27
28 _debug("key %s", cell->anonymous_key->description);
29 key = request_key(&key_type_rxrpc, cell->anonymous_key->description,
30 NULL);
31 if (IS_ERR(key)) {
32 if (PTR_ERR(key) != -ENOKEY) {
33 _leave(" = %ld", PTR_ERR(key));
34 return key;
35 }
36
37 /* act as anonymous user */
38 _leave(" = {%x} [anon]", key_serial(cell->anonymous_key));
39 return key_get(cell->anonymous_key);
40 } else {
41 /* act as authorised user */
42 _leave(" = {%x} [auth]", key_serial(key));
43 return key;
44 }
45}
46
47/*
48 * dispose of a permits list
49 */
50void afs_zap_permits(struct rcu_head *rcu)
51{
52 struct afs_permits *permits =
53 container_of(rcu, struct afs_permits, rcu);
54 int loop;
55
56 _enter("{%d}", permits->count);
57
58 for (loop = permits->count - 1; loop >= 0; loop--)
59 key_put(permits->permits[loop].key);
60 kfree(permits);
61}
62
63/*
64 * dispose of a permits list in which all the key pointers have been copied
65 */
66static void afs_dispose_of_permits(struct rcu_head *rcu)
67{
68 struct afs_permits *permits =
69 container_of(rcu, struct afs_permits, rcu);
70
71 _enter("{%d}", permits->count);
72
73 kfree(permits);
74}
75
76/*
77 * get the authorising vnode - this is the specified inode itself if it's a
78 * directory or it's the parent directory if the specified inode is a file or
79 * symlink
80 * - the caller must release the ref on the inode
81 */
82static struct afs_vnode *afs_get_auth_inode(struct afs_vnode *vnode,
83 struct key *key)
84{
85 struct afs_vnode *auth_vnode;
86 struct inode *auth_inode;
87
88 _enter("");
89
90 if (S_ISDIR(vnode->vfs_inode.i_mode)) {
91 auth_inode = igrab(&vnode->vfs_inode);
92 ASSERT(auth_inode != NULL);
93 } else {
94 auth_inode = afs_iget(vnode->vfs_inode.i_sb, key,
95 &vnode->status.parent);
96 if (IS_ERR(auth_inode))
97 return ERR_PTR(PTR_ERR(auth_inode));
98 }
99
100 auth_vnode = AFS_FS_I(auth_inode);
101 _leave(" = {%x}", auth_vnode->fid.vnode);
102 return auth_vnode;
103}
104
105/*
106 * clear the permit cache on a directory vnode
107 */
108void afs_clear_permits(struct afs_vnode *vnode)
109{
110 struct afs_permits *permits;
111
112 _enter("{%x}", vnode->fid.vnode);
113
114 mutex_lock(&vnode->permits_lock);
115 permits = vnode->permits;
116 rcu_assign_pointer(vnode->permits, NULL);
117 mutex_unlock(&vnode->permits_lock);
118
119 if (permits)
120 call_rcu(&permits->rcu, afs_zap_permits);
121 _leave("");
122}
123
124/*
125 * add the result obtained for a vnode to its or its parent directory's cache
126 * for the key used to access it
127 */
128void afs_cache_permit(struct afs_vnode *vnode, struct key *key, long acl_order)
129{
130 struct afs_permits *permits, *xpermits;
131 struct afs_permit *permit;
132 struct afs_vnode *auth_vnode;
133 int count, loop;
134
135 _enter("{%x},%x,%lx", vnode->fid.vnode, key_serial(key), acl_order);
136
137 auth_vnode = afs_get_auth_inode(vnode, key);
138 if (IS_ERR(auth_vnode)) {
139 _leave(" [get error %ld]", PTR_ERR(auth_vnode));
140 return;
141 }
142
143 mutex_lock(&auth_vnode->permits_lock);
144
145 /* guard against a rename being detected whilst we waited for the
146 * lock */
147 if (memcmp(&auth_vnode->fid, &vnode->status.parent,
148 sizeof(struct afs_fid)) != 0) {
149 _debug("renamed");
150 goto out_unlock;
151 }
152
153 /* have to be careful as the directory's callback may be broken between
154 * us receiving the status we're trying to cache and us getting the
155 * lock to update the cache for the status */
156 if (auth_vnode->acl_order - acl_order > 0) {
157 _debug("ACL changed?");
158 goto out_unlock;
159 }
160
161 /* always update the anonymous mask */
162 _debug("anon access %x", vnode->status.anon_access);
163 auth_vnode->status.anon_access = vnode->status.anon_access;
164 if (key == vnode->volume->cell->anonymous_key)
165 goto out_unlock;
166
167 xpermits = auth_vnode->permits;
168 count = 0;
169 if (xpermits) {
170 /* see if the permit is already in the list
171 * - if it is then we just amend the list
172 */
173 count = xpermits->count;
174 permit = xpermits->permits;
175 for (loop = count; loop > 0; loop--) {
176 if (permit->key == key) {
177 permit->access_mask =
178 vnode->status.caller_access;
179 goto out_unlock;
180 }
181 permit++;
182 }
183 }
184
185 permits = kmalloc(sizeof(*permits) + sizeof(*permit) * (count + 1),
186 GFP_NOFS);
187 if (!permits)
188 goto out_unlock;
189
190 memcpy(permits->permits, xpermits->permits,
191 count * sizeof(struct afs_permit));
192
193 _debug("key %x access %x",
194 key_serial(key), vnode->status.caller_access);
195 permits->permits[count].access_mask = vnode->status.caller_access;
196 permits->permits[count].key = key_get(key);
197 permits->count = count + 1;
198
199 rcu_assign_pointer(auth_vnode->permits, permits);
200 if (xpermits)
201 call_rcu(&xpermits->rcu, afs_dispose_of_permits);
202
203out_unlock:
204 mutex_unlock(&auth_vnode->permits_lock);
205 iput(&auth_vnode->vfs_inode);
206 _leave("");
207}
208
209/*
210 * check with the fileserver to see if the directory or parent directory is
211 * permitted to be accessed with this authorisation, and if so, what access it
212 * is granted
213 */
214static int afs_check_permit(struct afs_vnode *vnode, struct key *key,
215 afs_access_t *_access)
216{
217 struct afs_permits *permits;
218 struct afs_permit *permit;
219 struct afs_vnode *auth_vnode;
220 bool valid;
221 int loop, ret;
222
223 _enter("");
224
225 auth_vnode = afs_get_auth_inode(vnode, key);
226 if (IS_ERR(auth_vnode)) {
227 *_access = 0;
228 _leave(" = %ld", PTR_ERR(auth_vnode));
229 return PTR_ERR(auth_vnode);
230 }
231
232 ASSERT(S_ISDIR(auth_vnode->vfs_inode.i_mode));
233
234 /* check the permits to see if we've got one yet */
235 if (key == auth_vnode->volume->cell->anonymous_key) {
236 _debug("anon");
237 *_access = auth_vnode->status.anon_access;
238 valid = true;
239 } else {
240 valid = false;
241 rcu_read_lock();
242 permits = rcu_dereference(auth_vnode->permits);
243 if (permits) {
244 permit = permits->permits;
245 for (loop = permits->count; loop > 0; loop--) {
246 if (permit->key == key) {
247 _debug("found in cache");
248 *_access = permit->access_mask;
249 valid = true;
250 break;
251 }
252 permit++;
253 }
254 }
255 rcu_read_unlock();
256 }
257
258 if (!valid) {
259 /* check the status on the file we're actually interested in
260 * (the post-processing will cache the result on auth_vnode) */
261 _debug("no valid permit");
262
263 set_bit(AFS_VNODE_CB_BROKEN, &vnode->flags);
264 ret = afs_vnode_fetch_status(vnode, auth_vnode, key);
265 if (ret < 0) {
266 iput(&auth_vnode->vfs_inode);
267 *_access = 0;
268 _leave(" = %d", ret);
269 return ret;
270 }
271 }
272
273 *_access = vnode->status.caller_access;
274 iput(&auth_vnode->vfs_inode);
275 _leave(" = 0 [access %x]", *_access);
276 return 0;
277}
278
279/*
280 * check the permissions on an AFS file
281 * - AFS ACLs are attached to directories only, and a file is controlled by its
282 * parent directory's ACL
283 */
284int afs_permission(struct inode *inode, int mask, struct nameidata *nd)
285{
286 struct afs_vnode *vnode = AFS_FS_I(inode);
287 afs_access_t access;
288 struct key *key;
289 int ret;
290
291 _enter("{%x:%x},%x,", vnode->fid.vid, vnode->fid.vnode, mask);
292
293 key = afs_request_key(vnode->volume->cell);
294 if (IS_ERR(key)) {
295 _leave(" = %ld [key]", PTR_ERR(key));
296 return PTR_ERR(key);
297 }
298
299 /* check the permits to see if we've got one yet */
300 ret = afs_check_permit(vnode, key, &access);
301 if (ret < 0) {
302 key_put(key);
303 _leave(" = %d [check]", ret);
304 return ret;
305 }
306
307 /* interpret the access mask */
308 _debug("REQ %x ACC %x on %s",
309 mask, access, S_ISDIR(inode->i_mode) ? "dir" : "file");
310
311 if (S_ISDIR(inode->i_mode)) {
312 if (mask & MAY_EXEC) {
313 if (!(access & AFS_ACE_LOOKUP))
314 goto permission_denied;
315 } else if (mask & MAY_READ) {
316 if (!(access & AFS_ACE_READ))
317 goto permission_denied;
318 } else if (mask & MAY_WRITE) {
319 if (!(access & (AFS_ACE_DELETE | /* rmdir, unlink, rename from */
320 AFS_ACE_INSERT | /* create, mkdir, symlink, rename to */
321 AFS_ACE_WRITE))) /* chmod */
322 goto permission_denied;
323 } else {
324 BUG();
325 }
326 } else {
327 if (!(access & AFS_ACE_LOOKUP))
328 goto permission_denied;
329 if (mask & (MAY_EXEC | MAY_READ)) {
330 if (!(access & AFS_ACE_READ))
331 goto permission_denied;
332 } else if (mask & MAY_WRITE) {
333 if (!(access & AFS_ACE_WRITE))
334 goto permission_denied;
335 }
336 }
337
338 key_put(key);
339 return generic_permission(inode, mask, NULL);
340
341permission_denied:
342 key_put(key);
343 _leave(" = -EACCES");
344 return -EACCES;
345}
diff --git a/fs/afs/super.c b/fs/afs/super.c
index 77e68759788f..497350a5463b 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -24,12 +24,6 @@
24 24
25#define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */ 25#define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */
26 26
27struct afs_mount_params {
28 int rwpath;
29 struct afs_cell *default_cell;
30 struct afs_volume *volume;
31};
32
33static void afs_i_init_once(void *foo, struct kmem_cache *cachep, 27static void afs_i_init_once(void *foo, struct kmem_cache *cachep,
34 unsigned long flags); 28 unsigned long flags);
35 29
@@ -150,8 +144,8 @@ static int want_no_value(char *const *_value, const char *option)
150 * - this function has been shamelessly adapted from the ext3 fs which 144 * - this function has been shamelessly adapted from the ext3 fs which
151 * shamelessly adapted it from the msdos fs 145 * shamelessly adapted it from the msdos fs
152 */ 146 */
153static int afs_super_parse_options(struct afs_mount_params *params, 147static int afs_parse_options(struct afs_mount_params *params,
154 char *options, const char **devname) 148 char *options, const char **devname)
155{ 149{
156 struct afs_cell *cell; 150 struct afs_cell *cell;
157 char *key, *value; 151 char *key, *value;
@@ -183,8 +177,8 @@ static int afs_super_parse_options(struct afs_mount_params *params,
183 cell = afs_cell_lookup(value, strlen(value)); 177 cell = afs_cell_lookup(value, strlen(value));
184 if (IS_ERR(cell)) 178 if (IS_ERR(cell))
185 return PTR_ERR(cell); 179 return PTR_ERR(cell);
186 afs_put_cell(params->default_cell); 180 afs_put_cell(params->cell);
187 params->default_cell = cell; 181 params->cell = cell;
188 } else { 182 } else {
189 printk("kAFS: Unknown mount option: '%s'\n", key); 183 printk("kAFS: Unknown mount option: '%s'\n", key);
190 ret = -EINVAL; 184 ret = -EINVAL;
@@ -199,6 +193,99 @@ error:
199} 193}
200 194
201/* 195/*
196 * parse a device name to get cell name, volume name, volume type and R/W
197 * selector
198 * - this can be one of the following:
199 * "%[cell:]volume[.]" R/W volume
200 * "#[cell:]volume[.]" R/O or R/W volume (rwpath=0),
201 * or R/W (rwpath=1) volume
202 * "%[cell:]volume.readonly" R/O volume
203 * "#[cell:]volume.readonly" R/O volume
204 * "%[cell:]volume.backup" Backup volume
205 * "#[cell:]volume.backup" Backup volume
206 */
207static int afs_parse_device_name(struct afs_mount_params *params,
208 const char *name)
209{
210 struct afs_cell *cell;
211 const char *cellname, *suffix;
212 int cellnamesz;
213
214 _enter(",%s", name);
215
216 if (!name) {
217 printk(KERN_ERR "kAFS: no volume name specified\n");
218 return -EINVAL;
219 }
220
221 if ((name[0] != '%' && name[0] != '#') || !name[1]) {
222 printk(KERN_ERR "kAFS: unparsable volume name\n");
223 return -EINVAL;
224 }
225
226 /* determine the type of volume we're looking for */
227 params->type = AFSVL_ROVOL;
228 params->force = false;
229 if (params->rwpath || name[0] == '%') {
230 params->type = AFSVL_RWVOL;
231 params->force = true;
232 }
233 name++;
234
235 /* split the cell name out if there is one */
236 params->volname = strchr(name, ':');
237 if (params->volname) {
238 cellname = name;
239 cellnamesz = params->volname - name;
240 params->volname++;
241 } else {
242 params->volname = name;
243 cellname = NULL;
244 cellnamesz = 0;
245 }
246
247 /* the volume type is further affected by a possible suffix */
248 suffix = strrchr(params->volname, '.');
249 if (suffix) {
250 if (strcmp(suffix, ".readonly") == 0) {
251 params->type = AFSVL_ROVOL;
252 params->force = true;
253 } else if (strcmp(suffix, ".backup") == 0) {
254 params->type = AFSVL_BACKVOL;
255 params->force = true;
256 } else if (suffix[1] == 0) {
257 } else {
258 suffix = NULL;
259 }
260 }
261
262 params->volnamesz = suffix ?
263 suffix - params->volname : strlen(params->volname);
264
265 _debug("cell %*.*s [%p]",
266 cellnamesz, cellnamesz, cellname ?: "", params->cell);
267
268 /* lookup the cell record */
269 if (cellname || !params->cell) {
270 cell = afs_cell_lookup(cellname, cellnamesz);
271 if (IS_ERR(cell)) {
272 printk(KERN_ERR "kAFS: unable to lookup cell '%s'\n",
273 cellname ?: "");
274 return PTR_ERR(cell);
275 }
276 afs_put_cell(params->cell);
277 params->cell = cell;
278 }
279
280 _debug("CELL:%s [%p] VOLUME:%*.*s SUFFIX:%s TYPE:%d%s",
281 params->cell->name, params->cell,
282 params->volnamesz, params->volnamesz, params->volname,
283 suffix ?: "-", params->type, params->force ? " FORCE" : "");
284
285 return 0;
286}
287
288/*
202 * check a superblock to see if it's the one we're looking for 289 * check a superblock to see if it's the one we're looking for
203 */ 290 */
204static int afs_test_super(struct super_block *sb, void *data) 291static int afs_test_super(struct super_block *sb, void *data)
@@ -244,7 +331,7 @@ static int afs_fill_super(struct super_block *sb, void *data)
244 fid.vid = as->volume->vid; 331 fid.vid = as->volume->vid;
245 fid.vnode = 1; 332 fid.vnode = 1;
246 fid.unique = 1; 333 fid.unique = 1;
247 inode = afs_iget(sb, &fid); 334 inode = afs_iget(sb, params->key, &fid);
248 if (IS_ERR(inode)) 335 if (IS_ERR(inode))
249 goto error_inode; 336 goto error_inode;
250 337
@@ -285,31 +372,40 @@ static int afs_get_sb(struct file_system_type *fs_type,
285 struct afs_mount_params params; 372 struct afs_mount_params params;
286 struct super_block *sb; 373 struct super_block *sb;
287 struct afs_volume *vol; 374 struct afs_volume *vol;
375 struct key *key;
288 int ret; 376 int ret;
289 377
290 _enter(",,%s,%p", dev_name, options); 378 _enter(",,%s,%p", dev_name, options);
291 379
292 memset(&params, 0, sizeof(params)); 380 memset(&params, 0, sizeof(params));
293 381
294 /* parse the options */ 382 /* parse the options and device name */
295 if (options) { 383 if (options) {
296 ret = afs_super_parse_options(&params, options, &dev_name); 384 ret = afs_parse_options(&params, options, &dev_name);
297 if (ret < 0) 385 if (ret < 0)
298 goto error; 386 goto error;
299 if (!dev_name) {
300 printk("kAFS: no volume name specified\n");
301 ret = -EINVAL;
302 goto error;
303 }
304 } 387 }
305 388
389
390 ret = afs_parse_device_name(&params, dev_name);
391 if (ret < 0)
392 goto error;
393
394 /* try and do the mount securely */
395 key = afs_request_key(params.cell);
396 if (IS_ERR(key)) {
397 _leave(" = %ld [key]", PTR_ERR(key));
398 ret = PTR_ERR(key);
399 goto error;
400 }
401 params.key = key;
402
306 /* parse the device name */ 403 /* parse the device name */
307 vol = afs_volume_lookup(dev_name, params.default_cell, params.rwpath); 404 vol = afs_volume_lookup(&params);
308 if (IS_ERR(vol)) { 405 if (IS_ERR(vol)) {
309 ret = PTR_ERR(vol); 406 ret = PTR_ERR(vol);
310 goto error; 407 goto error;
311 } 408 }
312
313 params.volume = vol; 409 params.volume = vol;
314 410
315 /* allocate a deviceless superblock */ 411 /* allocate a deviceless superblock */
@@ -337,13 +433,14 @@ static int afs_get_sb(struct file_system_type *fs_type,
337 433
338 simple_set_mnt(mnt, sb); 434 simple_set_mnt(mnt, sb);
339 afs_put_volume(params.volume); 435 afs_put_volume(params.volume);
340 afs_put_cell(params.default_cell); 436 afs_put_cell(params.cell);
341 _leave(" = 0 [%p]", sb); 437 _leave(" = 0 [%p]", sb);
342 return 0; 438 return 0;
343 439
344error: 440error:
345 afs_put_volume(params.volume); 441 afs_put_volume(params.volume);
346 afs_put_cell(params.default_cell); 442 afs_put_cell(params.cell);
443 key_put(params.key);
347 _leave(" = %d", ret); 444 _leave(" = %d", ret);
348 return ret; 445 return ret;
349} 446}
@@ -375,6 +472,7 @@ static void afs_i_init_once(void *_vnode, struct kmem_cache *cachep,
375 memset(vnode, 0, sizeof(*vnode)); 472 memset(vnode, 0, sizeof(*vnode));
376 inode_init_once(&vnode->vfs_inode); 473 inode_init_once(&vnode->vfs_inode);
377 init_waitqueue_head(&vnode->update_waitq); 474 init_waitqueue_head(&vnode->update_waitq);
475 mutex_init(&vnode->permits_lock);
378 spin_lock_init(&vnode->lock); 476 spin_lock_init(&vnode->lock);
379 INIT_WORK(&vnode->cb_broken_work, afs_broken_callback_work); 477 INIT_WORK(&vnode->cb_broken_work, afs_broken_callback_work);
380 mutex_init(&vnode->cb_broken_lock); 478 mutex_init(&vnode->cb_broken_lock);
diff --git a/fs/afs/vlclient.c b/fs/afs/vlclient.c
index 0c7eba174836..36c1306e09e0 100644
--- a/fs/afs/vlclient.c
+++ b/fs/afs/vlclient.c
@@ -127,6 +127,7 @@ static int afs_deliver_vl_get_entry_by_xxx(struct afs_call *call,
127 * VL.GetEntryByName operation type 127 * VL.GetEntryByName operation type
128 */ 128 */
129static const struct afs_call_type afs_RXVLGetEntryByName = { 129static const struct afs_call_type afs_RXVLGetEntryByName = {
130 .name = "VL.GetEntryByName",
130 .deliver = afs_deliver_vl_get_entry_by_xxx, 131 .deliver = afs_deliver_vl_get_entry_by_xxx,
131 .abort_to_error = afs_vl_abort_to_error, 132 .abort_to_error = afs_vl_abort_to_error,
132 .destructor = afs_flat_call_destructor, 133 .destructor = afs_flat_call_destructor,
@@ -136,6 +137,7 @@ static const struct afs_call_type afs_RXVLGetEntryByName = {
136 * VL.GetEntryById operation type 137 * VL.GetEntryById operation type
137 */ 138 */
138static const struct afs_call_type afs_RXVLGetEntryById = { 139static const struct afs_call_type afs_RXVLGetEntryById = {
140 .name = "VL.GetEntryById",
139 .deliver = afs_deliver_vl_get_entry_by_xxx, 141 .deliver = afs_deliver_vl_get_entry_by_xxx,
140 .abort_to_error = afs_vl_abort_to_error, 142 .abort_to_error = afs_vl_abort_to_error,
141 .destructor = afs_flat_call_destructor, 143 .destructor = afs_flat_call_destructor,
@@ -145,6 +147,7 @@ static const struct afs_call_type afs_RXVLGetEntryById = {
145 * dispatch a get volume entry by name operation 147 * dispatch a get volume entry by name operation
146 */ 148 */
147int afs_vl_get_entry_by_name(struct in_addr *addr, 149int afs_vl_get_entry_by_name(struct in_addr *addr,
150 struct key *key,
148 const char *volname, 151 const char *volname,
149 struct afs_cache_vlocation *entry, 152 struct afs_cache_vlocation *entry,
150 const struct afs_wait_mode *wait_mode) 153 const struct afs_wait_mode *wait_mode)
@@ -163,6 +166,7 @@ int afs_vl_get_entry_by_name(struct in_addr *addr,
163 if (!call) 166 if (!call)
164 return -ENOMEM; 167 return -ENOMEM;
165 168
169 call->key = key;
166 call->reply = entry; 170 call->reply = entry;
167 call->service_id = VL_SERVICE; 171 call->service_id = VL_SERVICE;
168 call->port = htons(AFS_VL_PORT); 172 call->port = htons(AFS_VL_PORT);
@@ -183,6 +187,7 @@ int afs_vl_get_entry_by_name(struct in_addr *addr,
183 * dispatch a get volume entry by ID operation 187 * dispatch a get volume entry by ID operation
184 */ 188 */
185int afs_vl_get_entry_by_id(struct in_addr *addr, 189int afs_vl_get_entry_by_id(struct in_addr *addr,
190 struct key *key,
186 afs_volid_t volid, 191 afs_volid_t volid,
187 afs_voltype_t voltype, 192 afs_voltype_t voltype,
188 struct afs_cache_vlocation *entry, 193 struct afs_cache_vlocation *entry,
@@ -197,6 +202,7 @@ int afs_vl_get_entry_by_id(struct in_addr *addr,
197 if (!call) 202 if (!call)
198 return -ENOMEM; 203 return -ENOMEM;
199 204
205 call->key = key;
200 call->reply = entry; 206 call->reply = entry;
201 call->service_id = VL_SERVICE; 207 call->service_id = VL_SERVICE;
202 call->port = htons(AFS_VL_PORT); 208 call->port = htons(AFS_VL_PORT);
diff --git a/fs/afs/vlocation.c b/fs/afs/vlocation.c
index 60cb2f408c75..7d9815e9ae0f 100644
--- a/fs/afs/vlocation.c
+++ b/fs/afs/vlocation.c
@@ -33,6 +33,7 @@ static struct workqueue_struct *afs_vlocation_update_worker;
33 * about the volume in question 33 * about the volume in question
34 */ 34 */
35static int afs_vlocation_access_vl_by_name(struct afs_vlocation *vl, 35static int afs_vlocation_access_vl_by_name(struct afs_vlocation *vl,
36 struct key *key,
36 struct afs_cache_vlocation *vldb) 37 struct afs_cache_vlocation *vldb)
37{ 38{
38 struct afs_cell *cell = vl->cell; 39 struct afs_cell *cell = vl->cell;
@@ -49,7 +50,7 @@ static int afs_vlocation_access_vl_by_name(struct afs_vlocation *vl,
49 _debug("CellServ[%hu]: %08x", cell->vl_curr_svix, addr.s_addr); 50 _debug("CellServ[%hu]: %08x", cell->vl_curr_svix, addr.s_addr);
50 51
51 /* attempt to access the VL server */ 52 /* attempt to access the VL server */
52 ret = afs_vl_get_entry_by_name(&addr, vl->vldb.name, vldb, 53 ret = afs_vl_get_entry_by_name(&addr, key, vl->vldb.name, vldb,
53 &afs_sync_call); 54 &afs_sync_call);
54 switch (ret) { 55 switch (ret) {
55 case 0: 56 case 0:
@@ -86,6 +87,7 @@ out:
86 * about the volume in question 87 * about the volume in question
87 */ 88 */
88static int afs_vlocation_access_vl_by_id(struct afs_vlocation *vl, 89static int afs_vlocation_access_vl_by_id(struct afs_vlocation *vl,
90 struct key *key,
89 afs_volid_t volid, 91 afs_volid_t volid,
90 afs_voltype_t voltype, 92 afs_voltype_t voltype,
91 struct afs_cache_vlocation *vldb) 93 struct afs_cache_vlocation *vldb)
@@ -104,7 +106,7 @@ static int afs_vlocation_access_vl_by_id(struct afs_vlocation *vl,
104 _debug("CellServ[%hu]: %08x", cell->vl_curr_svix, addr.s_addr); 106 _debug("CellServ[%hu]: %08x", cell->vl_curr_svix, addr.s_addr);
105 107
106 /* attempt to access the VL server */ 108 /* attempt to access the VL server */
107 ret = afs_vl_get_entry_by_id(&addr, volid, voltype, vldb, 109 ret = afs_vl_get_entry_by_id(&addr, key, volid, voltype, vldb,
108 &afs_sync_call); 110 &afs_sync_call);
109 switch (ret) { 111 switch (ret) {
110 case 0: 112 case 0:
@@ -188,6 +190,7 @@ static struct afs_vlocation *afs_vlocation_alloc(struct afs_cell *cell,
188 * update record if we found it in the cache 190 * update record if we found it in the cache
189 */ 191 */
190static int afs_vlocation_update_record(struct afs_vlocation *vl, 192static int afs_vlocation_update_record(struct afs_vlocation *vl,
193 struct key *key,
191 struct afs_cache_vlocation *vldb) 194 struct afs_cache_vlocation *vldb)
192{ 195{
193 afs_voltype_t voltype; 196 afs_voltype_t voltype;
@@ -228,7 +231,7 @@ static int afs_vlocation_update_record(struct afs_vlocation *vl,
228 /* contact the server to make sure the volume is still available 231 /* contact the server to make sure the volume is still available
229 * - TODO: need to handle disconnected operation here 232 * - TODO: need to handle disconnected operation here
230 */ 233 */
231 ret = afs_vlocation_access_vl_by_id(vl, vid, voltype, vldb); 234 ret = afs_vlocation_access_vl_by_id(vl, key, vid, voltype, vldb);
232 switch (ret) { 235 switch (ret) {
233 /* net error */ 236 /* net error */
234 default: 237 default:
@@ -287,7 +290,8 @@ static void afs_vlocation_apply_update(struct afs_vlocation *vl,
287 * fill in a volume location record, consulting the cache and the VL server 290 * fill in a volume location record, consulting the cache and the VL server
288 * both 291 * both
289 */ 292 */
290static int afs_vlocation_fill_in_record(struct afs_vlocation *vl) 293static int afs_vlocation_fill_in_record(struct afs_vlocation *vl,
294 struct key *key)
291{ 295{
292 struct afs_cache_vlocation vldb; 296 struct afs_cache_vlocation vldb;
293 int ret; 297 int ret;
@@ -310,11 +314,11 @@ static int afs_vlocation_fill_in_record(struct afs_vlocation *vl)
310 /* try to update a known volume in the cell VL databases by 314 /* try to update a known volume in the cell VL databases by
311 * ID as the name may have changed */ 315 * ID as the name may have changed */
312 _debug("found in cache"); 316 _debug("found in cache");
313 ret = afs_vlocation_update_record(vl, &vldb); 317 ret = afs_vlocation_update_record(vl, key, &vldb);
314 } else { 318 } else {
315 /* try to look up an unknown volume in the cell VL databases by 319 /* try to look up an unknown volume in the cell VL databases by
316 * name */ 320 * name */
317 ret = afs_vlocation_access_vl_by_name(vl, &vldb); 321 ret = afs_vlocation_access_vl_by_name(vl, key, &vldb);
318 if (ret < 0) { 322 if (ret < 0) {
319 printk("kAFS: failed to locate '%s' in cell '%s'\n", 323 printk("kAFS: failed to locate '%s' in cell '%s'\n",
320 vl->vldb.name, vl->cell->name); 324 vl->vldb.name, vl->cell->name);
@@ -366,14 +370,16 @@ void afs_vlocation_queue_for_updates(struct afs_vlocation *vl)
366 * - insert/update in the local cache if did get a VL response 370 * - insert/update in the local cache if did get a VL response
367 */ 371 */
368struct afs_vlocation *afs_vlocation_lookup(struct afs_cell *cell, 372struct afs_vlocation *afs_vlocation_lookup(struct afs_cell *cell,
373 struct key *key,
369 const char *name, 374 const char *name,
370 size_t namesz) 375 size_t namesz)
371{ 376{
372 struct afs_vlocation *vl; 377 struct afs_vlocation *vl;
373 int ret; 378 int ret;
374 379
375 _enter("{%s},%*.*s,%zu", 380 _enter("{%s},{%x},%*.*s,%zu",
376 cell->name, (int) namesz, (int) namesz, name, namesz); 381 cell->name, key_serial(key),
382 (int) namesz, (int) namesz, name, namesz);
377 383
378 if (namesz > sizeof(vl->vldb.name)) { 384 if (namesz > sizeof(vl->vldb.name)) {
379 _leave(" = -ENAMETOOLONG"); 385 _leave(" = -ENAMETOOLONG");
@@ -405,7 +411,7 @@ struct afs_vlocation *afs_vlocation_lookup(struct afs_cell *cell,
405 up_write(&cell->vl_sem); 411 up_write(&cell->vl_sem);
406 412
407fill_in_record: 413fill_in_record:
408 ret = afs_vlocation_fill_in_record(vl); 414 ret = afs_vlocation_fill_in_record(vl, key);
409 if (ret < 0) 415 if (ret < 0)
410 goto error_abandon; 416 goto error_abandon;
411 vl->state = AFS_VL_VALID; 417 vl->state = AFS_VL_VALID;
@@ -656,7 +662,7 @@ static void afs_vlocation_updater(struct work_struct *work)
656 vl->upd_rej_cnt = 0; 662 vl->upd_rej_cnt = 0;
657 vl->upd_busy_cnt = 0; 663 vl->upd_busy_cnt = 0;
658 664
659 ret = afs_vlocation_update_record(vl, &vldb); 665 ret = afs_vlocation_update_record(vl, NULL, &vldb);
660 switch (ret) { 666 switch (ret) {
661 case 0: 667 case 0:
662 afs_vlocation_apply_update(vl, &vldb); 668 afs_vlocation_apply_update(vl, &vldb);
diff --git a/fs/afs/vnode.c b/fs/afs/vnode.c
index d2ca1398474f..160097619ec7 100644
--- a/fs/afs/vnode.c
+++ b/fs/afs/vnode.c
@@ -238,9 +238,11 @@ static void afs_vnode_finalise_status_update(struct afs_vnode *vnode,
238 * - there are any outstanding ops that will fetch the status 238 * - there are any outstanding ops that will fetch the status
239 * - TODO implement local caching 239 * - TODO implement local caching
240 */ 240 */
241int afs_vnode_fetch_status(struct afs_vnode *vnode) 241int afs_vnode_fetch_status(struct afs_vnode *vnode,
242 struct afs_vnode *auth_vnode, struct key *key)
242{ 243{
243 struct afs_server *server; 244 struct afs_server *server;
245 unsigned long acl_order;
244 int ret; 246 int ret;
245 247
246 DECLARE_WAITQUEUE(myself, current); 248 DECLARE_WAITQUEUE(myself, current);
@@ -260,6 +262,10 @@ int afs_vnode_fetch_status(struct afs_vnode *vnode)
260 return -ENOENT; 262 return -ENOENT;
261 } 263 }
262 264
265 acl_order = 0;
266 if (auth_vnode)
267 acl_order = auth_vnode->acl_order;
268
263 spin_lock(&vnode->lock); 269 spin_lock(&vnode->lock);
264 270
265 if (!test_bit(AFS_VNODE_CB_BROKEN, &vnode->flags) && 271 if (!test_bit(AFS_VNODE_CB_BROKEN, &vnode->flags) &&
@@ -324,12 +330,14 @@ get_anyway:
324 _debug("USING SERVER: %p{%08x}", 330 _debug("USING SERVER: %p{%08x}",
325 server, ntohl(server->addr.s_addr)); 331 server, ntohl(server->addr.s_addr));
326 332
327 ret = afs_fs_fetch_file_status(server, vnode, NULL, 333 ret = afs_fs_fetch_file_status(server, key, vnode, NULL,
328 &afs_sync_call); 334 &afs_sync_call);
329 335
330 } while (!afs_volume_release_fileserver(vnode, server, ret)); 336 } while (!afs_volume_release_fileserver(vnode, server, ret));
331 337
332 /* adjust the flags */ 338 /* adjust the flags */
339 if (ret == 0 && auth_vnode)
340 afs_cache_permit(vnode, key, acl_order);
333 afs_vnode_finalise_status_update(vnode, server, ret); 341 afs_vnode_finalise_status_update(vnode, server, ret);
334 342
335 _leave(" = %d", ret); 343 _leave(" = %d", ret);
@@ -340,17 +348,18 @@ get_anyway:
340 * fetch file data from the volume 348 * fetch file data from the volume
341 * - TODO implement caching and server failover 349 * - TODO implement caching and server failover
342 */ 350 */
343int afs_vnode_fetch_data(struct afs_vnode *vnode, off_t offset, size_t length, 351int afs_vnode_fetch_data(struct afs_vnode *vnode, struct key *key,
344 struct page *page) 352 off_t offset, size_t length, struct page *page)
345{ 353{
346 struct afs_server *server; 354 struct afs_server *server;
347 int ret; 355 int ret;
348 356
349 _enter("%s,{%u,%u,%u}", 357 _enter("%s{%u,%u,%u},%x,,,",
350 vnode->volume->vlocation->vldb.name, 358 vnode->volume->vlocation->vldb.name,
351 vnode->fid.vid, 359 vnode->fid.vid,
352 vnode->fid.vnode, 360 vnode->fid.vnode,
353 vnode->fid.unique); 361 vnode->fid.unique,
362 key_serial(key));
354 363
355 /* this op will fetch the status */ 364 /* this op will fetch the status */
356 spin_lock(&vnode->lock); 365 spin_lock(&vnode->lock);
@@ -367,8 +376,8 @@ int afs_vnode_fetch_data(struct afs_vnode *vnode, off_t offset, size_t length,
367 376
368 _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr)); 377 _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
369 378
370 ret = afs_fs_fetch_data(server, vnode, offset, length, page, 379 ret = afs_fs_fetch_data(server, key, vnode, offset, length,
371 NULL, &afs_sync_call); 380 page, NULL, &afs_sync_call);
372 381
373 } while (!afs_volume_release_fileserver(vnode, server, ret)); 382 } while (!afs_volume_release_fileserver(vnode, server, ret));
374 383
diff --git a/fs/afs/volume.c b/fs/afs/volume.c
index 45491cfd4f4f..15e13678c216 100644
--- a/fs/afs/volume.c
+++ b/fs/afs/volume.c
@@ -41,83 +41,20 @@ static const char *afs_voltypes[] = { "R/W", "R/O", "BAK" };
41 * - Rule 3: If parent volume is R/W, then only mount R/W volume unless 41 * - Rule 3: If parent volume is R/W, then only mount R/W volume unless
42 * explicitly told otherwise 42 * explicitly told otherwise
43 */ 43 */
44struct afs_volume *afs_volume_lookup(const char *name, struct afs_cell *cell, 44struct afs_volume *afs_volume_lookup(struct afs_mount_params *params)
45 int rwpath)
46{ 45{
47 struct afs_vlocation *vlocation = NULL; 46 struct afs_vlocation *vlocation = NULL;
48 struct afs_volume *volume = NULL; 47 struct afs_volume *volume = NULL;
49 struct afs_server *server = NULL; 48 struct afs_server *server = NULL;
50 afs_voltype_t type;
51 const char *cellname, *volname, *suffix;
52 char srvtmask; 49 char srvtmask;
53 int force, ret, loop, cellnamesz, volnamesz; 50 int ret, loop;
54 51
55 _enter("%s,,%d,", name, rwpath); 52 _enter("{%*.*s,%d}",
56 53 params->volnamesz, params->volnamesz, params->volname, params->rwpath);
57 if (!name || (name[0] != '%' && name[0] != '#') || !name[1]) {
58 printk("kAFS: unparsable volume name\n");
59 return ERR_PTR(-EINVAL);
60 }
61
62 /* determine the type of volume we're looking for */
63 force = 0;
64 type = AFSVL_ROVOL;
65
66 if (rwpath || name[0] == '%') {
67 type = AFSVL_RWVOL;
68 force = 1;
69 }
70
71 suffix = strrchr(name, '.');
72 if (suffix) {
73 if (strcmp(suffix, ".readonly") == 0) {
74 type = AFSVL_ROVOL;
75 force = 1;
76 } else if (strcmp(suffix, ".backup") == 0) {
77 type = AFSVL_BACKVOL;
78 force = 1;
79 } else if (suffix[1] == 0) {
80 } else {
81 suffix = NULL;
82 }
83 }
84
85 /* split the cell and volume names */
86 name++;
87 volname = strchr(name, ':');
88 if (volname) {
89 cellname = name;
90 cellnamesz = volname - name;
91 volname++;
92 } else {
93 volname = name;
94 cellname = NULL;
95 cellnamesz = 0;
96 }
97
98 volnamesz = suffix ? suffix - volname : strlen(volname);
99
100 _debug("CELL:%*.*s [%p] VOLUME:%*.*s SUFFIX:%s TYPE:%d%s",
101 cellnamesz, cellnamesz, cellname ?: "", cell,
102 volnamesz, volnamesz, volname, suffix ?: "-",
103 type,
104 force ? " FORCE" : "");
105
106 /* lookup the cell record */
107 if (cellname || !cell) {
108 cell = afs_cell_lookup(cellname, cellnamesz);
109 if (IS_ERR(cell)) {
110 ret = PTR_ERR(cell);
111 printk("kAFS: unable to lookup cell '%s'\n",
112 cellname ?: "");
113 goto error;
114 }
115 } else {
116 afs_get_cell(cell);
117 }
118 54
119 /* lookup the volume location record */ 55 /* lookup the volume location record */
120 vlocation = afs_vlocation_lookup(cell, volname, volnamesz); 56 vlocation = afs_vlocation_lookup(params->cell, params->key,
57 params->volname, params->volnamesz);
121 if (IS_ERR(vlocation)) { 58 if (IS_ERR(vlocation)) {
122 ret = PTR_ERR(vlocation); 59 ret = PTR_ERR(vlocation);
123 vlocation = NULL; 60 vlocation = NULL;
@@ -126,30 +63,30 @@ struct afs_volume *afs_volume_lookup(const char *name, struct afs_cell *cell,
126 63
127 /* make the final decision on the type we want */ 64 /* make the final decision on the type we want */
128 ret = -ENOMEDIUM; 65 ret = -ENOMEDIUM;
129 if (force && !(vlocation->vldb.vidmask & (1 << type))) 66 if (params->force && !(vlocation->vldb.vidmask & (1 << params->type)))
130 goto error; 67 goto error;
131 68
132 srvtmask = 0; 69 srvtmask = 0;
133 for (loop = 0; loop < vlocation->vldb.nservers; loop++) 70 for (loop = 0; loop < vlocation->vldb.nservers; loop++)
134 srvtmask |= vlocation->vldb.srvtmask[loop]; 71 srvtmask |= vlocation->vldb.srvtmask[loop];
135 72
136 if (force) { 73 if (params->force) {
137 if (!(srvtmask & (1 << type))) 74 if (!(srvtmask & (1 << params->type)))
138 goto error; 75 goto error;
139 } else if (srvtmask & AFS_VOL_VTM_RO) { 76 } else if (srvtmask & AFS_VOL_VTM_RO) {
140 type = AFSVL_ROVOL; 77 params->type = AFSVL_ROVOL;
141 } else if (srvtmask & AFS_VOL_VTM_RW) { 78 } else if (srvtmask & AFS_VOL_VTM_RW) {
142 type = AFSVL_RWVOL; 79 params->type = AFSVL_RWVOL;
143 } else { 80 } else {
144 goto error; 81 goto error;
145 } 82 }
146 83
147 down_write(&cell->vl_sem); 84 down_write(&params->cell->vl_sem);
148 85
149 /* is the volume already active? */ 86 /* is the volume already active? */
150 if (vlocation->vols[type]) { 87 if (vlocation->vols[params->type]) {
151 /* yes - re-use it */ 88 /* yes - re-use it */
152 volume = vlocation->vols[type]; 89 volume = vlocation->vols[params->type];
153 afs_get_volume(volume); 90 afs_get_volume(volume);
154 goto success; 91 goto success;
155 } 92 }
@@ -163,10 +100,10 @@ struct afs_volume *afs_volume_lookup(const char *name, struct afs_cell *cell,
163 goto error_up; 100 goto error_up;
164 101
165 atomic_set(&volume->usage, 1); 102 atomic_set(&volume->usage, 1);
166 volume->type = type; 103 volume->type = params->type;
167 volume->type_force = force; 104 volume->type_force = params->force;
168 volume->cell = cell; 105 volume->cell = params->cell;
169 volume->vid = vlocation->vldb.vid[type]; 106 volume->vid = vlocation->vldb.vid[params->type];
170 107
171 init_rwsem(&volume->server_sem); 108 init_rwsem(&volume->server_sem);
172 109
@@ -196,28 +133,26 @@ struct afs_volume *afs_volume_lookup(const char *name, struct afs_cell *cell,
196 afs_get_vlocation(vlocation); 133 afs_get_vlocation(vlocation);
197 volume->vlocation = vlocation; 134 volume->vlocation = vlocation;
198 135
199 vlocation->vols[type] = volume; 136 vlocation->vols[volume->type] = volume;
200 137
201success: 138success:
202 _debug("kAFS selected %s volume %08x", 139 _debug("kAFS selected %s volume %08x",
203 afs_voltypes[volume->type], volume->vid); 140 afs_voltypes[volume->type], volume->vid);
204 up_write(&cell->vl_sem); 141 up_write(&params->cell->vl_sem);
205 afs_put_vlocation(vlocation); 142 afs_put_vlocation(vlocation);
206 afs_put_cell(cell);
207 _leave(" = %p", volume); 143 _leave(" = %p", volume);
208 return volume; 144 return volume;
209 145
210 /* clean up */ 146 /* clean up */
211error_up: 147error_up:
212 up_write(&cell->vl_sem); 148 up_write(&params->cell->vl_sem);
213error: 149error:
214 afs_put_vlocation(vlocation); 150 afs_put_vlocation(vlocation);
215 afs_put_cell(cell);
216 _leave(" = %d", ret); 151 _leave(" = %d", ret);
217 return ERR_PTR(ret); 152 return ERR_PTR(ret);
218 153
219error_discard: 154error_discard:
220 up_write(&cell->vl_sem); 155 up_write(&params->cell->vl_sem);
221 156
222 for (loop = volume->nservers - 1; loop >= 0; loop--) 157 for (loop = volume->nservers - 1; loop >= 0; loop--)
223 afs_put_server(volume->servers[loop]); 158 afs_put_server(volume->servers[loop]);