Skip to contentSkip to conversation

PAG support only

PATCH In review David Howells 7 participants 12 messages May 13, 2003 – May 16, 2003

Subsystems (6)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 PAG support only

Hi Linus,

Due to the slight unpopularity of the AFS multiplexor, here's a patch with only the PAG support.

David

arch/i386/kernel/entry.S +2 -1
diff -uNr linux-2.5.69/arch/i386/kernel/entry.S linux-2.5.69-cred/arch/i386/kernel/entry.S
@@ -852,6 +852,7 @@
  	.long sys_clock_gettime		/* 265 */
  	.long sys_clock_getres
  	.long sys_clock_nanosleep
- 
+	.long sys_setpag
+	.long sys_getpag
  
 nr_syscalls=(.-sys_call_table)/4
fs/file_table.c +1 -0
diff -uNr linux-2.5.69/fs/file_table.c linux-2.5.69-cred/fs/file_table.c
@@ -166,6 +166,7 @@
 	if (file->f_op && file->f_op->release)
 		file->f_op->release(inode, file);
 	security_file_free(file);
+	if (file->f_token) vfs_token_put(file->f_token);
 	fops_put(file->f_op);
 	if (file->f_mode & FMODE_WRITE)
 		put_write_access(inode);
fs/open.c +1 -1
diff -uNr linux-2.5.69/fs/open.c linux-2.5.69-cred/fs/open.c
@@ -46,7 +46,7 @@
 	struct nameidata nd;
 	int error;
 
-	error = user_path_walk(path, &nd);
+	error = user_path_walk(path,&nd);
 	if (!error) {
 		struct statfs tmp;
 		error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp);
fs/proc/array.c +2 -1
diff -uNr linux-2.5.69/fs/proc/array.c linux-2.5.69-cred/fs/proc/array.c
@@ -154,13 +154,14 @@
 	read_lock(&tasklist_lock);
 	buffer += sprintf(buffer,
 		"State:\t%s\n"
+		"Pag:\t%d\n"
 		"Tgid:\t%d\n"
 		"Pid:\t%d\n"
 		"PPid:\t%d\n"
 		"TracerPid:\t%d\n"
 		"Uid:\t%d\t%d\t%d\t%d\n"
 		"Gid:\t%d\t%d\t%d\t%d\n",
-		get_task_state(p), p->tgid,
+		get_task_state(p), p->vfspag ? p->vfspag->pag : 0, p->tgid,
 		p->pid, p->pid ? p->real_parent->pid : 0,
 		p->pid && p->ptrace ? p->parent->pid : 0,
 		p->uid, p->euid, p->suid, p->fsuid,
include/asm-i386/posix_types.h +1 -0
diff -uNr linux-2.5.69/include/asm-i386/posix_types.h linux-2.5.69-cred/include/asm-i386/posix_types.h
@@ -13,6 +13,7 @@
 typedef unsigned short	__kernel_nlink_t;
 typedef long		__kernel_off_t;
 typedef int		__kernel_pid_t;
+typedef int		__kernel_pag_t;
 typedef unsigned short	__kernel_ipc_pid_t;
 typedef unsigned short	__kernel_uid_t;
 typedef unsigned short	__kernel_gid_t;
include/asm-i386/unistd.h +3 -1
diff -uNr linux-2.5.69/include/asm-i386/unistd.h linux-2.5.69-cred/include/asm-i386/unistd.h
@@ -273,8 +273,10 @@
 #define __NR_clock_gettime	(__NR_timer_create+6)
 #define __NR_clock_getres	(__NR_timer_create+7)
 #define __NR_clock_nanosleep	(__NR_timer_create+8)
+#define __NR_setpag		268
+#define __NR_getpag		269
 
-#define NR_syscalls 268
+#define NR_syscalls 270
 
 /* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */
 
include/linux/cred.h +79 -0

79 lines not on this page · raw message

include/linux/fs.h +1 -0
diff -uNr linux-2.5.69/include/linux/fs.h linux-2.5.69-cred/include/linux/fs.h
@@ -430,6 +430,7 @@
 	mode_t			f_mode;
 	loff_t			f_pos;
 	struct fown_struct	f_owner;
+	struct vfs_token	*f_token;	/* governing credential */
 	unsigned int		f_uid, f_gid;
 	int			f_error;
 	struct file_ra_state	f_ra;
include/linux/sched.h +2 -0
diff -uNr linux-2.5.69/include/linux/sched.h linux-2.5.69-cred/include/linux/sched.h
@@ -28,6 +28,7 @@
 #include <linux/completion.h>
 #include <linux/pid.h>
 #include <linux/percpu.h>
+#include <linux/cred.h>
 
 struct exec_domain;
 
@@ -387,6 +388,7 @@
 	gid_t gid,egid,sgid,fsgid;
 	int ngroups;
 	gid_t	groups[NGROUPS];
+	struct vfs_pag *vfspag;
 	kernel_cap_t   cap_effective, cap_inheritable, cap_permitted;
 	int keep_capabilities:1;
 	struct user_struct *user;
include/linux/types.h +1 -0
diff -uNr linux-2.5.69/include/linux/types.h linux-2.5.69-cred/include/linux/types.h
@@ -24,6 +24,7 @@
 typedef __kernel_nlink_t	nlink_t;
 typedef __kernel_off_t		off_t;
 typedef __kernel_pid_t		pid_t;
+typedef __kernel_pag_t		pag_t;
 typedef __kernel_daddr_t	daddr_t;
 typedef __kernel_key_t		key_t;
 typedef __kernel_suseconds_t	suseconds_t;
init/main.c +2 -0
diff -uNr linux-2.5.69/init/main.c linux-2.5.69-cred/init/main.c
@@ -80,6 +80,7 @@
 extern void pidhash_init(void);
 extern void pidmap_init(void);
 extern void pte_chain_init(void);
+extern void credentials_init(void);
 extern void radix_tree_init(void);
 extern void free_initmem(void);
 extern void populate_rootfs(void);
@@ -434,6 +435,7 @@
 	pidmap_init();
 	pgtable_cache_init();
 	pte_chain_init();
+	credentials_init();
 	fork_init(num_physpages);
 	proc_caches_init();
 	security_scaffolding_startup();
kernel/cred.c +367 -0

367 lines not on this page · raw message

kernel/fork.c +3 -0
diff -uNr linux-2.5.69/kernel/fork.c linux-2.5.69-cred/kernel/fork.c
@@ -884,6 +884,9 @@
 
 	if (clone_flags & CLONE_CHILD_SETTID)
 		p->set_child_tid = child_tidptr;
+
+	if (p->vfspag) vfs_pag_get(p->vfspag);
+
 	/*
 	 * Clear TID on mm_release()?
 	 */
kernel/Makefile +1 -1
diff -uNr linux-2.5.69/kernel/Makefile linux-2.5.69-cred/kernel/Makefile
@@ -3,7 +3,7 @@
 #
 
 obj-y     = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
-	    exit.o itimer.o time.o softirq.o resource.o \
+	    cred.o exit.o itimer.o time.o softirq.o resource.o \
 	    sysctl.o capability.o ptrace.o timer.o user.o \
 	    signal.o sys.o kmod.o workqueue.o futex.o pid.o \
 	    rcupdate.o intermodule.o extable.o params.o posix-timers.o
#1 lore raw
Quoted 1 line · David Howells

Due to the slight unpopularity of the AFS multiplexor, here's a patch with

I think of it as "bitter pill we will be forced to swallow", and then hope and pray that we can use your AFS stuff as a transition step to -- after many years -- migrate people away from AFS altogether. ;-)

Or maybe that's just wishful thinking.

fs/open.c line 49

Quoted 9 lines

diff -uNr linux-2.5.69/fs/open.c linux-2.5.69-cred/fs/open.c

fs/open.c +1 -1
@@ -46,7 +46,7 @@
 	struct nameidata nd;
 	int error;
 
-	error = user_path_walk(path, &nd);
+	error = user_path_walk(path,&nd);

a bit of noise

Quoted 10 lines
include/asm-i386/posix_types.h +1 -0
@@ -13,6 +13,7 @@
 typedef unsigned short	__kernel_nlink_t;
 typedef long		__kernel_off_t;
 typedef int		__kernel_pid_t;
+typedef int		__kernel_pag_t;
 typedef unsigned short	__kernel_ipc_pid_t;
 typedef unsigned short	__kernel_uid_t;
 typedef unsigned short	__kernel_gid_t;

[...]

include/asm-i386/posix_types.h

Quoted 2 lines
include/asm-i386/posix_types.h +2 -0
+int sys_setpag(pag_t pag)
+int sys_getpag(void)

Surely you want s/int/long/ here?

Two other comments:

* even though you're referencing 'current', I'm a bit surprised you don't need any locking at all in sys_getpag. Is that guaranteed through judicious use of xchg()?

* is it reasonable to make credentials support a config option? Long term I worry about Linux kernel becoming another Irix, supporting thousands of rarely used syscalls unconditionally.

Jeff

P.S. Looking forward to the "cachefs" code you have in your cvs repo hitting mainline. That will be fun for NFS. <grin>

#2 lore raw
In reply to David Howells

fs/file_table.c line 169

Quoted 5 lines
fs/file_table.c +1 -0
@@ -166,6 +166,7 @@
 	if (file->f_op && file->f_op->release)
 		file->f_op->release(inode, file);
 	security_file_free(file);
+	if (file->f_token) vfs_token_put(file->f_token);

Please split this into 2 lines as per Documentation/CodingStyle. Even better make vfs_token_put handle a NULL argument.

fs/open.c line 49

Quoted 9 lines

diff -uNr linux-2.5.69/fs/open.c linux-2.5.69-cred/fs/open.c

fs/open.c +1 -1
@@ -46,7 +46,7 @@
 	struct nameidata nd;
 	int error;
 
-	error = user_path_walk(path, &nd);
+	error = user_path_walk(path,&nd);

Random whitespace change - and even a wrong one..

fs/open.c

Quoted 4 lines
fs/open.c +4 -0
+static inline int is_vfs_token_valid(struct vfs_token *vtoken)
+{
+	return !list_empty(&vtoken->link);
+}

This one is not used - and the name would imply it would be used without taking a lock and thus racy..

fs/open.c

Quoted 2 lines
fs/open.c +2 -0
+static kmem_cache_t *vfs_token_cache;
+static kmem_cache_t *vfs_pag_cache;

How many of those will be around for a typical AFS client? I have the vague feeling the slabs are overkill..

fs/open.c

Quoted 5 lines
fs/open.c +5 -0
+	if (pag>0) {
+		/* join existing PAG */
+		if (tsk->vfspag->pag &&
+		    tsk->vfspag->pag==pag)
+			return pag;

Please try to get your code in conformance with Documentation/CodingStyle.

Quoted 1 line

+} /* end vfs_pag_put() */

#3 lore raw
Quoted 5 lines

kernel/cred.c line 22

Quoted 2 lines
kernel/cred.c +2 -0
+static kmem_cache_t *vfs_token_cache;
+static kmem_cache_t *vfs_pag_cache;

How many of those will be around for a typical AFS client? I have the vague feeling the slabs are overkill..

What's a "typical client"?

I have machines that typically have 0 pags and tokens in kernel, and I have machines that typically have a few hundred to a thousand.

Per pag on most clients will only have a single token, but number of pags will depend totally on the nature of the machine.

I also have machines that have a few hundred pags around that don't have any tokens in them, but could at any time.

-- Nathan

------------------------------------------------------------
Nathan Neulinger EMail: [email protected]
University of Missouri - Rolla Phone: (573) 341-4841
Computing Services Fax: (573) 341-4216

#4 lore raw

[openafs-devel dropped from the Cc-list due to stupid subscriber only policy]

Quoted 7 lines · Nathan Neulinger
Quoted 5 lines

kernel/cred.c line 22

Quoted 2 lines
kernel/cred.c +2 -0
+static kmem_cache_t *vfs_token_cache;
+static kmem_cache_t *vfs_pag_cache;

How many of those will be around for a typical AFS client? I have the vague feeling the slabs are overkill..

What's a "typical client"?

The case we wan to optimize for. The question here is whether we really want a separate slab or whether it makes more senze to just use the new kmalloc slab (usually power of two sized).

#5 lore raw
In reply to Nathan Neulinger
Quoted 2 lines · Nathan Neulinger

Per pag on most clients will only have a single token, but number of pags will depend totally on the nature of the machine.

Uh, no, at least around MIT per-pag users usually have about 2-3 tokens on average. I've run with as many as 10. Please do not assume some max. number of tokens in a pag.

Quoted 4 lines

I also have machines that have a few hundred pags around that don't have any tokens in them, but could at any time.

-- Nathan

Signature · 4 lines
       Derek Atkins, SB '93 MIT EE, SM '95 MIT Media Laboratory
       Member, MIT Student Information Processing Board  (SIPB)
       URL: http://web.mit.edu/warlord/    PP-ASEL-IA     N1NWH
       [email protected]                        PGP key available
#6 lore raw
In reply to Christoph Hellwig
Quoted 2 lines · Christoph Hellwig

Please split this into 2 lines as per Documentation/CodingStyle. Even better make vfs_token_put handle a NULL argument.

Done the latter.

Quoted 1 line

Random whitespace change

Gone.

Quoted 1 line

- and even a wrong one..

I disagree, but no matter.

Quoted 5 lines

kernel/cred.c line 22

Quoted 2 lines
kernel/cred.c +2 -0
+static kmem_cache_t *vfs_token_cache;
+static kmem_cache_t *vfs_pag_cache;

How many of those will be around for a typical AFS client? I have the vague feeling the slabs are overkill..

And then there's the people who said I shouldn't use kmalloc but should create a slab instead...

Quoted 7 lines

kernel/cred.c line 83

Quoted 5 lines
kernel/cred.c +5 -0
+	if (pag>0) {
+		/* join existing PAG */
+		if (tsk->vfspag->pag &&
+		    tsk->vfspag->pag==pag)
+			return pag;

Please try to get your code in conformance with Documentation/CodingStyle.

You are suggesting what changes exactly?

David

#7 lore raw
Quoted 3 lines · David Howells
Quoted 1 line

- and even a wrong one..

I disagree, but no matter.

It's not a matter of your (or my) personal opinion of coding style. Linux is a big project and it's only maintainable if everyone sticks to a slightly similar style.

Quoted 8 lines
Quoted 5 lines

kernel/cred.c line 22

Quoted 2 lines
kernel/cred.c +2 -0
+static kmem_cache_t *vfs_token_cache;
+static kmem_cache_t *vfs_pag_cache;

How many of those will be around for a typical AFS client? I have the vague feeling the slabs are overkill..

And then there's the people who said I shouldn't use kmalloc but should create a slab instead...

That's why I ask how much it is used. Could you answer the question maybe?

Quoted 10 lines
Quoted 8 lines

kernel/cred.c line 83

Quoted 6 lines
kernel/cred.c +5 -0
+	if (pag>0) {
+		/* join existing PAG */
+		if (tsk->vfspag->pag &&
+		    tsk->vfspag->pag==pag)
+			return pag;

Please try to get your code in conformance with Documentation/CodingStyle.

You are suggesting what changes exactly?

spaces between operators to start with. It's not that difficult to read the above document and other core kernel code, though.

#8 lore raw
In reply to David Howells
Quoted 7 lines · David Howells

Hi Linus,

Due to the slight unpopularity of the AFS multiplexor, here's a patch with only the PAG support.

David

Hi David,

Some quetions/comments about the code:

Quoted 19 lines

diff -uNr linux-2.5.69/include/linux/cred.h linux-2.5.69-cred/include/linux/cred.h

include/linux/cred.h +15 -0
@@ -0,0 +1,79 @@
+#ifndef _LINUX_CRED_H
+#define _LINUX_CRED_H
+
+#ifdef __KERNEL__
+
+#include <linux/param.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/rbtree.h>
+#include <asm/atomic.h>
+
+/*
+ * VFS session authentication token cache
+ *
+ * This is used to store the data required for extra levels of filesystem

include/linux/cred.h line 25

Quoted 10 lines
include/linux/cred.h +10 -0
+ * security (such as AFS/NFS kerberos keys, Samba workgroup/user/pass, or NTFS
+ * ACLs).
+ *
+ * VFS authentication tokens contain a single blob of data, consisting of three
+ * parts, all next to each other:
+ *   (1) An FS name
+ *   (2) A key
+ *   (3) An arbitrary chunk of data
+ *
+ * Token blobs must not be changed once passed to the core kernel for management

If you know the type of the data, why keep it all in one binary blob, instead of a struct? cache effects?

Quoted 75 lines

diff -uNr linux-2.5.69/kernel/cred.c linux-2.5.69-cred/kernel/cred.c

kernel/cred.c +71 -0
@@ -0,0 +1,367 @@
+/* cred.c: authentication credentials management
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells ([email protected])
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/cred.h>
+
+static kmem_cache_t *vfs_token_cache;
+static kmem_cache_t *vfs_pag_cache;
+
+static struct rb_root	vfs_pag_tree;
+static spinlock_t	vfs_pag_lock = SPIN_LOCK_UNLOCKED;
+static pag_t		vfs_pag_next = 1;
+
+static void vfs_pag_init_once(void *_vfspag, kmem_cache_t *cachep, unsigned long flags)
+{
+	struct vfs_pag *vfspag = _vfspag;
+
+	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) {
+		memset(vfspag,0,sizeof(*vfspag));
+		INIT_LIST_HEAD(&vfspag->tokens);
+		rwlock_init(&vfspag->lock);
+	}
+}
+
+static void vfs_token_init_once(void *_vtoken, kmem_cache_t *cachep, unsigned long flags)
+{
+	struct vfs_token *vtoken = _vtoken;
+
+	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) {
+		memset(vtoken,0,sizeof(*vtoken));
+		INIT_LIST_HEAD(&vtoken->link);
+	}
+}
+
+void __init credentials_init(void)
+{
+	vfs_pag_cache = kmem_cache_create("vfs_pag",
+					      sizeof(struct vfs_pag),
+					      0,
+					      SLAB_HWCACHE_ALIGN,
+					      vfs_pag_init_once, NULL);
+	if (!vfs_pag_cache)
+		panic("Cannot create vfs pag SLAB cache");
+
+	vfs_token_cache = kmem_cache_create("vfs_token",
+					    sizeof(struct vfs_token),
+					    0,
+					    SLAB_HWCACHE_ALIGN,
+					    vfs_token_init_once, NULL);
+	if (!vfs_token_cache)
+		panic("Cannot create vfs token SLAB cache");
+}
+
+/*****************************************************************************/
+/*
+ * join an existing PAG (+ve), run without PAG (0), or create and join new PAG (-1)
+ * - returns ID of PAG joined or 0 if now running without a PAG

kernel/cred.c line 81

Quoted 10 lines
kernel/cred.c +10 -0
+ */
+int sys_setpag(pag_t pag)
+{
+	struct task_struct *tsk = current;
+	struct vfs_pag *vfspag, *xvfspag;
+	struct rb_node **p, *parent;
+
+	if (pag>0) {
+		/* join existing PAG */
+		if (tsk->vfspag->pag &&

Isn't the check here meant to be against tsk->vfspag? If not, there should be.

Quoted 47 lines
kernel/cred.c +47 -0
+		    tsk->vfspag->pag==pag)
+			return pag;
+
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+
+		spin_lock(&vfs_pag_lock);
+
+		parent = NULL;
+		p = &vfs_pag_tree.rb_node;
+
+		while (*p) {
+			parent = *p;
+			vfspag = rb_entry(parent,struct vfs_pag,node);
+
+			if (pag < vfspag->pag)
+				p = &(*p)->rb_left;
+			else if (pag > vfspag->pag)
+				p = &(*p)->rb_right;
+			else
+				goto pag_found;
+		}
+
+		spin_unlock(&vfs_pag_lock);
+		return -ENOENT;
+
+	pag_found:
+		xvfspag = xchg(&current->vfspag,vfs_pag_get(vfspag));
+		spin_unlock(&vfs_pag_lock);
+
+		if (xvfspag) vfs_pag_put(xvfspag);
+		return pag;
+	}
+	else if (pag==0) {
+		/* run without a PAG */
+		xvfspag = xchg(&current->vfspag,NULL);
+
+		if (xvfspag) vfs_pag_put(xvfspag);
+		return 0;
+	}
+	else if (pag!=-1) {
+		     return -EINVAL;
+	}
+
+	/* start new PAG */
+	vfspag = kmem_cache_alloc(vfs_pag_cache,SLAB_KERNEL);
+	if (!vfspag)

kernel/cred.c line 138

Quoted 10 lines
kernel/cred.c +10 -0
+		return -ENOMEM;
+
+	atomic_set(&vfspag->usage,1);
+
+	/* PAG IDs must be +ve, >0 and unique */
+	spin_lock(&vfs_pag_lock);
+
+	vfspag->pag = vfs_pag_next++;
+	if (vfspag->pag<1)
+		vfspag->pag = 1;

If vfs_pag_next wraps around, you will get two pag's with the value '1'.

Quoted 14 lines
kernel/cred.c +14 -0
+
+	parent = NULL;
+	p = &vfs_pag_tree.rb_node;
+
+	while (*p) {
+		parent = *p;
+		xvfspag = rb_entry(parent,struct vfs_pag,node);
+
+		if (vfspag->pag < xvfspag->pag)
+			p = &(*p)->rb_left;
+		else if (vfspag->pag > xvfspag->pag)
+			p = &(*p)->rb_right;
+		else
+			goto pag_exists;

kernel/cred.c line 162

Quoted 10 lines
kernel/cred.c +10 -0
+	}
+	goto insert_here;
+
+	/* we found a PAG of the same ID - walk the tree from that point
+	 * looking for the next unused PAG */
+ pag_exists:
+	for (;;) {
+		vfspag->pag = vfs_pag_next++;
+		if (vfspag->pag<1)
+			vfspag->pag = 1;

Likewise.

Quoted 15 lines
kernel/cred.c +15 -0
+struct vfs_token *vfs_pag_find_token(const char *fsname,
+				     unsigned short klen,
+				     const void *key)
+{
+	struct vfs_token *vtoken;
+	struct vfs_pag *vfspag = current->vfspag;
+
+	if (!vfspag) return NULL;
+
+	read_lock(&vfspag->lock);
+
+	list_for_each_entry(vtoken,&vfspag->tokens,link) {
+		if (vtoken->d_off-vtoken->k_off == klen &&
+		    strcmp(vtoken->blob,fsname)==0 &&
+		    memcmp(vtoken->blob+vtoken->k_off,key,klen)==0)

kernel/cred.c line 316

Quoted 10 lines
kernel/cred.c +10 -0
+			goto found;		    
+	}
+
+	read_unlock(&vfspag->lock);
+	return NULL;
+
+ found:
+	read_unlock(&vfspag->lock);
+	return vtoken;
+} /* end vfs_pag_find_token() */

Nothing in this patch appears to be using it. You aren't taking a reference to the token here, what's protecting it from disappearing after the return and before the caller gets a chance to do something with it?

Quoted 51 lines
kernel/cred.c +51 -0
+
+EXPORT_SYMBOL(vfs_pag_find_token);
+
+/*****************************************************************************/
+/*
+ * withdraw a token from a pag list
+ */
+void vfs_pag_withdraw_token(struct vfs_token *vtoken)
+{
+	struct vfs_pag *vfspag = current->vfspag;
+
+	if (!vfspag)
+		return;
+
+	write_lock(&vfspag->lock);
+	list_del_init(&vtoken->link);
+	write_unlock(&vfspag->lock);
+
+	vfs_token_put(vtoken);
+
+} /* end vfs_pag_withdraw_token() */
+
+EXPORT_SYMBOL(vfs_pag_withdraw_token);
+
+/*****************************************************************************/
+/*
+ * withdraw all tokens for the named filesystem from the current PAG
+ */
+void vfs_unpag(const char *fsname)
+{
+	struct list_head *_n, *_p;
+	struct vfs_token *vtoken;
+	struct vfs_pag *vfspag = current->vfspag;
+
+	if (!vfspag)
+		return;
+
+	write_lock(&vfspag->lock);
+
+	list_for_each_safe(_p,_n,&vfspag->tokens) {
+		vtoken = list_entry(_p,struct vfs_token,link);
+
+		if (strcmp(fsname,vtoken->blob)==0) {
+			list_del_init(&vtoken->link);
+			vfs_token_put(vtoken);
+		}
+	}
+
+	write_unlock(&vfspag->lock);
+
+} /* end vfs_unpag() */
Signature · 2 lines
Muli Ben-Yehuda
http://www.mulix.org
#9 lore raw
Quoted 5 lines · Muli Ben-Yehuda
Quoted 1 line

+ * VFS session authentication token cache

...

If you know the type of the data, why keep it all in one binary blob, instead of a struct? cache effects?

No. We _don't_ know the type of the data. A filesystem entrusts us with a token to keep in the PAG on its behalf. However, since this is meant to be a generic mechanism, it's entirely dependent on the fs as to what's in the blob.

Quoted 4 lines

kernel/cred.c line 81

Quoted 1 line
kernel/cred.c +1 -0
+		if (tsk->vfspag->pag &&

Isn't the check here meant to be against tsk->vfspag? If not, there should be.

Good point. Fixed.

Quoted 2 lines

If vfs_pag_next wraps around, you will get two pag's with the value '1'.

Not so:

+ else
+ goto pag_exists;
+ }
+ goto insert_here;
+
+ /* we found a PAG of the same ID - walk the tree from that point
+ * looking for the next unused PAG */
+ pag_exists:

If we find the target PAG already present, we keep incrementing the counter (making sure it doesn't go -ve or 0) and searching from the current node in the tree until we find a gap in the currently instantiated PAG number space.

We can make use of the properties of rb trees to do this more efficiently than just incrementing and repeating the search every time. rb_next() will return the node with next highest instantiated PAG number (or NULL when it reaches the end of the tree).

Quoted 4 lines

Nothing in this patch appears to be using it. You aren't taking a reference to the token here, what's protecting it from disappearing after the return and before the caller gets a chance to do something with it?

Thanks. Fixed.

David

#10 lore raw
Quoted 6 lines · David Howells
Quoted 3 lines · Muli Ben-Yehuda
Quoted 1 line

+ * VFS session authentication token cache

...

Quoted 7 lines
Quoted 2 lines

If you know the type of the data, why keep it all in one binary blob, instead of a struct? cache effects?

No. We _don't_ know the type of the data. A filesystem entrusts us with a token to keep in the PAG on its behalf. However, since this is meant to be a generic mechanism, it's entirely dependent on the fs as to what's in the blob.

But you do know the type of the data in the blob... it's char* fsname, const void* key and const void* data, according to your code.

You do

void* blob = kmalloc(fsname size + key size + data size)

memcpy(blob, fsname, fsname size)
memcpy(blob + fsname offset, key, key size) mempcy(blob + fsname offset + key offset, data, data size)

I suggest

struct fsblob { 
       const char* fsname; 
       const void* key; 
       size_t keysize; 
       const void* data; 
       size_t datasize; 
}; 

struct fsblob b;

b->fsname = kmalloc(fsname size)
memcpy(b->fsname, fsname, fsname size)

etc.

Your method loses on additional complexity, and wins on speed. However, unless it's really, really speed sensitive code, I would go for KISS any day.

Quoted 6 lines
Quoted 4 lines

Nothing in this patch appears to be using it. You aren't taking a reference to the token here, what's protecting it from disappearing after the return and before the caller gets a chance to do something with it?

Thanks. Fixed.

My pleasure.

Signature · 2 lines
Muli Ben-Yehuda
http://www.mulix.org
#11 lore raw
Quoted 8 lines
Quoted 5 lines

No. We _don't_ know the type of the data. A filesystem entrusts us with a token to keep in the PAG on its behalf. However, since this is meant to be a generic mechanism, it's entirely dependent on the fs as to what's in the blob.

But you do know the type of the data in the blob... it's char* fsname, const void* key and const void* data, according to your code.

We only partially know the data type (btw you should ignore the const's).

Quoted 7 lines
struct fsblob { 
       const char* fsname; 
       const void* key; 
       size_t keysize; 
       const void* data; 
       size_t datasize; 
}; 

There shouldn't be any consts in there, or else the pointers have to be cast prior to freeing.

So I'd have to do three kmalloc's instead of just the one (assuming struct fsblob was folded back into struct vfs_token)...

Quoted 1 line

Your method loses on additional complexity, and wins on speed.

Yours may use more memory overhead, though that's not easy to judge. Also yours is more complex in that there's more bits of memory to keep track of. OTOH, your suggestion may permit sharing of fsname and maybe also key under some circumstances.

Quoted 2 lines

However, unless it's really, really speed sensitive code, I would go for KISS any day.

OTOH, resources are very precious, and the complexity is actually straightforward and can be wrapped with macros or inline funcs.

David