@@ -1,9 +1,18 @@
from st_create_session import create_session
from nfs4_const import *
from environment import check, fail, use_obj, create_file
+from nfs4_type import open_owner4, locker4, open_to_lock_owner4
import nfs4_ops as op
import nfs4lib
+def opt_result(res, opt=None):
+ """Get the corresponding result at res.resarray[]"""
+ if opt == None:
+ return
+ for resa in res.resarray:
+ if resa.resop == opt:
+ return resa
+
def testSupported(t, env):
"""Do a simple RECLAIM_COMPLETE
@@ -20,3 +29,44 @@ def testSupported(t, env):
res = sess.compound([op.reclaim_complete(FALSE)])
check(res)
sess.destroy()
+
+def testReclaimAfterRECC(t, env):
+ """If client does subsequent reclaims of locking state after
+ RECLAIM_COMPLETE is done, server will return NFS4ERR_NO_GRACE.
+ rfc5661 18.51.3
+
+ FLAGS: reclaim_complete all
+ CODE: RECC2
+ """
+ name = env.testname(t)
+ c = env.c1.new_client(name)
+ sess = c.create_session()
+
+ # RECLAIM_COMPLETE
+ res = sess.compound([op.reclaim_complete(FALSE)])
+ check(res)
+
+ fname = "owner_%s" % name
+ path = sess.c.homedir + [name]
+ res = create_file(sess, fname, path, access=OPEN4_SHARE_ACCESS_BOTH)
+ check(res)
+
+ # Get stateid from OPEN4resok for making a lockowner
+ nres = opt_result(res, OP_OPEN)
+ if nres == None:
+ fail("Can not get OPEN4resok!")
+ oseqid = nres.stateid
+
+ owner = open_owner4(0, "My Open Owner")
+ otlowner = open_to_lock_owner4(0, oseqid, 0, owner)
+ lowner = locker4(TRUE, otlowner)
+
+ # Get filehandle from GETFHresok for locking
+ nres = opt_result(res, OP_GETFH)
+ if nres == None:
+ fail("Can not get GETFHresok!")
+ cfh = nres.object
+
+ res = sess.compound([op.putfh(cfh), op.lock(READ_LT, TRUE, 0, 1, lowner)])
+ check(res, NFS4ERR_NO_GRACE)
+ sess.destroy()