Skip to content

fix(ioctl): handle partial GetEntryInfoV2 response via GetEntryInfoResult field#317

Open
pravar3088 wants to merge 2 commits intomainfrom
fix/getentryinfo-v2-basic-only-go
Open

fix(ioctl): handle partial GetEntryInfoV2 response via GetEntryInfoResult field#317
pravar3088 wants to merge 2 commits intomainfrom
fix/getentryinfo-v2-basic-only-go

Conversation

@pravar3088
Copy link
Copy Markdown
Contributor

@pravar3088 pravar3088 commented Apr 17, 2026

What does this PR do / why do we need it?

Required for all PRs.

The beegfs-core client module's GetEntryInfoV2 ioctl exposes a getEntryInfoResult field in BeegfsIoctl_GetEntryInfoV2_Arg that carries the exact FhgfsOpsErr code returned by the metadata RPC. When the RPC returns a non-success result, the kernel returns success from the ioctl with the error code in getEntryInfoResult; only the basic entry info fields are valid in that case.

This PR adds the corresponding GetEntryInfoResult uint8 field to the Go ioctl arg struct and passes its value directly as beegfs.OpsErr(arg.GetEntryInfoResult) in GetEntryInfoResponse.Result, letting callers distinguish a partial result from a complete one without any hardcoded error assumptions.

Related Issue(s)

Required when applicable.

Where should the reviewer(s) start reviewing this?

Only required for larger PRs when this may not be immediately obvious.

Are there any specific topics we should discuss before merging?

Not required.

What are the next steps after this PR?

Not required.

Checklist before merging:

Required for all PRs.

When creating a PR these are items to keep in mind that cannot be checked by GitHub actions:

  • Documentation:
    • Does developer documentation (code comments, readme, etc.) need to be added or updated?
    • Does the user documentation need to be expanded or updated for this change?
  • Testing:
    • Does this functionality require changing or adding new unit tests?
    • Does this functionality require changing or adding new integration tests?
  • Git Hygiene:

For more details refer to the Go coding standards and the pull request process.

The beegfs-core client module's GetEntryInfoV2 ioctl is updated to add
a basicOnly field: when the inode is locked in the global lock store
(e.g. chunk rebalancing in progress), the kernel now returns success
with basicOnly=1 instead of EBUSY. Only the basic entry info fields
(owner, entry/parent IDs, type, feature flags) are populated in that
case; stripe pattern, PathInfo, RST, and session fields are left unset.

This commit adds BasicOnly to the ioctl arg struct to match the updated
kernel ABI, and return early with OpsErr_INODELOCKED in
GetEntryInfoResponse.Result so callers can distinguish a partial result
from a complete one.
@pravar3088 pravar3088 requested a review from a team as a code owner April 17, 2026 13:38
@pravar3088 pravar3088 self-assigned this Apr 17, 2026
@pravar3088
Copy link
Copy Markdown
Contributor Author

I did some basic tests with fix from PR#4630 and changes seem to work fine.

So I triggered a rebalance operation for a 10GB file:

go run ctl/cmd/beegfs/main.go entry migrate --rebalance --from-targets=3 --targets=4 /mnt/beegfs/mount1/dir/file.txt --recurse --yes

I put a watch on entry info output and while operation was in progress (i.e. inode became locked) - below was response:

Entry type: file
EntryID: 0-69E1F302-2
Stripe pattern details:
+ Type: invalid
+ Chunksize: 0
+ Number of storage targets: desired: 0
Chunk path: ?
Inlined inode: yes
File state: Unlocked : Available
Dentry info:
 + Path: 77/78/0-69E1F2E3-1
 + Metadata node: node_meta_2 [ID: 2]
Client Sessions
+ Reading: 0
+ Writing: 0

After rebalance was finished - I can again see fields like stripePattern, chunkSize etc.

Entry type: file
EntryID: 0-69E1F302-2
Stripe pattern details:
+ Type: RAID0
+ Chunksize: 512K
+ Number of storage targets: desired: 4; actual: 2
+ Storage targets:
+ 4 @ node_storage_2 [ID: 2]
+ 7 @ node_storage_2 [ID: 2]
Chunk path: u0/69E1/F/0-69E1F2E3-1/0-69E1F302-2
Inlined inode: yes
File state: Unlocked : Available
Dentry info:
 + Path: 77/78/0-69E1F2E3-1
 + Metadata node: node_meta_2 [ID: 2]
Client Sessions
+ Reading: 0
+ Writing: 0

Comment thread common/ioctl/api.go Outdated
// above are valid, but stripe pattern, PathInfo, RST, and session fields are not populated.
// Return OpsErr_INODELOCKED in the response so callers can distinguish a partial result.
if arg.BasicOnly != 0 {
return entryInfo, msg.GetEntryInfoResponse{Result: beegfs.OpsErr_INODELOCKED}, nil
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not entirely sure about the design here. Currently, when arg.BasicOnly != 0, we return OpsErr_INODELOCKED in GetEntryInfoResponse.Result to signal a partial result — but this is technically an assumption: we know the ioctl returned partial data, not what the metadata server actually returned.

Options I could think of:

  1. Keep OpsErr_INODELOCKED — semantically correct today since basicOnly=1 is only set for INODELOCKED in the kernel, but it couples the Go layer to a kernel implementation detail
  2. Use a general/neutral error code — avoids the assumption, but I'm not sure what the right value would be here
  3. Just leave Result unset — callers can't explicitly distinguish partial data from a full result with no targets, but arguably the zero/default values themselves (e.g. no stripe targets, zero chunk size) already hint that full data wasn't fetched

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if we replace the BasicOnly boolean flag with a GetEntryInfoResult field that can be used to communicate the exact OpsErr back to the caller?

Then in the client code instead of having to check specific errors, we can always just report back any non-success rpcRes from FhgfsOpsRemoting_GetEntryInfo and let the caller decide what to do.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion. I made above change in this commit. Also equivalent changes on core side are done in PR#4630.

iamjoemccormick added a commit that referenced this pull request Apr 17, 2026
The new errors surfaced when using the `GetEntryInfoV2` ioctl and subsequent changes in
#317 prompted the realization that `beegfs entry info`
only worked before because `newEntry()` was never checking if `entryInfo msg.GetEntryInfoResponse`
actually contained valid data (based on `entryInfo.Result`). At best this returned misleading output
in CTL, at worst there are other places that make assumptions based on the validity of that data.

Before when GetEntryInfoResponse failed (e.g., OpsErr_INODELOCKED during chunk rebalancing), fields
derived from that response previously defaulted to Go zero values, causing consumers like 'beegfs
entry info' to silently display misleading data (e.g., Chunksize: 0, Reading: 0, Writing: 0).

This change extracts Pattern, Remote, NumSessionsRead, NumSessionsWrite, and FileState into a new
EntryDetails struct. Entry.Details is a pointer that is nil when EntryInfoPopulated != SUCCESS, so:

- Display functions gate all response-derived output behind a single nil check, showing
  (unavailable) instead of zero values.
- Backend consumers (set, migrate, create, RST) get explicit nil guards that surface errors instead
  of silently operating on empty data.
- Future fields added to EntryDetails are automatically handled by the display layer without
  requiring frontend changes.

Also introduces ErrEntryDetailsUnavailable in the migrate/chooser path, replacing the previous
behavior where a locked inode silently produced zero-value fields that triggered
ErrEntryHasNoTargets.

Assisted-by: Claude:claude-opus-4-6
Mirrors the core-side rename from basicOnly to getEntryInfoResult. The
field now carries the exact FhgfsOpsErr code from the metadata RPC
rather than a hardcoded boolean, so the partial result reason is
propagated to callers without assumption.
@pravar3088 pravar3088 force-pushed the fix/getentryinfo-v2-basic-only-go branch from 929f8df to 12f7689 Compare April 18, 2026 14:11
@pravar3088 pravar3088 changed the title fix(ioctl): handle basicOnly flag from GetEntryInfoV2 kernel ioctl fix(ioctl): handle partial GetEntryInfoV2 response via GetEntryInfoResult field Apr 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants