Commit 8e3ef35e authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://kernel.bkbits.net/davem/net-2.5

into home.osdl.org:/home/torvalds/v2.5/linux
parents f8012106 6d338bb2
......@@ -1300,7 +1300,6 @@ void __init print_IO_APIC(void)
reg_03.raw = io_apic_read(apic, 3);
spin_unlock_irqrestore(&ioapic_lock, flags);
printk("\n");
printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mpc_apicid);
printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw);
printk(KERN_DEBUG "....... : physical APIC id: %02X\n", reg_00.bits.ID);
......
......@@ -82,7 +82,7 @@ void die_if_kernel(char *str, struct pt_regs *fp, int nr)
printk("Process %s (pid: %d, stackpage=%08lx)\n",
current->comm, current->pid, PAGE_SIZE+(unsigned long)current);
show_stack((unsigned long *)fp);
show_stack(NULL, (unsigned long *)fp);
do_exit(SIGSEGV);
}
......@@ -106,7 +106,7 @@ asmlinkage void buserr_c(struct frame *fp)
int kstack_depth_to_print = 48;
void show_stack(unsigned long *esp)
void show_stack(struct task_struct *task, unsigned long *esp)
{
unsigned long *stack, *endstack, addr;
extern char _start, _etext;
......
......@@ -96,6 +96,7 @@ _start:
movec %d0, %CACR /* Enable cache */
#ifdef CONFIG_ROMFS_FS
/*
* Move ROM filesystem above bss :-)
*/
......@@ -117,6 +118,12 @@ _copy_romfs:
cmp.l %a0, %a2 /* Check if at end */
bne _copy_romfs
#else /* CONFIG_ROMFS_FS */
lea.l _ebss, %a1
move.l %a1, _ramstart
#endif /* CONFIG_ROMFS_FS */
/*
* Zero out the bss region.
*/
......
......@@ -116,6 +116,8 @@ _start:
movec %d0, %CACR /* Enable cache */
nop
#ifdef CONFIG_ROMFS_FS
#ifdef CONFIG_ROMFS_FROM_ROM
/*
* check for an in RAM romfs
......@@ -160,6 +162,12 @@ _copy_romfs:
done_romfs:
#endif
#else /* CONFIG_ROMFS_FS */
lea.l _ebss, %a1
move.l %a1, _ramstart
#endif /* CONFIG_ROMFS_FS */
/*
* Zero out the bss region.
*/
......
......@@ -1337,7 +1337,7 @@ static void bh_lru_install(struct buffer_head *bh)
check_irqs_on();
bh_lru_lock();
lru = &per_cpu(bh_lrus, smp_processor_id());
lru = &__get_cpu_var(bh_lrus);
if (lru->bhs[0] != bh) {
struct buffer_head *bhs[BH_LRU_SIZE];
int in;
......@@ -1381,7 +1381,7 @@ lookup_bh_lru(struct block_device *bdev, sector_t block, int size)
check_irqs_on();
bh_lru_lock();
lru = &per_cpu(bh_lrus, smp_processor_id());
lru = &__get_cpu_var(bh_lrus);
for (i = 0; i < BH_LRU_SIZE; i++) {
struct buffer_head *bh = lru->bhs[i];
......@@ -1474,15 +1474,14 @@ EXPORT_SYMBOL(__bread);
*/
static void invalidate_bh_lru(void *arg)
{
const int cpu = get_cpu();
struct bh_lru *b = &per_cpu(bh_lrus, cpu);
struct bh_lru *b = &get_cpu_var(bh_lrus);
int i;
for (i = 0; i < BH_LRU_SIZE; i++) {
brelse(b->bhs[i]);
b->bhs[i] = NULL;
}
put_cpu();
put_cpu_var(bh_lrus);
}
static void invalidate_bh_lrus(void)
......
......@@ -1562,6 +1562,8 @@ static int loop_status(unsigned int fd, unsigned int cmd, unsigned long arg)
extern int tty_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg);
#ifdef CONFIG_VT
static int vt_check(struct file *file)
{
struct tty_struct *tty;
......@@ -1693,6 +1695,8 @@ static int do_unimap_ioctl(unsigned int fd, unsigned int cmd, struct unimapdesc3
return 0;
}
#endif /* CONFIG_VT */
static int do_smb_getmountuid(unsigned int fd, unsigned int cmd, unsigned long arg)
{
mm_segment_t old_fs = get_fs();
......@@ -2398,11 +2402,13 @@ HANDLE_IOCTL(LOOP_SET_STATUS, loop_status)
HANDLE_IOCTL(LOOP_GET_STATUS, loop_status)
#define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int)
HANDLE_IOCTL(AUTOFS_IOC_SETTIMEOUT32, ioc_settimeout)
#ifdef CONFIG_VT
HANDLE_IOCTL(PIO_FONTX, do_fontx_ioctl)
HANDLE_IOCTL(GIO_FONTX, do_fontx_ioctl)
HANDLE_IOCTL(PIO_UNIMAP, do_unimap_ioctl)
HANDLE_IOCTL(GIO_UNIMAP, do_unimap_ioctl)
HANDLE_IOCTL(KDFONTOP, do_kdfontop_ioctl)
#endif
HANDLE_IOCTL(EXT2_IOC32_GETFLAGS, do_ext2_ioctl)
HANDLE_IOCTL(EXT2_IOC32_SETFLAGS, do_ext2_ioctl)
HANDLE_IOCTL(EXT2_IOC32_GETVERSION, do_ext2_ioctl)
......
......@@ -34,7 +34,6 @@
#include <linux/sunrpc/svcsock.h>
#include <linux/lockd/lockd.h>
#include <linux/nfs.h>
#include <linux/suspend.h>
#define NLMDBG_FACILITY NLMDBG_SVC
#define LOCKD_BUFSIZE (1024 + NLMSVC_XDRSIZE)
......@@ -122,8 +121,6 @@ lockd(struct svc_rqst *rqstp)
while ((nlmsvc_users || !signalled()) && nlmsvc_pid == current->pid) {
long timeout = MAX_SCHEDULE_TIMEOUT;
if (current->flags & PF_FREEZE)
refrigerator(PF_IOTHREAD);
if (signalled()) {
flush_signals(current);
if (nlmsvc_ops) {
......
......@@ -195,8 +195,7 @@ int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
static int expkey_show(struct seq_file *m,
struct cache_detail *cd,
struct cache_head *h,
char *pbuf)
struct cache_head *h)
{
struct svc_expkey *ek ;
......@@ -436,9 +435,8 @@ int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
static void exp_flags(struct seq_file *m, int flag, int fsid, uid_t anonu, uid_t anong);
static int svc_export_show(struct seq_file *m,
struct cache_detail *cd,
struct cache_head *h,
char *pbuf)
struct cache_detail *cd,
struct cache_head *h)
{
struct svc_export *exp ;
......@@ -1028,17 +1026,11 @@ static void exp_flags(struct seq_file *m, int flag, int fsid, uid_t anonu, uid_t
seq_printf(m, "%sanongid=%d", first++?",":"", anong);
}
static inline void mangle(struct seq_file *m, const char *s)
{
seq_escape(m, s, " \t\n\\");
}
static int e_show(struct seq_file *m, void *p)
{
struct cache_head *cp = p;
struct svc_export *exp = container_of(cp, struct svc_export, h);
svc_client *clp;
char *pbuf;
if (p == (void *)1) {
seq_puts(m, "# Version 1.1\n");
......@@ -1051,17 +1043,7 @@ static int e_show(struct seq_file *m, void *p)
if (cache_check(&svc_export_cache, &exp->h, NULL))
return 0;
if (cache_put(&exp->h, &svc_export_cache)) BUG();
pbuf = m->private;
mangle(m, d_path(exp->ex_dentry, exp->ex_mnt,
pbuf, PAGE_SIZE));
seq_putc(m, '\t');
mangle(m, clp->name);
seq_putc(m, '(');
exp_flags(m, exp->ex_flags, exp->ex_fsid,
exp->ex_anon_uid, exp->ex_anon_gid);
seq_puts(m, ")\n");
return 0;
return svc_export_show(m, &svc_export_cache, cp);
}
struct seq_operations nfs_exports_op = {
......
......@@ -55,12 +55,6 @@
#define NFSDDBG_FACILITY NFSDDBG_PROC
static inline int
nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_close *close)
{
return nfs_ok;
}
/* Note: The organization of the OPEN code seems a little strange; it
* has been superfluously split into three routines, one of which is named
* nfsd4_process_open2() even though there is no nfsd4_process_open1()!
......@@ -140,10 +134,6 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
status = nfsd4_process_open2(rqstp, current_fh, open);
if (status)
return status;
/*
* To finish the open response, we just need to set the rflags.
*/
open->op_rflags = 0;
return 0;
}
......@@ -356,14 +346,51 @@ nfsd4_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_loo
static inline int
nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read *read)
{
struct nfs4_stateid *stp;
int status;
/* no need to check permission - this will be done in nfsd_read() */
if (read->rd_offset >= OFFSET_MAX)
return nfserr_inval;
nfsd4_lock_state();
status = nfs_ok;
/* For stateid -1, we don't check share reservations. */
if (ONE_STATEID(&read->rd_stateid)) {
dprintk("NFSD: nfsd4_read: -1 stateid...\n");
goto out;
}
/*
* For stateid 0, the client doesn't have to have the file open, but
* we still check for share reservation conflicts.
*/
if (ZERO_STATEID(&read->rd_stateid)) {
dprintk("NFSD: nfsd4_read: zero stateid...\n");
if ((status = nfs4_share_conflict(current_fh, NFS4_SHARE_DENY_READ))) {
dprintk("NFSD: nfsd4_read: conflicting share reservation!\n");
goto out;
}
status = nfs_ok;
goto out;
}
/* check stateid */
if ((status = nfs4_preprocess_stateid_op(current_fh, &read->rd_stateid,
CHECK_FH, &stp))) {
dprintk("NFSD: nfsd4_read: couldn't process stateid!\n");
goto out;
}
status = nfserr_openmode;
if (!(stp->st_share_access & NFS4_SHARE_ACCESS_READ)) {
dprintk("NFSD: nfsd4_read: file not opened for read!\n");
goto out;
}
status = nfs_ok;
out:
nfsd4_unlock_state();
read->rd_rqstp = rqstp;
read->rd_fhp = current_fh;
return nfs_ok;
return status;
}
static inline int
......@@ -425,28 +452,85 @@ nfsd4_rename(struct svc_rqst *rqstp, struct svc_fh *current_fh,
static inline int
nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_setattr *setattr)
{
return nfsd_setattr(rqstp, current_fh, &setattr->sa_iattr, 0, (time_t)0);
struct nfs4_stateid *stp;
int status = nfs_ok;
if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
status = nfserr_bad_stateid;
if (ZERO_STATEID(&setattr->sa_stateid) || ONE_STATEID(&setattr->sa_stateid)) {
dprintk("NFSD: nfsd4_setattr: magic stateid!\n");
return status;
}
nfsd4_lock_state();
if ((status = nfs4_preprocess_stateid_op(current_fh,
&setattr->sa_stateid,
CHECK_FH, &stp))) {
dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n");
goto out;
}
status = nfserr_openmode;
if (!(stp->st_share_access & NFS4_SHARE_ACCESS_WRITE)) {
dprintk("NFSD: nfsd4_setattr: not opened for write!\n");
goto out;
}
nfsd4_unlock_state();
}
return (nfsd_setattr(rqstp, current_fh, &setattr->sa_iattr, 0, (time_t)0));
out:
nfsd4_unlock_state();
return status;
}
static inline int
nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_write *write)
{
struct nfs4_stateid *stp;
stateid_t *stateid = &write->wr_stateid;
u32 *p;
int status = nfs_ok;
/* no need to check permission - this will be done in nfsd_write() */
if (write->wr_offset >= OFFSET_MAX)
return nfserr_inval;
nfsd4_lock_state();
if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) {
dprintk("NFSD: nfsd4_write: zero stateid...\n");
if ((status = nfs4_share_conflict(current_fh, NFS4_SHARE_DENY_WRITE))) {
dprintk("NFSD: nfsd4_write: conflicting share reservation!\n");
goto out;
}
goto zero_stateid;
}
if ((status = nfs4_preprocess_stateid_op(current_fh, stateid,
CHECK_FH, &stp))) {
dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
goto out;
}
status = nfserr_openmode;
if (!(stp->st_share_access & NFS4_SHARE_ACCESS_WRITE)) {
dprintk("NFSD: nfsd4_write: file not open for write!\n");
goto out;
}
zero_stateid:
nfsd4_unlock_state();
write->wr_bytes_written = write->wr_buflen;
write->wr_how_written = write->wr_stable_how;
p = (u32 *)write->wr_verifier;
*p++ = nfssvc_boot.tv_sec;
*p++ = nfssvc_boot.tv_usec;
return nfsd_write(rqstp, current_fh, write->wr_offset,
return (nfsd_write(rqstp, current_fh, write->wr_offset,
write->wr_vec, write->wr_vlen, write->wr_buflen,
&write->wr_how_written);
&write->wr_how_written));
out:
nfsd4_unlock_state();
return status;
}
/* This routine never returns NFS_OK! If there are no other errors, it
......@@ -609,6 +693,12 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
case OP_OPEN:
op->status = nfsd4_open(rqstp, &current_fh, &op->u.open);
break;
case OP_OPEN_CONFIRM:
op->status = nfsd4_open_confirm(rqstp, &current_fh, &op->u.open_confirm);
break;
case OP_OPEN_DOWNGRADE:
op->status = nfsd4_open_downgrade(rqstp, &current_fh, &op->u.open_downgrade);
break;
case OP_PUTFH:
op->status = nfsd4_putfh(rqstp, &current_fh, &op->u.putfh);
break;
......
......@@ -56,12 +56,20 @@ static u32 current_clientid = 1;
static u32 current_ownerid = 0;
static u32 current_fileid = 0;
static u32 nfs4_init = 0;
stateid_t zerostateid; /* bits all 0 */
stateid_t onestateid; /* bits all 1 */
/* debug counters */
u32 list_add_perfile = 0;
u32 list_del_perfile = 0;
u32 add_perclient = 0;
u32 del_perclient = 0;
u32 alloc_file = 0;
u32 free_file = 0;
u32 alloc_sowner = 0;
u32 free_sowner = 0;
u32 vfsopen = 0;
u32 vfsclose = 0;
/* Locking:
*
......@@ -71,6 +79,18 @@ u32 del_perclient = 0;
*/
static struct semaphore client_sema;
void
nfsd4_lock_state(void)
{
down(&client_sema);
}
void
nfsd4_unlock_state(void)
{
up(&client_sema);
}
static inline u32
opaque_hashval(const void *ptr, int nbytes)
{
......@@ -87,6 +107,8 @@ opaque_hashval(const void *ptr, int nbytes)
/* forward declarations */
static void release_stateowner(struct nfs4_stateowner *sop);
static void release_stateid(struct nfs4_stateid *stp);
static void release_file(struct nfs4_file *fp);
/*
* SETCLIENTID state
......@@ -136,7 +158,8 @@ STALE_CLIENTID(clientid_t *clid)
{
if (clid->cl_boot == boot_time)
return 0;
printk("NFSD stale clientid (%08x/%08x)\n", clid->cl_boot, clid->cl_id);
dprintk("NFSD stale clientid (%08x/%08x)\n",
clid->cl_boot, clid->cl_id);
return 1;
}
......@@ -294,6 +317,7 @@ move_to_confirmed(struct nfs4_client *clp, unsigned int idhashval)
{
unsigned int strhashval;
dprintk("NFSD: move_to_confirm nfs4_client %p\n", clp);
list_del_init(&clp->cl_strhash);
list_del_init(&clp->cl_idhash);
list_add(&clp->cl_idhash, &conf_id_hashtbl[idhashval]);
......@@ -646,20 +670,30 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
#define OWNER_HASH_SIZE (1 << OWNER_HASH_BITS)
#define OWNER_HASH_MASK (OWNER_HASH_SIZE - 1)
#define ownerid_hashval(id) \
((id) & OWNER_HASH_MASK)
#define ownerstr_hashval(clientid, ownername) \
(((clientid) + opaque_hashval((ownername.data), (ownername.len))) & OWNER_HASH_MASK)
static struct list_head ownerid_hashtbl[OWNER_HASH_SIZE];
static struct list_head ownerstr_hashtbl[OWNER_HASH_SIZE];
/* hash table for nfs4_file */
#define FILE_HASH_BITS 8
#define FILE_HASH_SIZE (1 << FILE_HASH_BITS)
#define FILE_HASH_MASK (FILE_HASH_SIZE - 1)
/* hash table for (open)nfs4_stateid */
#define OPENSTATEID_HASH_BITS 10
#define OPENSTATEID_HASH_SIZE (1 << OPENSTATEID_HASH_BITS)
#define OPENSTATEID_HASH_MASK (OPENSTATEID_HASH_SIZE - 1)
#define file_hashval(x) \
((unsigned int)((x)->dev + (x)->ino + (x)->generation) & FILE_HASH_MASK)
#define openstateid_hashval(owner_id, file_id) \
(((owner_id) + (file_id)) & OPENSTATEID_HASH_MASK)
static struct list_head file_hashtbl[FILE_HASH_SIZE];
static struct list_head openstateid_hashtbl[OPENSTATEID_HASH_SIZE];
/* OPEN Share state helper functions */
static inline struct nfs4_file *
......@@ -671,6 +705,7 @@ alloc_init_file(unsigned int hashval, nfs4_ino_desc_t *ino) {
list_add(&fp->fi_hash, &file_hashtbl[hashval]);
memcpy(&fp->fi_ino, ino, sizeof(nfs4_ino_desc_t));
fp->fi_id = current_fileid++;
alloc_file++;
return fp;
}
return (struct nfs4_file *)NULL;
......@@ -689,8 +724,7 @@ release_all_files(void)
if(!list_empty(&fp->fi_perfile)) {
printk("ERROR: release_all_files: file %p is open, creating dangling state !!!\n",fp);
}
list_del_init(&fp->fi_hash);
kfree(fp);
release_file(fp);
}
}
}
......@@ -718,26 +752,31 @@ free_stateowner(struct nfs4_stateowner *sop) {
kfree(sop->so_owner.data);
kfree(sop);
sop = NULL;
free_sowner++;
}
}
static struct nfs4_stateowner *
alloc_init_stateowner(unsigned int strhashval, struct nfs4_client *clp, struct nfsd4_open *open) {
struct nfs4_stateowner *sop;
unsigned int idhashval;
if (!(sop = alloc_stateowner(&open->op_owner)))
return (struct nfs4_stateowner *)NULL;
idhashval = ownerid_hashval(current_ownerid);
INIT_LIST_HEAD(&sop->so_idhash);
INIT_LIST_HEAD(&sop->so_strhash);
INIT_LIST_HEAD(&sop->so_perclient);
INIT_LIST_HEAD(&sop->so_peropenstate);
list_add(&sop->so_idhash, &ownerid_hashtbl[idhashval]);
list_add(&sop->so_strhash, &ownerstr_hashtbl[strhashval]);
list_add(&sop->so_perclient, &clp->cl_perclient);
add_perclient++;
sop->so_id = current_ownerid++;
sop->so_client = clp;
sop->so_seqid = open->op_seqid;
/* until open_confirm is coded, pretend it happened! */
sop->so_confirmed = 1;
sop->so_confirmed = 0;
alloc_sowner++;
return sop;
}
......@@ -746,6 +785,7 @@ release_stateowner(struct nfs4_stateowner *sop)
{
struct nfs4_stateid *stp;
list_del_init(&sop->so_idhash);
list_del_init(&sop->so_strhash);
list_del_init(&sop->so_perclient);
del_perclient++;
......@@ -759,9 +799,12 @@ release_stateowner(struct nfs4_stateowner *sop)
static inline void
init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfs4_stateowner *sop, struct nfsd4_open *open) {
unsigned int hashval = openstateid_hashval(sop->so_id, fp->fi_id);
INIT_LIST_HEAD(&stp->st_hash);
INIT_LIST_HEAD(&stp->st_peropenstate);
INIT_LIST_HEAD(&stp->st_perfile);
list_add(&stp->st_hash, &openstateid_hashtbl[hashval]);
list_add(&stp->st_peropenstate, &sop->so_peropenstate);
list_add_perfile++;
list_add(&stp->st_perfile, &fp->fi_perfile);
......@@ -778,11 +821,13 @@ init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfs4_stateow
static void
release_stateid(struct nfs4_stateid *stp) {
list_del_init(&stp->st_hash);
list_del_perfile++;
list_del_init(&stp->st_perfile);
list_del_init(&stp->st_peropenstate);
if(stp->st_vfs_set) {
nfsd_close(&stp->st_vfs_file);
vfsclose++;
dput(stp->st_vfs_file.f_dentry);
mntput(stp->st_vfs_file.f_vfsmnt);
}
......@@ -791,6 +836,37 @@ release_stateid(struct nfs4_stateid *stp) {
stp = NULL;
}
static void
release_file(struct nfs4_file *fp)
{
free_file++;
list_del_init(&fp->fi_hash);
kfree(fp);
}
void
release_open_state(struct nfs4_stateid *stp)
{
struct nfs4_stateowner *sop = stp->st_stateowner;
struct nfs4_file *fp = stp->st_file;
dprintk("NFSD: release_open_state\n");
release_stateid(stp);
/*
* release unused nfs4_stateowners.
* XXX will need to be placed on an open_stateid_lru list to be
* released by the laundromat service after the lease period
* to enable us to handle CLOSE replay
*/
if (sop->so_confirmed && list_empty(&sop->so_peropenstate)) {
release_stateowner(sop);
}
/* unused nfs4_file's are releseed. XXX slab cache? */
if (list_empty(&fp->fi_perfile)) {
release_file(fp);
}
}
static int
cmp_owner_str(struct nfs4_stateowner *sop, struct nfsd4_open *open) {
return ((sop->so_owner.len == open->op_owner.len) &&
......@@ -872,6 +948,30 @@ nfs4_init_ino(nfs4_ino_desc_t *ino, struct svc_fh *fhp)
ino->generation = inode->i_generation;
}
int
nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type)
{
nfs4_ino_desc_t ino;
unsigned int fi_hashval;
struct nfs4_file *fp;
struct nfs4_stateid *stp;
struct list_head *pos, *next;
dprintk("NFSD: nfs4_share_conflict\n");
nfs4_init_ino(&ino, current_fh);
fi_hashval = file_hashval(&ino);
if (find_file(fi_hashval, &ino, &fp)) {
/* Search for conflicting share reservations */
list_for_each_safe(pos, next, &fp->fi_perfile) {
stp = list_entry(pos, struct nfs4_stateid, st_perfile);
if (stp->st_share_deny & deny_type)
return nfserr_share_denied;
}
}
return nfs_ok;
}
static inline int
nfs4_file_upgrade(struct file *filp, unsigned int share_access)
{
......@@ -887,6 +987,15 @@ int status;
return nfs_ok;
}
static inline void
nfs4_file_downgrade(struct file *filp, unsigned int share_access)
{
if (share_access & NFS4_SHARE_ACCESS_WRITE) {
put_write_access(filp->f_dentry->d_inode);
filp->f_mode = FMODE_READ;
}
}
/*
* nfsd4_process_open1()
......@@ -981,7 +1090,6 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
struct nfs4_stateid *stq, *stp = NULL;
int status;
status = nfserr_resource;
if (!sop)
goto out;
......@@ -1026,6 +1134,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
&stp->st_vfs_file)) != 0)
goto out_free;
vfsopen++;
dget(stp->st_vfs_file.f_dentry);
mntget(stp->st_vfs_file.f_vfsmnt);
......@@ -1063,6 +1172,13 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE;
status = nfs_ok;
out:
/*
* To finish the open response, we just need to set the rflags.
*/
open->op_rflags = 0;
if (!open->op_stateowner->so_confirmed)
open->op_rflags |= NFS4_OPEN_RESULT_CONFIRM;
up(&client_sema); /*XXX need finer grained locking */
return status;
out_free:
......@@ -1154,6 +1270,326 @@ laundromat_main(void *not_used)
schedule_delayed_work(&laundromat_work, t*HZ);
}
/* search openstateid_hashtbl[] for stateid */
struct nfs4_stateid *
find_stateid(stateid_t *stid)
{
struct list_head *pos, *next;
struct nfs4_stateid *local = NULL;
u32 st_id = stid->si_stateownerid;
u32 f_id = stid->si_fileid;
unsigned int hashval = openstateid_hashval(st_id, f_id);
list_for_each_safe(pos, next, &openstateid_hashtbl[hashval]) {
local = list_entry(pos, struct nfs4_stateid, st_hash);
if((local->st_stateid.si_stateownerid == st_id) &&
(local->st_stateid.si_fileid == f_id))
return local;
}
return NULL;
}
/* search ownerid_hashtbl[] for stateid owner (stateid->si_stateownerid) */
struct nfs4_stateowner *
find_stateowner_id(u32 st_id) {
struct list_head *pos, *next;
struct nfs4_stateowner *local = NULL;
unsigned int hashval = ownerid_hashval(st_id);
list_for_each_safe(pos, next, &ownerid_hashtbl[hashval]) {
local = list_entry(pos, struct nfs4_stateowner, so_idhash);
if(local->so_id == st_id)
return local;
}
return NULL;
}
static inline int
nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stateid *stp)
{
return (fhp->fh_dentry != stp->st_vfs_file.f_dentry);
}
static int
STALE_STATEID(stateid_t *stateid)
{
if (stateid->si_boot == boot_time)
return 0;
printk("NFSD: stale stateid (%08x/%08x/%08x/%08x)!\n",
stateid->si_boot, stateid->si_stateownerid, stateid->si_fileid,
stateid->si_generation);
return 1;
}
/*
* Checks for stateid operations
*/
int
nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int flags, struct nfs4_stateid **stpp)
{
struct nfs4_stateid *stp;
int status;
dprintk("NFSD: preprocess_stateid_op:stateid = (%08x/%08x/%08x/%08x)\n",
stateid->si_boot, stateid->si_stateownerid,
stateid->si_fileid, stateid->si_generation);
*stpp = NULL;
/* STALE STATEID */
status = nfserr_stale_stateid;
if (STALE_STATEID(stateid))
goto out;
/* BAD STATEID */
status = nfserr_bad_stateid;
if (!(stp = find_stateid(stateid))) {
dprintk("NFSD: process stateid: no open stateid!\n");
goto out;
}
if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) {
dprintk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n");
goto out;
}
if (!stp->st_stateowner->so_confirmed) {
dprintk("process_stateid: lockowner not confirmed yet!\n");
goto out;
}
if (stateid->si_generation > stp->st_stateid.si_generation) {
dprintk("process_stateid: future stateid?!\n");
goto out;
}
/* OLD STATEID */
status = nfserr_old_stateid;
if (stateid->si_generation < stp->st_stateid.si_generation) {
dprintk("process_stateid: old stateid!\n");
goto out;
}
*stpp = stp;
status = nfs_ok;
renew_client(stp->st_stateowner->so_client);
out:
return status;
}
/*
* Checks for sequence id mutating operations.
*
* XXX need to code replay cache logic
*/
int
nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp)
{
int status;
struct nfs4_stateid *stp;
struct nfs4_stateowner *sop;
dprintk("NFSD: preprocess_seqid_op: seqid=%d "
"stateid = (%08x/%08x/%08x/%08x)\n", seqid,
stateid->si_boot, stateid->si_stateownerid, stateid->si_fileid,
stateid->si_generation);
*stpp = NULL;
*sopp = NULL;
status = nfserr_bad_stateid;
if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) {
printk("NFSD: preprocess_seqid_op: magic stateid!\n");
goto out;
}
status = nfserr_stale_stateid;
if (STALE_STATEID(stateid))
goto out;
/*
* We return BAD_STATEID if filehandle doesn't match stateid,
* the confirmed flag is incorrecly set, or the generation
* number is incorrect.
* If there is no entry in the openfile table for this id,
* we can't always return BAD_STATEID;
* this might be a retransmitted CLOSE which has arrived after
* the openfile has been released.
*/
if (!(stp = find_stateid(stateid)))
goto no_nfs4_stateid;
status = nfserr_bad_stateid;
if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) {
printk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n");
goto out;
}
*stpp = stp;
*sopp = sop = stp->st_stateowner;
/*
* We now validate the seqid and stateid generation numbers.
* For the moment, we ignore the possibility of
* generation number wraparound.
*/
if (seqid != sop->so_seqid + 1)
goto check_replay;
if (sop->so_confirmed) {
if (flags & CONFIRM) {
printk("NFSD: preprocess_seqid_op: expected unconfirmed stateowner!\n");
goto out;
}
}
else {
if (!(flags & CONFIRM)) {
printk("NFSD: preprocess_seqid_op: stateowner not confirmed yet!\n");
goto out;
}
}
if (stateid->si_generation > stp->st_stateid.si_generation) {
printk("NFSD: preprocess_seqid_op: future stateid?!\n");
goto out;
}
status = nfserr_old_stateid;
if (stateid->si_generation < stp->st_stateid.si_generation) {
printk("NFSD: preprocess_seqid_op: old stateid!\n");
goto out;
}
/* XXX renew the client lease here */
status = nfs_ok;
out:
return status;
no_nfs4_stateid:
/*
* We determine whether this is a bad stateid or a replay,
* starting by trying to look up the stateowner.
* If stateowner is not found - stateid is bad.
*/
if (!(sop = find_stateowner_id(stateid->si_stateownerid))) {
printk("NFSD: preprocess_seqid_op: no stateowner or nfs4_stateid!\n");
status = nfserr_bad_stateid;
goto out;
}
check_replay:
status = nfserr_bad_seqid;
if (seqid == sop->so_seqid) {
printk("NFSD: preprocess_seqid_op: retransmission?\n");
/* XXX will need to indicate replay to calling function here */
} else
printk("NFSD: preprocess_seqid_op: bad seqid (expected %d, got %d\n", sop->so_seqid +1, seqid);
goto out;
}
int
nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_confirm *oc)
{
int status;
struct nfs4_stateowner *sop;
struct nfs4_stateid *stp;
dprintk("NFSD: nfsd4_open_confirm on file %.*s\n",
current_fh->fh_dentry->d_name.len,
current_fh->fh_dentry->d_name.name);
oc->oc_stateowner = NULL;
down(&client_sema); /* XXX need finer grained locking */
if ((status = nfs4_preprocess_seqid_op(current_fh, oc->oc_seqid,
&oc->oc_req_stateid,
CHECK_FH | CONFIRM,
&oc->oc_stateowner, &stp)))
goto out;
sop = oc->oc_stateowner;
sop->so_confirmed = 1;
update_stateid(&stp->st_stateid);
memcpy(&oc->oc_resp_stateid, &stp->st_stateid, sizeof(stateid_t));
/* XXX renew the client lease here */
dprintk("NFSD: nfsd4_open_confirm: success, seqid=%d "
"stateid=(%08x/%08x/%08x/%08x)\n", oc->oc_seqid,
stp->st_stateid.si_boot,
stp->st_stateid.si_stateownerid,
stp->st_stateid.si_fileid,
stp->st_stateid.si_generation);
status = nfs_ok;
out:
up(&client_sema);
return status;
}
int
nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_downgrade *od)
{
int status;
struct nfs4_stateid *stp;
dprintk("NFSD: nfsd4_open_downgrade on file %.*s\n",
current_fh->fh_dentry->d_name.len,
current_fh->fh_dentry->d_name.name);
down(&client_sema); /* XXX need finer grained locking */
if ((status = nfs4_preprocess_seqid_op(current_fh, od->od_seqid,
&od->od_stateid,
CHECK_FH, &od->od_stateowner, &stp)))
goto out;
status = nfserr_inval;
if (od->od_share_access & ~stp->st_share_access) {
dprintk("NFSD:access not a subset current=%08x, desired=%08x\n",
stp->st_share_access, od->od_share_access);
goto out;
}
if (od->od_share_deny & ~stp->st_share_deny) {
dprintk("NFSD:deny not a subset current=%08x, desired=%08x\n",
stp->st_share_deny, od->od_share_deny);
goto out;
}
nfs4_file_downgrade(&stp->st_vfs_file,
stp->st_share_access & ~od->od_share_access);
stp->st_share_access = od->od_share_access;
stp->st_share_deny = od->od_share_deny;
update_stateid(&stp->st_stateid);
memcpy(&od->od_stateid, &stp->st_stateid, sizeof(stateid_t));
status = nfs_ok;
out:
up(&client_sema);
return status;
}
int
nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_close *close)
{
int status;
struct nfs4_stateid *stp;
dprintk("NFSD: nfsd4_close on file %.*s\n",
current_fh->fh_dentry->d_name.len,
current_fh->fh_dentry->d_name.name);
down(&client_sema); /* XXX need finer grained locking */
if ((status = nfs4_preprocess_seqid_op(current_fh, close->cl_seqid,
&close->cl_stateid,
CHECK_FH,
&close->cl_stateowner, &stp)))
goto out;
/*
* Return success, but first update the stateid.
*/
status = nfs_ok;
update_stateid(&stp->st_stateid);
memcpy(&close->cl_stateid, &stp->st_stateid, sizeof(stateid_t));
/* release_open_state() calls nfsd_close() if needed */
release_open_state(stp);
out:
up(&client_sema);
return status;
}
void
nfs4_state_init(void)
{
......@@ -1172,7 +1608,14 @@ nfs4_state_init(void)
}
for (i = 0; i < OWNER_HASH_SIZE; i++) {
INIT_LIST_HEAD(&ownerstr_hashtbl[i]);
INIT_LIST_HEAD(&ownerid_hashtbl[i]);
}
for (i = 0; i < OPENSTATEID_HASH_SIZE; i++) {
INIT_LIST_HEAD(&openstateid_hashtbl[i]);
}
memset(&zerostateid, 0, sizeof(stateid_t));
memset(&onestateid, ~0, sizeof(stateid_t));
INIT_LIST_HEAD(&client_lru);
init_MUTEX(&client_sema);
boot_time = get_seconds();
......@@ -1206,6 +1649,12 @@ __nfs4_state_shutdown(void)
list_add_perfile, list_del_perfile);
dprintk("NFSD: add_perclient %d del_perclient %d\n",
add_perclient, del_perclient);
dprintk("NFSD: alloc_file %d free_file %d\n",
alloc_file, free_file);
dprintk("NFSD: alloc_sowner %d free_sowner %d\n",
alloc_sowner, free_sowner);
dprintk("NFSD: vfsopen %d vfsclose %d\n",
vfsopen, vfsclose);
}
void
......
......@@ -659,6 +659,34 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
DECODE_TAIL;
}
static int
nfsd4_decode_open_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_open_confirm *open_conf)
{
DECODE_HEAD;
READ_BUF(4 + sizeof(stateid_t));
READ32(open_conf->oc_req_stateid.si_generation);
COPYMEM(&open_conf->oc_req_stateid.si_opaque, sizeof(stateid_opaque_t));
READ32(open_conf->oc_seqid);
DECODE_TAIL;
}
static int
nfsd4_decode_open_downgrade(struct nfsd4_compoundargs *argp, struct nfsd4_open_downgrade *open_down)
{
DECODE_HEAD;
READ_BUF(4 + sizeof(stateid_t));
READ32(open_down->od_stateid.si_generation);
COPYMEM(&open_down->od_stateid.si_opaque, sizeof(stateid_opaque_t));
READ32(open_down->od_seqid);
READ32(open_down->od_share_access);
READ32(open_down->od_share_deny);
DECODE_TAIL;
}
static int
nfsd4_decode_putfh(struct nfsd4_compoundargs *argp, struct nfsd4_putfh *putfh)
{
......@@ -953,6 +981,12 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
case OP_OPEN:
op->status = nfsd4_decode_open(argp, &op->u.open);
break;
case OP_OPEN_CONFIRM:
op->status = nfsd4_decode_open_confirm(argp, &op->u.open_confirm);
break;
case OP_OPEN_DOWNGRADE:
op->status = nfsd4_decode_open_downgrade(argp, &op->u.open_downgrade);
break;
case OP_PUTFH:
op->status = nfsd4_decode_putfh(argp, &op->u.putfh);
break;
......@@ -1057,6 +1091,21 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
} while (0)
#define ADJUST_ARGS() resp->p = p
/*
* Routine for encoding the result of a
* "seqid-mutating" NFSv4 operation. This is
* where seqids are incremented
*/
#define ENCODE_SEQID_OP_TAIL(stateowner) \
BUG_ON(!stateowner); \
if (seqid_mutating_err(nfserr) && stateowner) { \
if (stateowner->so_confirmed) \
stateowner->so_seqid++; \
} \
return nfserr;
static u32 nfs4_ftypes[16] = {
NF4BAD, NF4FIFO, NF4CHR, NF4BAD,
NF4DIR, NF4BAD, NF4BLK, NF4BAD,
......@@ -1701,6 +1750,36 @@ nfsd4_encode_open(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_open
}
}
static int
nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_open_confirm *oc)
{
ENCODE_HEAD;
if (!nfserr) {
RESERVE_SPACE(sizeof(stateid_t));
WRITE32(oc->oc_resp_stateid.si_generation);
WRITEMEM(&oc->oc_resp_stateid.si_opaque, sizeof(stateid_opaque_t));
ADJUST_ARGS();
}
ENCODE_SEQID_OP_TAIL(oc->oc_stateowner);
}
static int
nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_open_downgrade *od)
{
ENCODE_HEAD;
if (!nfserr) {
RESERVE_SPACE(sizeof(stateid_t));
WRITE32(od->od_stateid.si_generation);
WRITEMEM(&od->od_stateid.si_opaque, sizeof(stateid_opaque_t));
ADJUST_ARGS();
}
ENCODE_SEQID_OP_TAIL(od->od_stateowner);
}
static int
nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_read *read)
{
......@@ -2013,6 +2092,12 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
case OP_OPEN:
nfsd4_encode_open(resp, op->status, &op->u.open);
break;
case OP_OPEN_CONFIRM:
nfsd4_encode_open_confirm(resp, op->status, &op->u.open_confirm);
break;
case OP_OPEN_DOWNGRADE:
nfsd4_encode_open_downgrade(resp, op->status, &op->u.open_downgrade);
break;
case OP_PUTFH:
break;
case OP_PUTROOTFH:
......
......@@ -175,32 +175,14 @@ static struct file_operations transaction_ops = {
extern struct seq_operations nfs_exports_op;
static int exports_open(struct inode *inode, struct file *file)
{
int res;
char *namebuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (namebuf == NULL)
return -ENOMEM;
res = seq_open(file, &nfs_exports_op);
if (res)
kfree(namebuf);
else
((struct seq_file *)file->private_data)->private = namebuf;
return res;
}
static int exports_release(struct inode *inode, struct file *file)
{
struct seq_file *m = (struct seq_file *)file->private_data;
kfree(m->private);
m->private = NULL;
return seq_release(inode, file);
return seq_open(file, &nfs_exports_op);
}
static struct file_operations exports_operations = {
.open = exports_open,
.read = seq_read,
.llseek = seq_lseek,
.release = exports_release,
.release = seq_release,
};
/*----------------------------------------------------------------------------*/
......
......@@ -100,7 +100,18 @@
NFSERR_RECLAIM_CONFLICT = 10035,/* v4 */
NFSERR_BAD_XDR = 10036, /* v4 */
NFSERR_LOCKS_HELD = 10037, /* v4 */
NFSERR_REPLAY_ME = 10038 /* v4 */
NFSERR_OPENMODE = 10038, /* v4 */
NFSERR_BADOWNER = 10039, /* v4 */
NFSERR_BADCHAR = 10040, /* v4 */
NFSERR_BADNAME = 10041, /* v4 */
NFSERR_BAD_RANGE = 10042, /* v4 */
NFSERR_LOCK_NOTSUPP = 10043, /* v4 */
NFSERR_OP_ILLEGAL = 10044, /* v4 */
NFSERR_DEADLOCK = 10045, /* v4 */
NFSERR_FILE_OPEN = 10046, /* v4 */
NFSERR_ADMIN_REVOKED = 10047, /* v4 */
NFSERR_CB_PATH_DOWN = 10048, /* v4 */
NFSERR_REPLAY_ME = 10049 /* v4 */
};
/* NFSv2 file types - beware, these are not the same in NFSv3 */
......
......@@ -35,6 +35,8 @@
#define NFS4_SHARE_ACCESS_READ 0x0001
#define NFS4_SHARE_ACCESS_WRITE 0x0002
#define NFS4_SHARE_ACCESS_BOTH 0x0003
#define NFS4_SHARE_DENY_READ 0x0001
#define NFS4_SHARE_DENY_WRITE 0x0002
#define NFS4_SET_TO_SERVER_TIME 0
#define NFS4_SET_TO_CLIENT_TIME 1
......
......@@ -189,6 +189,7 @@ void nfsd_lockd_shutdown(void);
#define nfserr_not_same __constant_htonl(NFSERR_NOT_SAME)
#define nfserr_readdir_nospc __constant_htonl(NFSERR_READDIR_NOSPC)
#define nfserr_bad_xdr __constant_htonl(NFSERR_BAD_XDR)
#define nfserr_openmode __constant_htonl(NFSERR_OPENMODE)
/* error codes for internal use */
/* if a request fails due to kmalloc failure, it gets dropped.
......
......@@ -59,6 +59,12 @@ typedef struct {
#define si_stateownerid si_opaque.so_stateownerid
#define si_fileid si_opaque.so_fileid
extern stateid_t zerostateid;
extern stateid_t onestateid;
#define ZERO_STATEID(stateid) (!memcmp((stateid), &zerostateid, sizeof(stateid_t)))
#define ONE_STATEID(stateid) (!memcmp((stateid), &onestateid, sizeof(stateid_t)))
/*
* struct nfs4_client - one per client. Clientids live here.
* o Each nfs4_client is hashed by clientid.
......@@ -83,16 +89,12 @@ struct nfs4_client {
nfs4_verifier cl_confirm; /* generated by server */
};
extern time_t nfs4_laundromat(void);
int nfsd4_renew(clientid_t *clid);
static inline void
update_stateid(stateid_t *stateid)
{
stateid->si_generation++;
stateid->si_generation++;
}
/*
* nfs4_stateowner can either be an open_owner, or (eventually) a lock_owner
*
......@@ -100,6 +102,7 @@ stateid->si_generation++;
* reverences when we release a stateowner.
*/
struct nfs4_stateowner {
struct list_head so_idhash; /* hash by so_id */
struct list_head so_strhash; /* hash by op_name */
struct list_head so_perclient; /* nfs4_client->cl_perclient */
struct list_head so_peropenstate; /* list: nfs4_stateid */
......@@ -136,6 +139,7 @@ struct nfs4_file {
*/
struct nfs4_stateid {
struct list_head st_hash; /* openstateid_hashtbl[]*/
struct list_head st_perfile; /* file_hashtbl[]*/
struct list_head st_peropenstate; /* nfs4_stateowner->so_peropenstate */
struct nfs4_stateowner * st_stateowner;
......@@ -147,4 +151,22 @@ struct nfs4_stateid {
unsigned int st_share_deny;
};
/* flags for preprocess_seqid_op() */
#define CHECK_FH 0x00000001
#define CONFIRM 0x00000002
#define seqid_mutating_err(err) \
(((err) != nfserr_stale_clientid) && \
((err) != nfserr_bad_seqid) && \
((err) != nfserr_stale_stateid) && \
((err) != nfserr_bad_stateid))
extern time_t nfs4_laundromat(void);
extern int nfsd4_renew(clientid_t *clid);
extern int nfs4_preprocess_stateid_op(struct svc_fh *current_fh,
stateid_t *stateid, int flags, struct nfs4_stateid **stpp);
extern int nfs4_share_conflict(struct svc_fh *current_fh,
unsigned int deny_type);
extern void nfsd4_lock_state(void);
extern void nfsd4_unlock_state(void);
#endif /* NFSD4_STATE_H */
......@@ -68,6 +68,7 @@ struct nfsd4_access {
struct nfsd4_close {
u32 cl_seqid; /* request */
stateid_t cl_stateid; /* request+response */
struct nfs4_stateowner * cl_stateowner; /* response */
};
struct nfsd4_commit {
......@@ -147,6 +148,22 @@ struct nfsd4_open {
#define op_iattr u.iattr
#define op_verf u.verf
struct nfsd4_open_confirm {
stateid_t oc_req_stateid /* request */;
u32 oc_seqid /* request */;
stateid_t oc_resp_stateid /* response */;
struct nfs4_stateowner * oc_stateowner; /* response */
};
struct nfsd4_open_downgrade {
stateid_t od_stateid;
u32 od_seqid;
u32 od_share_access;
u32 od_share_deny;
struct nfs4_stateowner *od_stateowner;
};
struct nfsd4_read {
stateid_t rd_stateid; /* request */
u64 rd_offset; /* request */
......@@ -252,6 +269,8 @@ struct nfsd4_op {
struct nfsd4_lookup lookup;
struct nfsd4_verify nverify;
struct nfsd4_open open;
struct nfsd4_open_confirm open_confirm;
struct nfsd4_open_downgrade open_downgrade;
struct nfsd4_putfh putfh;
struct nfsd4_read read;
struct nfsd4_readdir readdir;
......@@ -315,16 +334,27 @@ set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp)
}
int nfs4svc_encode_voidres(struct svc_rqst *, u32 *, void *);
int nfs4svc_decode_compoundargs(struct svc_rqst *, u32 *, struct nfsd4_compoundargs *);
int nfs4svc_encode_compoundres(struct svc_rqst *, u32 *, struct nfsd4_compoundres *);
int nfs4svc_decode_compoundargs(struct svc_rqst *, u32 *,
struct nfsd4_compoundargs *);
int nfs4svc_encode_compoundres(struct svc_rqst *, u32 *,
struct nfsd4_compoundres *);
void nfsd4_encode_operation(struct nfsd4_compoundres *, struct nfsd4_op *);
int nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
struct dentry *dentry, u32 *buffer, int *countp, u32 *bmval);
extern int nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid);
extern int nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confirm *setclientid_confirm);
struct dentry *dentry, u32 *buffer, int *countp,
u32 *bmval);
extern int nfsd4_setclientid(struct svc_rqst *rqstp,
struct nfsd4_setclientid *setclid);
extern int nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
struct nfsd4_setclientid_confirm *setclientid_confirm);
extern int nfsd4_process_open1(struct nfsd4_open *open);
extern int nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open);
extern int nfsd4_process_open2(struct svc_rqst *rqstp,
struct svc_fh *current_fh, struct nfsd4_open *open);
extern int nfsd4_open_confirm(struct svc_rqst *rqstp,
struct svc_fh *current_fh, struct nfsd4_open_confirm *oc);
extern int nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh,
struct nfsd4_close *close);
extern int nfsd4_open_downgrade(struct svc_rqst *rqstp,
struct svc_fh *current_fh, struct nfsd4_open_downgrade *od);
#endif
/*
......
......@@ -80,8 +80,7 @@ struct cache_detail {
int (*cache_show)(struct seq_file *m,
struct cache_detail *cd,
struct cache_head *h,
char *pbuf);
struct cache_head *h);
/* fields below this comment are for internal use
* and should not be touched by cache owners
......
......@@ -41,7 +41,7 @@ static void __unhash_process(struct task_struct *p)
detach_pid(p, PIDTYPE_PGID);
detach_pid(p, PIDTYPE_SID);
if (p->pid)
per_cpu(process_counts, smp_processor_id())--;
__get_cpu_var(process_counts)--;
}
REMOVE_LINKS(p);
......
......@@ -1006,7 +1006,7 @@ struct task_struct *copy_process(unsigned long clone_flags,
attach_pid(p, PIDTYPE_PGID, p->pgrp);
attach_pid(p, PIDTYPE_SID, p->session);
if (p->pid)
per_cpu(process_counts, smp_processor_id())++;
__get_cpu_var(process_counts)++;
} else
link_pid(p, p->pids + PIDTYPE_TGID, &p->group_leader->pids[PIDTYPE_TGID].pid);
......
......@@ -156,8 +156,7 @@ static void internal_add_timer(tvec_base_t *base, struct timer_list *timer)
*/
void add_timer(struct timer_list *timer)
{
int cpu = get_cpu();
tvec_base_t *base = &per_cpu(tvec_bases, cpu);
tvec_base_t *base = &get_cpu_var(tvec_bases);
unsigned long flags;
BUG_ON(timer_pending(timer) || !timer->function);
......@@ -168,7 +167,7 @@ void add_timer(struct timer_list *timer)
internal_add_timer(base, timer);
timer->base = base;
spin_unlock_irqrestore(&base->lock, flags);
put_cpu();
put_cpu_var(tvec_bases);
}
/***
......@@ -231,7 +230,7 @@ int mod_timer(struct timer_list *timer, unsigned long expires)
return 1;
spin_lock_irqsave(&timer->lock, flags);
new_base = &per_cpu(tvec_bases, smp_processor_id());
new_base = &__get_cpu_var(tvec_bases);
repeat:
old_base = timer->base;
......@@ -789,7 +788,7 @@ seqlock_t xtime_lock __cacheline_aligned_in_smp = SEQLOCK_UNLOCKED;
*/
static void run_timer_softirq(struct softirq_action *h)
{
tvec_base_t *base = &per_cpu(tvec_bases, smp_processor_id());
tvec_base_t *base = &__get_cpu_var(tvec_bases);
if (time_after_eq(jiffies, base->timer_jiffies))
__run_timers(base);
......
......@@ -213,21 +213,19 @@ void balance_dirty_pages(struct address_space *mapping)
void balance_dirty_pages_ratelimited(struct address_space *mapping)
{
static DEFINE_PER_CPU(int, ratelimits) = 0;
int cpu;
long ratelimit;
ratelimit = ratelimit_pages;
if (dirty_exceeded)
ratelimit = 8;
cpu = get_cpu();
if (per_cpu(ratelimits, cpu)++ >= ratelimit) {
per_cpu(ratelimits, cpu) = 0;
put_cpu();
if (get_cpu_var(ratelimits)++ >= ratelimit) {
__get_cpu_var(ratelimits) = 0;
put_cpu_var(ratelimits);
balance_dirty_pages(mapping);
return;
}
put_cpu();
put_cpu_var(ratelimits);
}
/*
......
......@@ -477,16 +477,15 @@ DEFINE_PER_CPU(struct pte_chain *, local_pte_chain) = 0;
*/
void __pte_chain_free(struct pte_chain *pte_chain)
{
int cpu = get_cpu();
struct pte_chain **pte_chainp;
pte_chainp = &get_cpu_var(local_pte_chain);
if (pte_chain->next_and_idx)
pte_chain->next_and_idx = 0;
pte_chainp = &per_cpu(local_pte_chain, cpu);
if (*pte_chainp)
kmem_cache_free(pte_chain_cache, *pte_chainp);
*pte_chainp = pte_chain;
put_cpu();
put_cpu_var(local_pte_chain);
}
/*
......@@ -501,21 +500,19 @@ void __pte_chain_free(struct pte_chain *pte_chain)
*/
struct pte_chain *pte_chain_alloc(int gfp_flags)
{
int cpu;
struct pte_chain *ret;
struct pte_chain **pte_chainp;
if (gfp_flags & __GFP_WAIT)
might_sleep();
cpu = get_cpu();
pte_chainp = &per_cpu(local_pte_chain, cpu);
pte_chainp = &get_cpu_var(local_pte_chain);
if (*pte_chainp) {
ret = *pte_chainp;
*pte_chainp = NULL;
put_cpu();
put_cpu_var(local_pte_chain);
} else {
put_cpu();
put_cpu_var(local_pte_chain);
ret = kmem_cache_alloc(pte_chain_cache, gfp_flags);
}
return ret;
......
......@@ -112,35 +112,34 @@ static DEFINE_PER_CPU(struct pagevec, lru_add_active_pvecs) = { 0, };
void lru_cache_add(struct page *page)
{
struct pagevec *pvec = &per_cpu(lru_add_pvecs, get_cpu());
struct pagevec *pvec = &get_cpu_var(lru_add_pvecs);
page_cache_get(page);
if (!pagevec_add(pvec, page))
__pagevec_lru_add(pvec);
put_cpu();
put_cpu_var(lru_add_pvecs);
}
void lru_cache_add_active(struct page *page)
{
struct pagevec *pvec = &per_cpu(lru_add_active_pvecs, get_cpu());
struct pagevec *pvec = &get_cpu_var(lru_add_active_pvecs);
page_cache_get(page);
if (!pagevec_add(pvec, page))
__pagevec_lru_add_active(pvec);
put_cpu();
put_cpu_var(lru_add_active_pvecs);
}
void lru_add_drain(void)
{
int cpu = get_cpu();
struct pagevec *pvec = &per_cpu(lru_add_pvecs, cpu);
struct pagevec *pvec = &get_cpu_var(lru_add_pvecs);
if (pagevec_count(pvec))
__pagevec_lru_add(pvec);
pvec = &per_cpu(lru_add_active_pvecs, cpu);
pvec = &__get_cpu_var(lru_add_active_pvecs);
if (pagevec_count(pvec))
__pagevec_lru_add_active(pvec);
put_cpu();
put_cpu_var(lru_add_pvecs);
}
/*
......
......@@ -228,7 +228,7 @@ static struct icmp_control icmp_pointers[NR_ICMP_TYPES+1];
* On SMP we have one ICMP socket per-cpu.
*/
static DEFINE_PER_CPU(struct socket *, __icmp_socket) = NULL;
#define icmp_socket per_cpu(__icmp_socket, smp_processor_id())
#define icmp_socket __get_cpu_var(__icmp_socket)
static __inline__ void icmp_xmit_lock(void)
{
......
......@@ -1018,7 +1018,6 @@ int qword_get(char **bpp, char *dest, int bufsize)
struct handle {
struct cache_detail *cd;
char *pbuf;
};
static void *c_start(struct seq_file *m, loff_t *pos)
......@@ -1087,10 +1086,9 @@ static int c_show(struct seq_file *m, void *p)
{
struct cache_head *cp = p;
struct cache_detail *cd = ((struct handle*)m->private)->cd;
char *pbuf = ((struct handle*)m->private)->pbuf;
if (p == (void *)1)
return cd->cache_show(m, cd, NULL, pbuf);
return cd->cache_show(m, cd, NULL);
ifdebug(CACHE)
seq_printf(m, "# expiry=%ld refcnt=%d\n",
......@@ -1102,7 +1100,7 @@ static int c_show(struct seq_file *m, void *p)
else
cache_put(cp, cd);
return cd->cache_show(m, cd, cp, pbuf);
return cd->cache_show(m, cd, cp);
}
struct seq_operations cache_content_op = {
......@@ -1115,26 +1113,19 @@ struct seq_operations cache_content_op = {
static int content_open(struct inode *inode, struct file *file)
{
int res;
char *namebuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
struct handle *han;
struct cache_detail *cd = PDE(inode)->data;
if (namebuf == NULL)
return -ENOMEM;
han = kmalloc(sizeof(*han), GFP_KERNEL);
if (han == NULL) {
kfree(namebuf);
if (han == NULL)
return -ENOMEM;
}
han->pbuf = namebuf;
han->cd = cd;
res = seq_open(file, &cache_content_op);
if (res) {
kfree(namebuf);
if (res)
kfree(han);
} else
else
((struct seq_file *)file->private_data)->private = han;
return res;
......@@ -1143,7 +1134,6 @@ static int content_release(struct inode *inode, struct file *file)
{
struct seq_file *m = (struct seq_file *)file->private_data;
struct handle *han = m->private;
kfree(han->pbuf);
kfree(han);
m->private = NULL;
return seq_release(inode, file);
......
......@@ -215,8 +215,7 @@ static int ip_map_parse(struct cache_detail *cd,
static int ip_map_show(struct seq_file *m,
struct cache_detail *cd,
struct cache_head *h,
char *pbuf)
struct cache_head *h)
{
struct ip_map *im;
struct in_addr addr;
......
......@@ -32,6 +32,7 @@
#include <linux/slab.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/suspend.h>
#include <net/sock.h>
#include <net/checksum.h>
#include <net/ip.h>
......@@ -1190,6 +1191,9 @@ svc_recv(struct svc_serv *serv, struct svc_rqst *rqstp, long timeout)
schedule_timeout(timeout);
if (current->flags & PF_FREEZE)
refrigerator(PF_IOTHREAD);
spin_lock_bh(&serv->sv_lock);
remove_wait_queue(&rqstp->rq_wait, &wait);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment