diff --git a/daemon/nfs41_ops.c b/daemon/nfs41_ops.c index b637f76..28c9b0d 100644 --- a/daemon/nfs41_ops.c +++ b/daemon/nfs41_ops.c @@ -407,6 +407,89 @@ out: return status; } +int nfs41_open_reclaim( + IN nfs41_session *session, + IN nfs41_path_fh *parent, + IN nfs41_path_fh *file, + IN state_owner4 *owner, + IN uint32_t allow, + IN uint32_t deny, + OUT stateid4 *stateid) +{ + int status; + nfs41_compound compound; + nfs_argop4 argops[6]; + nfs_resop4 resops[6]; + nfs41_sequence_args sequence_args; + nfs41_sequence_res sequence_res; + nfs41_putfh_args putfh_args[2]; + nfs41_putfh_res putfh_res[2]; + nfs41_op_open_args open_args; + nfs41_op_open_res open_res; + bitmap4 attr_request; + nfs41_getattr_args getattr_args; + nfs41_getattr_res getattr_res, pgetattr_res; + nfs41_file_info info, dir_info; + + init_getattr_request(&attr_request); + + compound_init(&compound, argops, resops, "open reclaim"); + + compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res); + status = nfs41_session_sequence(&sequence_args, session, 1); + if (status) + goto out; + + compound_add_op(&compound, OP_PUTFH, &putfh_args[0], &putfh_res[0]); + putfh_args[0].file = file; + putfh_args[0].in_recovery = 0; + + compound_add_op(&compound, OP_OPEN, &open_args, &open_res); + open_args.seqid = 0; + open_args.share_access = allow | OPEN4_SHARE_ACCESS_WANT_NO_DELEG; + open_args.share_deny = deny; + open_args.owner = owner; + open_args.openhow.opentype = OPEN4_NOCREATE; + open_args.claim.claim = CLAIM_PREVIOUS; + open_args.claim.u.prev.delegate_type = OPEN_DELEGATE_NONE; + open_res.resok4.stateid = stateid; + + compound_add_op(&compound, OP_GETATTR, &getattr_args, &getattr_res); + getattr_args.attr_request = &attr_request; + getattr_res.obj_attributes.attr_vals_len = NFS4_OPAQUE_LIMIT; + getattr_res.info = &info; + + compound_add_op(&compound, OP_PUTFH, &putfh_args[1], &putfh_res[1]); + putfh_args[1].file = parent; + putfh_args[1].in_recovery = 0; + + compound_add_op(&compound, OP_GETATTR, &getattr_args, &pgetattr_res); + getattr_args.attr_request = &attr_request; + pgetattr_res.obj_attributes.attr_vals_len = NFS4_OPAQUE_LIMIT; + pgetattr_res.info = &dir_info; + + status = compound_encode_send_decode(session, &compound, 0, 0); + if (status) + goto out; + + if (compound_error(status = compound.res.status)) + goto out; + + /* update the attributes of the parent directory */ + memcpy(&dir_info.attrmask, &pgetattr_res.obj_attributes.attrmask, + sizeof(bitmap4)); + nfs41_attr_cache_update(session_name_cache(session), + parent->fh.fileid, &dir_info); + + /* update the attributes of the file */ + memcpy(&info.attrmask, &getattr_res.obj_attributes.attrmask, + sizeof(bitmap4)); + nfs41_attr_cache_update(session_name_cache(session), + file->fh.fileid, &info); +out: + return status; +} + int nfs41_create( IN nfs41_session *session, IN uint32_t type, diff --git a/daemon/nfs41_ops.h b/daemon/nfs41_ops.h index 10b3a97..4bbb256 100644 --- a/daemon/nfs41_ops.h +++ b/daemon/nfs41_ops.h @@ -585,6 +585,10 @@ typedef struct __open_claim4 { struct __open_claim_null { const nfs41_component *filename; } null; + /* case CLAIM_PREVIOUS: */ + struct __open_claim_prev { + uint32_t delegate_type; + } prev; } u; } open_claim4; @@ -900,6 +904,15 @@ int nfs41_open( IN OUT nfs41_open_state *state, OUT nfs41_file_info *info); +int nfs41_open_reclaim( + IN nfs41_session *session, + IN nfs41_path_fh *parent, + IN nfs41_path_fh *file, + IN state_owner4 *owner, + IN uint32_t allow, + IN uint32_t deny, + OUT stateid4 *stateid); + int nfs41_create( IN nfs41_session *session, IN uint32_t type, diff --git a/daemon/nfs41_xdr.c b/daemon/nfs41_xdr.c index db919b8..9fcab60 100644 --- a/daemon/nfs41_xdr.c +++ b/daemon/nfs41_xdr.c @@ -1743,6 +1743,9 @@ static bool_t encode_open_claim4( case CLAIM_NULL: result = encode_component(xdr, oc->u.null.filename); break; + case CLAIM_PREVIOUS: + result = xdr_u_int32_t(xdr, &oc->u.prev.delegate_type); + break; case CLAIM_FH: /* use current file handle */ break;