summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-03-04 21:30:44 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-03-04 21:30:44 -0800
commit58a96a605ee4e5d573bec35c73bb6d015171cc16 (patch)
tree52d49ddf2e58f38f457a1e50ffc7254cd8683783 /fs
parent55d411d0e475235b36343c10216657d96e9da156 (diff)
parent05e7304908ec281ce4ef29d1db58ec8d6fd73563 (diff)
Merge bk://gkernel.bkbits.net/libata-2.6
into ppc970.osdl.org:/home/torvalds/v2.6/linux
Diffstat (limited to 'fs')
-rw-r--r--fs/binfmt_elf.c38
-rw-r--r--fs/buffer.c4
-rw-r--r--fs/direct-io.c7
-rw-r--r--fs/exec.c8
-rw-r--r--fs/exportfs/expfs.c4
-rw-r--r--fs/inode.c2
-rw-r--r--fs/lockd/svc.c33
-rw-r--r--fs/nfs/callback.c156
-rw-r--r--fs/nfsd/export.c22
-rw-r--r--fs/nfsd/lockd.c2
-rw-r--r--fs/nfsd/nfs3xdr.c5
-rw-r--r--fs/nfsd/nfscache.c133
-rw-r--r--fs/nfsd/nfsfh.c11
-rw-r--r--fs/nfsd/nfssvc.c4
-rw-r--r--fs/nfsd/vfs.c8
15 files changed, 158 insertions, 279 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 3be133aa4a79..4c873236d06a 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -37,6 +37,7 @@
#include <linux/pagemap.h>
#include <linux/security.h>
#include <linux/syscalls.h>
+#include <linux/random.h>
#include <asm/uaccess.h>
#include <asm/param.h>
@@ -165,21 +166,14 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec,
if (k_platform) {
size_t len = strlen(k_platform) + 1;
-#ifdef CONFIG_X86_HT
/*
* In some cases (e.g. Hyper-Threading), we want to avoid L1
* evictions by the processes running on the same package. One
* thing we can do is to shuffle the initial stack for them.
- *
- * The conditionals here are unneeded, but kept in to make the
- * code behaviour the same as pre change unless we have
- * hyperthreaded processors. This should be cleaned up
- * before 2.6
*/
- if (smp_num_siblings > 1)
- STACK_ALLOC(p, ((current->pid % 64) << 7));
-#endif
+ p = arch_align_stack(p);
+
u_platform = (elf_addr_t __user *)STACK_ALLOC(p, len);
if (__copy_to_user(u_platform, k_platform, len))
return -EFAULT;
@@ -501,6 +495,19 @@ out:
#define INTERPRETER_ELF 2
+static unsigned long randomize_stack_top(unsigned long stack_top)
+{
+ unsigned int random_variable = 0;
+
+ if (current->flags & PF_RANDOMIZE)
+ random_variable = get_random_int() % (8*1024*1024);
+#ifdef CONFIG_STACK_GROWSUP
+ return PAGE_ALIGN(stack_top + random_variable);
+#else
+ return PAGE_ALIGN(stack_top - random_variable);
+#endif
+}
+
static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
{
struct file *interpreter = NULL; /* to shut gcc up */
@@ -760,18 +767,29 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
if (elf_read_implies_exec(loc->elf_ex, executable_stack))
current->personality |= READ_IMPLIES_EXEC;
+ if ( !(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
+ current->flags |= PF_RANDOMIZE;
arch_pick_mmap_layout(current->mm);
/* Do this so that we can load the interpreter, if need be. We will
change some of these later */
current->mm->rss = 0;
current->mm->free_area_cache = current->mm->mmap_base;
- retval = setup_arg_pages(bprm, STACK_TOP, executable_stack);
+ retval = setup_arg_pages(bprm, randomize_stack_top(STACK_TOP),
+ executable_stack);
if (retval < 0) {
send_sig(SIGKILL, current, 0);
goto out_free_dentry;
}
+#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
+ retval = arch_setup_additional_pages(bprm, executable_stack);
+ if (retval < 0) {
+ send_sig(SIGKILL, current, 0);
+ goto out_free_dentry;
+ }
+#endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */
+
current->mm->start_stack = bprm->p;
/* Now we do a little grungy work by mmaping the ELF image into
diff --git a/fs/buffer.c b/fs/buffer.c
index 3c40d6382925..ed6458f00d64 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -875,7 +875,7 @@ int __set_page_dirty_buffers(struct page *page)
spin_unlock(&mapping->private_lock);
if (!TestSetPageDirty(page)) {
- spin_lock_irq(&mapping->tree_lock);
+ write_lock_irq(&mapping->tree_lock);
if (page->mapping) { /* Race with truncate? */
if (!mapping->backing_dev_info->memory_backed)
inc_page_state(nr_dirty);
@@ -883,7 +883,7 @@ int __set_page_dirty_buffers(struct page *page)
page_index(page),
PAGECACHE_TAG_DIRTY);
}
- spin_unlock_irq(&mapping->tree_lock);
+ write_unlock_irq(&mapping->tree_lock);
__mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
}
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 283268396a15..5a674a0c7146 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -1206,7 +1206,8 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
*/
dio->lock_type = dio_lock_type;
if (dio_lock_type != DIO_NO_LOCKING) {
- if (rw == READ) {
+ /* watch out for a 0 len io from a tricksy fs */
+ if (rw == READ && end > offset) {
struct address_space *mapping;
mapping = iocb->ki_filp->f_mapping;
@@ -1214,7 +1215,9 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
down(&inode->i_sem);
reader_with_isem = 1;
}
- retval = filemap_write_and_wait(mapping);
+
+ retval = filemap_write_and_wait_range(mapping, offset,
+ end - 1);
if (retval) {
kfree(dio);
goto out;
diff --git a/fs/exec.c b/fs/exec.c
index ee58e91a9d7f..393605cdc101 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -400,7 +400,8 @@ int setup_arg_pages(struct linux_binprm *bprm,
while (i < MAX_ARG_PAGES)
bprm->page[i++] = NULL;
#else
- stack_base = stack_top - MAX_ARG_PAGES * PAGE_SIZE;
+ stack_base = arch_align_stack(stack_top - MAX_ARG_PAGES*PAGE_SIZE);
+ stack_base = PAGE_ALIGN(stack_base);
bprm->p += stack_base;
mm->arg_start = bprm->p;
arg_size = stack_top - (PAGE_MASK & (unsigned long) mm->arg_start);
@@ -877,6 +878,7 @@ int flush_old_exec(struct linux_binprm * bprm)
tcomm[i] = '\0';
set_task_comm(current, tcomm);
+ current->flags &= ~PF_RANDOMIZE;
flush_thread();
if (bprm->e_uid != current->euid || bprm->e_gid != current->egid ||
@@ -1191,8 +1193,8 @@ int do_execve(char * filename,
/* execve success */
security_bprm_free(bprm);
- acct_update_integrals();
- update_mem_hiwater();
+ acct_update_integrals(current);
+ update_mem_hiwater(current);
kfree(bprm);
return retval;
}
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
index 0a6f7b06b8d7..c49d6254379a 100644
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -55,7 +55,7 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
struct list_head *le, *head;
struct dentry *toput = NULL;
int noprogress;
-
+ char nbuf[NAME_MAX+1];
/*
* Attempt to find the inode.
@@ -176,7 +176,6 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
*/
struct dentry *ppd;
struct dentry *npd;
- char nbuf[NAME_MAX+1];
down(&pd->d_inode->i_sem);
ppd = CALL(nops,get_parent)(pd);
@@ -241,7 +240,6 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
/* if we weren't after a directory, have one more step to go */
if (result != target_dir) {
struct dentry *nresult;
- char nbuf[NAME_MAX+1];
err = CALL(nops,get_name)(target_dir, nbuf, result);
if (!err) {
down(&target_dir->d_inode->i_sem);
diff --git a/fs/inode.c b/fs/inode.c
index d76a6e4b3ee1..ff654a268331 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -196,7 +196,7 @@ void inode_init_once(struct inode *inode)
sema_init(&inode->i_sem, 1);
init_rwsem(&inode->i_alloc_sem);
INIT_RADIX_TREE(&inode->i_data.page_tree, GFP_ATOMIC);
- spin_lock_init(&inode->i_data.tree_lock);
+ rwlock_init(&inode->i_data.tree_lock);
spin_lock_init(&inode->i_data.i_mmap_lock);
INIT_LIST_HEAD(&inode->i_data.private_list);
spin_lock_init(&inode->i_data.private_lock);
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index d3ee09c5196e..b82e470912e8 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -403,6 +403,38 @@ static int param_set_##name(const char *val, struct kernel_param *kp) \
return 0; \
}
+static inline int is_callback(u32 proc)
+{
+ return proc == NLMPROC_GRANTED
+ || proc == NLMPROC_GRANTED_MSG
+ || proc == NLMPROC_TEST_RES
+ || proc == NLMPROC_LOCK_RES
+ || proc == NLMPROC_CANCEL_RES
+ || proc == NLMPROC_UNLOCK_RES
+ || proc == NLMPROC_NSM_NOTIFY;
+}
+
+
+static int lockd_authenticate(struct svc_rqst *rqstp)
+{
+ rqstp->rq_client = NULL;
+ switch (rqstp->rq_authop->flavour) {
+ case RPC_AUTH_NULL:
+ case RPC_AUTH_UNIX:
+ if (rqstp->rq_proc == 0)
+ return SVC_OK;
+ if (is_callback(rqstp->rq_proc)) {
+ /* Leave it to individual procedures to
+ * call nlmsvc_lookup_host(rqstp)
+ */
+ return SVC_OK;
+ }
+ return svc_set_client(rqstp);
+ }
+ return SVC_DENIED;
+}
+
+
param_set_min_max(port, int, simple_strtol, 0, 65535)
param_set_min_max(grace_period, unsigned long, simple_strtoul,
nlm_grace_period_min, nlm_grace_period_max)
@@ -483,4 +515,5 @@ static struct svc_program nlmsvc_program = {
.pg_name = "lockd", /* service name */
.pg_class = "nfsd", /* share authentication with nfsd */
.pg_stats = &nlmsvc_stats, /* stats table */
+ .pg_authenticate = &lockd_authenticate /* export authentication */
};
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index ad7677b4f21d..560d6175dd58 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -139,133 +139,10 @@ out:
return ret;
}
-/*
- * AUTH_NULL authentication
- */
-static int nfs_callback_null_accept(struct svc_rqst *rqstp, u32 *authp)
-{
- struct kvec *argv = &rqstp->rq_arg.head[0];
- struct kvec *resv = &rqstp->rq_res.head[0];
-
- if (argv->iov_len < 3*4)
- return SVC_GARBAGE;
-
- if (svc_getu32(argv) != 0) {
- dprintk("svc: bad null cred\n");
- *authp = rpc_autherr_badcred;
- return SVC_DENIED;
- }
- if (svc_getu32(argv) != RPC_AUTH_NULL || svc_getu32(argv) != 0) {
- dprintk("svc: bad null verf\n");
- *authp = rpc_autherr_badverf;
- return SVC_DENIED;
- }
-
- /* Signal that mapping to nobody uid/gid is required */
- rqstp->rq_cred.cr_uid = (uid_t) -1;
- rqstp->rq_cred.cr_gid = (gid_t) -1;
- rqstp->rq_cred.cr_group_info = groups_alloc(0);
- if (rqstp->rq_cred.cr_group_info == NULL)
- return SVC_DROP; /* kmalloc failure - client must retry */
-
- /* Put NULL verifier */
- svc_putu32(resv, RPC_AUTH_NULL);
- svc_putu32(resv, 0);
- dprintk("%s: success, returning %d!\n", __FUNCTION__, SVC_OK);
- return SVC_OK;
-}
-
-static int nfs_callback_null_release(struct svc_rqst *rqstp)
-{
- if (rqstp->rq_cred.cr_group_info)
- put_group_info(rqstp->rq_cred.cr_group_info);
- rqstp->rq_cred.cr_group_info = NULL;
- return 0; /* don't drop */
-}
-
-static struct auth_ops nfs_callback_auth_null = {
- .name = "null",
- .flavour = RPC_AUTH_NULL,
- .accept = nfs_callback_null_accept,
- .release = nfs_callback_null_release,
-};
-
-/*
- * AUTH_SYS authentication
- */
-static int nfs_callback_unix_accept(struct svc_rqst *rqstp, u32 *authp)
-{
- struct kvec *argv = &rqstp->rq_arg.head[0];
- struct kvec *resv = &rqstp->rq_res.head[0];
- struct svc_cred *cred = &rqstp->rq_cred;
- u32 slen, i;
- int len = argv->iov_len;
-
- dprintk("%s: start\n", __FUNCTION__);
- cred->cr_group_info = NULL;
- rqstp->rq_client = NULL;
- if ((len -= 3*4) < 0)
- return SVC_GARBAGE;
-
- /* Get length, time stamp and machine name */
- svc_getu32(argv);
- svc_getu32(argv);
- slen = XDR_QUADLEN(ntohl(svc_getu32(argv)));
- if (slen > 64 || (len -= (slen + 3)*4) < 0)
- goto badcred;
- argv->iov_base = (void*)((u32*)argv->iov_base + slen);
- argv->iov_len -= slen*4;
-
- cred->cr_uid = ntohl(svc_getu32(argv));
- cred->cr_gid = ntohl(svc_getu32(argv));
- slen = ntohl(svc_getu32(argv));
- if (slen > 16 || (len -= (slen + 2)*4) < 0)
- goto badcred;
- cred->cr_group_info = groups_alloc(slen);
- if (cred->cr_group_info == NULL)
- return SVC_DROP;
- for (i = 0; i < slen; i++)
- GROUP_AT(cred->cr_group_info, i) = ntohl(svc_getu32(argv));
-
- if (svc_getu32(argv) != RPC_AUTH_NULL || svc_getu32(argv) != 0) {
- *authp = rpc_autherr_badverf;
- return SVC_DENIED;
- }
- /* Put NULL verifier */
- svc_putu32(resv, RPC_AUTH_NULL);
- svc_putu32(resv, 0);
- dprintk("%s: success, returning %d!\n", __FUNCTION__, SVC_OK);
- return SVC_OK;
-badcred:
- *authp = rpc_autherr_badcred;
- return SVC_DENIED;
-}
-
-static int nfs_callback_unix_release(struct svc_rqst *rqstp)
-{
- if (rqstp->rq_cred.cr_group_info)
- put_group_info(rqstp->rq_cred.cr_group_info);
- rqstp->rq_cred.cr_group_info = NULL;
- return 0;
-}
-
-static struct auth_ops nfs_callback_auth_unix = {
- .name = "unix",
- .flavour = RPC_AUTH_UNIX,
- .accept = nfs_callback_unix_accept,
- .release = nfs_callback_unix_release,
-};
-
-/*
- * Hook the authentication protocol
- */
-static int nfs_callback_auth(struct svc_rqst *rqstp, u32 *authp)
+static int nfs_callback_authenticate(struct svc_rqst *rqstp)
{
struct in_addr *addr = &rqstp->rq_addr.sin_addr;
struct nfs4_client *clp;
- struct kvec *argv = &rqstp->rq_arg.head[0];
- int flavour;
- int retval;
/* Don't talk to strangers */
clp = nfs4_find_client(addr);
@@ -273,34 +150,19 @@ static int nfs_callback_auth(struct svc_rqst *rqstp, u32 *authp)
return SVC_DROP;
dprintk("%s: %u.%u.%u.%u NFSv4 callback!\n", __FUNCTION__, NIPQUAD(addr));
nfs4_put_client(clp);
- flavour = ntohl(svc_getu32(argv));
- switch(flavour) {
+ switch (rqstp->rq_authop->flavour) {
case RPC_AUTH_NULL:
- if (rqstp->rq_proc != CB_NULL) {
- *authp = rpc_autherr_tooweak;
- retval = SVC_DENIED;
- break;
- }
- rqstp->rq_authop = &nfs_callback_auth_null;
- retval = nfs_callback_null_accept(rqstp, authp);
+ if (rqstp->rq_proc != CB_NULL)
+ return SVC_DENIED;
break;
case RPC_AUTH_UNIX:
- /* Eat the authentication flavour */
- rqstp->rq_authop = &nfs_callback_auth_unix;
- retval = nfs_callback_unix_accept(rqstp, authp);
break;
+ case RPC_AUTH_GSS:
+ /* FIXME: RPCSEC_GSS handling? */
default:
- /* FIXME: need to add RPCSEC_GSS upcalls */
-#if 0
- svc_ungetu32(argv);
- retval = svc_authenticate(rqstp, authp);
-#else
- *authp = rpc_autherr_rejectedcred;
- retval = SVC_DENIED;
-#endif
+ return SVC_DENIED;
}
- dprintk("%s: flavour %d returning error %d\n", __FUNCTION__, flavour, retval);
- return retval;
+ return SVC_OK;
}
/*
@@ -321,5 +183,5 @@ static struct svc_program nfs4_callback_program = {
.pg_name = "NFSv4 callback", /* service name */
.pg_class = "nfs", /* authentication class */
.pg_stats = &nfs4_callback_stats,
- .pg_authenticate = nfs_callback_auth,
+ .pg_authenticate = nfs_callback_authenticate,
};
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 96c0ea8f60ce..9a11aa39e2e4 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -79,9 +79,9 @@ void expkey_put(struct cache_head *item, struct cache_detail *cd)
}
}
-void expkey_request(struct cache_detail *cd,
- struct cache_head *h,
- char **bpp, int *blen)
+static void expkey_request(struct cache_detail *cd,
+ struct cache_head *h,
+ char **bpp, int *blen)
{
/* client fsidtype \xfsid */
struct svc_expkey *ek = container_of(h, struct svc_expkey, h);
@@ -95,7 +95,7 @@ void expkey_request(struct cache_detail *cd,
}
static struct svc_expkey *svc_expkey_lookup(struct svc_expkey *, int);
-int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
+static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
{
/* client fsidtype fsid [path] */
char *buf;
@@ -284,9 +284,9 @@ void svc_export_put(struct cache_head *item, struct cache_detail *cd)
}
}
-void svc_export_request(struct cache_detail *cd,
- struct cache_head *h,
- char **bpp, int *blen)
+static void svc_export_request(struct cache_detail *cd,
+ struct cache_head *h,
+ char **bpp, int *blen)
{
/* client path */
struct svc_export *exp = container_of(h, struct svc_export, h);
@@ -340,7 +340,7 @@ static int check_export(struct inode *inode, int flags)
}
-int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
+static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
{
/* client path expiry [flags anonuid anongid fsid] */
char *buf;
@@ -510,8 +510,8 @@ exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp)
return ek;
}
-int exp_set_key(svc_client *clp, int fsid_type, u32 *fsidv,
- struct svc_export *exp)
+static int exp_set_key(svc_client *clp, int fsid_type, u32 *fsidv,
+ struct svc_export *exp)
{
struct svc_expkey key, *ek;
@@ -999,7 +999,7 @@ static void e_stop(struct seq_file *m, void *p)
exp_readunlock();
}
-struct flags {
+static struct flags {
int flag;
char *name[2];
} expflags[] = {
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
index 3397bec47085..7b889ff15ae6 100644
--- a/fs/nfsd/lockd.c
+++ b/fs/nfsd/lockd.c
@@ -60,7 +60,7 @@ nlm_fclose(struct file *filp)
fput(filp);
}
-struct nlmsvc_binding nfsd_nlm_ops = {
+static struct nlmsvc_binding nfsd_nlm_ops = {
.fopen = nlm_fopen, /* open file for locking */
.fclose = nlm_fclose, /* close file */
};
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 941881de48a1..11f806835c5a 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -801,6 +801,11 @@ compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
if (isdotent(name, namlen)) {
if (namlen == 2) {
dchild = dget_parent(dparent);
+ if (dchild == dparent) {
+ /* filesystem root - cannot return filehandle for ".." */
+ dput(dchild);
+ return 1;
+ }
} else
dchild = dget(dparent);
} else
diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c
index a3236dfedf98..119e4d4495b8 100644
--- a/fs/nfsd/nfscache.c
+++ b/fs/nfsd/nfscache.c
@@ -15,6 +15,7 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/spinlock.h>
+#include <linux/list.h>
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
@@ -30,15 +31,8 @@
#define HASHSIZE 64
#define REQHASH(xid) ((((xid) >> 24) ^ (xid)) & (HASHSIZE-1))
-struct nfscache_head {
- struct svc_cacherep * next;
- struct svc_cacherep * prev;
-};
-
-static struct nfscache_head * hash_list;
-static struct svc_cacherep * lru_head;
-static struct svc_cacherep * lru_tail;
-static struct svc_cacherep * nfscache;
+static struct hlist_head * hash_list;
+static struct list_head lru_head;
static int cache_disabled = 1;
static int nfsd_cache_append(struct svc_rqst *rqstp, struct kvec *vec);
@@ -54,46 +48,32 @@ void
nfsd_cache_init(void)
{
struct svc_cacherep *rp;
- struct nfscache_head *rh;
- size_t i;
- unsigned long order;
-
-
- i = CACHESIZE * sizeof (struct svc_cacherep);
- for (order = 0; (PAGE_SIZE << order) < i; order++)
- ;
- nfscache = (struct svc_cacherep *)
- __get_free_pages(GFP_KERNEL, order);
- if (!nfscache) {
- printk (KERN_ERR "nfsd: cannot allocate %Zd bytes for reply cache\n", i);
- return;
+ int i;
+
+ INIT_LIST_HEAD(&lru_head);
+ i = CACHESIZE;
+ while(i) {
+ rp = kmalloc(sizeof(*rp), GFP_KERNEL);
+ if (!rp) break;
+ list_add(&rp->c_lru, &lru_head);
+ rp->c_state = RC_UNUSED;
+ rp->c_type = RC_NOCACHE;
+ INIT_HLIST_NODE(&rp->c_hash);
+ i--;
}
- memset(nfscache, 0, i);
- i = HASHSIZE * sizeof (struct nfscache_head);
- hash_list = kmalloc (i, GFP_KERNEL);
+ if (i)
+ printk (KERN_ERR "nfsd: cannot allocate all %d cache entries, only got %d\n",
+ CACHESIZE, CACHESIZE-i);
+
+ hash_list = kmalloc (HASHSIZE * sizeof(struct hlist_head), GFP_KERNEL);
if (!hash_list) {
- free_pages ((unsigned long)nfscache, order);
- nfscache = NULL;
- printk (KERN_ERR "nfsd: cannot allocate %Zd bytes for hash list\n", i);
+ nfsd_cache_shutdown();
+ printk (KERN_ERR "nfsd: cannot allocate %Zd bytes for hash list\n",
+ HASHSIZE * sizeof(struct hlist_head));
return;
}
-
- for (i = 0, rh = hash_list; i < HASHSIZE; i++, rh++)
- rh->next = rh->prev = (struct svc_cacherep *) rh;
-
- for (i = 0, rp = nfscache; i < CACHESIZE; i++, rp++) {
- rp->c_state = RC_UNUSED;
- rp->c_type = RC_NOCACHE;
- rp->c_hash_next =
- rp->c_hash_prev = rp;
- rp->c_lru_next = rp + 1;
- rp->c_lru_prev = rp - 1;
- }
- lru_head = nfscache;
- lru_tail = nfscache + CACHESIZE - 1;
- lru_head->c_lru_prev = NULL;
- lru_tail->c_lru_next = NULL;
+ memset(hash_list, 0, HASHSIZE * sizeof(struct hlist_head));
cache_disabled = 0;
}
@@ -102,48 +82,30 @@ void
nfsd_cache_shutdown(void)
{
struct svc_cacherep *rp;
- size_t i;
- unsigned long order;
- for (rp = lru_head; rp; rp = rp->c_lru_next) {
+ while (!list_empty(&lru_head)) {
+ rp = list_entry(lru_head.next, struct svc_cacherep, c_lru);
if (rp->c_state == RC_DONE && rp->c_type == RC_REPLBUFF)
kfree(rp->c_replvec.iov_base);
+ list_del(&rp->c_lru);
+ kfree(rp);
}
cache_disabled = 1;
- i = CACHESIZE * sizeof (struct svc_cacherep);
- for (order = 0; (PAGE_SIZE << order) < i; order++)
- ;
- free_pages ((unsigned long)nfscache, order);
- nfscache = NULL;
- kfree (hash_list);
+ if (hash_list)
+ kfree (hash_list);
hash_list = NULL;
}
/*
- * Move cache entry to front of LRU list
+ * Move cache entry to end of LRU list
*/
static void
-lru_put_front(struct svc_cacherep *rp)
+lru_put_end(struct svc_cacherep *rp)
{
- struct svc_cacherep *prev = rp->c_lru_prev,
- *next = rp->c_lru_next;
-
- if (prev)
- prev->c_lru_next = next;
- else
- lru_head = next;
- if (next)
- next->c_lru_prev = prev;
- else
- lru_tail = prev;
-
- rp->c_lru_next = lru_head;
- rp->c_lru_prev = NULL;
- if (lru_head)
- lru_head->c_lru_prev = rp;
- lru_head = rp;
+ list_del(&rp->c_lru);
+ list_add_tail(&rp->c_lru, &lru_head);
}
/*
@@ -152,17 +114,8 @@ lru_put_front(struct svc_cacherep *rp)
static void
hash_refile(struct svc_cacherep *rp)
{
- struct svc_cacherep *prev = rp->c_hash_prev,
- *next = rp->c_hash_next;
- struct nfscache_head *head = hash_list + REQHASH(rp->c_xid);
-
- prev->c_hash_next = next;
- next->c_hash_prev = prev;
-
- rp->c_hash_next = head->next;
- rp->c_hash_prev = (struct svc_cacherep *) head;
- head->next->c_hash_prev = rp;
- head->next = rp;
+ hlist_del_init(&rp->c_hash);
+ hlist_add_head(&rp->c_hash, hash_list + REQHASH(rp->c_xid));
}
/*
@@ -173,7 +126,9 @@ hash_refile(struct svc_cacherep *rp)
int
nfsd_cache_lookup(struct svc_rqst *rqstp, int type)
{
- struct svc_cacherep *rh, *rp;
+ struct hlist_node *hn;
+ struct hlist_head *rh;
+ struct svc_cacherep *rp;
u32 xid = rqstp->rq_xid,
proto = rqstp->rq_prot,
vers = rqstp->rq_vers,
@@ -190,8 +145,8 @@ nfsd_cache_lookup(struct svc_rqst *rqstp, int type)
spin_lock(&cache_lock);
rtn = RC_DOIT;
- rp = rh = (struct svc_cacherep *) &hash_list[REQHASH(xid)];
- while ((rp = rp->c_hash_next) != rh) {
+ rh = &hash_list[REQHASH(xid)];
+ hlist_for_each_entry(rp, hn, rh, c_hash) {
if (rp->c_state != RC_UNUSED &&
xid == rp->c_xid && proc == rp->c_proc &&
proto == rp->c_prot && vers == rp->c_vers &&
@@ -206,7 +161,7 @@ nfsd_cache_lookup(struct svc_rqst *rqstp, int type)
/* This loop shouldn't take more than a few iterations normally */
{
int safe = 0;
- for (rp = lru_tail; rp; rp = rp->c_lru_prev) {
+ list_for_each_entry(rp, &lru_head, c_lru) {
if (rp->c_state != RC_INPROG)
break;
if (safe++ > CACHESIZE) {
@@ -254,7 +209,7 @@ found_entry:
/* We found a matching entry which is either in progress or done. */
age = jiffies - rp->c_timestamp;
rp->c_timestamp = jiffies;
- lru_put_front(rp);
+ lru_put_end(rp);
rtn = RC_DROPIT;
/* Request being processed or excessive rexmits */
@@ -343,7 +298,7 @@ nfsd_cache_update(struct svc_rqst *rqstp, int cachetype, u32 *statp)
break;
}
spin_lock(&cache_lock);
- lru_put_front(rp);
+ lru_put_end(rp);
rp->c_secure = rqstp->rq_secure;
rp->c_type = cachetype;
rp->c_state = RC_DONE;
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 0cf106106674..7a3e397b4ed3 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -41,7 +41,7 @@ extern struct export_operations export_op_default;
* if not, require that we can walk up to exp->ex_dentry
* doing some checks on the 'x' bits
*/
-int nfsd_acceptable(void *expv, struct dentry *dentry)
+static int nfsd_acceptable(void *expv, struct dentry *dentry)
{
struct svc_export *exp = expv;
int rv;
@@ -280,8 +280,8 @@ out:
* an inode. In this case a call to fh_update should be made
* before the fh goes out on the wire ...
*/
-inline int _fh_update(struct dentry *dentry, struct svc_export *exp,
- __u32 *datap, int *maxsize)
+static inline int _fh_update(struct dentry *dentry, struct svc_export *exp,
+ __u32 *datap, int *maxsize)
{
struct export_operations *nop = exp->ex_mnt->mnt_sb->s_export_op;
@@ -297,8 +297,9 @@ inline int _fh_update(struct dentry *dentry, struct svc_export *exp,
/*
* for composing old style file handles
*/
-inline void _fh_update_old(struct dentry *dentry, struct svc_export *exp,
- struct knfsd_fh *fh)
+static inline void _fh_update_old(struct dentry *dentry,
+ struct svc_export *exp,
+ struct knfsd_fh *fh)
{
fh->ofh_ino = ino_t_to_u32(dentry->d_inode->i_ino);
fh->ofh_generation = dentry->d_inode->i_generation;
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 291dd8cd3214..f7e41965b043 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -60,7 +60,7 @@ struct nfsd_list {
struct list_head list;
struct task_struct *task;
};
-struct list_head nfsd_list = LIST_HEAD_INIT(nfsd_list);
+static struct list_head nfsd_list = LIST_HEAD_INIT(nfsd_list);
/*
* Maximum number of nfsd processes
@@ -378,4 +378,6 @@ struct svc_program nfsd_program = {
.pg_name = "nfsd", /* program name */
.pg_class = "nfsd", /* authentication class */
.pg_stats = &nfsd_svcstats, /* version table */
+ .pg_authenticate = &svc_set_client, /* export authentication */
+
};
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index a5a58a1dba0a..e86ee9ac6654 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -707,8 +707,8 @@ nfsd_close(struct file *filp)
* As this calls fsync (not fdatasync) there is no need for a write_inode
* after it.
*/
-inline void nfsd_dosync(struct file *filp, struct dentry *dp,
- struct file_operations *fop)
+static inline void nfsd_dosync(struct file *filp, struct dentry *dp,
+ struct file_operations *fop)
{
struct inode *inode = dp->d_inode;
int (*fsync) (struct file *, struct dentry *, int);
@@ -720,7 +720,7 @@ inline void nfsd_dosync(struct file *filp, struct dentry *dp,
}
-void
+static void
nfsd_sync(struct file *filp)
{
struct inode *inode = filp->f_dentry->d_inode;
@@ -730,7 +730,7 @@ nfsd_sync(struct file *filp)
up(&inode->i_sem);
}
-void
+static void
nfsd_sync_dir(struct dentry *dp)
{
nfsd_dosync(NULL, dp, dp->d_inode->i_fop);