Bug 842435
Summary: | NFSv4 Handle a bad or revoked delegation | ||||||
---|---|---|---|---|---|---|---|
Product: | Red Hat Enterprise Linux 6 | Reporter: | Andy Adamson <andros> | ||||
Component: | kernel | Assignee: | Steve Dickson <steved> | ||||
Status: | CLOSED ERRATA | QA Contact: | Jian Li <jiali> | ||||
Severity: | high | Docs Contact: | |||||
Priority: | urgent | ||||||
Version: | 6.4 | CC: | acase, bfields, cww, dhoward, dwysocha, eguan, fhrbata, jiali, jlayton, msvoboda, nmurray, rwheeler, steved | ||||
Target Milestone: | rc | Keywords: | ZStream | ||||
Target Release: | --- | ||||||
Hardware: | All | ||||||
OS: | Linux | ||||||
Whiteboard: | |||||||
Fixed In Version: | kernel-2.6.32-315.el6 | Doc Type: | Bug Fix | ||||
Doc Text: |
When an NFSv4 client received a read delegation, a race between the OPEN and DELEGRETURN operation could occur. If the DELEGRETURN operation was processed first, the NFSv4 client treated the delegation returned by the following OPEN as a new delegation. Also, the NFSv4 client did not correctly handle errors caused by requests that used a bad or revoked delegation state ID. As a result, applications running on the client could receive spurious EIO errors. This update applies a series of patches that fix the NFSv4 code so an NFSv4 client recovers correctly in the described situations instead of returning errors to applications.
|
Story Points: | --- | ||||
Clone Of: | |||||||
: | 967051 (view as bug list) | Environment: | |||||
Last Closed: | 2013-02-21 06:42:48 UTC | Type: | Bug | ||||
Regression: | --- | Mount Type: | --- | ||||
Documentation: | --- | CRM: | |||||
Verified Versions: | Category: | --- | |||||
oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |||||
Cloudforms Team: | --- | Target Upstream Version: | |||||
Embargoed: | |||||||
Bug Depends On: | |||||||
Bug Blocks: | 846840, 967051 | ||||||
Attachments: |
|
This request was evaluated by Red Hat Product Management for inclusion in a Red Hat Enterprise Linux release. Product Management has requested further review of this request by Red Hat Engineering, for potential inclusion in a Red Hat Enterprise Linux release for currently deployed products. This request is not yet committed for inclusion in a release. reproducer refer to comment 0, regression nfs test is needed. Patch(es) available on kernel-2.6.32-315.el6 *** Bug 800681 has been marked as a duplicate of this bug. *** This bug is reproduced on 2.6.32-287.el6, and verified on 2.6.32-338.el6. When bug is reproduced, client would send READ call looply always. newpynfs output: (sequenceid is increasing..) **snip** INFO :nfs.server:**************************************** INFO :nfs.server:Handling COMPOUND INFO :nfs.server:COMPOUND4args(tag='', minorversion=1, argarray=[nfs_argop4(argop=OP_SEQUENCE, opsequence=SEQUENCE4args(sa_sessionid='0000000200000001', sa_sequenceid=2342, sa_slotid=0, sa_highest_slotid=0, sa_cachethis=False)), nfs_argop4(argop=OP_PUTFH, opputfh=PUTFH4args(object='\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x02')), nfs_argop4(argop=OP_READ, opread=READ4args(stateid=stateid4(seqid=0, other='\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x02'), offset=0L, count=29))]) INFO :nfs.server:*** OP_SEQUENCE (53) *** INFO :nfs.server:*** OP_PUTFH (22) *** INFO :nfs.server:*** OP_READ (25) *** INFO :nfs.server:Replying. Status NFS4ERR_BAD_STATEID (10025) INFO :nfs.server:COMPOUND4res(status=NFS4ERR_BAD_STATEID, tag='', resarray=[nfs_resop4(resop=OP_SEQUENCE, opsequence=SEQUENCE4res(sr_status=NFS4_OK, sr_resok4=SEQUENCE4resok(sr_sessionid='0000000200000001', sr_sequenceid=2342, sr_slotid=0, sr_highest_slotid=0, sr_target_highest_slotid=8, sr_status_flags=0))), nfs_resop4(resop=OP_PUTFH, opputfh=PUTFH4res(status=NFS4_OK)), nfs_resop4(resop=OP_READ, opread=READ4res(status=NFS4ERR_BAD_STATEID))]) INFO :nfs.server:**************************************** INFO :nfs.server:Handling COMPOUND INFO :nfs.server:COMPOUND4args(tag='', minorversion=1, argarray=[nfs_argop4(argop=OP_SEQUENCE, opsequence=SEQUENCE4args(sa_sessionid='0000000200000001', sa_sequenceid=2343, sa_slotid=0, sa_highest_slotid=0, sa_cachethis=False)), nfs_argop4(argop=OP_PUTFH, opputfh=PUTFH4args(object='\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x02')), nfs_argop4(argop=OP_READ, opread=READ4args(stateid=stateid4(seqid=0, other='\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x02'), offset=0L, count=29))]) INFO :nfs.server:*** OP_SEQUENCE (53) *** INFO :nfs.server:*** OP_PUTFH (22) *** INFO :nfs.server:*** OP_READ (25) *** INFO :nfs.server:Replying. Status NFS4ERR_BAD_STATEID (10025) INFO :nfs.server:COMPOUND4res(status=NFS4ERR_BAD_STATEID, tag='', resarray=[nfs_resop4(resop=OP_SEQUENCE, opsequence=SEQUENCE4res(sr_status=NFS4_OK, sr_resok4=SEQUENCE4resok(sr_sessionid='0000000200000001', sr_sequenceid=2343, sr_slotid=0, sr_highest_slotid=0, sr_target_highest_slotid=8, sr_status_flags=0))), nfs_resop4(resop=OP_PUTFH, opputfh=PUTFH4res(status=NFS4_OK)), nfs_resop4(resop=OP_READ, opread=READ4res(status=NFS4ERR_BAD_STATEID))]) **snip** when verified, after READ call get NFS4ERR_BAD_STATEID, an 'OPEN' call is send again. newpynfs output: INFO :nfs.server:**************************************** INFO :nfs.server:Handling COMPOUND INFO :nfs.server:COMPOUND4args(tag='', minorversion=1, argarray=[nfs_argop4(argop=OP_SEQUENCE, opsequence=SEQUENCE4args(sa_ sessionid='0000000100000001', sa_sequenceid=21, sa_slotid=0, sa_highest_slotid=0, sa_cachethis=True)), nfs_argop4(argop=OP_PU TFH, opputfh=PUTFH4args(object='\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\ x00\x01')), nfs_argop4(argop=OP_SAVEFH), nfs_argop4(argop=OP_OPEN, opopen=OPEN4args(seqid=0, share_access=1, share_deny=0, ow ner=state_owner4(clientid=1L, owner='open id:\x00\x00\x00\x14#\xb8*\x8e N\xa82'), openhow=openflag4(opentype=OPEN4_NOCREATE), claim=open_claim4(claim=CLAIM_NULL, file='date'))), nfs_argop4(argop=OP_GETFH), nfs_argop4(argop=OP_GETATTR, opgetattr=GETAT TR4args(attr_request=42950721818L)), nfs_argop4(argop=OP_RESTOREFH), nfs_argop4(argop=OP_GETATTR, opgetattr=GETATTR4args(attr _request=24L))]) INFO :nfs.server:*** OP_SEQUENCE (53) *** INFO :nfs.server:*** OP_PUTFH (22) *** INFO :nfs.server:*** OP_SAVEFH (32) *** INFO :nfs.server:*** OP_OPEN (18) *** DEBUG :nfs.server:OPEN - fh = '\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\ x00\x02' DEBUG :nfs.server.state:GRANTING delegation: OPEN_DELEGATE_READ stateid4(seqid=1, other='\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x02') <nfs4state.DelegEntry object at 0xd2fcd0> test print, delete delegate INFO :nfs.server:*** OP_GETFH (10) *** INFO :nfs.server:*** OP_GETATTR (9) *** handling fattr4_type : 1 handling fattr4_change : 4 handling fattr4_size : 29 handling fattr4_fsid : fsid4(major=3, minor=1) handling fattr4_fileid : 2 handling fattr4_mode : 420 handling fattr4_numlinks : 1 INFO :nfs.server:*** OP_RESTOREFH (31) *** INFO :nfs.server:*** OP_GETATTR (9) *** handling fattr4_change : 1 handling fattr4_size : 1 INFO :nfs.server:Replying. Status NFS4_OK (0) INFO :nfs.server:COMPOUND4res(status=NFS4_OK, tag='', resarray=[nfs_resop4(resop=OP_SEQUENCE, opsequence=SEQUENCE4res(sr_status=NFS4_OK, sr_resok4=SEQUENCE4resok(sr_sessionid='0000000100000001', sr_sequenceid=21, sr_slotid=0, sr_highest_slotid=0, sr_target_highest_slotid=8, sr_status_flags=0))), nfs_resop4(resop=OP_PUTFH, opputfh=PUTFH4res(status=NFS4_OK)), nfs_resop4(resop=OP_SAVEFH, opsavefh=SAVEFH4res(status=NFS4_OK)), nfs_resop4(resop=OP_OPEN, opopen=OPEN4res(status=NFS4_OK, resok4=OPEN4resok(stateid=stateid4(seqid=1, other='\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01'), cinfo=change_info4(atomic=True, before=1, after=1), rflags=0, attrset=0L, delegation=open_delegation4(delegation_type=OPEN_DELEGATE_READ, read=open_read_delegation4(stateid=stateid4(seqid=1, other='\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x02'), recall=False, permissions=nfsace4(type=1L, flag=0, access_mask=1442215L, who='EVERYONE@')))))), nfs_resop4(resop=OP_GETFH, opgetfh=GETFH4res(status=NFS4_OK, resok4=GETFH4resok(object='\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x02'))), nfs_resop4(resop=OP_GETATTR, opgetattr=GETATTR4res(status=NFS4_OK, resok4=GETATTR4resok(obj_attributes={1: 1, 3: 4, 4: 29, 33: 420, 8: fsid4(major=3, minor=1), 35: 1, 20: 2}))), nfs_resop4(resop=OP_RESTOREFH, oprestorefh=RESTOREFH4res(status=NFS4_OK)), nfs_resop4(resop=OP_GETATTR, opgetattr=GETATTR4res(status=NFS4_OK, resok4=GETATTR4resok(obj_attributes={3: 1, 4: 1})))]) INFO :nfs.server:**************************************** INFO :nfs.server:Handling COMPOUND INFO :nfs.server:COMPOUND4args(tag='', minorversion=1, argarray=[nfs_argop4(argop=OP_SEQUENCE, opsequence=SEQUENCE4args(sa_sessionid='0000000100000001', sa_sequenceid=22, sa_slotid=0, sa_highest_slotid=0, sa_cachethis=False)), nfs_argop4(argop=OP_PUTFH, opputfh=PUTFH4args(object='\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x02')), nfs_argop4(argop=OP_READ, opread=READ4args(stateid=stateid4(seqid=0, other='\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x02'), offset=0L, count=29))]) INFO :nfs.server:*** OP_SEQUENCE (53) *** INFO :nfs.server:*** OP_PUTFH (22) *** INFO :nfs.server:*** OP_READ (25) *** INFO :nfs.server:Replying. Status NFS4ERR_BAD_STATEID (10025) INFO :nfs.server:COMPOUND4res(status=NFS4ERR_BAD_STATEID, tag='', resarray=[nfs_resop4(resop=OP_SEQUENCE, opsequence=SEQUENCE4res(sr_status=NFS4_OK, sr_resok4=SEQUENCE4resok(sr_sessionid='0000000100000001', sr_sequenceid=22, sr_slotid=0, sr_highest_slotid=0, sr_target_highest_slotid=8, sr_status_flags=0))), nfs_resop4(resop=OP_PUTFH, opputfh=PUTFH4res(status=NFS4_OK)), nfs_resop4(resop=OP_READ, opread=READ4res(status=NFS4ERR_BAD_STATEID))]) INFO :nfs.server:**************************************** INFO :nfs.server:Handling COMPOUND INFO :nfs.server:COMPOUND4args(tag='', minorversion=1, argarray=[nfs_argop4(argop=OP_SEQUENCE, opsequence=SEQUENCE4args(sa_sessionid='0000000100000001', sa_sequenceid=23, sa_slotid=0, sa_highest_slotid=0, sa_cachethis=True)), nfs_argop4(argop=OP_PUTFH, opputfh=PUTFH4args(object='\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01')), nfs_argop4(argop=OP_SAVEFH), nfs_argop4(argop=OP_OPEN, opopen=OPEN4args(seqid=0, share_access=1, share_deny=0, owner=state_owner4(clientid=1L, owner='open id:\x00\x00\x00\x14#\xb8*\x8e N\xa82'), openhow=openflag4(opentype=OPEN4_NOCREATE), claim=open_claim4(claim=CLAIM_NULL, file='date'))), nfs_argop4(argop=OP_GETFH), nfs_argop4(argop=OP_GETATTR, opgetattr=GETATTR4args(attr_request=42950721818L)), nfs_argop4(argop=OP_RESTOREFH), nfs_argop4(argop=OP_GETATTR, opgetattr=GETATTR4args(attr_request=24L))]) INFO :nfs.server:*** OP_SEQUENCE (53) *** INFO :nfs.server:*** OP_PUTFH (22) *** INFO :nfs.server:*** OP_SAVEFH (32) *** INFO :nfs.server:*** OP_OPEN (18) *** DEBUG :nfs.server:OPEN - fh = '\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x02' DEBUG :nfs.server.state:GRANTING delegation: OPEN_DELEGATE_READ test print, DON'T delete delegate INFO :nfs.server:*** OP_GETFH (10) *** INFO :nfs.server:*** OP_GETATTR (9) *** handling fattr4_type : 1 handling fattr4_change : 4 handling fattr4_size : 29 handling fattr4_fsid : fsid4(major=3, minor=1) handling fattr4_fileid : 2 handling fattr4_mode : 420 handling fattr4_numlinks : 1 INFO :nfs.server:*** OP_RESTOREFH (31) *** INFO :nfs.server:*** OP_GETATTR (9) *** handling fattr4_change : 1 handling fattr4_size : 1 INFO :nfs.server:Replying. Status NFS4_OK (0) INFO :nfs.server:COMPOUND4res(status=NFS4_OK, tag='', resarray=[nfs_resop4(resop=OP_SEQUENCE, opsequence=SEQUENCE4res(sr_status=NFS4_OK, sr_resok4=SEQUENCE4resok(sr_sessionid='0000000100000001', sr_sequenceid=23, sr_slotid=0, sr_highest_slotid=0, sr_target_highest_slotid=8, sr_status_flags=0))), nfs_resop4(resop=OP_PUTFH, opputfh=PUTFH4res(status=NFS4_OK)), nfs_resop4(resop=OP_SAVEFH, opsavefh=SAVEFH4res(status=NFS4_OK)), nfs_resop4(resop=OP_OPEN, opopen=OPEN4res(status=NFS4_OK, resok4=OPEN4resok(stateid=stateid4(seqid=2, other='\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01'), cinfo=change_info4(atomic=True, before=1, after=1), rflags=0, attrset=0L, delegation=open_delegation4(delegation_type=OPEN_DELEGATE_READ, read=open_read_delegation4(stateid=stateid4(seqid=1, other='\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03'), recall=False, permissions=nfsace4(type=1L, flag=0, access_mask=1442215L, who='EVERYONE@')))))), nfs_resop4(resop=OP_GETFH, opgetfh=GETFH4res(status=NFS4_OK, resok4=GETFH4resok(object='\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x02'))), nfs_resop4(resop=OP_GETATTR, opgetattr=GETATTR4res(status=NFS4_OK, resok4=GETATTR4resok(obj_attributes={1: 1, 3: 4, 4: 29, 33: 420, 8: fsid4(major=3, minor=1), 35: 1, 20: 2}))), nfs_resop4(resop=OP_RESTOREFH, oprestorefh=RESTOREFH4res(status=NFS4_OK)), nfs_resop4(resop=OP_GETATTR, opgetattr=GETATTR4res(status=NFS4_OK, resok4=GETATTR4resok(obj_attributes={3: 1, 4: 1})))]) INFO :nfs.server:**************************************** INFO :nfs.server:Handling COMPOUND INFO :nfs.server:COMPOUND4args(tag='', minorversion=1, argarray=[nfs_argop4(argop=OP_SEQUENCE, opsequence=SEQUENCE4args(sa_sessionid='0000000100000001', sa_sequenceid=24, sa_slotid=0, sa_highest_slotid=0, sa_cachethis=False)), nfs_argop4(argop=OP_PUTFH, opputfh=PUTFH4args(object='\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x02')), nfs_argop4(argop=OP_ACCESS, opaccess=ACCESS4args(access=45)), nfs_argop4(argop=OP_GETATTR, opgetattr=GETATTR4args(attr_request=42950721818L))]) INFO :nfs.server:*** OP_SEQUENCE (53) *** INFO :nfs.server:*** OP_PUTFH (22) *** INFO :nfs.server:*** OP_ACCESS (3) *** INFO :nfs.server:*** OP_GETATTR (9) *** handling fattr4_type : 1 handling fattr4_change : 4 handling fattr4_size : 29 handling fattr4_fsid : fsid4(major=3, minor=1) handling fattr4_fileid : 2 handling fattr4_mode : 420 handling fattr4_numlinks : 1 INFO :nfs.server:Replying. Status NFS4_OK (0) INFO :nfs.server:COMPOUND4res(status=NFS4_OK, tag='', resarray=[nfs_resop4(resop=OP_SEQUENCE, opsequence=SEQUENCE4res(sr_status=NFS4_OK, sr_resok4=SEQUENCE4resok(sr_sessionid='0000000100000001', sr_sequenceid=24, sr_slotid=0, sr_highest_slotid=0, sr_target_highest_slotid=8, sr_status_flags=0))), nfs_resop4(resop=OP_PUTFH, opputfh=PUTFH4res(status=NFS4_OK)), nfs_resop4(resop=OP_ACCESS, opaccess=ACCESS4res(status=NFS4_OK, resok4=ACCESS4resok(supported=45L, access=45L))), nfs_resop4(resop=OP_GETATTR, opgetattr=GETATTR4res(status=NFS4_OK, resok4=GETATTR4resok(obj_attributes={1: 1, 3: 4, 4: 29, 33: 420, 8: fsid4(major=3, minor=1), 35: 1, 20: 2})))]) INFO :nfs.server:**************************************** INFO :nfs.server:Handling COMPOUND INFO :nfs.server:COMPOUND4args(tag='', minorversion=1, argarray=[nfs_argop4(argop=OP_SEQUENCE, opsequence=SEQUENCE4args(sa_sessionid='0000000100000001', sa_sequenceid=25, sa_slotid=0, sa_highest_slotid=0, sa_cachethis=False)), nfs_argop4(argop=OP_PUTFH, opputfh=PUTFH4args(object='\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x02')), nfs_argop4(argop=OP_READ, opread=READ4args(stateid=stateid4(seqid=0, other='\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03'), offset=0L, count=29))]) INFO :nfs.server:*** OP_SEQUENCE (53) *** INFO :nfs.server:*** OP_PUTFH (22) *** INFO :nfs.server:*** OP_READ (25) *** INFO :nfs.server:Replying. Status NFS4_OK (0) INFO :nfs.server:COMPOUND4res(status=NFS4_OK, tag='', resarray=[nfs_resop4(resop=OP_SEQUENCE, opsequence=SEQUENCE4res(sr_status=NFS4_OK, sr_resok4=SEQUENCE4resok(sr_sessionid='0000000100000001', sr_sequenceid=25, sr_slotid=0, sr_highest_slotid=0, sr_target_highest_slotid=8, sr_status_flags=0))), nfs_resop4(resop=OP_PUTFH, opputfh=PUTFH4res(status=NFS4_OK)), nfs_resop4(resop=OP_READ, opread=READ4res(status=NFS4_OK, resok4=READ4resok(eof=True, data='Thu Nov 22 22:17:24 EST 2012\n')))]) ^[[A^[[A^[[A^[[A^[[A^[[A^[[A^[[A^[[A^[[A^[[B^[[B^[[B^[[B^[[BINFO :nfs.server:**************************************** INFO :nfs.server:Handling COMPOUND INFO :nfs.server:COMPOUND4args(tag='', minorversion=1, argarray=[nfs_argop4(argop=OP_SEQUENCE, opsequence=SEQUENCE4args(sa_sessionid='0000000000000001', sa_sequenceid=6, sa_slotid=0, sa_highest_slotid=0, sa_cachethis=False))]) INFO :nfs.server:*** OP_SEQUENCE (53) *** INFO :nfs.server:Replying. Status NFS4_OK (0) INFO :nfs.server:COMPOUND4res(status=NFS4_OK, tag='', resarray=[nfs_resop4(resop=OP_SEQUENCE, opsequence=SEQUENCE4res(sr_status=NFS4_OK, sr_resok4=SEQUENCE4resok(sr_sessionid='0000000000000001', sr_sequenceid=6, sr_slotid=0, sr_highest_slotid=0, sr_target_highest_slotid=8, sr_status_flags=0)))]) newpynfs modification for fault-injection: diff --git a/nfs4.1/nfs4commoncode.py b/nfs4.1/nfs4commoncode.py index 317f04c..2a961da 100644 --- a/nfs4.1/nfs4commoncode.py +++ b/nfs4.1/nfs4commoncode.py @@ -31,6 +31,7 @@ code_str = '''\ def %(encode_status)s_by_name(name, status, *args, **kwargs): """ returns %(nfs_resop4)s(OP_NAME, opname=NAME4res(status, *args)) """ tag = kwargs.pop("msg", None) + tag = None name_l = name.lower() name_u = name.upper() try: diff --git a/nfs4.1/nfs4server.py b/nfs4.1/nfs4server.py index b279292..69d9681 100755 --- a/nfs4.1/nfs4server.py +++ b/nfs4.1/nfs4server.py @@ -508,11 +508,13 @@ class Slot(object): # STUB - for client, need to track slot usage + ################################################## # The primary class - it is excessively long # ################################################## class NFS4Server(rpc.Server): + TEST_ONCE = 1 """Implement a nfsv4.1 server.""" # As the only per-server attribute, lease_time is handled specially @@ -1327,6 +1329,19 @@ class NFS4Server(rpc.Server): print "+++ client(id=%i).state =" % env.session.client.clientid print env.session.client.state res = OPEN4resok(sid, cinfo, flags, bitmask, deleg) + if deleg.switch and (NFS4Server.TEST_ONCE == 1): + tmpstateid = deleg.switch.stateid + print tmpstateid + tmpstate = env.session.client.state[tmpstateid.other] + print tmpstate + if tmpstate : + tmpstate.delete() + NFS4Server.TEST_ONCE = 0 + print "test print, delete delegate" + else: + NFS4Server.TEST_ONCE = 1 + print "test print, DON'T delete delegate" + return encode_status(NFS4_OK, res) def open_claim_null(self, arg, env): Hi bruce, To this patch, problem about delegation is resolved, could I verify this bug? Since the problem described in this bug report should be resolved in a recent advisory, it has been closed with a resolution of ERRATA. For information on the advisory, and where to find the updated files, follow the link below. If the solution does not work for you, open a new bug report. http://rhn.redhat.com/errata/RHSA-2013-0496.html |
Created attachment 599861 [details] back port of the 8 required patches to the 2.6.32-285 kernel Description of problem: The NFSv4 client does not order OPEN and DELEGRETURN, and so the two operations can race. When that happens, it looks to the client as if it has received a new delegation, when in fact it is the same one that is being delegareturned. Another instance of this problem occurs when a delegation stateid is bad (NFS4ERR_BAD_STATEID) or revoked (NFS4ERR_DELEG_REVOKED for NFSv4.1) where the client returns EIO to the application. Version-Release number of selected component (if applicable): RHEL 6.1/2/3/4 Tested against kernel 2.6.32-285. How reproducible: 100% Steps to Reproduce: 1.Use the pynfs NFSv4.1 server ops_config infrastructure to inject an NFS4ERR_BAD_STATEID on READ. 2. cat a file. The pynfs server hands out READ delegations on open. 3. Actual results: The pynfs server ops_config test not only returns NFS4ERR_BAD_STATEID on the first read, but also removes the stateid from the pynfs server state cache. The READ is retried several times, each READ returns an NFS4ERR_BAD_STATEID, and EIO is returned to the 'cat' command. Expected results: The NFS4ERR_BAD_STATEID should be handled, a new OPEN should be sent, and the READ retried with a new stateid. Additional info: This patch fixes the bug. From a1d0b5eebc4fd6e0edb02688b35f17f67f42aea5 Mon Sep 17 00:00:00 2001 From: Trond Myklebust <Trond.Myklebust> Date: Mon, 5 Mar 2012 19:56:44 -0500 Subject: [PATCH 1/1] NFS: Properly handle the case where the delegation is revoked If we know that the delegation stateid is bad or revoked, we need to remove that delegation as soon as possible, and then mark all the stateids that relied on that delegation for recovery. We cannot use the delegation as part of the recovery process. Also note that NFSv4.1 uses a different error code (NFS4ERR_DELEG_REVOKED) to indicate that the delegation was revoked. Finally, ensure that setlk() and setattr() can both recover safely from a revoked delegation. Signed-off-by: Trond Myklebust <Trond.Myklebust> Cc: stable.org --- I have back ported the following patches required by the above patch and tested the resultant 2.6.32-285 patched kernel to verify that the bug is fixed. Attached is a tar ball of the ported patch set which includes 1) A beginning patch 0001-ANDROS-fix-br_private.h-for-2.6.32-285.patch, required for compiling the 2.6.32-285 source (with my .config) 2) A final patch 0009-BACKPORT-remove-rcu_dereference_raw-define-from-rcul.patch which removes a duplicate declaration that I think is a result of past back ports. 8 Patches required: From 632ee200130899252508c478ad0e808222573fbc Mon Sep 17 00:00:00 2001 From: Paul E. McKenney <paulmck.ibm.com> Date: Mon, 22 Feb 2010 17:04:45 -0800 Subject: [PATCH 1/1] rcu: Introduce lockdep-based checking to RCU read-side primitives Inspection is proving insufficient to catch all RCU misuses, which is understandable given that rcu_dereference() might be protected by any of four different flavors of RCU (RCU, RCU-bh, RCU-sched, and SRCU), and might also/instead be protected by any of a number of locking primitives. It is therefore time to enlist the aid of lockdep. This set of patches is inspired by earlier work by Peter Zijlstra and Thomas Gleixner, and takes the following approach: o Set up separate lockdep classes for RCU, RCU-bh, and RCU-sched. o Set up separate lockdep classes for each instance of SRCU. o Create primitives that check for being in an RCU read-side critical section. These return exact answers if lockdep is fully enabled, but if unsure, report being in an RCU read-side critical section. (We want to avoid false positives!) The primitives are: For RCU: rcu_read_lock_held(void) For RCU-bh: rcu_read_lock_bh_held(void) For RCU-sched: rcu_read_lock_sched_held(void) For SRCU: srcu_read_lock_held(struct srcu_struct *sp) o Add rcu_dereference_check(), which takes a second argument in which one places a boolean expression based on the above primitives and/or lockdep_is_held(). o A new kernel configuration parameter, CONFIG_PROVE_RCU, enables rcu_dereference_check(). This depends on CONFIG_PROVE_LOCKING, and should be quite helpful during the transition period while CONFIG_PROVE_RCU-unaware patches are in flight. The existing rcu_dereference() primitive does no checking, but upcoming patches will change that. Signed-off-by: Paul E. McKenney <paulmck.ibm.com> Cc: laijs.com Cc: dipankar.com Cc: mathieu.desnoyers Cc: josh Cc: dvhltc.com Cc: niv.com Cc: peterz Cc: rostedt Cc: Valdis.Kletnieks Cc: dhowells LKML-Reference: <1266887105-1528-1-git-send-email-paulmck.ibm.com> Signed-off-by: Ingo Molnar <mingo> -------- From c26d34a5858f96a564c45048bf5f09319d2abad1 Mon Sep 17 00:00:00 2001 From: Paul E. McKenney <paulmck.ibm.com> Date: Mon, 22 Feb 2010 17:04:46 -0800 Subject: [PATCH 1/1] rcu: Add lockdep-enabled variants of rcu_dereference() Make rcu_dereference() check for being in an RCU read-side critical section, and create rcu_dereference_bh(), rcu_dereference_sched(), and srcu_dereference() to check for the other flavors of RCU. Also create rcu_dereference_raw() to avoid checking, and make rcu_dereference_check() use rcu_dereference_raw(). Acked-by: Eric Dumazet <eric.dumazet> Signed-off-by: Paul E. McKenney <paulmck.ibm.com> Cc: laijs.com Cc: dipankar.com Cc: mathieu.desnoyers Cc: josh Cc: dvhltc.com Cc: niv.com Cc: peterz Cc: rostedt Cc: Valdis.Kletnieks Cc: dhowells LKML-Reference: <1266887105-1528-2-git-send-email-paulmck.ibm.com> Signed-off-by: Ingo Molnar <mingo> ----------- From b62730baea32f86fe91a7930e4b7ee8d82778b79 Mon Sep 17 00:00:00 2001 From: Paul E. McKenney <paulmck.ibm.com> Date: Fri, 9 Apr 2010 15:39:10 -0700 Subject: [PATCH 1/1] rcu: Add rcu_access_pointer and rcu_dereference_protected This patch adds variants of rcu_dereference() that handle situations where the RCU-protected data structure cannot change, perhaps due to our holding the update-side lock, or where the RCU-protected pointer is only to be fetched, not dereferenced. These are needed due to some performance concerns with using rcu_dereference() where it is not required, aside from the need for lockdep/sparse checking. The new rcu_access_pointer() primitive is for the case where the pointer is be fetch and not dereferenced. This primitive may be used without protection, RCU or otherwise, due to the fact that it uses ACCESS_ONCE(). The new rcu_dereference_protected() primitive is for the case where updates are prevented, for example, due to holding the update-side lock. This primitive does neither ACCESS_ONCE() nor smp_read_barrier_depends(), so can only be used when updates are somehow prevented. Suggested-by: David Howells <dhowells> Signed-off-by: Paul E. McKenney <paulmck.ibm.com> --------- From 17d2c0a0c4d4e074f0a2a5c0090ff6d88f5e1d44 Mon Sep 17 00:00:00 2001 From: David Howells <dhowells> Date: Sat, 1 May 2010 12:37:18 -0400 Subject: [PATCH 1/1] NFS: Fix RCU issues in the NFSv4 delegation code Fix a number of RCU issues in the NFSv4 delegation code. (1) delegation->cred doesn't need to be RCU protected as it's essentially an invariant refcounted structure. By the time we get to nfs_free_delegation(), the delegation is being released, so no one else should be attempting to use the saved credentials, and they can be cleared. However, since the list of delegations could still be under traversal at this point by such as nfs_client_return_marked_delegations(), the cred should be released in nfs_do_free_delegation() rather than in nfs_free_delegation(). Simply using rcu_assign_pointer() to clear it is insufficient as that doesn't stop the cred from being destroyed, and nor does calling put_rpccred() after call_rcu(), given that the latter is asynchronous. (2) nfs_detach_delegation_locked() and nfs_inode_set_delegation() should use rcu_derefence_protected() because they can only be called if nfs_client::cl_lock is held, and that guards against anyone changing nfsi->delegation under it. Furthermore, the barrier imposed by rcu_dereference() is superfluous, given that the spin_lock() is also a barrier. (3) nfs_detach_delegation_locked() is now passed a pointer to the nfs_client struct so that it can issue lockdep advice based on clp->cl_lock for (2). (4) nfs_inode_return_delegation_noreclaim() and nfs_inode_return_delegation() should use rcu_access_pointer() outside the spinlocked region as they merely examine the pointer and don't follow it, thus rendering unnecessary the need to impose a partial ordering over the one item of interest. These result in an RCU warning like the following: --------- From dda4b225623f316335052828c24a16e2da313f8f Mon Sep 17 00:00:00 2001 From: Chuck Lever <chuck.lever> Date: Fri, 24 Dec 2010 01:32:54 +0000 Subject: [PATCH 1/1] NFS: Introduce nfs_detach_delegations() Clean up: Refactor code that takes clp->cl_lock and calls nfs_detach_delegations_locked() into its own function. While we're changing the call sites, get rid of the second parameter and the logic in nfs_detach_delegations_locked() that uses it, since callers always set that parameter of nfs_detach_delegations_locked() to NULL. Signed-off-by: Chuck Lever <chuck.lever> Signed-off-by: Trond Myklebust <Trond.Myklebust> ----------- From d3978bb325510f0a26ebd92f211b36c5f98b2306 Mon Sep 17 00:00:00 2001 From: Chuck Lever <chuck.lever> Date: Fri, 24 Dec 2010 01:33:04 +0000 Subject: [PATCH 1/1] NFS: Move cl_delegations to the nfs_server struct Delegations are per-inode, not per-nfs_client. When a server file system is migrated, delegations on the client must be moved from the source to the destination nfs_server. Make it easier to manage a mount point's delegation list across a migration event by moving the list to the nfs_server struct. Clean up: I added documenting comments to public functions I changed in this patch. For consistency I added comments to all the other public functions in fs/nfs/delegation.c. Signed-off-by: Chuck Lever <chuck.lever> Signed-off-by: Trond Myklebust <Trond.Myklebust> -------- From d3978bb325510f0a26ebd92f211b36c5f98b2306 Mon Sep 17 00:00:00 2001 From: Chuck Lever <chuck.lever> Date: Fri, 24 Dec 2010 01:33:04 +0000 Subject: [PATCH 1/1] NFS: Move cl_delegations to the nfs_server struct Delegations are per-inode, not per-nfs_client. When a server file system is migrated, delegations on the client must be moved from the source to the destination nfs_server. Make it easier to manage a mount point's delegation list across a migration event by moving the list to the nfs_server struct. Clean up: I added documenting comments to public functions I changed in this patch. For consistency I added comments to all the other public functions in fs/nfs/delegation.c. Signed-off-by: Chuck Lever <chuck.lever> Signed-off-by: Trond Myklebust <Trond.Myklebust>