From 86154cf204ccd328a5d532b908e193a8ac826c63 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 8 Nov 2012 10:01:26 -0500 Subject: [PATCH] --- yaml --- r: 346614 b: refs/heads/master c: 642fe4d00db56d65060ce2fd4c105884414acb16 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/arch/arm/include/asm/io.h | 4 +- trunk/arch/arm/include/asm/sched_clock.h | 2 - trunk/arch/arm/include/asm/vfpmacros.h | 12 +- trunk/arch/arm/include/uapi/asm/hwcap.h | 3 +- trunk/arch/arm/kernel/sched_clock.c | 18 +- trunk/arch/arm/mm/alignment.c | 2 +- trunk/arch/arm/vfp/vfpmodule.c | 9 +- trunk/drivers/gpu/drm/drm_fops.c | 44 +- trunk/drivers/gpu/drm/radeon/evergreen.c | 2 +- trunk/drivers/hwmon/asb100.c | 2 +- trunk/drivers/hwmon/w83627ehf.c | 1 + trunk/drivers/hwmon/w83627hf.c | 2 +- trunk/drivers/hwmon/w83781d.c | 2 +- trunk/drivers/hwmon/w83791d.c | 2 +- trunk/drivers/hwmon/w83792d.c | 2 +- trunk/drivers/hwmon/w83l786ng.c | 2 +- trunk/fs/gfs2/file.c | 14 +- trunk/fs/gfs2/lops.c | 16 +- trunk/fs/gfs2/quota.c | 7 +- trunk/fs/gfs2/rgrp.c | 33 +- trunk/fs/gfs2/super.c | 3 +- trunk/fs/gfs2/trans.c | 8 + trunk/fs/lockd/clnt4xdr.c | 8 + trunk/fs/lockd/clntproc.c | 3 +- trunk/fs/lockd/clntxdr.c | 8 + trunk/fs/lockd/host.c | 15 +- trunk/fs/lockd/mon.c | 3 + trunk/fs/nfs/Makefile | 2 +- trunk/fs/nfs/blocklayout/blocklayout.c | 1 - trunk/fs/nfs/cache_lib.c | 1 + trunk/fs/nfs/callback.h | 4 +- trunk/fs/nfs/callback_proc.c | 17 +- trunk/fs/nfs/callback_xdr.c | 5 +- trunk/fs/nfs/client.c | 6 +- trunk/fs/nfs/inode.c | 4 +- trunk/fs/nfs/internal.h | 35 ++ trunk/fs/nfs/mount_clnt.c | 7 +- trunk/fs/nfs/nfs2xdr.c | 4 +- trunk/fs/nfs/nfs3xdr.c | 7 +- trunk/fs/nfs/nfs4_fs.h | 27 +- trunk/fs/nfs/nfs4client.c | 5 +- trunk/fs/nfs/nfs4file.c | 1 + trunk/fs/nfs/nfs4filelayout.c | 44 +- trunk/fs/nfs/nfs4filelayoutdev.c | 3 +- trunk/fs/nfs/nfs4proc.c | 732 +++++++++++++++++------ trunk/fs/nfs/nfs4session.c | 542 ----------------- trunk/fs/nfs/nfs4session.h | 142 ----- trunk/fs/nfs/nfs4state.c | 119 ++-- trunk/fs/nfs/nfs4xdr.c | 44 +- trunk/fs/nfs/objlayout/objlayout.c | 11 + trunk/fs/nfs/pnfs.c | 17 +- trunk/fs/nfs/super.c | 1 - trunk/fs/nfs/write.c | 26 +- trunk/include/linux/nfs_fs_sb.h | 47 ++ trunk/include/linux/nfs_xdr.h | 154 ++--- trunk/include/linux/sunrpc/sched.h | 1 + trunk/net/sunrpc/backchannel_rqst.c | 9 +- trunk/net/sunrpc/bc_svc.c | 2 +- trunk/net/sunrpc/cache.c | 4 +- trunk/net/sunrpc/clnt.c | 45 +- trunk/net/sunrpc/rpc_pipe.c | 9 +- trunk/net/sunrpc/rpcb_clnt.c | 5 +- trunk/net/sunrpc/sched.c | 71 +-- trunk/net/sunrpc/svc.c | 12 +- trunk/net/sunrpc/svc_xprt.c | 11 +- trunk/net/sunrpc/svcsock.c | 6 +- trunk/net/sunrpc/xdr.c | 5 +- trunk/net/sunrpc/xprtsock.c | 13 +- 69 files changed, 1135 insertions(+), 1295 deletions(-) delete mode 100644 trunk/fs/nfs/nfs4session.c delete mode 100644 trunk/fs/nfs/nfs4session.h diff --git a/[refs] b/[refs] index 91c0b3122f83..ab11e9f40ada 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 1fa8064429d0acbf5bbf3c8a53f65679fdacc75e +refs/heads/master: 642fe4d00db56d65060ce2fd4c105884414acb16 diff --git a/trunk/arch/arm/include/asm/io.h b/trunk/arch/arm/include/asm/io.h index 35c1ed89b936..42f042ee4ada 100644 --- a/trunk/arch/arm/include/asm/io.h +++ b/trunk/arch/arm/include/asm/io.h @@ -64,7 +64,7 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen); static inline void __raw_writew(u16 val, volatile void __iomem *addr) { asm volatile("strh %1, %0" - : "+Qo" (*(volatile u16 __force *)addr) + : "+Q" (*(volatile u16 __force *)addr) : "r" (val)); } @@ -72,7 +72,7 @@ static inline u16 __raw_readw(const volatile void __iomem *addr) { u16 val; asm volatile("ldrh %1, %0" - : "+Qo" (*(volatile u16 __force *)addr), + : "+Q" (*(volatile u16 __force *)addr), "=r" (val)); return val; } diff --git a/trunk/arch/arm/include/asm/sched_clock.h b/trunk/arch/arm/include/asm/sched_clock.h index 05b8e82ec9f5..e3f757263438 100644 --- a/trunk/arch/arm/include/asm/sched_clock.h +++ b/trunk/arch/arm/include/asm/sched_clock.h @@ -10,7 +10,5 @@ extern void sched_clock_postinit(void); extern void setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate); -extern void setup_sched_clock_needs_suspend(u32 (*read)(void), int bits, - unsigned long rate); #endif diff --git a/trunk/arch/arm/include/asm/vfpmacros.h b/trunk/arch/arm/include/asm/vfpmacros.h index 6a6f1e485f41..301c1db3e99b 100644 --- a/trunk/arch/arm/include/asm/vfpmacros.h +++ b/trunk/arch/arm/include/asm/vfpmacros.h @@ -27,9 +27,9 @@ #if __LINUX_ARM_ARCH__ <= 6 ldr \tmp, =elf_hwcap @ may not have MVFR regs ldr \tmp, [\tmp, #0] - tst \tmp, #HWCAP_VFPv3D16 - ldceql p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d16-d31} - addne \base, \base, #32*4 @ step over unused register space + tst \tmp, #HWCAP_VFPD32 + ldcnel p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d16-d31} + addeq \base, \base, #32*4 @ step over unused register space #else VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0 and \tmp, \tmp, #MVFR0_A_SIMD_MASK @ A_SIMD field @@ -51,9 +51,9 @@ #if __LINUX_ARM_ARCH__ <= 6 ldr \tmp, =elf_hwcap @ may not have MVFR regs ldr \tmp, [\tmp, #0] - tst \tmp, #HWCAP_VFPv3D16 - stceql p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d16-d31} - addne \base, \base, #32*4 @ step over unused register space + tst \tmp, #HWCAP_VFPD32 + stcnel p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d16-d31} + addeq \base, \base, #32*4 @ step over unused register space #else VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0 and \tmp, \tmp, #MVFR0_A_SIMD_MASK @ A_SIMD field diff --git a/trunk/arch/arm/include/uapi/asm/hwcap.h b/trunk/arch/arm/include/uapi/asm/hwcap.h index f254f6503cce..3688fd15a32d 100644 --- a/trunk/arch/arm/include/uapi/asm/hwcap.h +++ b/trunk/arch/arm/include/uapi/asm/hwcap.h @@ -18,11 +18,12 @@ #define HWCAP_THUMBEE (1 << 11) #define HWCAP_NEON (1 << 12) #define HWCAP_VFPv3 (1 << 13) -#define HWCAP_VFPv3D16 (1 << 14) +#define HWCAP_VFPv3D16 (1 << 14) /* also set for VFPv4-D16 */ #define HWCAP_TLS (1 << 15) #define HWCAP_VFPv4 (1 << 16) #define HWCAP_IDIVA (1 << 17) #define HWCAP_IDIVT (1 << 18) +#define HWCAP_VFPD32 (1 << 19) /* set if VFP has 32 regs (not 16) */ #define HWCAP_IDIV (HWCAP_IDIVA | HWCAP_IDIVT) diff --git a/trunk/arch/arm/kernel/sched_clock.c b/trunk/arch/arm/kernel/sched_clock.c index e21bac20d90d..fc6692e2b603 100644 --- a/trunk/arch/arm/kernel/sched_clock.c +++ b/trunk/arch/arm/kernel/sched_clock.c @@ -107,13 +107,6 @@ static void sched_clock_poll(unsigned long wrap_ticks) update_sched_clock(); } -void __init setup_sched_clock_needs_suspend(u32 (*read)(void), int bits, - unsigned long rate) -{ - setup_sched_clock(read, bits, rate); - cd.needs_suspend = true; -} - void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate) { unsigned long r, w; @@ -189,18 +182,15 @@ void __init sched_clock_postinit(void) static int sched_clock_suspend(void) { sched_clock_poll(sched_clock_timer.data); - if (cd.needs_suspend) - cd.suspended = true; + cd.suspended = true; return 0; } static void sched_clock_resume(void) { - if (cd.needs_suspend) { - cd.epoch_cyc = read_sched_clock(); - cd.epoch_cyc_copy = cd.epoch_cyc; - cd.suspended = false; - } + cd.epoch_cyc = read_sched_clock(); + cd.epoch_cyc_copy = cd.epoch_cyc; + cd.suspended = false; } static struct syscore_ops sched_clock_ops = { diff --git a/trunk/arch/arm/mm/alignment.c b/trunk/arch/arm/mm/alignment.c index 023f443784ec..b820edaf3184 100644 --- a/trunk/arch/arm/mm/alignment.c +++ b/trunk/arch/arm/mm/alignment.c @@ -745,7 +745,7 @@ do_alignment_t32_to_handler(unsigned long *pinstr, struct pt_regs *regs, static int do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) { - union offset_union offset; + union offset_union uninitialized_var(offset); unsigned long instr = 0, instrptr; int (*handler)(unsigned long addr, unsigned long instr, struct pt_regs *regs); unsigned int type; diff --git a/trunk/arch/arm/vfp/vfpmodule.c b/trunk/arch/arm/vfp/vfpmodule.c index c834b32af275..3b44e0dd0a93 100644 --- a/trunk/arch/arm/vfp/vfpmodule.c +++ b/trunk/arch/arm/vfp/vfpmodule.c @@ -701,11 +701,14 @@ static int __init vfp_init(void) elf_hwcap |= HWCAP_VFPv3; /* - * Check for VFPv3 D16. CPUs in this configuration - * only have 16 x 64bit registers. + * Check for VFPv3 D16 and VFPv4 D16. CPUs in + * this configuration only have 16 x 64bit + * registers. */ if (((fmrx(MVFR0) & MVFR0_A_SIMD_MASK)) == 1) - elf_hwcap |= HWCAP_VFPv3D16; + elf_hwcap |= HWCAP_VFPv3D16; /* also v4-D16 */ + else + elf_hwcap |= HWCAP_VFPD32; } #endif /* diff --git a/trunk/drivers/gpu/drm/drm_fops.c b/trunk/drivers/gpu/drm/drm_fops.c index 7ef1b673e1be..133b4132983e 100644 --- a/trunk/drivers/gpu/drm/drm_fops.c +++ b/trunk/drivers/gpu/drm/drm_fops.c @@ -121,6 +121,8 @@ int drm_open(struct inode *inode, struct file *filp) int minor_id = iminor(inode); struct drm_minor *minor; int retcode = 0; + int need_setup = 0; + struct address_space *old_mapping; minor = idr_find(&drm_minors_idr, minor_id); if (!minor) @@ -132,23 +134,37 @@ int drm_open(struct inode *inode, struct file *filp) if (drm_device_is_unplugged(dev)) return -ENODEV; + if (!dev->open_count++) + need_setup = 1; + mutex_lock(&dev->struct_mutex); + old_mapping = dev->dev_mapping; + if (old_mapping == NULL) + dev->dev_mapping = &inode->i_data; + /* ihold ensures nobody can remove inode with our i_data */ + ihold(container_of(dev->dev_mapping, struct inode, i_data)); + inode->i_mapping = dev->dev_mapping; + filp->f_mapping = dev->dev_mapping; + mutex_unlock(&dev->struct_mutex); + retcode = drm_open_helper(inode, filp, dev); - if (!retcode) { - atomic_inc(&dev->counts[_DRM_STAT_OPENS]); - if (!dev->open_count++) - retcode = drm_setup(dev); - } - if (!retcode) { - mutex_lock(&dev->struct_mutex); - if (dev->dev_mapping == NULL) - dev->dev_mapping = &inode->i_data; - /* ihold ensures nobody can remove inode with our i_data */ - ihold(container_of(dev->dev_mapping, struct inode, i_data)); - inode->i_mapping = dev->dev_mapping; - filp->f_mapping = dev->dev_mapping; - mutex_unlock(&dev->struct_mutex); + if (retcode) + goto err_undo; + atomic_inc(&dev->counts[_DRM_STAT_OPENS]); + if (need_setup) { + retcode = drm_setup(dev); + if (retcode) + goto err_undo; } + return 0; +err_undo: + mutex_lock(&dev->struct_mutex); + filp->f_mapping = old_mapping; + inode->i_mapping = old_mapping; + iput(container_of(dev->dev_mapping, struct inode, i_data)); + dev->dev_mapping = old_mapping; + mutex_unlock(&dev->struct_mutex); + dev->open_count--; return retcode; } EXPORT_SYMBOL(drm_open); diff --git a/trunk/drivers/gpu/drm/radeon/evergreen.c b/trunk/drivers/gpu/drm/radeon/evergreen.c index 14313ad43b76..af31f829f4a8 100644 --- a/trunk/drivers/gpu/drm/radeon/evergreen.c +++ b/trunk/drivers/gpu/drm/radeon/evergreen.c @@ -1372,7 +1372,7 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s WREG32(BIF_FB_EN, FB_READ_EN | FB_WRITE_EN); for (i = 0; i < rdev->num_crtc; i++) { - if (save->crtc_enabled) { + if (save->crtc_enabled[i]) { if (ASIC_IS_DCE6(rdev)) { tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; diff --git a/trunk/drivers/hwmon/asb100.c b/trunk/drivers/hwmon/asb100.c index a227be47149f..520e5bf4f76d 100644 --- a/trunk/drivers/hwmon/asb100.c +++ b/trunk/drivers/hwmon/asb100.c @@ -32,7 +32,7 @@ * ASB100-A supports pwm1, while plain ASB100 does not. There is no known * way for the driver to tell which one is there. * - * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA + * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA * asb100 7 3 1 4 0x31 0x0694 yes no */ diff --git a/trunk/drivers/hwmon/w83627ehf.c b/trunk/drivers/hwmon/w83627ehf.c index 1821b7423d5b..de3c7e04c3b5 100644 --- a/trunk/drivers/hwmon/w83627ehf.c +++ b/trunk/drivers/hwmon/w83627ehf.c @@ -2083,6 +2083,7 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev) mutex_init(&data->lock); mutex_init(&data->update_lock); data->name = w83627ehf_device_names[sio_data->kind]; + data->bank = 0xff; /* Force initial bank selection */ platform_set_drvdata(pdev, data); /* 627EHG and 627EHF have 10 voltage inputs; 627DHG and 667HG have 9 */ diff --git a/trunk/drivers/hwmon/w83627hf.c b/trunk/drivers/hwmon/w83627hf.c index 5b1a6a666441..af1589908709 100644 --- a/trunk/drivers/hwmon/w83627hf.c +++ b/trunk/drivers/hwmon/w83627hf.c @@ -25,7 +25,7 @@ /* * Supports following chips: * - * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA + * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA * w83627hf 9 3 2 3 0x20 0x5ca3 no yes(LPC) * w83627thf 7 3 3 3 0x90 0x5ca3 no yes(LPC) * w83637hf 7 3 3 3 0x80 0x5ca3 no yes(LPC) diff --git a/trunk/drivers/hwmon/w83781d.c b/trunk/drivers/hwmon/w83781d.c index 5a5046d94c3e..20f11d31da40 100644 --- a/trunk/drivers/hwmon/w83781d.c +++ b/trunk/drivers/hwmon/w83781d.c @@ -24,7 +24,7 @@ /* * Supports following chips: * - * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA + * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA * as99127f 7 3 0 3 0x31 0x12c3 yes no * as99127f rev.2 (type_name = as99127f) 0x31 0x5ca3 yes no * w83781d 7 3 0 3 0x10-1 0x5ca3 yes yes diff --git a/trunk/drivers/hwmon/w83791d.c b/trunk/drivers/hwmon/w83791d.c index 39ab7bcc616e..ed397c645198 100644 --- a/trunk/drivers/hwmon/w83791d.c +++ b/trunk/drivers/hwmon/w83791d.c @@ -22,7 +22,7 @@ /* * Supports following chips: * - * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA + * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA * w83791d 10 5 5 3 0x71 0x5ca3 yes no * * The w83791d chip appears to be part way between the 83781d and the diff --git a/trunk/drivers/hwmon/w83792d.c b/trunk/drivers/hwmon/w83792d.c index 053645279f38..301942d08453 100644 --- a/trunk/drivers/hwmon/w83792d.c +++ b/trunk/drivers/hwmon/w83792d.c @@ -31,7 +31,7 @@ /* * Supports following chips: * - * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA + * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA * w83792d 9 7 7 3 0x7a 0x5ca3 yes no */ diff --git a/trunk/drivers/hwmon/w83l786ng.c b/trunk/drivers/hwmon/w83l786ng.c index f0e8286c3c70..79710bcac2f7 100644 --- a/trunk/drivers/hwmon/w83l786ng.c +++ b/trunk/drivers/hwmon/w83l786ng.c @@ -20,7 +20,7 @@ /* * Supports following chips: * - * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA + * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA * w83l786ng 3 2 2 2 0x7b 0x5ca3 yes no */ diff --git a/trunk/fs/gfs2/file.c b/trunk/fs/gfs2/file.c index 0def0504afc1..e056b4ce4877 100644 --- a/trunk/fs/gfs2/file.c +++ b/trunk/fs/gfs2/file.c @@ -516,15 +516,13 @@ static int gfs2_mmap(struct file *file, struct vm_area_struct *vma) struct gfs2_holder i_gh; int error; - gfs2_holder_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); - error = gfs2_glock_nq(&i_gh); - if (error == 0) { - file_accessed(file); - gfs2_glock_dq(&i_gh); - } - gfs2_holder_uninit(&i_gh); + error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, + &i_gh); if (error) return error; + /* grab lock to update inode */ + gfs2_glock_dq_uninit(&i_gh); + file_accessed(file); } vma->vm_ops = &gfs2_vm_ops; @@ -677,10 +675,8 @@ static ssize_t gfs2_file_aio_write(struct kiocb *iocb, const struct iovec *iov, size_t writesize = iov_length(iov, nr_segs); struct dentry *dentry = file->f_dentry; struct gfs2_inode *ip = GFS2_I(dentry->d_inode); - struct gfs2_sbd *sdp; int ret; - sdp = GFS2_SB(file->f_mapping->host); ret = gfs2_rs_alloc(ip); if (ret) return ret; diff --git a/trunk/fs/gfs2/lops.c b/trunk/fs/gfs2/lops.c index 8ff95a2d54ee..9ceccb1595a3 100644 --- a/trunk/fs/gfs2/lops.c +++ b/trunk/fs/gfs2/lops.c @@ -393,12 +393,10 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) struct gfs2_meta_header *mh; struct gfs2_trans *tr; - lock_buffer(bd->bd_bh); - gfs2_log_lock(sdp); tr = current->journal_info; tr->tr_touched = 1; if (!list_empty(&bd->bd_list)) - goto out; + return; set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags); set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags); mh = (struct gfs2_meta_header *)bd->bd_bh->b_data; @@ -414,9 +412,6 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) sdp->sd_log_num_buf++; list_add(&bd->bd_list, &sdp->sd_log_le_buf); tr->tr_num_buf_new++; -out: - gfs2_log_unlock(sdp); - unlock_buffer(bd->bd_bh); } static void gfs2_check_magic(struct buffer_head *bh) @@ -621,7 +616,6 @@ static void revoke_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) static void revoke_lo_before_commit(struct gfs2_sbd *sdp) { - struct gfs2_log_descriptor *ld; struct gfs2_meta_header *mh; unsigned int offset; struct list_head *head = &sdp->sd_log_le_revoke; @@ -634,7 +628,6 @@ static void revoke_lo_before_commit(struct gfs2_sbd *sdp) length = gfs2_struct2blk(sdp, sdp->sd_log_num_revoke, sizeof(u64)); page = gfs2_get_log_desc(sdp, GFS2_LOG_DESC_REVOKE, length, sdp->sd_log_num_revoke); - ld = page_address(page); offset = sizeof(struct gfs2_log_descriptor); list_for_each_entry(bd, head, bd_list) { @@ -777,12 +770,10 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) struct address_space *mapping = bd->bd_bh->b_page->mapping; struct gfs2_inode *ip = GFS2_I(mapping->host); - lock_buffer(bd->bd_bh); - gfs2_log_lock(sdp); if (tr) tr->tr_touched = 1; if (!list_empty(&bd->bd_list)) - goto out; + return; set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags); set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags); if (gfs2_is_jdata(ip)) { @@ -793,9 +784,6 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) } else { list_add_tail(&bd->bd_list, &sdp->sd_log_le_ordered); } -out: - gfs2_log_unlock(sdp); - unlock_buffer(bd->bd_bh); } /** diff --git a/trunk/fs/gfs2/quota.c b/trunk/fs/gfs2/quota.c index 40c4b0d42fa8..c5af8e18f27a 100644 --- a/trunk/fs/gfs2/quota.c +++ b/trunk/fs/gfs2/quota.c @@ -497,8 +497,11 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid) struct gfs2_quota_data **qd; int error; - if (ip->i_res == NULL) - gfs2_rs_alloc(ip); + if (ip->i_res == NULL) { + error = gfs2_rs_alloc(ip); + if (error) + return error; + } qd = ip->i_res->rs_qa_qd; diff --git a/trunk/fs/gfs2/rgrp.c b/trunk/fs/gfs2/rgrp.c index 3cc402ce6fea..38fe18f2f055 100644 --- a/trunk/fs/gfs2/rgrp.c +++ b/trunk/fs/gfs2/rgrp.c @@ -553,7 +553,6 @@ void gfs2_free_clones(struct gfs2_rgrpd *rgd) */ int gfs2_rs_alloc(struct gfs2_inode *ip) { - int error = 0; struct gfs2_blkreserv *res; if (ip->i_res) @@ -561,7 +560,7 @@ int gfs2_rs_alloc(struct gfs2_inode *ip) res = kmem_cache_zalloc(gfs2_rsrv_cachep, GFP_NOFS); if (!res) - error = -ENOMEM; + return -ENOMEM; RB_CLEAR_NODE(&res->rs_node); @@ -571,7 +570,7 @@ int gfs2_rs_alloc(struct gfs2_inode *ip) else ip->i_res = res; up_write(&ip->i_rw_mutex); - return error; + return 0; } static void dump_rs(struct seq_file *seq, const struct gfs2_blkreserv *rs) @@ -1263,7 +1262,9 @@ int gfs2_fitrim(struct file *filp, void __user *argp) int ret = 0; u64 amt; u64 trimmed = 0; + u64 start, end, minlen; unsigned int x; + unsigned bs_shift = sdp->sd_sb.sb_bsize_shift; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -1271,19 +1272,25 @@ int gfs2_fitrim(struct file *filp, void __user *argp) if (!blk_queue_discard(q)) return -EOPNOTSUPP; - if (argp == NULL) { - r.start = 0; - r.len = ULLONG_MAX; - r.minlen = 0; - } else if (copy_from_user(&r, argp, sizeof(r))) + if (copy_from_user(&r, argp, sizeof(r))) return -EFAULT; ret = gfs2_rindex_update(sdp); if (ret) return ret; - rgd = gfs2_blk2rgrpd(sdp, r.start, 0); - rgd_end = gfs2_blk2rgrpd(sdp, r.start + r.len, 0); + start = r.start >> bs_shift; + end = start + (r.len >> bs_shift); + minlen = max_t(u64, r.minlen, + q->limits.discard_granularity) >> bs_shift; + + rgd = gfs2_blk2rgrpd(sdp, start, 0); + rgd_end = gfs2_blk2rgrpd(sdp, end - 1, 0); + + if (end <= start || + minlen > sdp->sd_max_rg_data || + start > rgd_end->rd_data0 + rgd_end->rd_data) + return -EINVAL; while (1) { @@ -1295,7 +1302,9 @@ int gfs2_fitrim(struct file *filp, void __user *argp) /* Trim each bitmap in the rgrp */ for (x = 0; x < rgd->rd_length; x++) { struct gfs2_bitmap *bi = rgd->rd_bits + x; - ret = gfs2_rgrp_send_discards(sdp, rgd->rd_data0, NULL, bi, r.minlen, &amt); + ret = gfs2_rgrp_send_discards(sdp, + rgd->rd_data0, NULL, bi, minlen, + &amt); if (ret) { gfs2_glock_dq_uninit(&gh); goto out; @@ -1324,7 +1333,7 @@ int gfs2_fitrim(struct file *filp, void __user *argp) out: r.len = trimmed << 9; - if (argp && copy_to_user(argp, &r, sizeof(r))) + if (copy_to_user(argp, &r, sizeof(r))) return -EFAULT; return ret; diff --git a/trunk/fs/gfs2/super.c b/trunk/fs/gfs2/super.c index bc737261f234..d6488674d916 100644 --- a/trunk/fs/gfs2/super.c +++ b/trunk/fs/gfs2/super.c @@ -810,7 +810,8 @@ static void gfs2_dirty_inode(struct inode *inode, int flags) return; } need_unlock = 1; - } + } else if (WARN_ON_ONCE(ip->i_gl->gl_state != LM_ST_EXCLUSIVE)) + return; if (current->journal_info == NULL) { ret = gfs2_trans_begin(sdp, RES_DINODE, 0); diff --git a/trunk/fs/gfs2/trans.c b/trunk/fs/gfs2/trans.c index adbd27875ef9..413627072f36 100644 --- a/trunk/fs/gfs2/trans.c +++ b/trunk/fs/gfs2/trans.c @@ -155,14 +155,22 @@ void gfs2_trans_add_bh(struct gfs2_glock *gl, struct buffer_head *bh, int meta) struct gfs2_sbd *sdp = gl->gl_sbd; struct gfs2_bufdata *bd; + lock_buffer(bh); + gfs2_log_lock(sdp); bd = bh->b_private; if (bd) gfs2_assert(sdp, bd->bd_gl == gl); else { + gfs2_log_unlock(sdp); + unlock_buffer(bh); gfs2_attach_bufdata(gl, bh, meta); bd = bh->b_private; + lock_buffer(bh); + gfs2_log_lock(sdp); } lops_add(sdp, bd); + gfs2_log_unlock(sdp); + unlock_buffer(bh); } void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) diff --git a/trunk/fs/lockd/clnt4xdr.c b/trunk/fs/lockd/clnt4xdr.c index 00ec0b9c94d1..13ad1539fbf2 100644 --- a/trunk/fs/lockd/clnt4xdr.c +++ b/trunk/fs/lockd/clnt4xdr.c @@ -64,6 +64,10 @@ static void nlm4_compute_offsets(const struct nlm_lock *lock, { const struct file_lock *fl = &lock->fl; + BUG_ON(fl->fl_start > NLM4_OFFSET_MAX); + BUG_ON(fl->fl_end > NLM4_OFFSET_MAX && + fl->fl_end != OFFSET_MAX); + *l_offset = loff_t_to_s64(fl->fl_start); if (fl->fl_end == OFFSET_MAX) *l_len = 0; @@ -118,6 +122,7 @@ static void encode_netobj(struct xdr_stream *xdr, { __be32 *p; + BUG_ON(length > XDR_MAX_NETOBJ); p = xdr_reserve_space(xdr, 4 + length); xdr_encode_opaque(p, data, length); } @@ -151,6 +156,7 @@ static int decode_netobj(struct xdr_stream *xdr, static void encode_cookie(struct xdr_stream *xdr, const struct nlm_cookie *cookie) { + BUG_ON(cookie->len > NLM_MAXCOOKIELEN); encode_netobj(xdr, (u8 *)&cookie->data, cookie->len); } @@ -192,6 +198,7 @@ static int decode_cookie(struct xdr_stream *xdr, */ static void encode_fh(struct xdr_stream *xdr, const struct nfs_fh *fh) { + BUG_ON(fh->size > NFS3_FHSIZE); encode_netobj(xdr, (u8 *)&fh->data, fh->size); } @@ -329,6 +336,7 @@ static void encode_caller_name(struct xdr_stream *xdr, const char *name) u32 length = strlen(name); __be32 *p; + BUG_ON(length > NLM_MAXSTRLEN); p = xdr_reserve_space(xdr, 4 + length); xdr_encode_opaque(p, name, length); } diff --git a/trunk/fs/lockd/clntproc.c b/trunk/fs/lockd/clntproc.c index 54f9e6ce0430..05d29124c6ab 100644 --- a/trunk/fs/lockd/clntproc.c +++ b/trunk/fs/lockd/clntproc.c @@ -141,7 +141,7 @@ static void nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl) static void nlmclnt_release_lockargs(struct nlm_rqst *req) { - WARN_ON_ONCE(req->a_args.lock.fl.fl_ops != NULL); + BUG_ON(req->a_args.lock.fl.fl_ops != NULL); } /** @@ -465,6 +465,7 @@ static const struct file_lock_operations nlmclnt_lock_ops = { static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *host) { + BUG_ON(fl->fl_ops != NULL); fl->fl_u.nfs_fl.state = 0; fl->fl_u.nfs_fl.owner = nlm_find_lockowner(host, fl->fl_owner); INIT_LIST_HEAD(&fl->fl_u.nfs_fl.list); diff --git a/trunk/fs/lockd/clntxdr.c b/trunk/fs/lockd/clntxdr.c index 9a55797a1cd4..982d2676e1f8 100644 --- a/trunk/fs/lockd/clntxdr.c +++ b/trunk/fs/lockd/clntxdr.c @@ -60,6 +60,10 @@ static void nlm_compute_offsets(const struct nlm_lock *lock, { const struct file_lock *fl = &lock->fl; + BUG_ON(fl->fl_start > NLM_OFFSET_MAX); + BUG_ON(fl->fl_end > NLM_OFFSET_MAX && + fl->fl_end != OFFSET_MAX); + *l_offset = loff_t_to_s32(fl->fl_start); if (fl->fl_end == OFFSET_MAX) *l_len = 0; @@ -115,6 +119,7 @@ static void encode_netobj(struct xdr_stream *xdr, { __be32 *p; + BUG_ON(length > XDR_MAX_NETOBJ); p = xdr_reserve_space(xdr, 4 + length); xdr_encode_opaque(p, data, length); } @@ -148,6 +153,7 @@ static int decode_netobj(struct xdr_stream *xdr, static void encode_cookie(struct xdr_stream *xdr, const struct nlm_cookie *cookie) { + BUG_ON(cookie->len > NLM_MAXCOOKIELEN); encode_netobj(xdr, (u8 *)&cookie->data, cookie->len); } @@ -189,6 +195,7 @@ static int decode_cookie(struct xdr_stream *xdr, */ static void encode_fh(struct xdr_stream *xdr, const struct nfs_fh *fh) { + BUG_ON(fh->size != NFS2_FHSIZE); encode_netobj(xdr, (u8 *)&fh->data, NFS2_FHSIZE); } @@ -323,6 +330,7 @@ static void encode_caller_name(struct xdr_stream *xdr, const char *name) u32 length = strlen(name); __be32 *p; + BUG_ON(length > NLM_MAXSTRLEN); p = xdr_reserve_space(xdr, 4 + length); xdr_encode_opaque(p, name, length); } diff --git a/trunk/fs/lockd/host.c b/trunk/fs/lockd/host.c index 0e17090c310f..f9b22e58f78f 100644 --- a/trunk/fs/lockd/host.c +++ b/trunk/fs/lockd/host.c @@ -177,6 +177,9 @@ static void nlm_destroy_host_locked(struct nlm_host *host) dprintk("lockd: destroy host %s\n", host->h_name); + BUG_ON(!list_empty(&host->h_lockowners)); + BUG_ON(atomic_read(&host->h_count)); + hlist_del_init(&host->h_hash); nsm_unmonitor(host); @@ -286,12 +289,13 @@ void nlmclnt_release_host(struct nlm_host *host) dprintk("lockd: release client host %s\n", host->h_name); - WARN_ON_ONCE(host->h_server); + BUG_ON(atomic_read(&host->h_count) < 0); + BUG_ON(host->h_server); if (atomic_dec_and_test(&host->h_count)) { - WARN_ON_ONCE(!list_empty(&host->h_lockowners)); - WARN_ON_ONCE(!list_empty(&host->h_granted)); - WARN_ON_ONCE(!list_empty(&host->h_reclaim)); + BUG_ON(!list_empty(&host->h_lockowners)); + BUG_ON(!list_empty(&host->h_granted)); + BUG_ON(!list_empty(&host->h_reclaim)); mutex_lock(&nlm_host_mutex); nlm_destroy_host_locked(host); @@ -408,7 +412,8 @@ void nlmsvc_release_host(struct nlm_host *host) dprintk("lockd: release server host %s\n", host->h_name); - WARN_ON_ONCE(!host->h_server); + BUG_ON(atomic_read(&host->h_count) < 0); + BUG_ON(!host->h_server); atomic_dec(&host->h_count); } diff --git a/trunk/fs/lockd/mon.c b/trunk/fs/lockd/mon.c index 3c2cfc683631..3d7e09bcc0e9 100644 --- a/trunk/fs/lockd/mon.c +++ b/trunk/fs/lockd/mon.c @@ -154,6 +154,8 @@ static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res, .rpc_resp = res, }; + BUG_ON(clnt == NULL); + memset(res, 0, sizeof(*res)); msg.rpc_proc = &clnt->cl_procinfo[proc]; @@ -464,6 +466,7 @@ static void encode_nsm_string(struct xdr_stream *xdr, const char *string) const u32 len = strlen(string); __be32 *p; + BUG_ON(len > SM_MAXSTRLEN); p = xdr_reserve_space(xdr, 4 + len); xdr_encode_opaque(p, string, len); } diff --git a/trunk/fs/nfs/Makefile b/trunk/fs/nfs/Makefile index cce2c057bd2d..b7db60897f91 100644 --- a/trunk/fs/nfs/Makefile +++ b/trunk/fs/nfs/Makefile @@ -24,7 +24,7 @@ nfsv4-y := nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o nfs4super.o nfs4file.o delegation.o idmap.o callback.o callback_xdr.o callback_proc.o \ nfs4namespace.o nfs4getroot.o nfs4client.o nfsv4-$(CONFIG_SYSCTL) += nfs4sysctl.o -nfsv4-$(CONFIG_NFS_V4_1) += nfs4session.o pnfs.o pnfs_dev.o +nfsv4-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o obj-$(CONFIG_PNFS_FILE_LAYOUT) += nfs_layout_nfsv41_files.o nfs_layout_nfsv41_files-y := nfs4filelayout.o nfs4filelayoutdev.o diff --git a/trunk/fs/nfs/blocklayout/blocklayout.c b/trunk/fs/nfs/blocklayout/blocklayout.c index 4fa788c93f46..f1027b06a1a9 100644 --- a/trunk/fs/nfs/blocklayout/blocklayout.c +++ b/trunk/fs/nfs/blocklayout/blocklayout.c @@ -40,7 +40,6 @@ #include #include "../pnfs.h" -#include "../nfs4session.h" #include "../internal.h" #include "blocklayout.h" diff --git a/trunk/fs/nfs/cache_lib.c b/trunk/fs/nfs/cache_lib.c index 862a2f16db64..dded26368111 100644 --- a/trunk/fs/nfs/cache_lib.c +++ b/trunk/fs/nfs/cache_lib.c @@ -118,6 +118,7 @@ int nfs_cache_register_sb(struct super_block *sb, struct cache_detail *cd) struct dentry *dir; dir = rpc_d_lookup_sb(sb, "cache"); + BUG_ON(dir == NULL); ret = sunrpc_cache_register_pipefs(dir, cd->name, 0600, cd); dput(dir); return ret; diff --git a/trunk/fs/nfs/callback.h b/trunk/fs/nfs/callback.h index efd54f0a4c46..4251c2ae06ad 100644 --- a/trunk/fs/nfs/callback.h +++ b/trunk/fs/nfs/callback.h @@ -142,7 +142,7 @@ extern __be32 nfs4_callback_recallany(struct cb_recallanyargs *args, struct cb_recallslotargs { struct sockaddr *crsa_addr; - uint32_t crsa_target_highest_slotid; + uint32_t crsa_target_max_slots; }; extern __be32 nfs4_callback_recallslot(struct cb_recallslotargs *args, void *dummy, @@ -167,6 +167,8 @@ extern __be32 nfs4_callback_layoutrecall( struct cb_layoutrecallargs *args, void *dummy, struct cb_process_state *cps); +extern void nfs4_check_drain_bc_complete(struct nfs4_session *ses); + struct cb_devicenotifyitem { uint32_t cbd_notify_type; uint32_t cbd_layout_type; diff --git a/trunk/fs/nfs/callback_proc.c b/trunk/fs/nfs/callback_proc.c index c89b26bc9759..76b4a7a3e559 100644 --- a/trunk/fs/nfs/callback_proc.c +++ b/trunk/fs/nfs/callback_proc.c @@ -14,7 +14,6 @@ #include "delegation.h" #include "internal.h" #include "pnfs.h" -#include "nfs4session.h" #ifdef NFS_DEBUG #define NFSDBG_FACILITY NFSDBG_CALLBACK @@ -217,6 +216,7 @@ static u32 initiate_bulk_draining(struct nfs_client *clp, } pnfs_get_layout_hdr(lo); spin_unlock(&ino->i_lock); + BUG_ON(!list_empty(&lo->plh_bulk_recall)); list_add(&lo->plh_bulk_recall, &recall_list); } } @@ -562,16 +562,23 @@ __be32 nfs4_callback_recallslot(struct cb_recallslotargs *args, void *dummy, if (!cps->clp) /* set in cb_sequence */ goto out; - dprintk_rcu("NFS: CB_RECALL_SLOT request from %s target highest slotid %d\n", + dprintk_rcu("NFS: CB_RECALL_SLOT request from %s target max slots %d\n", rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR), - args->crsa_target_highest_slotid); + args->crsa_target_max_slots); fc_tbl = &cps->clp->cl_session->fc_slot_table; + status = htonl(NFS4ERR_BAD_HIGH_SLOT); + if (args->crsa_target_max_slots > fc_tbl->max_slots || + args->crsa_target_max_slots < 1) + goto out; + status = htonl(NFS4_OK); + if (args->crsa_target_max_slots == fc_tbl->max_slots) + goto out; - nfs41_set_target_slotid(fc_tbl, args->crsa_target_highest_slotid); - nfs41_server_notify_target_slotid_update(cps->clp); + fc_tbl->target_max_slots = args->crsa_target_max_slots; + nfs41_handle_recall_slot(cps->clp); out: dprintk("%s: exit with status = %d\n", __func__, ntohl(status)); return status; diff --git a/trunk/fs/nfs/callback_xdr.c b/trunk/fs/nfs/callback_xdr.c index 59461c957d9d..742ff4ffced7 100644 --- a/trunk/fs/nfs/callback_xdr.c +++ b/trunk/fs/nfs/callback_xdr.c @@ -16,7 +16,6 @@ #include "nfs4_fs.h" #include "callback.h" #include "internal.h" -#include "nfs4session.h" #define CB_OP_TAGLEN_MAXSZ (512) #define CB_OP_HDR_RES_MAXSZ (2 + CB_OP_TAGLEN_MAXSZ) @@ -521,7 +520,7 @@ static __be32 decode_recallslot_args(struct svc_rqst *rqstp, p = read_buf(xdr, 4); if (unlikely(p == NULL)) return htonl(NFS4ERR_BADXDR); - args->crsa_target_highest_slotid = ntohl(*p++); + args->crsa_target_max_slots = ntohl(*p++); return 0; } @@ -763,7 +762,7 @@ static void nfs4_callback_free_slot(struct nfs4_session *session) * A single slot, so highest used slotid is either 0 or -1 */ tbl->highest_used_slotid = NFS4_NO_SLOT; - nfs4_session_drain_complete(session, tbl); + nfs4_check_drain_bc_complete(session); spin_unlock(&tbl->slot_tbl_lock); } diff --git a/trunk/fs/nfs/client.c b/trunk/fs/nfs/client.c index c285e0a117e4..8b39a42ac35e 100644 --- a/trunk/fs/nfs/client.c +++ b/trunk/fs/nfs/client.c @@ -277,7 +277,7 @@ void nfs_put_client(struct nfs_client *clp) nfs_cb_idr_remove_locked(clp); spin_unlock(&nn->nfs_client_lock); - WARN_ON_ONCE(!list_empty(&clp->cl_superblocks)); + BUG_ON(!list_empty(&clp->cl_superblocks)); clp->rpc_ops->free_client(clp); } @@ -1061,6 +1061,10 @@ struct nfs_server *nfs_create_server(struct nfs_mount_info *mount_info, if (error < 0) goto error; + BUG_ON(!server->nfs_client); + BUG_ON(!server->nfs_client->rpc_ops); + BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); + /* Probe the root fh to retrieve its FSID */ error = nfs_probe_fsinfo(server, mount_info->mntfh, fattr); if (error < 0) diff --git a/trunk/fs/nfs/inode.c b/trunk/fs/nfs/inode.c index 117183b1ee09..6fa01aea2488 100644 --- a/trunk/fs/nfs/inode.c +++ b/trunk/fs/nfs/inode.c @@ -112,8 +112,8 @@ void nfs_clear_inode(struct inode *inode) /* * The following should never happen... */ - WARN_ON_ONCE(nfs_have_writebacks(inode)); - WARN_ON_ONCE(!list_empty(&NFS_I(inode)->open_files)); + BUG_ON(nfs_have_writebacks(inode)); + BUG_ON(!list_empty(&NFS_I(inode)->open_files)); nfs_zap_acl_cache(inode); nfs_access_zap_cache(inode); nfs_fscache_release_inode_cookie(inode); diff --git a/trunk/fs/nfs/internal.h b/trunk/fs/nfs/internal.h index fb994471bd32..05521cadac2e 100644 --- a/trunk/fs/nfs/internal.h +++ b/trunk/fs/nfs/internal.h @@ -18,6 +18,27 @@ struct nfs_string; */ #define NFS_MAX_READAHEAD (RPC_DEF_SLOT_TABLE - 1) +/* + * Determine if sessions are in use. + */ +static inline int nfs4_has_session(const struct nfs_client *clp) +{ +#ifdef CONFIG_NFS_V4_1 + if (clp->cl_session) + return 1; +#endif /* CONFIG_NFS_V4_1 */ + return 0; +} + +static inline int nfs4_has_persistent_session(const struct nfs_client *clp) +{ +#ifdef CONFIG_NFS_V4_1 + if (nfs4_has_session(clp)) + return (clp->cl_session->flags & SESSION4_PERSIST); +#endif /* CONFIG_NFS_V4_1 */ + return 0; +} + static inline void nfs_attr_check_mountpoint(struct super_block *parent, struct nfs_fattr *fattr) { if (!nfs_fsid_equal(&NFS_SB(parent)->fsid, &fattr->fsid)) @@ -255,6 +276,8 @@ extern const u32 nfs41_maxwrite_overhead; extern struct rpc_procinfo nfs4_procedures[]; #endif +extern int nfs4_init_ds_session(struct nfs_client *, unsigned long); + /* proc.c */ void nfs_close_context(struct nfs_open_context *ctx, int is_sync); extern struct nfs_client *nfs_init_client(struct nfs_client *clp, @@ -451,6 +474,18 @@ extern struct nfs_client *nfs4_init_client(struct nfs_client *clp, const struct rpc_timeout *timeparms, const char *ip_addr, rpc_authflavor_t authflavour); +extern int _nfs4_call_sync(struct rpc_clnt *clnt, + struct nfs_server *server, + struct rpc_message *msg, + struct nfs4_sequence_args *args, + struct nfs4_sequence_res *res, + int cache_reply); +extern int _nfs4_call_sync_session(struct rpc_clnt *clnt, + struct nfs_server *server, + struct rpc_message *msg, + struct nfs4_sequence_args *args, + struct nfs4_sequence_res *res, + int cache_reply); extern int nfs40_walk_client_list(struct nfs_client *clp, struct nfs_client **result, struct rpc_cred *cred); diff --git a/trunk/fs/nfs/mount_clnt.c b/trunk/fs/nfs/mount_clnt.c index 91a6faf811ac..015f71f8f62c 100644 --- a/trunk/fs/nfs/mount_clnt.c +++ b/trunk/fs/nfs/mount_clnt.c @@ -169,9 +169,6 @@ int nfs_mount(struct nfs_mount_request *info) (info->hostname ? info->hostname : "server"), info->dirpath); - if (strlen(info->dirpath) > MNTPATHLEN) - return -ENAMETOOLONG; - if (info->noresvport) args.flags |= RPC_CLNT_CREATE_NONPRIVPORT; @@ -245,9 +242,6 @@ void nfs_umount(const struct nfs_mount_request *info) struct rpc_clnt *clnt; int status; - if (strlen(info->dirpath) > MNTPATHLEN) - return; - if (info->noresvport) args.flags |= RPC_CLNT_CREATE_NONPRIVPORT; @@ -289,6 +283,7 @@ static void encode_mntdirpath(struct xdr_stream *xdr, const char *pathname) const u32 pathname_len = strlen(pathname); __be32 *p; + BUG_ON(pathname_len > MNTPATHLEN); p = xdr_reserve_space(xdr, 4 + pathname_len); xdr_encode_opaque(p, pathname, pathname_len); } diff --git a/trunk/fs/nfs/nfs2xdr.c b/trunk/fs/nfs/nfs2xdr.c index 06b9df49f7f7..d04f0df7be55 100644 --- a/trunk/fs/nfs/nfs2xdr.c +++ b/trunk/fs/nfs/nfs2xdr.c @@ -195,6 +195,7 @@ static void encode_fhandle(struct xdr_stream *xdr, const struct nfs_fh *fh) { __be32 *p; + BUG_ON(fh->size != NFS2_FHSIZE); p = xdr_reserve_space(xdr, NFS2_FHSIZE); memcpy(p, fh->data, NFS2_FHSIZE); } @@ -387,7 +388,7 @@ static void encode_filename(struct xdr_stream *xdr, { __be32 *p; - WARN_ON_ONCE(length > NFS2_MAXNAMLEN); + BUG_ON(length > NFS2_MAXNAMLEN); p = xdr_reserve_space(xdr, 4 + length); xdr_encode_opaque(p, name, length); } @@ -427,6 +428,7 @@ static void encode_path(struct xdr_stream *xdr, struct page **pages, u32 length) { __be32 *p; + BUG_ON(length > NFS2_MAXPATHLEN); p = xdr_reserve_space(xdr, 4); *p = cpu_to_be32(length); xdr_write_pages(xdr, pages, 0, length); diff --git a/trunk/fs/nfs/nfs3xdr.c b/trunk/fs/nfs/nfs3xdr.c index bffc32406fbf..6cbe89400dfc 100644 --- a/trunk/fs/nfs/nfs3xdr.c +++ b/trunk/fs/nfs/nfs3xdr.c @@ -198,7 +198,7 @@ static void encode_filename3(struct xdr_stream *xdr, { __be32 *p; - WARN_ON_ONCE(length > NFS3_MAXNAMLEN); + BUG_ON(length > NFS3_MAXNAMLEN); p = xdr_reserve_space(xdr, 4 + length); xdr_encode_opaque(p, name, length); } @@ -238,6 +238,7 @@ static int decode_inline_filename3(struct xdr_stream *xdr, static void encode_nfspath3(struct xdr_stream *xdr, struct page **pages, const u32 length) { + BUG_ON(length > NFS3_MAXPATHLEN); encode_uint32(xdr, length); xdr_write_pages(xdr, pages, 0, length); } @@ -387,6 +388,7 @@ static int decode_nfsstat3(struct xdr_stream *xdr, enum nfs_stat *status) */ static void encode_ftype3(struct xdr_stream *xdr, const u32 type) { + BUG_ON(type > NF3FIFO); encode_uint32(xdr, type); } @@ -441,7 +443,7 @@ static void encode_nfs_fh3(struct xdr_stream *xdr, const struct nfs_fh *fh) { __be32 *p; - WARN_ON_ONCE(fh->size > NFS3_FHSIZE); + BUG_ON(fh->size > NFS3_FHSIZE); p = xdr_reserve_space(xdr, 4 + fh->size); xdr_encode_opaque(p, fh->data, fh->size); } @@ -1337,7 +1339,6 @@ static void nfs3_xdr_enc_setacl3args(struct rpc_rqst *req, error = nfsacl_encode(xdr->buf, base, args->inode, (args->mask & NFS_ACL) ? args->acl_access : NULL, 1, 0); - /* FIXME: this is just broken */ BUG_ON(error < 0); error = nfsacl_encode(xdr->buf, base + error, args->inode, (args->mask & NFS_DFACL) ? diff --git a/trunk/fs/nfs/nfs4_fs.h b/trunk/fs/nfs/nfs4_fs.h index 4635bf51b3e6..a525fdefccde 100644 --- a/trunk/fs/nfs/nfs4_fs.h +++ b/trunk/fs/nfs/nfs4_fs.h @@ -11,8 +11,6 @@ #if IS_ENABLED(CONFIG_NFS_V4) -#define NFS4_MAX_LOOP_ON_RECOVER (10) - struct idmap; enum nfs4_client_state { @@ -23,12 +21,18 @@ enum nfs4_client_state { NFS4CLNT_RECLAIM_NOGRACE, NFS4CLNT_DELEGRETURN, NFS4CLNT_SESSION_RESET, + NFS4CLNT_RECALL_SLOT, NFS4CLNT_LEASE_CONFIRM, NFS4CLNT_SERVER_SCOPE_MISMATCH, NFS4CLNT_PURGE_STATE, NFS4CLNT_BIND_CONN_TO_SESSION, }; +enum nfs4_session_state { + NFS4_SESSION_INITING, + NFS4_SESSION_DRAINING, +}; + #define NFS4_RENEW_TIMEOUT 0x01 #define NFS4_RENEW_DELEGATION_CB 0x02 @@ -39,7 +43,8 @@ struct nfs4_minor_version_ops { struct nfs_server *server, struct rpc_message *msg, struct nfs4_sequence_args *args, - struct nfs4_sequence_res *res); + struct nfs4_sequence_res *res, + int cache_reply); bool (*match_stateid)(const nfs4_stateid *, const nfs4_stateid *); int (*find_root_sec)(struct nfs_server *, struct nfs_fh *, @@ -236,14 +241,18 @@ static inline struct nfs4_session *nfs4_get_session(const struct nfs_server *ser return server->nfs_client->cl_session; } +extern bool nfs4_set_task_privileged(struct rpc_task *task, void *dummy); extern int nfs4_setup_sequence(const struct nfs_server *server, struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, struct rpc_task *task); extern int nfs41_setup_sequence(struct nfs4_session *session, struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, struct rpc_task *task); +extern void nfs4_destroy_session(struct nfs4_session *session); +extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp); extern int nfs4_proc_create_session(struct nfs_client *, struct rpc_cred *); extern int nfs4_proc_destroy_session(struct nfs4_session *, struct rpc_cred *); +extern int nfs4_init_session(struct nfs_server *server); extern int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo); extern int nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data, @@ -271,7 +280,11 @@ static inline int nfs4_setup_sequence(const struct nfs_server *server, struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, struct rpc_task *task) { - rpc_call_start(task); + return 0; +} + +static inline int nfs4_init_session(struct nfs_server *server) +{ return 0; } @@ -319,9 +332,6 @@ struct rpc_cred *nfs4_get_exchange_id_cred(struct nfs_client *clp); int nfs41_discover_server_trunking(struct nfs_client *clp, struct nfs_client **, struct rpc_cred *); extern void nfs4_schedule_session_recovery(struct nfs4_session *, int); -extern void nfs41_server_notify_target_slotid_update(struct nfs_client *clp); -extern void nfs41_server_notify_highest_slotid_update(struct nfs_client *clp); - #else static inline void nfs4_schedule_session_recovery(struct nfs4_session *session, int err) { @@ -339,12 +349,11 @@ extern void nfs4_state_set_mode_locked(struct nfs4_state *, fmode_t); extern void nfs_inode_find_state_and_recover(struct inode *inode, const nfs4_stateid *stateid); extern void nfs4_schedule_lease_recovery(struct nfs_client *); -extern int nfs4_wait_clnt_recover(struct nfs_client *clp); -extern int nfs4_client_recover_expired_lease(struct nfs_client *clp); extern void nfs4_schedule_state_manager(struct nfs_client *); extern void nfs4_schedule_path_down_recovery(struct nfs_client *clp); extern void nfs4_schedule_stateid_recovery(const struct nfs_server *, struct nfs4_state *); extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags); +extern void nfs41_handle_recall_slot(struct nfs_client *clp); extern void nfs41_handle_server_scope(struct nfs_client *, struct nfs41_server_scope **); extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); diff --git a/trunk/fs/nfs/nfs4client.c b/trunk/fs/nfs/nfs4client.c index acc347268124..6bacfde1319a 100644 --- a/trunk/fs/nfs/nfs4client.c +++ b/trunk/fs/nfs/nfs4client.c @@ -12,7 +12,6 @@ #include "internal.h" #include "callback.h" #include "delegation.h" -#include "nfs4session.h" #include "pnfs.h" #include "netns.h" @@ -714,6 +713,10 @@ static int nfs4_server_common_setup(struct nfs_server *server, struct nfs_fattr *fattr; int error; + BUG_ON(!server->nfs_client); + BUG_ON(!server->nfs_client->rpc_ops); + BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); + /* data servers support only a subset of NFSv4.1 */ if (is_ds_only_client(server->nfs_client)) return -EPROTONOSUPPORT; diff --git a/trunk/fs/nfs/nfs4file.c b/trunk/fs/nfs/nfs4file.c index e7699308364a..afddd6639afb 100644 --- a/trunk/fs/nfs/nfs4file.c +++ b/trunk/fs/nfs/nfs4file.c @@ -20,6 +20,7 @@ nfs4_file_open(struct inode *inode, struct file *filp) struct iattr attr; int err; + BUG_ON(inode != dentry->d_inode); /* * If no cached dentry exists or if it's negative, NFSv4 handled the * opens in ->lookup() or ->create(). diff --git a/trunk/fs/nfs/nfs4filelayout.c b/trunk/fs/nfs/nfs4filelayout.c index 1e42413fab8f..2e45fd9c02a3 100644 --- a/trunk/fs/nfs/nfs4filelayout.c +++ b/trunk/fs/nfs/nfs4filelayout.c @@ -35,7 +35,6 @@ #include -#include "nfs4session.h" #include "internal.h" #include "delegation.h" #include "nfs4filelayout.h" @@ -307,10 +306,12 @@ static void filelayout_read_prepare(struct rpc_task *task, void *data) } rdata->read_done_cb = filelayout_read_done_cb; - nfs41_setup_sequence(rdata->ds_clp->cl_session, - &rdata->args.seq_args, - &rdata->res.seq_res, - task); + if (nfs41_setup_sequence(rdata->ds_clp->cl_session, + &rdata->args.seq_args, &rdata->res.seq_res, + task)) + return; + + rpc_call_start(task); } static void filelayout_read_call_done(struct rpc_task *task, void *data) @@ -407,10 +408,12 @@ static void filelayout_write_prepare(struct rpc_task *task, void *data) rpc_exit(task, 0); return; } - nfs41_setup_sequence(wdata->ds_clp->cl_session, - &wdata->args.seq_args, - &wdata->res.seq_res, - task); + if (nfs41_setup_sequence(wdata->ds_clp->cl_session, + &wdata->args.seq_args, &wdata->res.seq_res, + task)) + return; + + rpc_call_start(task); } static void filelayout_write_call_done(struct rpc_task *task, void *data) @@ -446,10 +449,12 @@ static void filelayout_commit_prepare(struct rpc_task *task, void *data) { struct nfs_commit_data *wdata = data; - nfs41_setup_sequence(wdata->ds_clp->cl_session, - &wdata->args.seq_args, - &wdata->res.seq_res, - task); + if (nfs41_setup_sequence(wdata->ds_clp->cl_session, + &wdata->args.seq_args, &wdata->res.seq_res, + task)) + return; + + rpc_call_start(task); } static void filelayout_write_commit_done(struct rpc_task *task, void *data) @@ -507,6 +512,7 @@ filelayout_read_pagelist(struct nfs_read_data *data) loff_t offset = data->args.offset; u32 j, idx; struct nfs_fh *fh; + int status; dprintk("--> %s ino %lu pgbase %u req %Zu@%llu\n", __func__, hdr->inode->i_ino, @@ -532,8 +538,9 @@ filelayout_read_pagelist(struct nfs_read_data *data) data->mds_offset = offset; /* Perform an asynchronous read to ds */ - nfs_initiate_read(ds->ds_clp->cl_rpcclient, data, + status = nfs_initiate_read(ds->ds_clp->cl_rpcclient, data, &filelayout_read_call_ops, RPC_TASK_SOFTCONN); + BUG_ON(status != 0); return PNFS_ATTEMPTED; } @@ -547,6 +554,7 @@ filelayout_write_pagelist(struct nfs_write_data *data, int sync) loff_t offset = data->args.offset; u32 j, idx; struct nfs_fh *fh; + int status; /* Retrieve the correct rpc_client for the byte range */ j = nfs4_fl_calc_j_index(lseg, offset); @@ -571,9 +579,10 @@ filelayout_write_pagelist(struct nfs_write_data *data, int sync) data->args.offset = filelayout_get_dserver_offset(lseg, offset); /* Perform an asynchronous write */ - nfs_initiate_write(ds->ds_clp->cl_rpcclient, data, + status = nfs_initiate_write(ds->ds_clp->cl_rpcclient, data, &filelayout_write_call_ops, sync, RPC_TASK_SOFTCONN); + BUG_ON(status != 0); return PNFS_ATTEMPTED; } @@ -900,7 +909,7 @@ static void filelayout_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) { - WARN_ON_ONCE(pgio->pg_lseg != NULL); + BUG_ON(pgio->pg_lseg != NULL); if (req->wb_offset != req->wb_pgbase) { /* @@ -930,7 +939,7 @@ filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_commit_info cinfo; int status; - WARN_ON_ONCE(pgio->pg_lseg != NULL); + BUG_ON(pgio->pg_lseg != NULL); if (req->wb_offset != req->wb_pgbase) goto out_mds; @@ -1178,6 +1187,7 @@ static void filelayout_recover_commit_reqs(struct list_head *dst, */ for (i = 0, b = cinfo->ds->buckets; i < cinfo->ds->nbuckets; i++, b++) { if (transfer_commit_list(&b->written, dst, cinfo, 0)) { + BUG_ON(!list_empty(&b->written)); pnfs_put_lseg(b->wlseg); b->wlseg = NULL; } diff --git a/trunk/fs/nfs/nfs4filelayoutdev.c b/trunk/fs/nfs/nfs4filelayoutdev.c index b720064bcd7f..a8eaa9b7bb0f 100644 --- a/trunk/fs/nfs/nfs4filelayoutdev.c +++ b/trunk/fs/nfs/nfs4filelayoutdev.c @@ -33,7 +33,6 @@ #include #include "internal.h" -#include "nfs4session.h" #include "nfs4filelayout.h" #define NFSDBG_FACILITY NFSDBG_PNFS_LD @@ -163,6 +162,8 @@ nfs4_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds) dprintk("--> %s DS %s au_flavor %d\n", __func__, ds->ds_remotestr, mds_srv->nfs_client->cl_rpcclient->cl_auth->au_flavor); + BUG_ON(list_empty(&ds->ds_addrs)); + list_for_each_entry(da, &ds->ds_addrs, da_node) { dprintk("%s: DS %s: trying address %s\n", __func__, ds->ds_remotestr, da->da_remotestr); diff --git a/trunk/fs/nfs/nfs4proc.c b/trunk/fs/nfs/nfs4proc.c index 992233561dbd..5eec4429970c 100644 --- a/trunk/fs/nfs/nfs4proc.c +++ b/trunk/fs/nfs/nfs4proc.c @@ -52,6 +52,7 @@ #include #include #include +#include #include #include #include @@ -63,14 +64,14 @@ #include "callback.h" #include "pnfs.h" #include "netns.h" -#include "nfs4session.h" - #define NFSDBG_FACILITY NFSDBG_PROC #define NFS4_POLL_RETRY_MIN (HZ/10) #define NFS4_POLL_RETRY_MAX (15*HZ) +#define NFS4_MAX_LOOP_ON_RECOVER (10) + struct nfs4_opendata; static int _nfs4_proc_open(struct nfs4_opendata *data); static int _nfs4_recover_proc_open(struct nfs4_opendata *data); @@ -205,6 +206,7 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent { __be32 *start, *p; + BUG_ON(readdir->count < 80); if (cookie > 2) { readdir->cookie = cookie; memcpy(&readdir->verifier, verifier, sizeof(readdir->verifier)); @@ -254,6 +256,22 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent kunmap_atomic(start); } +static int nfs4_wait_clnt_recover(struct nfs_client *clp) +{ + int res; + + might_sleep(); + + res = wait_on_bit(&clp->cl_state, NFS4CLNT_MANAGER_RUNNING, + nfs_wait_bit_killable, TASK_KILLABLE); + if (res) + return res; + + if (clp->cl_cons_state < 0) + return clp->cl_cons_state; + return 0; +} + static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) { int res = 0; @@ -379,47 +397,97 @@ static void renew_lease(const struct nfs_server *server, unsigned long timestamp #if defined(CONFIG_NFS_V4_1) +/* + * nfs4_free_slot - free a slot and efficiently update slot table. + * + * freeing a slot is trivially done by clearing its respective bit + * in the bitmap. + * If the freed slotid equals highest_used_slotid we want to update it + * so that the server would be able to size down the slot table if needed, + * otherwise we know that the highest_used_slotid is still in use. + * When updating highest_used_slotid there may be "holes" in the bitmap + * so we need to scan down from highest_used_slotid to 0 looking for the now + * highest slotid in use. + * If none found, highest_used_slotid is set to NFS4_NO_SLOT. + * + * Must be called while holding tbl->slot_tbl_lock + */ +static void +nfs4_free_slot(struct nfs4_slot_table *tbl, u32 slotid) +{ + BUG_ON(slotid >= NFS4_MAX_SLOT_TABLE); + /* clear used bit in bitmap */ + __clear_bit(slotid, tbl->used_slots); + + /* update highest_used_slotid when it is freed */ + if (slotid == tbl->highest_used_slotid) { + slotid = find_last_bit(tbl->used_slots, tbl->max_slots); + if (slotid < tbl->max_slots) + tbl->highest_used_slotid = slotid; + else + tbl->highest_used_slotid = NFS4_NO_SLOT; + } + dprintk("%s: slotid %u highest_used_slotid %d\n", __func__, + slotid, tbl->highest_used_slotid); +} + +bool nfs4_set_task_privileged(struct rpc_task *task, void *dummy) +{ + rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); + return true; +} + +/* + * Signal state manager thread if session fore channel is drained + */ +static void nfs4_check_drain_fc_complete(struct nfs4_session *ses) +{ + if (!test_bit(NFS4_SESSION_DRAINING, &ses->session_state)) { + rpc_wake_up_first(&ses->fc_slot_table.slot_tbl_waitq, + nfs4_set_task_privileged, NULL); + return; + } + + if (ses->fc_slot_table.highest_used_slotid != NFS4_NO_SLOT) + return; + + dprintk("%s COMPLETE: Session Fore Channel Drained\n", __func__); + complete(&ses->fc_slot_table.complete); +} + +/* + * Signal state manager thread if session back channel is drained + */ +void nfs4_check_drain_bc_complete(struct nfs4_session *ses) +{ + if (!test_bit(NFS4_SESSION_DRAINING, &ses->session_state) || + ses->bc_slot_table.highest_used_slotid != NFS4_NO_SLOT) + return; + dprintk("%s COMPLETE: Session Back Channel Drained\n", __func__); + complete(&ses->bc_slot_table.complete); +} + static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res) { - struct nfs4_session *session; struct nfs4_slot_table *tbl; - bool send_new_highest_used_slotid = false; + tbl = &res->sr_session->fc_slot_table; if (!res->sr_slot) { /* just wake up the next guy waiting since * we may have not consumed a slot after all */ dprintk("%s: No slot\n", __func__); return; } - tbl = res->sr_slot->table; - session = tbl->session; spin_lock(&tbl->slot_tbl_lock); - /* Be nice to the server: try to ensure that the last transmitted - * value for highest_user_slotid <= target_highest_slotid - */ - if (tbl->highest_used_slotid > tbl->target_highest_slotid) - send_new_highest_used_slotid = true; - - if (nfs41_wake_and_assign_slot(tbl, res->sr_slot)) { - send_new_highest_used_slotid = false; - goto out_unlock; - } - nfs4_free_slot(tbl, res->sr_slot); - - if (tbl->highest_used_slotid != NFS4_NO_SLOT) - send_new_highest_used_slotid = false; -out_unlock: + nfs4_free_slot(tbl, res->sr_slot - tbl->slots); + nfs4_check_drain_fc_complete(res->sr_session); spin_unlock(&tbl->slot_tbl_lock); res->sr_slot = NULL; - if (send_new_highest_used_slotid) - nfs41_server_notify_highest_slotid_update(session->clp); } static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res) { - struct nfs4_session *session; - struct nfs4_slot *slot; unsigned long timestamp; struct nfs_client *clp; @@ -436,35 +504,31 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res * if (!RPC_WAS_SENT(task)) goto out; - slot = res->sr_slot; - session = slot->table->session; - /* Check the SEQUENCE operation status */ switch (res->sr_status) { case 0: /* Update the slot's sequence and clientid lease timer */ - ++slot->seq_nr; - timestamp = slot->renewal_time; - clp = session->clp; + ++res->sr_slot->seq_nr; + timestamp = res->sr_renewal_time; + clp = res->sr_session->clp; do_renew_lease(clp, timestamp); /* Check sequence flags */ if (res->sr_status_flags != 0) nfs4_schedule_lease_recovery(clp); - nfs41_update_target_slotid(slot->table, slot, res); break; case -NFS4ERR_DELAY: /* The server detected a resend of the RPC call and * returned NFS4ERR_DELAY as per Section 2.10.6.2 * of RFC5661. */ - dprintk("%s: slot=%u seq=%u: Operation in progress\n", + dprintk("%s: slot=%td seq=%d: Operation in progress\n", __func__, - slot->slot_nr, - slot->seq_nr); + res->sr_slot - res->sr_session->fc_slot_table.slots, + res->sr_slot->seq_nr); goto out_retry; default: /* Just update the slot sequence no. */ - ++slot->seq_nr; + ++res->sr_slot->seq_nr; } out: /* The session may be reset by one of the error handlers. */ @@ -481,27 +545,55 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res * static int nfs4_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res) { - if (res->sr_slot == NULL) + if (res->sr_session == NULL) return 1; return nfs41_sequence_done(task, res); } +/* + * nfs4_find_slot - efficiently look for a free slot + * + * nfs4_find_slot looks for an unset bit in the used_slots bitmap. + * If found, we mark the slot as used, update the highest_used_slotid, + * and respectively set up the sequence operation args. + * The slot number is returned if found, or NFS4_NO_SLOT otherwise. + * + * Note: must be called with under the slot_tbl_lock. + */ +static u32 +nfs4_find_slot(struct nfs4_slot_table *tbl) +{ + u32 slotid; + u32 ret_id = NFS4_NO_SLOT; + + dprintk("--> %s used_slots=%04lx highest_used=%u max_slots=%u\n", + __func__, tbl->used_slots[0], tbl->highest_used_slotid, + tbl->max_slots); + slotid = find_first_zero_bit(tbl->used_slots, tbl->max_slots); + if (slotid >= tbl->max_slots) + goto out; + __set_bit(slotid, tbl->used_slots); + if (slotid > tbl->highest_used_slotid || + tbl->highest_used_slotid == NFS4_NO_SLOT) + tbl->highest_used_slotid = slotid; + ret_id = slotid; +out: + dprintk("<-- %s used_slots=%04lx highest_used=%d slotid=%d \n", + __func__, tbl->used_slots[0], tbl->highest_used_slotid, ret_id); + return ret_id; +} + static void nfs41_init_sequence(struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, int cache_reply) { - args->sa_slot = NULL; + args->sa_session = NULL; args->sa_cache_this = 0; - args->sa_privileged = 0; if (cache_reply) args->sa_cache_this = 1; + res->sr_session = NULL; res->sr_slot = NULL; } -static void nfs4_set_sequence_privileged(struct nfs4_sequence_args *args) -{ - args->sa_privileged = 1; -} - int nfs41_setup_sequence(struct nfs4_session *session, struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, @@ -509,58 +601,59 @@ int nfs41_setup_sequence(struct nfs4_session *session, { struct nfs4_slot *slot; struct nfs4_slot_table *tbl; + u32 slotid; dprintk("--> %s\n", __func__); /* slot already allocated? */ if (res->sr_slot != NULL) - goto out_success; + return 0; tbl = &session->fc_slot_table; - task->tk_timeout = 0; - spin_lock(&tbl->slot_tbl_lock); if (test_bit(NFS4_SESSION_DRAINING, &session->session_state) && - !args->sa_privileged) { + !rpc_task_has_priority(task, RPC_PRIORITY_PRIVILEGED)) { /* The state manager will wait until the slot table is empty */ + rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL); + spin_unlock(&tbl->slot_tbl_lock); dprintk("%s session is draining\n", __func__); - goto out_sleep; + return -EAGAIN; } - slot = nfs4_alloc_slot(tbl); - if (IS_ERR(slot)) { - /* If out of memory, try again in 1/4 second */ - if (slot == ERR_PTR(-ENOMEM)) - task->tk_timeout = HZ >> 2; + if (!rpc_queue_empty(&tbl->slot_tbl_waitq) && + !rpc_task_has_priority(task, RPC_PRIORITY_PRIVILEGED)) { + rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL); + spin_unlock(&tbl->slot_tbl_lock); + dprintk("%s enforce FIFO order\n", __func__); + return -EAGAIN; + } + + slotid = nfs4_find_slot(tbl); + if (slotid == NFS4_NO_SLOT) { + rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL); + spin_unlock(&tbl->slot_tbl_lock); dprintk("<-- %s: no free slots\n", __func__); - goto out_sleep; + return -EAGAIN; } spin_unlock(&tbl->slot_tbl_lock); - args->sa_slot = slot; + rpc_task_set_priority(task, RPC_PRIORITY_NORMAL); + slot = tbl->slots + slotid; + args->sa_session = session; + args->sa_slotid = slotid; - dprintk("<-- %s slotid=%d seqid=%d\n", __func__, - slot->slot_nr, slot->seq_nr); + dprintk("<-- %s slotid=%d seqid=%d\n", __func__, slotid, slot->seq_nr); + res->sr_session = session; res->sr_slot = slot; + res->sr_renewal_time = jiffies; res->sr_status_flags = 0; /* * sr_status is only set in decode_sequence, and so will remain * set to 1 if an rpc level failure occurs. */ res->sr_status = 1; -out_success: - rpc_call_start(task); return 0; -out_sleep: - /* Privileged tasks are queued with top priority */ - if (args->sa_privileged) - rpc_sleep_on_priority(&tbl->slot_tbl_waitq, task, - NULL, RPC_PRIORITY_PRIVILEGED); - else - rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL); - spin_unlock(&tbl->slot_tbl_lock); - return -EAGAIN; } EXPORT_SYMBOL_GPL(nfs41_setup_sequence); @@ -572,14 +665,12 @@ int nfs4_setup_sequence(const struct nfs_server *server, struct nfs4_session *session = nfs4_get_session(server); int ret = 0; - if (session == NULL) { - rpc_call_start(task); + if (session == NULL) goto out; - } - dprintk("--> %s clp %p session %p sr_slot %d\n", + dprintk("--> %s clp %p session %p sr_slot %td\n", __func__, session->clp, session, res->sr_slot ? - res->sr_slot->slot_nr : -1); + res->sr_slot - session->fc_slot_table.slots : -1); ret = nfs41_setup_sequence(session, args, res, task); out: @@ -596,11 +687,19 @@ struct nfs41_call_sync_data { static void nfs41_call_sync_prepare(struct rpc_task *task, void *calldata) { struct nfs41_call_sync_data *data = calldata; - struct nfs4_session *session = nfs4_get_session(data->seq_server); dprintk("--> %s data->seq_server %p\n", __func__, data->seq_server); - nfs41_setup_sequence(session, data->seq_args, data->seq_res, task); + if (nfs4_setup_sequence(data->seq_server, data->seq_args, + data->seq_res, task)) + return; + rpc_call_start(task); +} + +static void nfs41_call_priv_sync_prepare(struct rpc_task *task, void *calldata) +{ + rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); + nfs41_call_sync_prepare(task, calldata); } static void nfs41_call_sync_done(struct rpc_task *task, void *calldata) @@ -615,11 +714,17 @@ static const struct rpc_call_ops nfs41_call_sync_ops = { .rpc_call_done = nfs41_call_sync_done, }; +static const struct rpc_call_ops nfs41_call_priv_sync_ops = { + .rpc_call_prepare = nfs41_call_priv_sync_prepare, + .rpc_call_done = nfs41_call_sync_done, +}; + static int nfs4_call_sync_sequence(struct rpc_clnt *clnt, struct nfs_server *server, struct rpc_message *msg, struct nfs4_sequence_args *args, - struct nfs4_sequence_res *res) + struct nfs4_sequence_res *res, + int privileged) { int ret; struct rpc_task *task; @@ -635,6 +740,8 @@ static int nfs4_call_sync_sequence(struct rpc_clnt *clnt, .callback_data = &data }; + if (privileged) + task_setup.callback_ops = &nfs41_call_priv_sync_ops; task = rpc_run_task(&task_setup); if (IS_ERR(task)) ret = PTR_ERR(task); @@ -645,18 +752,24 @@ static int nfs4_call_sync_sequence(struct rpc_clnt *clnt, return ret; } -#else -static -void nfs41_init_sequence(struct nfs4_sequence_args *args, - struct nfs4_sequence_res *res, int cache_reply) +int _nfs4_call_sync_session(struct rpc_clnt *clnt, + struct nfs_server *server, + struct rpc_message *msg, + struct nfs4_sequence_args *args, + struct nfs4_sequence_res *res, + int cache_reply) { + nfs41_init_sequence(args, res, cache_reply); + return nfs4_call_sync_sequence(clnt, server, msg, args, res, 0); } -static void nfs4_set_sequence_privileged(struct nfs4_sequence_args *args) +#else +static inline +void nfs41_init_sequence(struct nfs4_sequence_args *args, + struct nfs4_sequence_res *res, int cache_reply) { } - static int nfs4_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res) { @@ -664,17 +777,18 @@ static int nfs4_sequence_done(struct rpc_task *task, } #endif /* CONFIG_NFS_V4_1 */ -static int _nfs4_call_sync(struct rpc_clnt *clnt, struct nfs_server *server, struct rpc_message *msg, struct nfs4_sequence_args *args, - struct nfs4_sequence_res *res) + struct nfs4_sequence_res *res, + int cache_reply) { + nfs41_init_sequence(args, res, cache_reply); return rpc_call_sync(clnt, msg, 0); } -static +static inline int nfs4_call_sync(struct rpc_clnt *clnt, struct nfs_server *server, struct rpc_message *msg, @@ -682,9 +796,8 @@ int nfs4_call_sync(struct rpc_clnt *clnt, struct nfs4_sequence_res *res, int cache_reply) { - nfs41_init_sequence(args, res, cache_reply); return server->nfs_client->cl_mvops->call_sync(clnt, server, msg, - args, res); + args, res, cache_reply); } static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) @@ -1461,12 +1574,20 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata) &data->o_res.seq_res, task) != 0) nfs_release_seqid(data->o_arg.seqid); + else + rpc_call_start(task); return; unlock_no_action: rcu_read_unlock(); out_no_action: task->tk_action = NULL; - nfs4_sequence_done(task, &data->o_res.seq_res); + +} + +static void nfs4_recover_open_prepare(struct rpc_task *task, void *calldata) +{ + rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); + nfs4_open_prepare(task, calldata); } static void nfs4_open_done(struct rpc_task *task, void *calldata) @@ -1527,6 +1648,12 @@ static const struct rpc_call_ops nfs4_open_ops = { .rpc_release = nfs4_open_release, }; +static const struct rpc_call_ops nfs4_recover_open_ops = { + .rpc_call_prepare = nfs4_recover_open_prepare, + .rpc_call_done = nfs4_open_done, + .rpc_release = nfs4_open_release, +}; + static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover) { struct inode *dir = data->dir->d_inode; @@ -1556,7 +1683,7 @@ static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover) data->rpc_status = 0; data->cancelled = 0; if (isrecover) - nfs4_set_sequence_privileged(&o_arg->seq_args); + task_setup_data.callback_ops = &nfs4_recover_open_ops; task = rpc_run_task(&task_setup_data); if (IS_ERR(task)) return PTR_ERR(task); @@ -1662,6 +1789,24 @@ static int _nfs4_proc_open(struct nfs4_opendata *data) return 0; } +static int nfs4_client_recover_expired_lease(struct nfs_client *clp) +{ + unsigned int loop; + int ret; + + for (loop = NFS4_MAX_LOOP_ON_RECOVER; loop != 0; loop--) { + ret = nfs4_wait_clnt_recover(clp); + if (ret != 0) + break; + if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) && + !test_bit(NFS4CLNT_CHECK_LEASE,&clp->cl_state)) + break; + nfs4_schedule_state_manager(clp); + ret = -EIO; + } + return ret; +} + static int nfs4_recover_expired_lease(struct nfs_server *server) { return nfs4_client_recover_expired_lease(server->nfs_client); @@ -2137,7 +2282,6 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) if (!call_close) { /* Note: exit _without_ calling nfs4_close_done */ task->tk_action = NULL; - nfs4_sequence_done(task, &calldata->res.seq_res); goto out; } @@ -2155,6 +2299,8 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) &calldata->res.seq_res, task) != 0) nfs_release_seqid(calldata->arg.seqid); + else + rpc_call_start(task); out: dprintk("%s: done!\n", __func__); } @@ -2387,8 +2533,7 @@ static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS]; len = rpcauth_list_flavors(flav_array, ARRAY_SIZE(flav_array)); - if (len < 0) - return len; + BUG_ON(len < 0); for (i = 0; i < len; i++) { /* AUTH_UNIX is the default flavor if none was specified, @@ -2893,10 +3038,12 @@ static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct inode *dir) static void nfs4_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlinkdata *data) { - nfs4_setup_sequence(NFS_SERVER(data->dir), - &data->args.seq_args, - &data->res.seq_res, - task); + if (nfs4_setup_sequence(NFS_SERVER(data->dir), + &data->args.seq_args, + &data->res.seq_res, + task)) + return; + rpc_call_start(task); } static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir) @@ -2924,10 +3071,12 @@ static void nfs4_proc_rename_setup(struct rpc_message *msg, struct inode *dir) static void nfs4_proc_rename_rpc_prepare(struct rpc_task *task, struct nfs_renamedata *data) { - nfs4_setup_sequence(NFS_SERVER(data->old_dir), - &data->args.seq_args, - &data->res.seq_res, - task); + if (nfs4_setup_sequence(NFS_SERVER(data->old_dir), + &data->args.seq_args, + &data->res.seq_res, + task)) + return; + rpc_call_start(task); } static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir, @@ -3213,6 +3362,9 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, int mode = sattr->ia_mode; int status = -ENOMEM; + BUG_ON(!(sattr->ia_valid & ATTR_MODE)); + BUG_ON(!S_ISFIFO(mode) && !S_ISBLK(mode) && !S_ISCHR(mode) && !S_ISSOCK(mode)); + data = nfs4_alloc_createdata(dir, &dentry->d_name, sattr, NF4SOCK); if (data == NULL) goto out; @@ -3228,13 +3380,10 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, data->arg.ftype = NF4CHR; data->arg.u.device.specdata1 = MAJOR(rdev); data->arg.u.device.specdata2 = MINOR(rdev); - } else if (!S_ISSOCK(mode)) { - status = -EINVAL; - goto out_free; } status = nfs4_do_create(dir, dentry, data); -out_free: + nfs4_free_createdata(data); out: return status; @@ -3416,10 +3565,12 @@ static void nfs4_proc_read_setup(struct nfs_read_data *data, struct rpc_message static void nfs4_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_data *data) { - nfs4_setup_sequence(NFS_SERVER(data->header->inode), - &data->args.seq_args, - &data->res.seq_res, - task); + if (nfs4_setup_sequence(NFS_SERVER(data->header->inode), + &data->args.seq_args, + &data->res.seq_res, + task)) + return; + rpc_call_start(task); } static int nfs4_write_done_cb(struct rpc_task *task, struct nfs_write_data *data) @@ -3480,18 +3631,22 @@ static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_messag static void nfs4_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_write_data *data) { - nfs4_setup_sequence(NFS_SERVER(data->header->inode), - &data->args.seq_args, - &data->res.seq_res, - task); + if (nfs4_setup_sequence(NFS_SERVER(data->header->inode), + &data->args.seq_args, + &data->res.seq_res, + task)) + return; + rpc_call_start(task); } static void nfs4_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data) { - nfs4_setup_sequence(NFS_SERVER(data->inode), - &data->args.seq_args, - &data->res.seq_res, - task); + if (nfs4_setup_sequence(NFS_SERVER(data->inode), + &data->args.seq_args, + &data->res.seq_res, + task)) + return; + rpc_call_start(task); } static int nfs4_commit_done_cb(struct rpc_task *task, struct nfs_commit_data *data) @@ -4138,10 +4293,11 @@ static void nfs4_delegreturn_prepare(struct rpc_task *task, void *data) d_data = (struct nfs4_delegreturndata *)data; - nfs4_setup_sequence(d_data->res.server, - &d_data->args.seq_args, - &d_data->res.seq_res, - task); + if (nfs4_setup_sequence(d_data->res.server, + &d_data->args.seq_args, + &d_data->res.seq_res, task)) + return; + rpc_call_start(task); } #endif /* CONFIG_NFS_V4_1 */ @@ -4387,7 +4543,6 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data) if (test_bit(NFS_LOCK_INITIALIZED, &calldata->lsp->ls_flags) == 0) { /* Note: exit _without_ running nfs4_locku_done */ task->tk_action = NULL; - nfs4_sequence_done(task, &calldata->res.seq_res); return; } calldata->timestamp = jiffies; @@ -4396,6 +4551,8 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data) &calldata->res.seq_res, task) != 0) nfs_release_seqid(calldata->arg.seqid); + else + rpc_call_start(task); } static const struct rpc_call_ops nfs4_locku_ops = { @@ -4539,9 +4696,8 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata) return; /* Do we need to do an open_to_lock_owner? */ if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) { - if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0) { + if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0) goto out_release_lock_seqid; - } data->arg.open_stateid = &state->stateid; data->arg.new_lock_owner = 1; data->res.open_seqid = data->arg.open_seqid; @@ -4551,12 +4707,20 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata) if (nfs4_setup_sequence(data->server, &data->arg.seq_args, &data->res.seq_res, - task) == 0) + task) == 0) { + rpc_call_start(task); return; + } nfs_release_seqid(data->arg.open_seqid); out_release_lock_seqid: nfs_release_seqid(data->arg.lock_seqid); - dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status); + dprintk("%s: done!, ret = %d\n", __func__, task->tk_status); +} + +static void nfs4_recover_lock_prepare(struct rpc_task *task, void *calldata) +{ + rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); + nfs4_lock_prepare(task, calldata); } static void nfs4_lock_done(struct rpc_task *task, void *calldata) @@ -4611,6 +4775,12 @@ static const struct rpc_call_ops nfs4_lock_ops = { .rpc_release = nfs4_lock_release, }; +static const struct rpc_call_ops nfs4_recover_lock_ops = { + .rpc_call_prepare = nfs4_recover_lock_prepare, + .rpc_call_done = nfs4_lock_done, + .rpc_release = nfs4_lock_release, +}; + static void nfs4_handle_setlk_error(struct nfs_server *server, struct nfs4_lock_state *lsp, int new_lock_owner, int error) { switch (error) { @@ -4653,15 +4823,15 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f return -ENOMEM; if (IS_SETLKW(cmd)) data->arg.block = 1; - nfs41_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1); - msg.rpc_argp = &data->arg; - msg.rpc_resp = &data->res; - task_setup_data.callback_data = data; if (recovery_type > NFS_LOCK_NEW) { if (recovery_type == NFS_LOCK_RECLAIM) data->arg.reclaim = NFS_LOCK_RECLAIM; - nfs4_set_sequence_privileged(&data->arg.seq_args); + task_setup_data.callback_ops = &nfs4_recover_lock_ops; } + nfs41_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1); + msg.rpc_argp = &data->arg; + msg.rpc_resp = &data->res; + task_setup_data.callback_data = data; task = rpc_run_task(&task_setup_data); if (IS_ERR(task)) return PTR_ERR(task); @@ -5187,6 +5357,7 @@ int nfs4_proc_bind_conn_to_session(struct nfs_client *clp, struct rpc_cred *cred }; dprintk("--> %s\n", __func__); + BUG_ON(clp == NULL); res.session = kzalloc(sizeof(struct nfs4_session), GFP_NOFS); if (unlikely(res.session == NULL)) { @@ -5398,16 +5569,20 @@ struct nfs4_get_lease_time_data { static void nfs4_get_lease_time_prepare(struct rpc_task *task, void *calldata) { + int ret; struct nfs4_get_lease_time_data *data = (struct nfs4_get_lease_time_data *)calldata; dprintk("--> %s\n", __func__); + rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); /* just setup sequence, do not trigger session recovery since we're invoked within one */ - nfs41_setup_sequence(data->clp->cl_session, - &data->args->la_seq_args, - &data->res->lr_seq_res, - task); + ret = nfs41_setup_sequence(data->clp->cl_session, + &data->args->la_seq_args, + &data->res->lr_seq_res, task); + + BUG_ON(ret == -EAGAIN); + rpc_call_start(task); dprintk("<-- %s\n", __func__); } @@ -5469,7 +5644,6 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo) int status; nfs41_init_sequence(&args.la_seq_args, &res.lr_seq_res, 0); - nfs4_set_sequence_privileged(&args.la_seq_args); dprintk("--> %s\n", __func__); task = rpc_run_task(&task_setup); @@ -5484,6 +5658,145 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo) return status; } +static struct nfs4_slot *nfs4_alloc_slots(u32 max_slots, gfp_t gfp_flags) +{ + return kcalloc(max_slots, sizeof(struct nfs4_slot), gfp_flags); +} + +static void nfs4_add_and_init_slots(struct nfs4_slot_table *tbl, + struct nfs4_slot *new, + u32 max_slots, + u32 ivalue) +{ + struct nfs4_slot *old = NULL; + u32 i; + + spin_lock(&tbl->slot_tbl_lock); + if (new) { + old = tbl->slots; + tbl->slots = new; + tbl->max_slots = max_slots; + } + tbl->highest_used_slotid = NFS4_NO_SLOT; + for (i = 0; i < tbl->max_slots; i++) + tbl->slots[i].seq_nr = ivalue; + spin_unlock(&tbl->slot_tbl_lock); + kfree(old); +} + +/* + * (re)Initialise a slot table + */ +static int nfs4_realloc_slot_table(struct nfs4_slot_table *tbl, u32 max_reqs, + u32 ivalue) +{ + struct nfs4_slot *new = NULL; + int ret = -ENOMEM; + + dprintk("--> %s: max_reqs=%u, tbl->max_slots %d\n", __func__, + max_reqs, tbl->max_slots); + + /* Does the newly negotiated max_reqs match the existing slot table? */ + if (max_reqs != tbl->max_slots) { + new = nfs4_alloc_slots(max_reqs, GFP_NOFS); + if (!new) + goto out; + } + ret = 0; + + nfs4_add_and_init_slots(tbl, new, max_reqs, ivalue); + dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__, + tbl, tbl->slots, tbl->max_slots); +out: + dprintk("<-- %s: return %d\n", __func__, ret); + return ret; +} + +/* Destroy the slot table */ +static void nfs4_destroy_slot_tables(struct nfs4_session *session) +{ + if (session->fc_slot_table.slots != NULL) { + kfree(session->fc_slot_table.slots); + session->fc_slot_table.slots = NULL; + } + if (session->bc_slot_table.slots != NULL) { + kfree(session->bc_slot_table.slots); + session->bc_slot_table.slots = NULL; + } + return; +} + +/* + * Initialize or reset the forechannel and backchannel tables + */ +static int nfs4_setup_session_slot_tables(struct nfs4_session *ses) +{ + struct nfs4_slot_table *tbl; + int status; + + dprintk("--> %s\n", __func__); + /* Fore channel */ + tbl = &ses->fc_slot_table; + status = nfs4_realloc_slot_table(tbl, ses->fc_attrs.max_reqs, 1); + if (status) /* -ENOMEM */ + return status; + /* Back channel */ + tbl = &ses->bc_slot_table; + status = nfs4_realloc_slot_table(tbl, ses->bc_attrs.max_reqs, 0); + if (status && tbl->slots == NULL) + /* Fore and back channel share a connection so get + * both slot tables or neither */ + nfs4_destroy_slot_tables(ses); + return status; +} + +struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp) +{ + struct nfs4_session *session; + struct nfs4_slot_table *tbl; + + session = kzalloc(sizeof(struct nfs4_session), GFP_NOFS); + if (!session) + return NULL; + + tbl = &session->fc_slot_table; + tbl->highest_used_slotid = NFS4_NO_SLOT; + spin_lock_init(&tbl->slot_tbl_lock); + rpc_init_priority_wait_queue(&tbl->slot_tbl_waitq, "ForeChannel Slot table"); + init_completion(&tbl->complete); + + tbl = &session->bc_slot_table; + tbl->highest_used_slotid = NFS4_NO_SLOT; + spin_lock_init(&tbl->slot_tbl_lock); + rpc_init_wait_queue(&tbl->slot_tbl_waitq, "BackChannel Slot table"); + init_completion(&tbl->complete); + + session->session_state = 1<clp = clp; + return session; +} + +void nfs4_destroy_session(struct nfs4_session *session) +{ + struct rpc_xprt *xprt; + struct rpc_cred *cred; + + cred = nfs4_get_exchange_id_cred(session->clp); + nfs4_proc_destroy_session(session, cred); + if (cred) + put_rpccred(cred); + + rcu_read_lock(); + xprt = rcu_dereference(session->clp->cl_rpcclient->cl_xprt); + rcu_read_unlock(); + dprintk("%s Destroy backchannel for xprt %p\n", + __func__, xprt); + xprt_destroy_backchannel(xprt, NFS41_BC_MIN_CALLBACKS); + nfs4_destroy_slot_tables(session); + kfree(session); +} + /* * Initialize the values to be used by the client in CREATE_SESSION * If nfs4_init_session set the fore channel request and response sizes, @@ -5496,8 +5809,8 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo) static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args) { struct nfs4_session *session = args->client->cl_session; - unsigned int mxrqst_sz = session->fc_target_max_rqst_sz, - mxresp_sz = session->fc_target_max_resp_sz; + unsigned int mxrqst_sz = session->fc_attrs.max_rqst_sz, + mxresp_sz = session->fc_attrs.max_resp_sz; if (mxrqst_sz == 0) mxrqst_sz = NFS_MAX_FILE_IO_SIZE; @@ -5606,9 +5919,10 @@ static int _nfs4_proc_create_session(struct nfs_client *clp, status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); - if (!status) { + if (!status) /* Verify the session's negotiated channel_attrs values */ status = nfs4_verify_channel_attrs(&args, session); + if (!status) { /* Increment the clientid slot sequence id */ clp->cl_seqid++; } @@ -5677,6 +5991,83 @@ int nfs4_proc_destroy_session(struct nfs4_session *session, return status; } +/* + * With sessions, the client is not marked ready until after a + * successful EXCHANGE_ID and CREATE_SESSION. + * + * Map errors cl_cons_state errors to EPROTONOSUPPORT to indicate + * other versions of NFS can be tried. + */ +static int nfs41_check_session_ready(struct nfs_client *clp) +{ + int ret; + + if (clp->cl_cons_state == NFS_CS_SESSION_INITING) { + ret = nfs4_client_recover_expired_lease(clp); + if (ret) + return ret; + } + if (clp->cl_cons_state < NFS_CS_READY) + return -EPROTONOSUPPORT; + smp_rmb(); + return 0; +} + +int nfs4_init_session(struct nfs_server *server) +{ + struct nfs_client *clp = server->nfs_client; + struct nfs4_session *session; + unsigned int rsize, wsize; + + if (!nfs4_has_session(clp)) + return 0; + + session = clp->cl_session; + spin_lock(&clp->cl_lock); + if (test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state)) { + + rsize = server->rsize; + if (rsize == 0) + rsize = NFS_MAX_FILE_IO_SIZE; + wsize = server->wsize; + if (wsize == 0) + wsize = NFS_MAX_FILE_IO_SIZE; + + session->fc_attrs.max_rqst_sz = wsize + nfs41_maxwrite_overhead; + session->fc_attrs.max_resp_sz = rsize + nfs41_maxread_overhead; + } + spin_unlock(&clp->cl_lock); + + return nfs41_check_session_ready(clp); +} + +int nfs4_init_ds_session(struct nfs_client *clp, unsigned long lease_time) +{ + struct nfs4_session *session = clp->cl_session; + int ret; + + spin_lock(&clp->cl_lock); + if (test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state)) { + /* + * Do not set NFS_CS_CHECK_LEASE_TIME instead set the + * DS lease to be equal to the MDS lease. + */ + clp->cl_lease_time = lease_time; + clp->cl_last_renewal = jiffies; + } + spin_unlock(&clp->cl_lock); + + ret = nfs41_check_session_ready(clp); + if (ret) + return ret; + /* Test for the DS role */ + if (!is_ds_client(clp)) + return -ENODEV; + return 0; +} +EXPORT_SYMBOL_GPL(nfs4_init_ds_session); + + /* * Renew the cl_session lease. */ @@ -5742,7 +6133,9 @@ static void nfs41_sequence_prepare(struct rpc_task *task, void *data) args = task->tk_msg.rpc_argp; res = task->tk_msg.rpc_resp; - nfs41_setup_sequence(clp->cl_session, args, res, task); + if (nfs41_setup_sequence(clp->cl_session, args, res, task)) + return; + rpc_call_start(task); } static const struct rpc_call_ops nfs41_sequence_ops = { @@ -5751,9 +6144,7 @@ static const struct rpc_call_ops nfs41_sequence_ops = { .rpc_release = nfs41_sequence_release, }; -static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, - struct rpc_cred *cred, - bool is_privileged) +static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred) { struct nfs4_sequence_data *calldata; struct rpc_message msg = { @@ -5775,8 +6166,6 @@ static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, return ERR_PTR(-ENOMEM); } nfs41_init_sequence(&calldata->args, &calldata->res, 0); - if (is_privileged) - nfs4_set_sequence_privileged(&calldata->args); msg.rpc_argp = &calldata->args; msg.rpc_resp = &calldata->res; calldata->clp = clp; @@ -5792,7 +6181,7 @@ static int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cr if ((renew_flags & NFS4_RENEW_TIMEOUT) == 0) return 0; - task = _nfs41_proc_sequence(clp, cred, false); + task = _nfs41_proc_sequence(clp, cred); if (IS_ERR(task)) ret = PTR_ERR(task); else @@ -5806,7 +6195,7 @@ static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred) struct rpc_task *task; int ret; - task = _nfs41_proc_sequence(clp, cred, true); + task = _nfs41_proc_sequence(clp, cred); if (IS_ERR(task)) { ret = PTR_ERR(task); goto out; @@ -5835,10 +6224,13 @@ static void nfs4_reclaim_complete_prepare(struct rpc_task *task, void *data) { struct nfs4_reclaim_complete_data *calldata = data; - nfs41_setup_sequence(calldata->clp->cl_session, - &calldata->arg.seq_args, - &calldata->res.seq_res, - task); + rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); + if (nfs41_setup_sequence(calldata->clp->cl_session, + &calldata->arg.seq_args, + &calldata->res.seq_res, task)) + return; + + rpc_call_start(task); } static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nfs_client *clp) @@ -5915,7 +6307,6 @@ static int nfs41_proc_reclaim_complete(struct nfs_client *clp) calldata->arg.one_fs = 0; nfs41_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 0); - nfs4_set_sequence_privileged(&calldata->arg.seq_args); msg.rpc_argp = &calldata->arg; msg.rpc_resp = &calldata->res; task_setup_data.callback_data = calldata; @@ -5939,7 +6330,6 @@ nfs4_layoutget_prepare(struct rpc_task *task, void *calldata) { struct nfs4_layoutget *lgp = calldata; struct nfs_server *server = NFS_SERVER(lgp->args.inode); - struct nfs4_session *session = nfs4_get_session(server); dprintk("--> %s\n", __func__); /* Note the is a race here, where a CB_LAYOUTRECALL can come in @@ -5947,14 +6337,16 @@ nfs4_layoutget_prepare(struct rpc_task *task, void *calldata) * However, that is not so catastrophic, and there seems * to be no way to prevent it completely. */ - if (nfs41_setup_sequence(session, &lgp->args.seq_args, + if (nfs4_setup_sequence(server, &lgp->args.seq_args, &lgp->res.seq_res, task)) return; if (pnfs_choose_layoutget_stateid(&lgp->args.stateid, NFS_I(lgp->args.inode)->layout, lgp->args.ctx->state)) { rpc_exit(task, NFS4_OK); + return; } + rpc_call_start(task); } static void nfs4_layoutget_done(struct rpc_task *task, void *calldata) @@ -5967,7 +6359,7 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata) dprintk("--> %s\n", __func__); - if (!nfs41_sequence_done(task, &lgp->res.seq_res)) + if (!nfs4_sequence_done(task, &lgp->res.seq_res)) goto out; switch (task->tk_status) { @@ -6118,10 +6510,10 @@ nfs4_layoutreturn_prepare(struct rpc_task *task, void *calldata) struct nfs4_layoutreturn *lrp = calldata; dprintk("--> %s\n", __func__); - nfs41_setup_sequence(lrp->clp->cl_session, - &lrp->args.seq_args, - &lrp->res.seq_res, - task); + if (nfs41_setup_sequence(lrp->clp->cl_session, &lrp->args.seq_args, + &lrp->res.seq_res, task)) + return; + rpc_call_start(task); } static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata) @@ -6131,7 +6523,7 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata) dprintk("--> %s\n", __func__); - if (!nfs41_sequence_done(task, &lrp->res.seq_res)) + if (!nfs4_sequence_done(task, &lrp->res.seq_res)) return; server = NFS_SERVER(lrp->args.inode); @@ -6280,12 +6672,11 @@ static void nfs4_layoutcommit_prepare(struct rpc_task *task, void *calldata) { struct nfs4_layoutcommit_data *data = calldata; struct nfs_server *server = NFS_SERVER(data->args.inode); - struct nfs4_session *session = nfs4_get_session(server); - nfs41_setup_sequence(session, - &data->args.seq_args, - &data->res.seq_res, - task); + if (nfs4_setup_sequence(server, &data->args.seq_args, + &data->res.seq_res, task)) + return; + rpc_call_start(task); } static void @@ -6294,7 +6685,7 @@ nfs4_layoutcommit_done(struct rpc_task *task, void *calldata) struct nfs4_layoutcommit_data *data = calldata; struct nfs_server *server = NFS_SERVER(data->args.inode); - if (!nfs41_sequence_done(task, &data->res.seq_res)) + if (!nfs4_sequence_done(task, &data->res.seq_res)) return; switch (task->tk_status) { /* Just ignore these failures */ @@ -6482,9 +6873,7 @@ static int _nfs41_test_stateid(struct nfs_server *server, nfs4_stateid *stateid) dprintk("NFS call test_stateid %p\n", stateid); nfs41_init_sequence(&args.seq_args, &res.seq_res, 0); - nfs4_set_sequence_privileged(&args.seq_args); - status = nfs4_call_sync_sequence(server->client, server, &msg, - &args.seq_args, &res.seq_res); + status = nfs4_call_sync_sequence(server->client, server, &msg, &args.seq_args, &res.seq_res, 1); if (status != NFS_OK) { dprintk("NFS reply test_stateid: failed, %d\n", status); return status; @@ -6531,9 +6920,8 @@ static int _nfs4_free_stateid(struct nfs_server *server, nfs4_stateid *stateid) dprintk("NFS call free_stateid %p\n", stateid); nfs41_init_sequence(&args.seq_args, &res.seq_res, 0); - nfs4_set_sequence_privileged(&args.seq_args); status = nfs4_call_sync_sequence(server->client, server, &msg, - &args.seq_args, &res.seq_res); + &args.seq_args, &res.seq_res, 1); dprintk("NFS reply free_stateid: %d\n", status); return status; } @@ -6653,7 +7041,7 @@ static const struct nfs4_minor_version_ops nfs_v4_0_minor_ops = { #if defined(CONFIG_NFS_V4_1) static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = { .minor_version = 1, - .call_sync = nfs4_call_sync_sequence, + .call_sync = _nfs4_call_sync_session, .match_stateid = nfs41_match_stateid, .find_root_sec = nfs41_find_root_sec, .reboot_recovery_ops = &nfs41_reboot_recovery_ops, diff --git a/trunk/fs/nfs/nfs4session.c b/trunk/fs/nfs/nfs4session.c deleted file mode 100644 index ed5aa9fa9c7b..000000000000 --- a/trunk/fs/nfs/nfs4session.c +++ /dev/null @@ -1,542 +0,0 @@ -/* - * fs/nfs/nfs4session.c - * - * Copyright (c) 2012 Trond Myklebust - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "nfs4_fs.h" -#include "internal.h" -#include "nfs4session.h" -#include "callback.h" - -#define NFSDBG_FACILITY NFSDBG_STATE - -/* - * nfs4_shrink_slot_table - free retired slots from the slot table - */ -static void nfs4_shrink_slot_table(struct nfs4_slot_table *tbl, u32 newsize) -{ - struct nfs4_slot **p; - if (newsize >= tbl->max_slots) - return; - - p = &tbl->slots; - while (newsize--) - p = &(*p)->next; - while (*p) { - struct nfs4_slot *slot = *p; - - *p = slot->next; - kfree(slot); - tbl->max_slots--; - } -} - -/* - * nfs4_free_slot - free a slot and efficiently update slot table. - * - * freeing a slot is trivially done by clearing its respective bit - * in the bitmap. - * If the freed slotid equals highest_used_slotid we want to update it - * so that the server would be able to size down the slot table if needed, - * otherwise we know that the highest_used_slotid is still in use. - * When updating highest_used_slotid there may be "holes" in the bitmap - * so we need to scan down from highest_used_slotid to 0 looking for the now - * highest slotid in use. - * If none found, highest_used_slotid is set to NFS4_NO_SLOT. - * - * Must be called while holding tbl->slot_tbl_lock - */ -void nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot) -{ - u32 slotid = slot->slot_nr; - - /* clear used bit in bitmap */ - __clear_bit(slotid, tbl->used_slots); - - /* update highest_used_slotid when it is freed */ - if (slotid == tbl->highest_used_slotid) { - u32 new_max = find_last_bit(tbl->used_slots, slotid); - if (new_max < slotid) - tbl->highest_used_slotid = new_max; - else { - tbl->highest_used_slotid = NFS4_NO_SLOT; - nfs4_session_drain_complete(tbl->session, tbl); - } - } - dprintk("%s: slotid %u highest_used_slotid %d\n", __func__, - slotid, tbl->highest_used_slotid); -} - -static struct nfs4_slot *nfs4_new_slot(struct nfs4_slot_table *tbl, - u32 slotid, u32 seq_init, gfp_t gfp_mask) -{ - struct nfs4_slot *slot; - - slot = kzalloc(sizeof(*slot), gfp_mask); - if (slot) { - slot->table = tbl; - slot->slot_nr = slotid; - slot->seq_nr = seq_init; - } - return slot; -} - -static struct nfs4_slot *nfs4_find_or_create_slot(struct nfs4_slot_table *tbl, - u32 slotid, u32 seq_init, gfp_t gfp_mask) -{ - struct nfs4_slot **p, *slot; - - p = &tbl->slots; - for (;;) { - if (*p == NULL) { - *p = nfs4_new_slot(tbl, tbl->max_slots, - seq_init, gfp_mask); - if (*p == NULL) - break; - tbl->max_slots++; - } - slot = *p; - if (slot->slot_nr == slotid) - return slot; - p = &slot->next; - } - return ERR_PTR(-ENOMEM); -} - -/* - * nfs4_alloc_slot - efficiently look for a free slot - * - * nfs4_alloc_slot looks for an unset bit in the used_slots bitmap. - * If found, we mark the slot as used, update the highest_used_slotid, - * and respectively set up the sequence operation args. - * - * Note: must be called with under the slot_tbl_lock. - */ -struct nfs4_slot *nfs4_alloc_slot(struct nfs4_slot_table *tbl) -{ - struct nfs4_slot *ret = ERR_PTR(-EBUSY); - u32 slotid; - - dprintk("--> %s used_slots=%04lx highest_used=%u max_slots=%u\n", - __func__, tbl->used_slots[0], tbl->highest_used_slotid, - tbl->max_slotid + 1); - slotid = find_first_zero_bit(tbl->used_slots, tbl->max_slotid + 1); - if (slotid > tbl->max_slotid) - goto out; - ret = nfs4_find_or_create_slot(tbl, slotid, 1, GFP_NOWAIT); - if (IS_ERR(ret)) - goto out; - __set_bit(slotid, tbl->used_slots); - if (slotid > tbl->highest_used_slotid || - tbl->highest_used_slotid == NFS4_NO_SLOT) - tbl->highest_used_slotid = slotid; - ret->renewal_time = jiffies; - ret->generation = tbl->generation; - -out: - dprintk("<-- %s used_slots=%04lx highest_used=%d slotid=%d \n", - __func__, tbl->used_slots[0], tbl->highest_used_slotid, - !IS_ERR(ret) ? ret->slot_nr : -1); - return ret; -} - -static int nfs4_grow_slot_table(struct nfs4_slot_table *tbl, - u32 max_reqs, u32 ivalue) -{ - if (max_reqs <= tbl->max_slots) - return 0; - if (!IS_ERR(nfs4_find_or_create_slot(tbl, max_reqs - 1, ivalue, GFP_NOFS))) - return 0; - return -ENOMEM; -} - -static void nfs4_reset_slot_table(struct nfs4_slot_table *tbl, - u32 server_highest_slotid, - u32 ivalue) -{ - struct nfs4_slot **p; - - nfs4_shrink_slot_table(tbl, server_highest_slotid + 1); - p = &tbl->slots; - while (*p) { - (*p)->seq_nr = ivalue; - p = &(*p)->next; - } - tbl->highest_used_slotid = NFS4_NO_SLOT; - tbl->target_highest_slotid = server_highest_slotid; - tbl->server_highest_slotid = server_highest_slotid; - tbl->d_target_highest_slotid = 0; - tbl->d2_target_highest_slotid = 0; - tbl->max_slotid = server_highest_slotid; -} - -/* - * (re)Initialise a slot table - */ -static int nfs4_realloc_slot_table(struct nfs4_slot_table *tbl, - u32 max_reqs, u32 ivalue) -{ - int ret; - - dprintk("--> %s: max_reqs=%u, tbl->max_slots %d\n", __func__, - max_reqs, tbl->max_slots); - - if (max_reqs > NFS4_MAX_SLOT_TABLE) - max_reqs = NFS4_MAX_SLOT_TABLE; - - ret = nfs4_grow_slot_table(tbl, max_reqs, ivalue); - if (ret) - goto out; - - spin_lock(&tbl->slot_tbl_lock); - nfs4_reset_slot_table(tbl, max_reqs - 1, ivalue); - spin_unlock(&tbl->slot_tbl_lock); - - dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__, - tbl, tbl->slots, tbl->max_slots); -out: - dprintk("<-- %s: return %d\n", __func__, ret); - return ret; -} - -/* Destroy the slot table */ -static void nfs4_destroy_slot_tables(struct nfs4_session *session) -{ - nfs4_shrink_slot_table(&session->fc_slot_table, 0); - nfs4_shrink_slot_table(&session->bc_slot_table, 0); -} - -static bool nfs41_assign_slot(struct rpc_task *task, void *pslot) -{ - struct nfs4_sequence_args *args = task->tk_msg.rpc_argp; - struct nfs4_sequence_res *res = task->tk_msg.rpc_resp; - struct nfs4_slot *slot = pslot; - struct nfs4_slot_table *tbl = slot->table; - - if (nfs4_session_draining(tbl->session) && !args->sa_privileged) - return false; - slot->renewal_time = jiffies; - slot->generation = tbl->generation; - args->sa_slot = slot; - res->sr_slot = slot; - res->sr_status_flags = 0; - res->sr_status = 1; - return true; -} - -static bool __nfs41_wake_and_assign_slot(struct nfs4_slot_table *tbl, - struct nfs4_slot *slot) -{ - if (rpc_wake_up_first(&tbl->slot_tbl_waitq, nfs41_assign_slot, slot)) - return true; - return false; -} - -bool nfs41_wake_and_assign_slot(struct nfs4_slot_table *tbl, - struct nfs4_slot *slot) -{ - if (slot->slot_nr > tbl->max_slotid) - return false; - return __nfs41_wake_and_assign_slot(tbl, slot); -} - -static bool nfs41_try_wake_next_slot_table_entry(struct nfs4_slot_table *tbl) -{ - struct nfs4_slot *slot = nfs4_alloc_slot(tbl); - if (!IS_ERR(slot)) { - bool ret = __nfs41_wake_and_assign_slot(tbl, slot); - if (ret) - return ret; - nfs4_free_slot(tbl, slot); - } - return false; -} - -void nfs41_wake_slot_table(struct nfs4_slot_table *tbl) -{ - for (;;) { - if (!nfs41_try_wake_next_slot_table_entry(tbl)) - break; - } -} - -/* Update the client's idea of target_highest_slotid */ -static void nfs41_set_target_slotid_locked(struct nfs4_slot_table *tbl, - u32 target_highest_slotid) -{ - unsigned int max_slotid; - - if (tbl->target_highest_slotid == target_highest_slotid) - return; - tbl->target_highest_slotid = target_highest_slotid; - tbl->generation++; - - max_slotid = min(NFS4_MAX_SLOT_TABLE - 1, tbl->target_highest_slotid); - tbl->max_slotid = max_slotid; - nfs41_wake_slot_table(tbl); -} - -void nfs41_set_target_slotid(struct nfs4_slot_table *tbl, - u32 target_highest_slotid) -{ - spin_lock(&tbl->slot_tbl_lock); - nfs41_set_target_slotid_locked(tbl, target_highest_slotid); - tbl->d_target_highest_slotid = 0; - tbl->d2_target_highest_slotid = 0; - spin_unlock(&tbl->slot_tbl_lock); -} - -static void nfs41_set_server_slotid_locked(struct nfs4_slot_table *tbl, - u32 highest_slotid) -{ - if (tbl->server_highest_slotid == highest_slotid) - return; - if (tbl->highest_used_slotid > highest_slotid) - return; - /* Deallocate slots */ - nfs4_shrink_slot_table(tbl, highest_slotid + 1); - tbl->server_highest_slotid = highest_slotid; -} - -static s32 nfs41_derivative_target_slotid(s32 s1, s32 s2) -{ - s1 -= s2; - if (s1 == 0) - return 0; - if (s1 < 0) - return (s1 - 1) >> 1; - return (s1 + 1) >> 1; -} - -static int nfs41_sign_s32(s32 s1) -{ - if (s1 > 0) - return 1; - if (s1 < 0) - return -1; - return 0; -} - -static bool nfs41_same_sign_or_zero_s32(s32 s1, s32 s2) -{ - if (!s1 || !s2) - return true; - return nfs41_sign_s32(s1) == nfs41_sign_s32(s2); -} - -/* Try to eliminate outliers by checking for sharp changes in the - * derivatives and second derivatives - */ -static bool nfs41_is_outlier_target_slotid(struct nfs4_slot_table *tbl, - u32 new_target) -{ - s32 d_target, d2_target; - bool ret = true; - - d_target = nfs41_derivative_target_slotid(new_target, - tbl->target_highest_slotid); - d2_target = nfs41_derivative_target_slotid(d_target, - tbl->d_target_highest_slotid); - /* Is first derivative same sign? */ - if (nfs41_same_sign_or_zero_s32(d_target, tbl->d_target_highest_slotid)) - ret = false; - /* Is second derivative same sign? */ - if (nfs41_same_sign_or_zero_s32(d2_target, tbl->d2_target_highest_slotid)) - ret = false; - tbl->d_target_highest_slotid = d_target; - tbl->d2_target_highest_slotid = d2_target; - return ret; -} - -void nfs41_update_target_slotid(struct nfs4_slot_table *tbl, - struct nfs4_slot *slot, - struct nfs4_sequence_res *res) -{ - spin_lock(&tbl->slot_tbl_lock); - if (!nfs41_is_outlier_target_slotid(tbl, res->sr_target_highest_slotid)) - nfs41_set_target_slotid_locked(tbl, res->sr_target_highest_slotid); - if (tbl->generation == slot->generation) - nfs41_set_server_slotid_locked(tbl, res->sr_highest_slotid); - spin_unlock(&tbl->slot_tbl_lock); -} - -/* - * Initialize or reset the forechannel and backchannel tables - */ -int nfs4_setup_session_slot_tables(struct nfs4_session *ses) -{ - struct nfs4_slot_table *tbl; - int status; - - dprintk("--> %s\n", __func__); - /* Fore channel */ - tbl = &ses->fc_slot_table; - tbl->session = ses; - status = nfs4_realloc_slot_table(tbl, ses->fc_attrs.max_reqs, 1); - if (status) /* -ENOMEM */ - return status; - /* Back channel */ - tbl = &ses->bc_slot_table; - tbl->session = ses; - status = nfs4_realloc_slot_table(tbl, ses->bc_attrs.max_reqs, 0); - if (status && tbl->slots == NULL) - /* Fore and back channel share a connection so get - * both slot tables or neither */ - nfs4_destroy_slot_tables(ses); - return status; -} - -struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp) -{ - struct nfs4_session *session; - struct nfs4_slot_table *tbl; - - session = kzalloc(sizeof(struct nfs4_session), GFP_NOFS); - if (!session) - return NULL; - - tbl = &session->fc_slot_table; - tbl->highest_used_slotid = NFS4_NO_SLOT; - spin_lock_init(&tbl->slot_tbl_lock); - rpc_init_priority_wait_queue(&tbl->slot_tbl_waitq, "ForeChannel Slot table"); - init_completion(&tbl->complete); - - tbl = &session->bc_slot_table; - tbl->highest_used_slotid = NFS4_NO_SLOT; - spin_lock_init(&tbl->slot_tbl_lock); - rpc_init_wait_queue(&tbl->slot_tbl_waitq, "BackChannel Slot table"); - init_completion(&tbl->complete); - - session->session_state = 1<clp = clp; - return session; -} - -void nfs4_destroy_session(struct nfs4_session *session) -{ - struct rpc_xprt *xprt; - struct rpc_cred *cred; - - cred = nfs4_get_exchange_id_cred(session->clp); - nfs4_proc_destroy_session(session, cred); - if (cred) - put_rpccred(cred); - - rcu_read_lock(); - xprt = rcu_dereference(session->clp->cl_rpcclient->cl_xprt); - rcu_read_unlock(); - dprintk("%s Destroy backchannel for xprt %p\n", - __func__, xprt); - xprt_destroy_backchannel(xprt, NFS41_BC_MIN_CALLBACKS); - nfs4_destroy_slot_tables(session); - kfree(session); -} - -/* - * With sessions, the client is not marked ready until after a - * successful EXCHANGE_ID and CREATE_SESSION. - * - * Map errors cl_cons_state errors to EPROTONOSUPPORT to indicate - * other versions of NFS can be tried. - */ -static int nfs41_check_session_ready(struct nfs_client *clp) -{ - int ret; - - if (clp->cl_cons_state == NFS_CS_SESSION_INITING) { - ret = nfs4_client_recover_expired_lease(clp); - if (ret) - return ret; - } - if (clp->cl_cons_state < NFS_CS_READY) - return -EPROTONOSUPPORT; - smp_rmb(); - return 0; -} - -int nfs4_init_session(struct nfs_server *server) -{ - struct nfs_client *clp = server->nfs_client; - struct nfs4_session *session; - unsigned int target_max_rqst_sz = NFS_MAX_FILE_IO_SIZE; - unsigned int target_max_resp_sz = NFS_MAX_FILE_IO_SIZE; - - if (!nfs4_has_session(clp)) - return 0; - - if (server->rsize != 0) - target_max_resp_sz = server->rsize; - target_max_resp_sz += nfs41_maxread_overhead; - - if (server->wsize != 0) - target_max_rqst_sz = server->wsize; - target_max_rqst_sz += nfs41_maxwrite_overhead; - - session = clp->cl_session; - spin_lock(&clp->cl_lock); - if (test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state)) { - /* Initialise targets and channel attributes */ - session->fc_target_max_rqst_sz = target_max_rqst_sz; - session->fc_attrs.max_rqst_sz = target_max_rqst_sz; - session->fc_target_max_resp_sz = target_max_resp_sz; - session->fc_attrs.max_resp_sz = target_max_resp_sz; - } else { - /* Just adjust the targets */ - if (target_max_rqst_sz > session->fc_target_max_rqst_sz) { - session->fc_target_max_rqst_sz = target_max_rqst_sz; - set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); - } - if (target_max_resp_sz > session->fc_target_max_resp_sz) { - session->fc_target_max_resp_sz = target_max_resp_sz; - set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); - } - } - spin_unlock(&clp->cl_lock); - - if (test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state)) - nfs4_schedule_lease_recovery(clp); - - return nfs41_check_session_ready(clp); -} - -int nfs4_init_ds_session(struct nfs_client *clp, unsigned long lease_time) -{ - struct nfs4_session *session = clp->cl_session; - int ret; - - spin_lock(&clp->cl_lock); - if (test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state)) { - /* - * Do not set NFS_CS_CHECK_LEASE_TIME instead set the - * DS lease to be equal to the MDS lease. - */ - clp->cl_lease_time = lease_time; - clp->cl_last_renewal = jiffies; - } - spin_unlock(&clp->cl_lock); - - ret = nfs41_check_session_ready(clp); - if (ret) - return ret; - /* Test for the DS role */ - if (!is_ds_client(clp)) - return -ENODEV; - return 0; -} -EXPORT_SYMBOL_GPL(nfs4_init_ds_session); - - diff --git a/trunk/fs/nfs/nfs4session.h b/trunk/fs/nfs/nfs4session.h deleted file mode 100644 index 04f834cab16c..000000000000 --- a/trunk/fs/nfs/nfs4session.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * fs/nfs/nfs4session.h - * - * Copyright (c) 2012 Trond Myklebust - * - */ -#ifndef __LINUX_FS_NFS_NFS4SESSION_H -#define __LINUX_FS_NFS_NFS4SESSION_H - -/* maximum number of slots to use */ -#define NFS4_DEF_SLOT_TABLE_SIZE (16U) -#define NFS4_MAX_SLOT_TABLE (1024U) -#define NFS4_NO_SLOT ((u32)-1) - -#if IS_ENABLED(CONFIG_NFS_V4) - -/* Sessions slot seqid */ -struct nfs4_slot { - struct nfs4_slot_table *table; - struct nfs4_slot *next; - unsigned long generation; - unsigned long renewal_time; - u32 slot_nr; - u32 seq_nr; -}; - -/* Sessions */ -#define SLOT_TABLE_SZ DIV_ROUND_UP(NFS4_MAX_SLOT_TABLE, 8*sizeof(long)) -struct nfs4_slot_table { - struct nfs4_session *session; /* Parent session */ - struct nfs4_slot *slots; /* seqid per slot */ - unsigned long used_slots[SLOT_TABLE_SZ]; /* used/unused bitmap */ - spinlock_t slot_tbl_lock; - struct rpc_wait_queue slot_tbl_waitq; /* allocators may wait here */ - u32 max_slots; /* # slots in table */ - u32 max_slotid; /* Max allowed slotid value */ - u32 highest_used_slotid; /* sent to server on each SEQ. - * op for dynamic resizing */ - u32 target_highest_slotid; /* Server max_slot target */ - u32 server_highest_slotid; /* Server highest slotid */ - s32 d_target_highest_slotid; /* Derivative */ - s32 d2_target_highest_slotid; /* 2nd derivative */ - unsigned long generation; /* Generation counter for - target_highest_slotid */ - struct completion complete; -}; - -/* - * Session related parameters - */ -struct nfs4_session { - struct nfs4_sessionid sess_id; - u32 flags; - unsigned long session_state; - u32 hash_alg; - u32 ssv_len; - - /* The fore and back channel */ - struct nfs4_channel_attrs fc_attrs; - struct nfs4_slot_table fc_slot_table; - struct nfs4_channel_attrs bc_attrs; - struct nfs4_slot_table bc_slot_table; - struct nfs_client *clp; - /* Create session arguments */ - unsigned int fc_target_max_rqst_sz; - unsigned int fc_target_max_resp_sz; -}; - -enum nfs4_session_state { - NFS4_SESSION_INITING, - NFS4_SESSION_DRAINING, -}; - -#if defined(CONFIG_NFS_V4_1) -extern struct nfs4_slot *nfs4_alloc_slot(struct nfs4_slot_table *tbl); -extern void nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot); - -extern void nfs41_set_target_slotid(struct nfs4_slot_table *tbl, - u32 target_highest_slotid); -extern void nfs41_update_target_slotid(struct nfs4_slot_table *tbl, - struct nfs4_slot *slot, - struct nfs4_sequence_res *res); - -extern int nfs4_setup_session_slot_tables(struct nfs4_session *ses); - -extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp); -extern void nfs4_destroy_session(struct nfs4_session *session); -extern int nfs4_init_session(struct nfs_server *server); -extern int nfs4_init_ds_session(struct nfs_client *, unsigned long); - -extern void nfs4_session_drain_complete(struct nfs4_session *session, - struct nfs4_slot_table *tbl); - -static inline bool nfs4_session_draining(struct nfs4_session *session) -{ - return !!test_bit(NFS4_SESSION_DRAINING, &session->session_state); -} - -bool nfs41_wake_and_assign_slot(struct nfs4_slot_table *tbl, - struct nfs4_slot *slot); -void nfs41_wake_slot_table(struct nfs4_slot_table *tbl); - -/* - * Determine if sessions are in use. - */ -static inline int nfs4_has_session(const struct nfs_client *clp) -{ - if (clp->cl_session) - return 1; - return 0; -} - -static inline int nfs4_has_persistent_session(const struct nfs_client *clp) -{ - if (nfs4_has_session(clp)) - return (clp->cl_session->flags & SESSION4_PERSIST); - return 0; -} - -#else /* defined(CONFIG_NFS_V4_1) */ - -static inline int nfs4_init_session(struct nfs_server *server) -{ - return 0; -} - -/* - * Determine if sessions are in use. - */ -static inline int nfs4_has_session(const struct nfs_client *clp) -{ - return 0; -} - -static inline int nfs4_has_persistent_session(const struct nfs_client *clp) -{ - return 0; -} - -#endif /* defined(CONFIG_NFS_V4_1) */ -#endif /* IS_ENABLED(CONFIG_NFS_V4) */ -#endif /* __LINUX_FS_NFS_NFS4SESSION_H */ diff --git a/trunk/fs/nfs/nfs4state.c b/trunk/fs/nfs/nfs4state.c index 78e90a80fc3a..c351e6b39838 100644 --- a/trunk/fs/nfs/nfs4state.c +++ b/trunk/fs/nfs/nfs4state.c @@ -57,7 +57,6 @@ #include "callback.h" #include "delegation.h" #include "internal.h" -#include "nfs4session.h" #include "pnfs.h" #include "netns.h" @@ -255,27 +254,24 @@ static void nfs4_end_drain_session(struct nfs_client *clp) { struct nfs4_session *ses = clp->cl_session; struct nfs4_slot_table *tbl; + int max_slots; if (ses == NULL) return; tbl = &ses->fc_slot_table; if (test_and_clear_bit(NFS4_SESSION_DRAINING, &ses->session_state)) { spin_lock(&tbl->slot_tbl_lock); - nfs41_wake_slot_table(tbl); + max_slots = tbl->max_slots; + while (max_slots--) { + if (rpc_wake_up_first(&tbl->slot_tbl_waitq, + nfs4_set_task_privileged, + NULL) == NULL) + break; + } spin_unlock(&tbl->slot_tbl_lock); } } -/* - * Signal state manager thread if session fore channel is drained - */ -void nfs4_session_drain_complete(struct nfs4_session *session, - struct nfs4_slot_table *tbl) -{ - if (nfs4_session_draining(session)) - complete(&tbl->complete); -} - static int nfs4_wait_on_slot_tbl(struct nfs4_slot_table *tbl) { spin_lock(&tbl->slot_tbl_lock); @@ -307,6 +303,7 @@ static void nfs41_finish_session_reset(struct nfs_client *clp) clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); /* create_session negotiated new slot table */ + clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state); clear_bit(NFS4CLNT_BIND_CONN_TO_SESSION, &clp->cl_state); nfs41_setup_state_renewal(clp); } @@ -1089,6 +1086,7 @@ void nfs_free_seqid(struct nfs_seqid *seqid) */ static void nfs_increment_seqid(int status, struct nfs_seqid *seqid) { + BUG_ON(list_first_entry(&seqid->sequence->list, struct nfs_seqid, list) != seqid); switch (status) { case 0: break; @@ -1211,40 +1209,6 @@ void nfs4_schedule_lease_recovery(struct nfs_client *clp) } EXPORT_SYMBOL_GPL(nfs4_schedule_lease_recovery); -int nfs4_wait_clnt_recover(struct nfs_client *clp) -{ - int res; - - might_sleep(); - - res = wait_on_bit(&clp->cl_state, NFS4CLNT_MANAGER_RUNNING, - nfs_wait_bit_killable, TASK_KILLABLE); - if (res) - return res; - - if (clp->cl_cons_state < 0) - return clp->cl_cons_state; - return 0; -} - -int nfs4_client_recover_expired_lease(struct nfs_client *clp) -{ - unsigned int loop; - int ret; - - for (loop = NFS4_MAX_LOOP_ON_RECOVER; loop != 0; loop--) { - ret = nfs4_wait_clnt_recover(clp); - if (ret != 0) - break; - if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) && - !test_bit(NFS4CLNT_CHECK_LEASE,&clp->cl_state)) - break; - nfs4_schedule_state_manager(clp); - ret = -EIO; - } - return ret; -} - /* * nfs40_handle_cb_pathdown - return all delegations after NFS4ERR_CB_PATH_DOWN * @clp: client to process @@ -1943,23 +1907,14 @@ void nfs4_schedule_session_recovery(struct nfs4_session *session, int err) } EXPORT_SYMBOL_GPL(nfs4_schedule_session_recovery); -static void nfs41_ping_server(struct nfs_client *clp) +void nfs41_handle_recall_slot(struct nfs_client *clp) { - /* Use CHECK_LEASE to ping the server with a SEQUENCE */ - set_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state); + set_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state); + dprintk("%s: scheduling slot recall for server %s\n", __func__, + clp->cl_hostname); nfs4_schedule_state_manager(clp); } -void nfs41_server_notify_target_slotid_update(struct nfs_client *clp) -{ - nfs41_ping_server(clp); -} - -void nfs41_server_notify_highest_slotid_update(struct nfs_client *clp) -{ - nfs41_ping_server(clp); -} - static void nfs4_reset_all_state(struct nfs_client *clp) { if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) { @@ -2069,6 +2024,35 @@ static int nfs4_reset_session(struct nfs_client *clp) return status; } +static int nfs4_recall_slot(struct nfs_client *clp) +{ + struct nfs4_slot_table *fc_tbl; + struct nfs4_slot *new, *old; + int i; + + if (!nfs4_has_session(clp)) + return 0; + nfs4_begin_drain_session(clp); + fc_tbl = &clp->cl_session->fc_slot_table; + new = kmalloc(fc_tbl->target_max_slots * sizeof(struct nfs4_slot), + GFP_NOFS); + if (!new) + return -ENOMEM; + + spin_lock(&fc_tbl->slot_tbl_lock); + for (i = 0; i < fc_tbl->target_max_slots; i++) + new[i].seq_nr = fc_tbl->slots[i].seq_nr; + old = fc_tbl->slots; + fc_tbl->slots = new; + fc_tbl->max_slots = fc_tbl->target_max_slots; + fc_tbl->target_max_slots = 0; + clp->cl_session->fc_attrs.max_reqs = fc_tbl->max_slots; + spin_unlock(&fc_tbl->slot_tbl_lock); + + kfree(old); + return 0; +} + static int nfs4_bind_conn_to_session(struct nfs_client *clp) { struct rpc_cred *cred; @@ -2099,6 +2083,7 @@ static int nfs4_bind_conn_to_session(struct nfs_client *clp) #else /* CONFIG_NFS_V4_1 */ static int nfs4_reset_session(struct nfs_client *clp) { return 0; } static int nfs4_end_drain_session(struct nfs_client *clp) { return 0; } +static int nfs4_recall_slot(struct nfs_client *clp) { return 0; } static int nfs4_bind_conn_to_session(struct nfs_client *clp) { @@ -2130,6 +2115,15 @@ static void nfs4_state_manager(struct nfs_client *clp) continue; } + if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) { + section = "check lease"; + status = nfs4_check_lease(clp); + if (status < 0) + goto out_error; + if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) + continue; + } + /* Initialize or reset the session */ if (test_and_clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state)) { section = "reset session"; @@ -2150,9 +2144,10 @@ static void nfs4_state_manager(struct nfs_client *clp) continue; } - if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) { - section = "check lease"; - status = nfs4_check_lease(clp); + /* Recall session slots */ + if (test_and_clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state)) { + section = "recall slot"; + status = nfs4_recall_slot(clp); if (status < 0) goto out_error; continue; diff --git a/trunk/fs/nfs/nfs4xdr.c b/trunk/fs/nfs/nfs4xdr.c index e786dc7582b1..40836ee5dc3a 100644 --- a/trunk/fs/nfs/nfs4xdr.c +++ b/trunk/fs/nfs/nfs4xdr.c @@ -56,7 +56,6 @@ #include "nfs4_fs.h" #include "internal.h" -#include "nfs4session.h" #include "pnfs.h" #include "netns.h" @@ -937,7 +936,7 @@ static void encode_compound_hdr(struct xdr_stream *xdr, * but this is not required as a MUST for the server to do so. */ hdr->replen = RPC_REPHDRSIZE + auth->au_rslack + 3 + hdr->taglen; - WARN_ON_ONCE(hdr->taglen > NFS4_MAXTAGLEN); + BUG_ON(hdr->taglen > NFS4_MAXTAGLEN); encode_string(xdr, hdr->taglen, hdr->tag); p = reserve_space(xdr, 8); *p++ = cpu_to_be32(hdr->minorversion); @@ -956,7 +955,7 @@ static void encode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 op, static void encode_nops(struct compound_hdr *hdr) { - WARN_ON_ONCE(hdr->nops > NFS4_MAX_OPS); + BUG_ON(hdr->nops > NFS4_MAX_OPS); *hdr->nops_p = htonl(hdr->nops); } @@ -1404,6 +1403,7 @@ static void encode_opentype(struct xdr_stream *xdr, const struct nfs_openargs *a *p = cpu_to_be32(NFS4_OPEN_NOCREATE); break; default: + BUG_ON(arg->claim != NFS4_OPEN_CLAIM_NULL); *p = cpu_to_be32(NFS4_OPEN_CREATE); encode_createmode(xdr, arg); } @@ -1621,6 +1621,7 @@ encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg, struct compoun p = reserve_space(xdr, 2*4); *p++ = cpu_to_be32(1); *p = cpu_to_be32(FATTR4_WORD0_ACL); + BUG_ON(arg->acl_len % 4); p = reserve_space(xdr, 4); *p = cpu_to_be32(arg->acl_len); xdr_write_pages(xdr, arg->acl_pages, arg->acl_pgbase, arg->acl_len); @@ -1834,16 +1835,18 @@ static void encode_sequence(struct xdr_stream *xdr, struct compound_hdr *hdr) { #if defined(CONFIG_NFS_V4_1) - struct nfs4_session *session; + struct nfs4_session *session = args->sa_session; struct nfs4_slot_table *tp; - struct nfs4_slot *slot = args->sa_slot; + struct nfs4_slot *slot; __be32 *p; - if (slot == NULL) + if (!session) return; - tp = slot->table; - session = tp->session; + tp = &session->fc_slot_table; + + WARN_ON(args->sa_slotid == NFS4_MAX_SLOT_TABLE); + slot = tp->slots + args->sa_slotid; encode_op_hdr(xdr, OP_SEQUENCE, decode_sequence_maxsz, hdr); @@ -1857,12 +1860,12 @@ static void encode_sequence(struct xdr_stream *xdr, ((u32 *)session->sess_id.data)[1], ((u32 *)session->sess_id.data)[2], ((u32 *)session->sess_id.data)[3], - slot->seq_nr, slot->slot_nr, + slot->seq_nr, args->sa_slotid, tp->highest_used_slotid, args->sa_cache_this); p = reserve_space(xdr, NFS4_MAX_SESSIONID_LEN + 16); p = xdr_encode_opaque_fixed(p, session->sess_id.data, NFS4_MAX_SESSIONID_LEN); *p++ = cpu_to_be32(slot->seq_nr); - *p++ = cpu_to_be32(slot->slot_nr); + *p++ = cpu_to_be32(args->sa_slotid); *p++ = cpu_to_be32(tp->highest_used_slotid); *p = cpu_to_be32(args->sa_cache_this); #endif /* CONFIG_NFS_V4_1 */ @@ -2024,9 +2027,8 @@ static void encode_free_stateid(struct xdr_stream *xdr, static u32 nfs4_xdr_minorversion(const struct nfs4_sequence_args *args) { #if defined(CONFIG_NFS_V4_1) - - if (args->sa_slot) - return args->sa_slot->table->session->clp->cl_mvops->minor_version; + if (args->sa_session) + return args->sa_session->clp->cl_mvops->minor_version; #endif /* CONFIG_NFS_V4_1 */ return 0; } @@ -5507,13 +5509,12 @@ static int decode_sequence(struct xdr_stream *xdr, struct rpc_rqst *rqstp) { #if defined(CONFIG_NFS_V4_1) - struct nfs4_session *session; struct nfs4_sessionid id; u32 dummy; int status; __be32 *p; - if (res->sr_slot == NULL) + if (!res->sr_session) return 0; status = decode_op_hdr(xdr, OP_SEQUENCE); @@ -5527,9 +5528,8 @@ static int decode_sequence(struct xdr_stream *xdr, * sequence number, the server is looney tunes. */ status = -EREMOTEIO; - session = res->sr_slot->table->session; - if (memcmp(id.data, session->sess_id.data, + if (memcmp(id.data, res->sr_session->sess_id.data, NFS4_MAX_SESSIONID_LEN)) { dprintk("%s Invalid session id\n", __func__); goto out_err; @@ -5547,14 +5547,14 @@ static int decode_sequence(struct xdr_stream *xdr, } /* slot id */ dummy = be32_to_cpup(p++); - if (dummy != res->sr_slot->slot_nr) { + if (dummy != res->sr_slot - res->sr_session->fc_slot_table.slots) { dprintk("%s Invalid slot id\n", __func__); goto out_err; } - /* highest slot id */ - res->sr_highest_slotid = be32_to_cpup(p++); - /* target highest slot id */ - res->sr_target_highest_slotid = be32_to_cpup(p++); + /* highest slot id - currently not processed */ + dummy = be32_to_cpup(p++); + /* target highest slot id - currently not processed */ + dummy = be32_to_cpup(p++); /* result flags */ res->sr_status_flags = be32_to_cpup(p); status = 0; diff --git a/trunk/fs/nfs/objlayout/objlayout.c b/trunk/fs/nfs/objlayout/objlayout.c index a9ebd817278b..874613545301 100644 --- a/trunk/fs/nfs/objlayout/objlayout.c +++ b/trunk/fs/nfs/objlayout/objlayout.c @@ -148,6 +148,17 @@ end_offset(u64 start, u64 len) return end >= start ? end : NFS4_MAX_UINT64; } +/* last octet in a range */ +static inline u64 +last_byte_offset(u64 start, u64 len) +{ + u64 end; + + BUG_ON(!len); + end = start + len; + return end > start ? end - 1 : NFS4_MAX_UINT64; +} + static void _fix_verify_io_params(struct pnfs_layout_segment *lseg, struct page ***p_pages, unsigned *p_pgbase, u64 offset, unsigned long count) diff --git a/trunk/fs/nfs/pnfs.c b/trunk/fs/nfs/pnfs.c index e7165d915362..2878f97bd78d 100644 --- a/trunk/fs/nfs/pnfs.c +++ b/trunk/fs/nfs/pnfs.c @@ -369,6 +369,17 @@ end_offset(u64 start, u64 len) return end >= start ? end : NFS4_MAX_UINT64; } +/* last octet in a range */ +static inline u64 +last_byte_offset(u64 start, u64 len) +{ + u64 end; + + BUG_ON(!len); + end = start + len; + return end > start ? end - 1 : NFS4_MAX_UINT64; +} + /* * is l2 fully contained in l1? * start1 end1 @@ -634,6 +645,7 @@ send_layoutget(struct pnfs_layout_hdr *lo, dprintk("--> %s\n", __func__); + BUG_ON(ctx == NULL); lgp = kzalloc(sizeof(*lgp), gfp_flags); if (lgp == NULL) return NULL; @@ -1114,6 +1126,7 @@ pnfs_update_layout(struct inode *ino, * chance of a CB_LAYOUTRECALL(FILE) coming in. */ spin_lock(&clp->cl_lock); + BUG_ON(!list_empty(&lo->plh_layouts)); list_add_tail(&lo->plh_layouts, &server->layouts); spin_unlock(&clp->cl_lock); } @@ -1209,7 +1222,7 @@ pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *r { u64 rd_size = req->wb_bytes; - WARN_ON_ONCE(pgio->pg_lseg != NULL); + BUG_ON(pgio->pg_lseg != NULL); if (req->wb_offset != req->wb_pgbase) { nfs_pageio_reset_read_mds(pgio); @@ -1238,7 +1251,7 @@ void pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req, u64 wb_size) { - WARN_ON_ONCE(pgio->pg_lseg != NULL); + BUG_ON(pgio->pg_lseg != NULL); if (req->wb_offset != req->wb_pgbase) { nfs_pageio_reset_write_mds(pgio); diff --git a/trunk/fs/nfs/super.c b/trunk/fs/nfs/super.c index e12cea4b36a5..652d3f7176a9 100644 --- a/trunk/fs/nfs/super.c +++ b/trunk/fs/nfs/super.c @@ -64,7 +64,6 @@ #include "iostat.h" #include "internal.h" #include "fscache.h" -#include "nfs4session.h" #include "pnfs.h" #include "nfs.h" diff --git a/trunk/fs/nfs/write.c b/trunk/fs/nfs/write.c index f5bc8e11713b..9347ab7c9574 100644 --- a/trunk/fs/nfs/write.c +++ b/trunk/fs/nfs/write.c @@ -239,18 +239,21 @@ int nfs_congestion_kb; #define NFS_CONGESTION_OFF_THRESH \ (NFS_CONGESTION_ON_THRESH - (NFS_CONGESTION_ON_THRESH >> 2)) -static void nfs_set_page_writeback(struct page *page) +static int nfs_set_page_writeback(struct page *page) { - struct nfs_server *nfss = NFS_SERVER(page_file_mapping(page)->host); int ret = test_set_page_writeback(page); - WARN_ON_ONCE(ret != 0); + if (!ret) { + struct inode *inode = page_file_mapping(page)->host; + struct nfs_server *nfss = NFS_SERVER(inode); - if (atomic_long_inc_return(&nfss->writeback) > - NFS_CONGESTION_ON_THRESH) { - set_bdi_congested(&nfss->backing_dev_info, - BLK_RW_ASYNC); + if (atomic_long_inc_return(&nfss->writeback) > + NFS_CONGESTION_ON_THRESH) { + set_bdi_congested(&nfss->backing_dev_info, + BLK_RW_ASYNC); + } } + return ret; } static void nfs_end_page_writeback(struct page *page) @@ -312,10 +315,10 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, if (IS_ERR(req)) goto out; - nfs_set_page_writeback(page); - WARN_ON_ONCE(test_bit(PG_CLEAN, &req->wb_flags)); + ret = nfs_set_page_writeback(page); + BUG_ON(ret != 0); + BUG_ON(test_bit(PG_CLEAN, &req->wb_flags)); - ret = 0; if (!nfs_pageio_add_request(pgio, req)) { nfs_redirty_request(req); ret = pgio->pg_error; @@ -448,6 +451,8 @@ static void nfs_inode_remove_request(struct nfs_page *req) struct inode *inode = req->wb_context->dentry->d_inode; struct nfs_inode *nfsi = NFS_I(inode); + BUG_ON (!NFS_WBACK_BUSY(req)); + spin_lock(&inode->i_lock); if (likely(!PageSwapCache(req->wb_page))) { set_page_private(req->wb_page, 0); @@ -1722,6 +1727,7 @@ int nfs_wb_page_cancel(struct inode *inode, struct page *page) struct nfs_page *req; int ret = 0; + BUG_ON(!PageLocked(page)); for (;;) { wait_on_page_writeback(page); req = nfs_page_find_request(page); diff --git a/trunk/include/linux/nfs_fs_sb.h b/trunk/include/linux/nfs_fs_sb.h index 6c6ed153a9b4..a9e76ee1adca 100644 --- a/trunk/include/linux/nfs_fs_sb.h +++ b/trunk/include/linux/nfs_fs_sb.h @@ -198,4 +198,51 @@ struct nfs_server { #define NFS_CAP_POSIX_LOCK (1U << 14) #define NFS_CAP_UIDGID_NOMAP (1U << 15) + +/* maximum number of slots to use */ +#define NFS4_DEF_SLOT_TABLE_SIZE (16U) +#define NFS4_MAX_SLOT_TABLE (256U) +#define NFS4_NO_SLOT ((u32)-1) + +#if IS_ENABLED(CONFIG_NFS_V4) + +/* Sessions */ +#define SLOT_TABLE_SZ DIV_ROUND_UP(NFS4_MAX_SLOT_TABLE, 8*sizeof(long)) +struct nfs4_slot_table { + struct nfs4_slot *slots; /* seqid per slot */ + unsigned long used_slots[SLOT_TABLE_SZ]; /* used/unused bitmap */ + spinlock_t slot_tbl_lock; + struct rpc_wait_queue slot_tbl_waitq; /* allocators may wait here */ + u32 max_slots; /* # slots in table */ + u32 highest_used_slotid; /* sent to server on each SEQ. + * op for dynamic resizing */ + u32 target_max_slots; /* Set by CB_RECALL_SLOT as + * the new max_slots */ + struct completion complete; +}; + +static inline int slot_idx(struct nfs4_slot_table *tbl, struct nfs4_slot *sp) +{ + return sp - tbl->slots; +} + +/* + * Session related parameters + */ +struct nfs4_session { + struct nfs4_sessionid sess_id; + u32 flags; + unsigned long session_state; + u32 hash_alg; + u32 ssv_len; + + /* The fore and back channel */ + struct nfs4_channel_attrs fc_attrs; + struct nfs4_slot_table fc_slot_table; + struct nfs4_channel_attrs bc_attrs; + struct nfs4_slot_table bc_slot_table; + struct nfs_client *clp; +}; + +#endif /* CONFIG_NFS_V4 */ #endif diff --git a/trunk/include/linux/nfs_xdr.h b/trunk/include/linux/nfs_xdr.h index a55abd499c21..a73ea89789d1 100644 --- a/trunk/include/linux/nfs_xdr.h +++ b/trunk/include/linux/nfs_xdr.h @@ -185,19 +185,23 @@ struct nfs4_channel_attrs { u32 max_reqs; }; -struct nfs4_slot; +/* nfs41 sessions slot seqid */ +struct nfs4_slot { + u32 seq_nr; +}; + struct nfs4_sequence_args { - struct nfs4_slot *sa_slot; - u8 sa_cache_this : 1, - sa_privileged : 1; + struct nfs4_session *sa_session; + u32 sa_slotid; + u8 sa_cache_this; }; struct nfs4_sequence_res { + struct nfs4_session *sr_session; struct nfs4_slot *sr_slot; /* slot used to send request */ int sr_status; /* sequence operation status */ + unsigned long sr_renewal_time; u32 sr_status_flags; - u32 sr_highest_slotid; - u32 sr_target_highest_slotid; }; struct nfs4_get_lease_time_args { @@ -205,8 +209,8 @@ struct nfs4_get_lease_time_args { }; struct nfs4_get_lease_time_res { - struct nfs4_sequence_res lr_seq_res; struct nfs_fsinfo *lr_fsinfo; + struct nfs4_sequence_res lr_seq_res; }; #define PNFS_LAYOUT_MAXSIZE 4096 @@ -224,23 +228,23 @@ struct pnfs_layout_range { }; struct nfs4_layoutget_args { - struct nfs4_sequence_args seq_args; __u32 type; struct pnfs_layout_range range; __u64 minlength; __u32 maxcount; struct inode *inode; struct nfs_open_context *ctx; + struct nfs4_sequence_args seq_args; nfs4_stateid stateid; struct nfs4_layoutdriver_data layout; }; struct nfs4_layoutget_res { - struct nfs4_sequence_res seq_res; __u32 return_on_close; struct pnfs_layout_range range; __u32 type; nfs4_stateid stateid; + struct nfs4_sequence_res seq_res; struct nfs4_layoutdriver_data *layoutp; }; @@ -251,38 +255,38 @@ struct nfs4_layoutget { }; struct nfs4_getdevicelist_args { - struct nfs4_sequence_args seq_args; const struct nfs_fh *fh; u32 layoutclass; + struct nfs4_sequence_args seq_args; }; struct nfs4_getdevicelist_res { - struct nfs4_sequence_res seq_res; struct pnfs_devicelist *devlist; + struct nfs4_sequence_res seq_res; }; struct nfs4_getdeviceinfo_args { - struct nfs4_sequence_args seq_args; struct pnfs_device *pdev; + struct nfs4_sequence_args seq_args; }; struct nfs4_getdeviceinfo_res { - struct nfs4_sequence_res seq_res; struct pnfs_device *pdev; + struct nfs4_sequence_res seq_res; }; struct nfs4_layoutcommit_args { - struct nfs4_sequence_args seq_args; nfs4_stateid stateid; __u64 lastbytewritten; struct inode *inode; const u32 *bitmask; + struct nfs4_sequence_args seq_args; }; struct nfs4_layoutcommit_res { - struct nfs4_sequence_res seq_res; struct nfs_fattr *fattr; const struct nfs_server *server; + struct nfs4_sequence_res seq_res; int status; }; @@ -296,11 +300,11 @@ struct nfs4_layoutcommit_data { }; struct nfs4_layoutreturn_args { - struct nfs4_sequence_args seq_args; struct pnfs_layout_hdr *layout; struct inode *inode; nfs4_stateid stateid; __u32 layout_type; + struct nfs4_sequence_args seq_args; }; struct nfs4_layoutreturn_res { @@ -326,7 +330,6 @@ struct stateowner_id { * Arguments to the open call. */ struct nfs_openargs { - struct nfs4_sequence_args seq_args; const struct nfs_fh * fh; struct nfs_seqid * seqid; int open_flags; @@ -347,10 +350,10 @@ struct nfs_openargs { const u32 * bitmask; const u32 * open_bitmap; __u32 claim; + struct nfs4_sequence_args seq_args; }; struct nfs_openres { - struct nfs4_sequence_res seq_res; nfs4_stateid stateid; struct nfs_fh fh; struct nfs4_change_info cinfo; @@ -365,6 +368,7 @@ struct nfs_openres { __u32 attrset[NFS4_BITMAP_SIZE]; struct nfs4_string *owner; struct nfs4_string *group_owner; + struct nfs4_sequence_res seq_res; __u32 access_request; __u32 access_supported; __u32 access_result; @@ -388,20 +392,20 @@ struct nfs_open_confirmres { * Arguments to the close call. */ struct nfs_closeargs { - struct nfs4_sequence_args seq_args; struct nfs_fh * fh; nfs4_stateid * stateid; struct nfs_seqid * seqid; fmode_t fmode; const u32 * bitmask; + struct nfs4_sequence_args seq_args; }; struct nfs_closeres { - struct nfs4_sequence_res seq_res; nfs4_stateid stateid; struct nfs_fattr * fattr; struct nfs_seqid * seqid; const struct nfs_server *server; + struct nfs4_sequence_res seq_res; }; /* * * Arguments to the lock,lockt, and locku call. @@ -413,7 +417,6 @@ struct nfs_lowner { }; struct nfs_lock_args { - struct nfs4_sequence_args seq_args; struct nfs_fh * fh; struct file_lock * fl; struct nfs_seqid * lock_seqid; @@ -424,39 +427,40 @@ struct nfs_lock_args { unsigned char block : 1; unsigned char reclaim : 1; unsigned char new_lock_owner : 1; + struct nfs4_sequence_args seq_args; }; struct nfs_lock_res { - struct nfs4_sequence_res seq_res; nfs4_stateid stateid; struct nfs_seqid * lock_seqid; struct nfs_seqid * open_seqid; + struct nfs4_sequence_res seq_res; }; struct nfs_locku_args { - struct nfs4_sequence_args seq_args; struct nfs_fh * fh; struct file_lock * fl; struct nfs_seqid * seqid; nfs4_stateid * stateid; + struct nfs4_sequence_args seq_args; }; struct nfs_locku_res { - struct nfs4_sequence_res seq_res; nfs4_stateid stateid; struct nfs_seqid * seqid; + struct nfs4_sequence_res seq_res; }; struct nfs_lockt_args { - struct nfs4_sequence_args seq_args; struct nfs_fh * fh; struct file_lock * fl; struct nfs_lowner lock_owner; + struct nfs4_sequence_args seq_args; }; struct nfs_lockt_res { - struct nfs4_sequence_res seq_res; struct file_lock * denied; /* LOCK, LOCKT failed */ + struct nfs4_sequence_res seq_res; }; struct nfs_release_lockowner_args { @@ -464,23 +468,22 @@ struct nfs_release_lockowner_args { }; struct nfs4_delegreturnargs { - struct nfs4_sequence_args seq_args; const struct nfs_fh *fhandle; const nfs4_stateid *stateid; const u32 * bitmask; + struct nfs4_sequence_args seq_args; }; struct nfs4_delegreturnres { - struct nfs4_sequence_res seq_res; struct nfs_fattr * fattr; const struct nfs_server *server; + struct nfs4_sequence_res seq_res; }; /* * Arguments to the read call. */ struct nfs_readargs { - struct nfs4_sequence_args seq_args; struct nfs_fh * fh; struct nfs_open_context *context; struct nfs_lock_context *lock_context; @@ -488,20 +491,20 @@ struct nfs_readargs { __u32 count; unsigned int pgbase; struct page ** pages; + struct nfs4_sequence_args seq_args; }; struct nfs_readres { - struct nfs4_sequence_res seq_res; struct nfs_fattr * fattr; __u32 count; int eof; + struct nfs4_sequence_res seq_res; }; /* * Arguments to the write call. */ struct nfs_writeargs { - struct nfs4_sequence_args seq_args; struct nfs_fh * fh; struct nfs_open_context *context; struct nfs_lock_context *lock_context; @@ -511,6 +514,7 @@ struct nfs_writeargs { unsigned int pgbase; struct page ** pages; const u32 * bitmask; + struct nfs4_sequence_args seq_args; }; struct nfs_write_verifier { @@ -523,65 +527,65 @@ struct nfs_writeverf { }; struct nfs_writeres { - struct nfs4_sequence_res seq_res; struct nfs_fattr * fattr; struct nfs_writeverf * verf; __u32 count; const struct nfs_server *server; + struct nfs4_sequence_res seq_res; }; /* * Arguments to the commit call. */ struct nfs_commitargs { - struct nfs4_sequence_args seq_args; struct nfs_fh *fh; __u64 offset; __u32 count; const u32 *bitmask; + struct nfs4_sequence_args seq_args; }; struct nfs_commitres { - struct nfs4_sequence_res seq_res; struct nfs_fattr *fattr; struct nfs_writeverf *verf; const struct nfs_server *server; + struct nfs4_sequence_res seq_res; }; /* * Common arguments to the unlink call */ struct nfs_removeargs { - struct nfs4_sequence_args seq_args; const struct nfs_fh *fh; struct qstr name; + struct nfs4_sequence_args seq_args; }; struct nfs_removeres { - struct nfs4_sequence_res seq_res; const struct nfs_server *server; struct nfs_fattr *dir_attr; struct nfs4_change_info cinfo; + struct nfs4_sequence_res seq_res; }; /* * Common arguments to the rename call */ struct nfs_renameargs { - struct nfs4_sequence_args seq_args; const struct nfs_fh *old_dir; const struct nfs_fh *new_dir; const struct qstr *old_name; const struct qstr *new_name; + struct nfs4_sequence_args seq_args; }; struct nfs_renameres { - struct nfs4_sequence_res seq_res; const struct nfs_server *server; struct nfs4_change_info old_cinfo; struct nfs_fattr *old_fattr; struct nfs4_change_info new_cinfo; struct nfs_fattr *new_fattr; + struct nfs4_sequence_res seq_res; }; /* @@ -622,20 +626,20 @@ struct nfs_createargs { }; struct nfs_setattrargs { - struct nfs4_sequence_args seq_args; struct nfs_fh * fh; nfs4_stateid stateid; struct iattr * iap; const struct nfs_server * server; /* Needed for name mapping */ const u32 * bitmask; + struct nfs4_sequence_args seq_args; }; struct nfs_setaclargs { - struct nfs4_sequence_args seq_args; struct nfs_fh * fh; size_t acl_len; unsigned int acl_pgbase; struct page ** acl_pages; + struct nfs4_sequence_args seq_args; }; struct nfs_setaclres { @@ -643,27 +647,27 @@ struct nfs_setaclres { }; struct nfs_getaclargs { - struct nfs4_sequence_args seq_args; struct nfs_fh * fh; size_t acl_len; unsigned int acl_pgbase; struct page ** acl_pages; + struct nfs4_sequence_args seq_args; }; /* getxattr ACL interface flags */ #define NFS4_ACL_TRUNC 0x0001 /* ACL was truncated */ struct nfs_getaclres { - struct nfs4_sequence_res seq_res; size_t acl_len; size_t acl_data_offset; int acl_flags; struct page * acl_scratch; + struct nfs4_sequence_res seq_res; }; struct nfs_setattrres { - struct nfs4_sequence_res seq_res; struct nfs_fattr * fattr; const struct nfs_server * server; + struct nfs4_sequence_res seq_res; }; struct nfs_linkargs { @@ -828,22 +832,21 @@ struct nfs3_getaclres { typedef u64 clientid4; struct nfs4_accessargs { - struct nfs4_sequence_args seq_args; const struct nfs_fh * fh; const u32 * bitmask; u32 access; + struct nfs4_sequence_args seq_args; }; struct nfs4_accessres { - struct nfs4_sequence_res seq_res; const struct nfs_server * server; struct nfs_fattr * fattr; u32 supported; u32 access; + struct nfs4_sequence_res seq_res; }; struct nfs4_create_arg { - struct nfs4_sequence_args seq_args; u32 ftype; union { struct { @@ -860,88 +863,88 @@ struct nfs4_create_arg { const struct iattr * attrs; const struct nfs_fh * dir_fh; const u32 * bitmask; + struct nfs4_sequence_args seq_args; }; struct nfs4_create_res { - struct nfs4_sequence_res seq_res; const struct nfs_server * server; struct nfs_fh * fh; struct nfs_fattr * fattr; struct nfs4_change_info dir_cinfo; + struct nfs4_sequence_res seq_res; }; struct nfs4_fsinfo_arg { - struct nfs4_sequence_args seq_args; const struct nfs_fh * fh; const u32 * bitmask; + struct nfs4_sequence_args seq_args; }; struct nfs4_fsinfo_res { - struct nfs4_sequence_res seq_res; struct nfs_fsinfo *fsinfo; + struct nfs4_sequence_res seq_res; }; struct nfs4_getattr_arg { - struct nfs4_sequence_args seq_args; const struct nfs_fh * fh; const u32 * bitmask; + struct nfs4_sequence_args seq_args; }; struct nfs4_getattr_res { - struct nfs4_sequence_res seq_res; const struct nfs_server * server; struct nfs_fattr * fattr; + struct nfs4_sequence_res seq_res; }; struct nfs4_link_arg { - struct nfs4_sequence_args seq_args; const struct nfs_fh * fh; const struct nfs_fh * dir_fh; const struct qstr * name; const u32 * bitmask; + struct nfs4_sequence_args seq_args; }; struct nfs4_link_res { - struct nfs4_sequence_res seq_res; const struct nfs_server * server; struct nfs_fattr * fattr; struct nfs4_change_info cinfo; struct nfs_fattr * dir_attr; + struct nfs4_sequence_res seq_res; }; struct nfs4_lookup_arg { - struct nfs4_sequence_args seq_args; const struct nfs_fh * dir_fh; const struct qstr * name; const u32 * bitmask; + struct nfs4_sequence_args seq_args; }; struct nfs4_lookup_res { - struct nfs4_sequence_res seq_res; const struct nfs_server * server; struct nfs_fattr * fattr; struct nfs_fh * fh; + struct nfs4_sequence_res seq_res; }; struct nfs4_lookup_root_arg { - struct nfs4_sequence_args seq_args; const u32 * bitmask; + struct nfs4_sequence_args seq_args; }; struct nfs4_pathconf_arg { - struct nfs4_sequence_args seq_args; const struct nfs_fh * fh; const u32 * bitmask; + struct nfs4_sequence_args seq_args; }; struct nfs4_pathconf_res { - struct nfs4_sequence_res seq_res; struct nfs_pathconf *pathconf; + struct nfs4_sequence_res seq_res; }; struct nfs4_readdir_arg { - struct nfs4_sequence_args seq_args; const struct nfs_fh * fh; u64 cookie; nfs4_verifier verifier; @@ -950,20 +953,21 @@ struct nfs4_readdir_arg { unsigned int pgbase; /* zero-copy data */ const u32 * bitmask; int plus; + struct nfs4_sequence_args seq_args; }; struct nfs4_readdir_res { - struct nfs4_sequence_res seq_res; nfs4_verifier verifier; unsigned int pgbase; + struct nfs4_sequence_res seq_res; }; struct nfs4_readlink { - struct nfs4_sequence_args seq_args; const struct nfs_fh * fh; unsigned int pgbase; unsigned int pglen; /* zero-copy data */ struct page ** pages; /* zero-copy data */ + struct nfs4_sequence_args seq_args; }; struct nfs4_readlink_res { @@ -989,28 +993,28 @@ struct nfs4_setclientid_res { }; struct nfs4_statfs_arg { - struct nfs4_sequence_args seq_args; const struct nfs_fh * fh; const u32 * bitmask; + struct nfs4_sequence_args seq_args; }; struct nfs4_statfs_res { - struct nfs4_sequence_res seq_res; struct nfs_fsstat *fsstat; + struct nfs4_sequence_res seq_res; }; struct nfs4_server_caps_arg { - struct nfs4_sequence_args seq_args; struct nfs_fh *fhandle; + struct nfs4_sequence_args seq_args; }; struct nfs4_server_caps_res { - struct nfs4_sequence_res seq_res; u32 attr_bitmask[3]; u32 acl_bitmask; u32 has_links; u32 has_symlinks; u32 fh_expire_type; + struct nfs4_sequence_res seq_res; }; #define NFS4_PATHNAME_MAXCOMPONENTS 512 @@ -1036,16 +1040,16 @@ struct nfs4_fs_locations { }; struct nfs4_fs_locations_arg { - struct nfs4_sequence_args seq_args; const struct nfs_fh *dir_fh; const struct qstr *name; struct page *page; const u32 *bitmask; + struct nfs4_sequence_args seq_args; }; struct nfs4_fs_locations_res { - struct nfs4_sequence_res seq_res; struct nfs4_fs_locations *fs_locations; + struct nfs4_sequence_res seq_res; }; struct nfs4_secinfo_oid { @@ -1070,14 +1074,14 @@ struct nfs4_secinfo_flavors { }; struct nfs4_secinfo_arg { - struct nfs4_sequence_args seq_args; const struct nfs_fh *dir_fh; const struct qstr *name; + struct nfs4_sequence_args seq_args; }; struct nfs4_secinfo_res { - struct nfs4_sequence_res seq_res; struct nfs4_secinfo_flavors *flavors; + struct nfs4_sequence_res seq_res; }; #endif /* CONFIG_NFS_V4 */ @@ -1157,9 +1161,9 @@ struct nfs41_create_session_res { }; struct nfs41_reclaim_complete_args { - struct nfs4_sequence_args seq_args; /* In the future extend to include curr_fh for use with migration */ unsigned char one_fs:1; + struct nfs4_sequence_args seq_args; }; struct nfs41_reclaim_complete_res { @@ -1169,28 +1173,28 @@ struct nfs41_reclaim_complete_res { #define SECINFO_STYLE_CURRENT_FH 0 #define SECINFO_STYLE_PARENT 1 struct nfs41_secinfo_no_name_args { - struct nfs4_sequence_args seq_args; int style; + struct nfs4_sequence_args seq_args; }; struct nfs41_test_stateid_args { - struct nfs4_sequence_args seq_args; nfs4_stateid *stateid; + struct nfs4_sequence_args seq_args; }; struct nfs41_test_stateid_res { - struct nfs4_sequence_res seq_res; unsigned int status; + struct nfs4_sequence_res seq_res; }; struct nfs41_free_stateid_args { - struct nfs4_sequence_args seq_args; nfs4_stateid *stateid; + struct nfs4_sequence_args seq_args; }; struct nfs41_free_stateid_res { - struct nfs4_sequence_res seq_res; unsigned int status; + struct nfs4_sequence_res seq_res; }; #else diff --git a/trunk/include/linux/sunrpc/sched.h b/trunk/include/linux/sunrpc/sched.h index b64f8eb0b973..dc0c3cc3ada3 100644 --- a/trunk/include/linux/sunrpc/sched.h +++ b/trunk/include/linux/sunrpc/sched.h @@ -192,6 +192,7 @@ struct rpc_wait_queue { pid_t owner; /* process id of last task serviced */ unsigned char maxpriority; /* maximum priority (0 if queue is not a priority queue) */ unsigned char priority; /* current priority */ + unsigned char count; /* # task groups remaining serviced so far */ unsigned char nr; /* # tasks remaining for cookie */ unsigned short qlen; /* total # tasks waiting in queue */ struct rpc_timer timer_list; diff --git a/trunk/net/sunrpc/backchannel_rqst.c b/trunk/net/sunrpc/backchannel_rqst.c index 890a29912d5a..a9c0bbccad6b 100644 --- a/trunk/net/sunrpc/backchannel_rqst.c +++ b/trunk/net/sunrpc/backchannel_rqst.c @@ -59,7 +59,7 @@ static void xprt_free_allocation(struct rpc_rqst *req) struct xdr_buf *xbufp; dprintk("RPC: free allocations for req= %p\n", req); - WARN_ON_ONCE(test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state)); + BUG_ON(test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state)); xbufp = &req->rq_private_buf; free_page((unsigned long)xbufp->head[0].iov_base); xbufp = &req->rq_snd_buf; @@ -191,9 +191,7 @@ void xprt_destroy_backchannel(struct rpc_xprt *xprt, unsigned int max_reqs) dprintk("RPC: destroy backchannel transport\n"); - if (max_reqs == 0) - goto out; - + BUG_ON(max_reqs == 0); spin_lock_bh(&xprt->bc_pa_lock); xprt_dec_alloc_count(xprt, max_reqs); list_for_each_entry_safe(req, tmp, &xprt->bc_pa_list, rq_bc_pa_list) { @@ -204,7 +202,6 @@ void xprt_destroy_backchannel(struct rpc_xprt *xprt, unsigned int max_reqs) } spin_unlock_bh(&xprt->bc_pa_lock); -out: dprintk("RPC: backchannel list empty= %s\n", list_empty(&xprt->bc_pa_list) ? "true" : "false"); } @@ -258,7 +255,7 @@ void xprt_free_bc_request(struct rpc_rqst *req) dprintk("RPC: free backchannel req=%p\n", req); smp_mb__before_clear_bit(); - WARN_ON_ONCE(!test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state)); + BUG_ON(!test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state)); clear_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state); smp_mb__after_clear_bit(); diff --git a/trunk/net/sunrpc/bc_svc.c b/trunk/net/sunrpc/bc_svc.c index 15c7a8a1c24f..0b2eb388cbda 100644 --- a/trunk/net/sunrpc/bc_svc.c +++ b/trunk/net/sunrpc/bc_svc.c @@ -53,7 +53,7 @@ int bc_send(struct rpc_rqst *req) if (IS_ERR(task)) ret = PTR_ERR(task); else { - WARN_ON_ONCE(atomic_read(&task->tk_count) != 1); + BUG_ON(atomic_read(&task->tk_count) != 1); ret = task->tk_status; rpc_put_task(task); } diff --git a/trunk/net/sunrpc/cache.c b/trunk/net/sunrpc/cache.c index 9afa4393c217..fc2f7aa4dca7 100644 --- a/trunk/net/sunrpc/cache.c +++ b/trunk/net/sunrpc/cache.c @@ -775,11 +775,11 @@ static ssize_t cache_read(struct file *filp, char __user *buf, size_t count, if (rp->q.list.next == &cd->queue) { spin_unlock(&queue_lock); mutex_unlock(&inode->i_mutex); - WARN_ON_ONCE(rp->offset); + BUG_ON(rp->offset); return 0; } rq = container_of(rp->q.list.next, struct cache_request, q.list); - WARN_ON_ONCE(rq->q.reader); + BUG_ON(rq->q.reader); if (rp->offset == 0) rq->readers++; spin_unlock(&queue_lock); diff --git a/trunk/net/sunrpc/clnt.c b/trunk/net/sunrpc/clnt.c index c69e199b1082..cdc7564b4512 100644 --- a/trunk/net/sunrpc/clnt.c +++ b/trunk/net/sunrpc/clnt.c @@ -132,10 +132,8 @@ static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb, int error; dir = rpc_d_lookup_sb(sb, dir_name); - if (dir == NULL) { - pr_info("RPC: pipefs directory doesn't exist: %s\n", dir_name); + if (dir == NULL) return dir; - } for (;;) { q.len = snprintf(name, sizeof(name), "clnt%x", (unsigned int)clntid++); name[sizeof(name) - 1] = '\0'; @@ -194,8 +192,7 @@ static int __rpc_clnt_handle_event(struct rpc_clnt *clnt, unsigned long event, case RPC_PIPEFS_MOUNT: dentry = rpc_setup_pipedir_sb(sb, clnt, clnt->cl_program->pipe_dir_name); - if (!dentry) - return -ENOENT; + BUG_ON(dentry == NULL); if (IS_ERR(dentry)) return PTR_ERR(dentry); clnt->cl_dentry = dentry; @@ -610,13 +607,6 @@ EXPORT_SYMBOL_GPL(rpc_killall_tasks); */ void rpc_shutdown_client(struct rpc_clnt *clnt) { - /* - * To avoid deadlock, never call rpc_shutdown_client from a - * workqueue context! - */ - WARN_ON_ONCE(current->flags & PF_WQ_WORKER); - might_sleep(); - dprintk_rcu("RPC: shutting down %s client for %s\n", clnt->cl_protname, rcu_dereference(clnt->cl_xprt)->servername); @@ -703,19 +693,21 @@ struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old, const struct rpc_program *program, u32 vers) { - struct rpc_create_args args = { - .program = program, - .prognumber = program->number, - .version = vers, - .authflavor = old->cl_auth->au_flavor, - .client_name = old->cl_principal, - }; struct rpc_clnt *clnt; + const struct rpc_version *version; int err; - clnt = __rpc_clone_client(&args, old); + BUG_ON(vers >= program->nrvers || !program->version[vers]); + version = program->version[vers]; + clnt = rpc_clone_client(old); if (IS_ERR(clnt)) goto out; + clnt->cl_procinfo = version->procs; + clnt->cl_maxproc = version->nrprocs; + clnt->cl_protname = program->name; + clnt->cl_prog = program->number; + clnt->cl_vers = version->number; + clnt->cl_stats = program->stats; err = rpc_ping(clnt); if (err != 0) { rpc_shutdown_client(clnt); @@ -840,12 +832,7 @@ int rpc_call_sync(struct rpc_clnt *clnt, const struct rpc_message *msg, int flag }; int status; - WARN_ON_ONCE(flags & RPC_TASK_ASYNC); - if (flags & RPC_TASK_ASYNC) { - rpc_release_calldata(task_setup_data.callback_ops, - task_setup_data.callback_data); - return -EINVAL; - } + BUG_ON(flags & RPC_TASK_ASYNC); task = rpc_run_task(&task_setup_data); if (IS_ERR(task)) @@ -921,7 +908,7 @@ struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req, task->tk_action = call_bc_transmit; atomic_inc(&task->tk_count); - WARN_ON_ONCE(atomic_read(&task->tk_count) != 2); + BUG_ON(atomic_read(&task->tk_count) != 2); rpc_execute(task); out: @@ -1667,6 +1654,7 @@ call_transmit(struct rpc_task *task) task->tk_action = call_transmit_status; /* Encode here so that rpcsec_gss can use correct sequence number. */ if (rpc_task_need_encode(task)) { + BUG_ON(task->tk_rqstp->rq_bytes_sent != 0); rpc_xdr_encode(task); /* Did the encode result in an error condition? */ if (task->tk_status != 0) { @@ -1750,6 +1738,7 @@ call_bc_transmit(struct rpc_task *task) { struct rpc_rqst *req = task->tk_rqstp; + BUG_ON(task->tk_status != 0); task->tk_status = xprt_prepare_transmit(task); if (task->tk_status == -EAGAIN) { /* @@ -1796,7 +1785,7 @@ call_bc_transmit(struct rpc_task *task) * We were unable to reply and will have to drop the * request. The server should reconnect and retransmit. */ - WARN_ON_ONCE(task->tk_status == -EAGAIN); + BUG_ON(task->tk_status == -EAGAIN); printk(KERN_NOTICE "RPC: Could not send backchannel reply " "error: %d\n", task->tk_status); break; diff --git a/trunk/net/sunrpc/rpc_pipe.c b/trunk/net/sunrpc/rpc_pipe.c index 3128a1503d8e..e659def77742 100644 --- a/trunk/net/sunrpc/rpc_pipe.c +++ b/trunk/net/sunrpc/rpc_pipe.c @@ -1093,7 +1093,7 @@ void rpc_put_sb_net(const struct net *net) { struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); - WARN_ON(sn->pipefs_sb == NULL); + BUG_ON(sn->pipefs_sb == NULL); mutex_unlock(&sn->pipefs_sb_lock); } EXPORT_SYMBOL_GPL(rpc_put_sb_net); @@ -1152,14 +1152,19 @@ static void rpc_kill_sb(struct super_block *sb) struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); mutex_lock(&sn->pipefs_sb_lock); + if (sn->pipefs_sb != sb) { + mutex_unlock(&sn->pipefs_sb_lock); + goto out; + } sn->pipefs_sb = NULL; mutex_unlock(&sn->pipefs_sb_lock); - put_net(net); dprintk("RPC: sending pipefs UMOUNT notification for net %p%s\n", net, NET_NAME(net)); blocking_notifier_call_chain(&rpc_pipefs_notifier_list, RPC_PIPEFS_UMOUNT, sb); + put_net(net); +out: kill_litter_super(sb); } diff --git a/trunk/net/sunrpc/rpcb_clnt.c b/trunk/net/sunrpc/rpcb_clnt.c index 411f332de0b3..a70acae496e4 100644 --- a/trunk/net/sunrpc/rpcb_clnt.c +++ b/trunk/net/sunrpc/rpcb_clnt.c @@ -884,10 +884,7 @@ static void encode_rpcb_string(struct xdr_stream *xdr, const char *string, u32 len; len = strlen(string); - WARN_ON_ONCE(len > maxstrlen); - if (len > maxstrlen) - /* truncate and hope for the best */ - len = maxstrlen; + BUG_ON(len > maxstrlen); p = xdr_reserve_space(xdr, 4 + len); xdr_encode_opaque(p, string, len); } diff --git a/trunk/net/sunrpc/sched.c b/trunk/net/sunrpc/sched.c index d17a704aaf5f..6357fcb00c7e 100644 --- a/trunk/net/sunrpc/sched.c +++ b/trunk/net/sunrpc/sched.c @@ -98,23 +98,6 @@ __rpc_add_timer(struct rpc_wait_queue *queue, struct rpc_task *task) list_add(&task->u.tk_wait.timer_list, &queue->timer_list.list); } -static void rpc_set_waitqueue_priority(struct rpc_wait_queue *queue, int priority) -{ - queue->priority = priority; -} - -static void rpc_set_waitqueue_owner(struct rpc_wait_queue *queue, pid_t pid) -{ - queue->owner = pid; - queue->nr = RPC_BATCH_COUNT; -} - -static void rpc_reset_waitqueue_priority(struct rpc_wait_queue *queue) -{ - rpc_set_waitqueue_priority(queue, queue->maxpriority); - rpc_set_waitqueue_owner(queue, 0); -} - /* * Add new request to a priority queue. */ @@ -126,11 +109,9 @@ static void __rpc_add_wait_queue_priority(struct rpc_wait_queue *queue, struct rpc_task *t; INIT_LIST_HEAD(&task->u.tk_wait.links); - if (unlikely(queue_priority > queue->maxpriority)) - queue_priority = queue->maxpriority; - if (queue_priority > queue->priority) - rpc_set_waitqueue_priority(queue, queue_priority); q = &queue->tasks[queue_priority]; + if (unlikely(queue_priority > queue->maxpriority)) + q = &queue->tasks[queue->maxpriority]; list_for_each_entry(t, q, u.tk_wait.list) { if (t->tk_owner == task->tk_owner) { list_add_tail(&task->u.tk_wait.list, &t->u.tk_wait.links); @@ -152,9 +133,7 @@ static void __rpc_add_wait_queue(struct rpc_wait_queue *queue, struct rpc_task *task, unsigned char queue_priority) { - WARN_ON_ONCE(RPC_IS_QUEUED(task)); - if (RPC_IS_QUEUED(task)) - return; + BUG_ON (RPC_IS_QUEUED(task)); if (RPC_IS_PRIORITY(queue)) __rpc_add_wait_queue_priority(queue, task, queue_priority); @@ -199,6 +178,24 @@ static void __rpc_remove_wait_queue(struct rpc_wait_queue *queue, struct rpc_tas task->tk_pid, queue, rpc_qname(queue)); } +static inline void rpc_set_waitqueue_priority(struct rpc_wait_queue *queue, int priority) +{ + queue->priority = priority; + queue->count = 1 << (priority * 2); +} + +static inline void rpc_set_waitqueue_owner(struct rpc_wait_queue *queue, pid_t pid) +{ + queue->owner = pid; + queue->nr = RPC_BATCH_COUNT; +} + +static inline void rpc_reset_waitqueue_priority(struct rpc_wait_queue *queue) +{ + rpc_set_waitqueue_priority(queue, queue->maxpriority); + rpc_set_waitqueue_owner(queue, 0); +} + static void __rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const char *qname, unsigned char nr_queues) { int i; @@ -337,7 +334,7 @@ static void __rpc_sleep_on_priority(struct rpc_wait_queue *q, __rpc_add_wait_queue(q, task, queue_priority); - WARN_ON_ONCE(task->tk_callback != NULL); + BUG_ON(task->tk_callback != NULL); task->tk_callback = action; __rpc_add_timer(q, task); } @@ -346,12 +343,7 @@ void rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task, rpc_action action) { /* We shouldn't ever put an inactive task to sleep */ - WARN_ON_ONCE(!RPC_IS_ACTIVATED(task)); - if (!RPC_IS_ACTIVATED(task)) { - task->tk_status = -EIO; - rpc_put_task_async(task); - return; - } + BUG_ON(!RPC_IS_ACTIVATED(task)); /* * Protect the queue operations. @@ -366,12 +358,7 @@ void rpc_sleep_on_priority(struct rpc_wait_queue *q, struct rpc_task *task, rpc_action action, int priority) { /* We shouldn't ever put an inactive task to sleep */ - WARN_ON_ONCE(!RPC_IS_ACTIVATED(task)); - if (!RPC_IS_ACTIVATED(task)) { - task->tk_status = -EIO; - rpc_put_task_async(task); - return; - } + BUG_ON(!RPC_IS_ACTIVATED(task)); /* * Protect the queue operations. @@ -380,7 +367,6 @@ void rpc_sleep_on_priority(struct rpc_wait_queue *q, struct rpc_task *task, __rpc_sleep_on_priority(q, task, action, priority - RPC_PRIORITY_LOW); spin_unlock_bh(&q->lock); } -EXPORT_SYMBOL_GPL(rpc_sleep_on_priority); /** * __rpc_do_wake_up_task - wake up a single rpc_task @@ -465,7 +451,8 @@ static struct rpc_task *__rpc_find_next_queued_priority(struct rpc_wait_queue *q /* * Check if we need to switch queues. */ - goto new_owner; + if (--queue->count) + goto new_owner; } /* @@ -710,9 +697,7 @@ static void __rpc_execute(struct rpc_task *task) dprintk("RPC: %5u __rpc_execute flags=0x%x\n", task->tk_pid, task->tk_flags); - WARN_ON_ONCE(RPC_IS_QUEUED(task)); - if (RPC_IS_QUEUED(task)) - return; + BUG_ON(RPC_IS_QUEUED(task)); for (;;) { void (*do_action)(struct rpc_task *); @@ -996,7 +981,7 @@ static void rpc_release_task(struct rpc_task *task) { dprintk("RPC: %5u release task\n", task->tk_pid); - WARN_ON_ONCE(RPC_IS_QUEUED(task)); + BUG_ON (RPC_IS_QUEUED(task)); rpc_release_resources_task(task); diff --git a/trunk/net/sunrpc/svc.c b/trunk/net/sunrpc/svc.c index dfa4ba69ff45..3ee7461926d8 100644 --- a/trunk/net/sunrpc/svc.c +++ b/trunk/net/sunrpc/svc.c @@ -324,9 +324,7 @@ svc_pool_map_set_cpumask(struct task_struct *task, unsigned int pidx) * The caller checks for sv_nrpools > 1, which * implies that we've been initialized. */ - WARN_ON_ONCE(m->count == 0); - if (m->count == 0) - return; + BUG_ON(m->count == 0); switch (m->mode) { case SVC_POOL_PERCPU: @@ -587,9 +585,7 @@ svc_init_buffer(struct svc_rqst *rqstp, unsigned int size, int node) * We assume one is at most one page */ arghi = 0; - WARN_ON_ONCE(pages > RPCSVC_MAXPAGES); - if (pages > RPCSVC_MAXPAGES) - pages = RPCSVC_MAXPAGES; + BUG_ON(pages > RPCSVC_MAXPAGES); while (pages) { struct page *p = alloc_pages_node(node, GFP_KERNEL, 0); if (!p) @@ -950,9 +946,7 @@ int svc_register(const struct svc_serv *serv, struct net *net, unsigned int i; int error = 0; - WARN_ON_ONCE(proto == 0 && port == 0); - if (proto == 0 && port == 0) - return -EINVAL; + BUG_ON(proto == 0 && port == 0); for (progp = serv->sv_program; progp; progp = progp->pg_next) { for (i = 0; i < progp->pg_nvers; i++) { diff --git a/trunk/net/sunrpc/svc_xprt.c b/trunk/net/sunrpc/svc_xprt.c index b8e47fac7315..194d865fae72 100644 --- a/trunk/net/sunrpc/svc_xprt.c +++ b/trunk/net/sunrpc/svc_xprt.c @@ -218,9 +218,7 @@ static struct svc_xprt *__svc_xpo_create(struct svc_xprt_class *xcl, */ static void svc_xprt_received(struct svc_xprt *xprt) { - WARN_ON_ONCE(!test_bit(XPT_BUSY, &xprt->xpt_flags)); - if (!test_bit(XPT_BUSY, &xprt->xpt_flags)) - return; + BUG_ON(!test_bit(XPT_BUSY, &xprt->xpt_flags)); /* As soon as we clear busy, the xprt could be closed and * 'put', so we need a reference to call svc_xprt_enqueue with: */ @@ -579,10 +577,7 @@ int svc_alloc_arg(struct svc_rqst *rqstp) /* now allocate needed pages. If we get a failure, sleep briefly */ pages = (serv->sv_max_mesg + PAGE_SIZE) / PAGE_SIZE; - WARN_ON_ONCE(pages >= RPCSVC_MAXPAGES); - if (pages >= RPCSVC_MAXPAGES) - /* use as many pages as possible */ - pages = RPCSVC_MAXPAGES - 1; + BUG_ON(pages >= RPCSVC_MAXPAGES); for (i = 0; i < pages ; i++) while (rqstp->rq_pages[i] == NULL) { struct page *p = alloc_page(GFP_KERNEL); @@ -931,7 +926,7 @@ static void svc_delete_xprt(struct svc_xprt *xprt) spin_lock_bh(&serv->sv_lock); if (!test_and_set_bit(XPT_DETACHED, &xprt->xpt_flags)) list_del_init(&xprt->xpt_list); - WARN_ON_ONCE(!list_empty(&xprt->xpt_ready)); + BUG_ON(!list_empty(&xprt->xpt_ready)); if (test_bit(XPT_TEMP, &xprt->xpt_flags)) serv->sv_tmpcnt--; spin_unlock_bh(&serv->sv_lock); diff --git a/trunk/net/sunrpc/svcsock.c b/trunk/net/sunrpc/svcsock.c index cc3020d16789..03827cef1fa7 100644 --- a/trunk/net/sunrpc/svcsock.c +++ b/trunk/net/sunrpc/svcsock.c @@ -84,11 +84,7 @@ static struct lock_class_key svc_slock_key[2]; static void svc_reclassify_socket(struct socket *sock) { struct sock *sk = sock->sk; - - WARN_ON_ONCE(sock_owned_by_user(sk)); - if (sock_owned_by_user(sk)) - return; - + BUG_ON(sock_owned_by_user(sk)); switch (sk->sk_family) { case AF_INET: sock_lock_init_class_and_name(sk, "slock-AF_INET-NFSD", diff --git a/trunk/net/sunrpc/xdr.c b/trunk/net/sunrpc/xdr.c index 56055632f151..08f50afd5f2a 100644 --- a/trunk/net/sunrpc/xdr.c +++ b/trunk/net/sunrpc/xdr.c @@ -318,10 +318,7 @@ xdr_shrink_bufhead(struct xdr_buf *buf, size_t len) tail = buf->tail; head = buf->head; - - WARN_ON_ONCE(len > head->iov_len); - if (len > head->iov_len) - len = head->iov_len; + BUG_ON (len > head->iov_len); /* Shift the tail first */ if (tail->iov_len != 0) { diff --git a/trunk/net/sunrpc/xprtsock.c b/trunk/net/sunrpc/xprtsock.c index 6db26e5538fb..75853cabf4c9 100644 --- a/trunk/net/sunrpc/xprtsock.c +++ b/trunk/net/sunrpc/xprtsock.c @@ -1746,6 +1746,7 @@ static inline void xs_reclassify_socketu(struct socket *sock) { struct sock *sk = sock->sk; + BUG_ON(sock_owned_by_user(sk)); sock_lock_init_class_and_name(sk, "slock-AF_LOCAL-RPC", &xs_slock_key[1], "sk_lock-AF_LOCAL-RPC", &xs_key[1]); } @@ -1754,6 +1755,7 @@ static inline void xs_reclassify_socket4(struct socket *sock) { struct sock *sk = sock->sk; + BUG_ON(sock_owned_by_user(sk)); sock_lock_init_class_and_name(sk, "slock-AF_INET-RPC", &xs_slock_key[0], "sk_lock-AF_INET-RPC", &xs_key[0]); } @@ -1762,16 +1764,13 @@ static inline void xs_reclassify_socket6(struct socket *sock) { struct sock *sk = sock->sk; + BUG_ON(sock_owned_by_user(sk)); sock_lock_init_class_and_name(sk, "slock-AF_INET6-RPC", &xs_slock_key[1], "sk_lock-AF_INET6-RPC", &xs_key[1]); } static inline void xs_reclassify_socket(int family, struct socket *sock) { - WARN_ON_ONCE(sock_owned_by_user(sock->sk)); - if (sock_owned_by_user(sock->sk)) - return; - switch (family) { case AF_LOCAL: xs_reclassify_socketu(sock); @@ -2330,11 +2329,9 @@ static void *bc_malloc(struct rpc_task *task, size_t size) struct page *page; struct rpc_buffer *buf; - WARN_ON_ONCE(size > PAGE_SIZE - sizeof(struct rpc_buffer)); - if (size > PAGE_SIZE - sizeof(struct rpc_buffer)) - return NULL; - + BUG_ON(size > PAGE_SIZE - sizeof(struct rpc_buffer)); page = alloc_page(GFP_KERNEL); + if (!page) return NULL;