fs/afs/dir_search.c

Source file repositories/reference/linux-study-clean/fs/afs/dir_search.c

File Facts

System
Linux kernel
Corpus path
fs/afs/dir_search.c
Extension
.c
Size
5521 bytes
Lines
228
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

if (blend <= fpos + fsize) {
				/* ... and then return the mapped block. */
				folio = folioq_folio(fq, slot);
				if (WARN_ON_ONCE(folio_pos(folio) != fpos))
					goto fail;
				iter->fq = fq;
				iter->fq_slot = slot;
				iter->fpos = fpos;
				iter->block = kmap_local_folio(folio, blpos - fpos);
				return iter->block;
			}
			fpos += fsize;
		}
		slot = 0;
	}

fail:
	iter->fq = NULL;
	iter->fq_slot = 0;
	afs_invalidate_dir(dvnode, afs_dir_invalid_edit_get_block);
	return NULL;
}

/*
 * Search through a directory bucket.
 */
int afs_dir_search_bucket(struct afs_dir_iter *iter, const struct qstr *name,
			  struct afs_fid *_fid)
{
	const union afs_xdr_dir_block *meta;
	unsigned int entry;
	int ret = -ESTALE;

	meta = afs_dir_find_block(iter, 0);
	if (!meta)
		return -ESTALE;

	entry = ntohs(meta->meta.hashtable[iter->bucket & (AFS_DIR_HASHTBL_SIZE - 1)]);
	_enter("%x,%x", iter->bucket, entry);

	while (entry) {
		const union afs_xdr_dir_block *block;
		const union afs_xdr_dirent *dire;
		unsigned int blnum = entry / AFS_DIR_SLOTS_PER_BLOCK;
		unsigned int slot = entry % AFS_DIR_SLOTS_PER_BLOCK;
		unsigned int resv = (blnum == 0 ? AFS_DIR_RESV_BLOCKS0 : AFS_DIR_RESV_BLOCKS);

		_debug("search %x", entry);

		if (slot < resv) {
			kdebug("slot out of range h=%x rs=%2x sl=%2x-%2x",
			       iter->bucket, resv, slot, slot + iter->nr_slots - 1);
			goto bad;
		}

		block = afs_dir_find_block(iter, blnum);
		if (!block)
			goto bad;
		dire = &block->dirents[slot];

		if (slot + iter->nr_slots <= AFS_DIR_SLOTS_PER_BLOCK &&
		    memcmp(dire->u.name, name->name, name->len) == 0 &&
		    dire->u.name[name->len] == '\0') {
			_fid->vnode  = ntohl(dire->u.vnode);
			_fid->unique = ntohl(dire->u.unique);
			ret = entry;
			goto found;
		}

		iter->prev_entry = entry;
		entry = ntohs(dire->u.hash_next);
		if (!--iter->loop_check) {
			kdebug("dir chain loop h=%x", iter->bucket);
			goto bad;
		}
	}

	ret = -ENOENT;
found:
	if (iter->block) {
		kunmap_local(iter->block);
		iter->block = NULL;
	}

bad:
	if (ret == -ESTALE)
		afs_invalidate_dir(iter->dvnode, afs_dir_invalid_iter_stale);
	_leave(" = %d", ret);
	return ret;
}

Annotation

Implementation Notes