fs/smb/client/cached_dir.c

Source file repositories/reference/linux-study-clean/fs/smb/client/cached_dir.c

File Facts

System
Linux kernel
Corpus path
fs/smb/client/cached_dir.c
Extension
.c
Size
22425 bytes
Lines
876
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

struct cached_dir_dentry {
	struct list_head entry;
	struct dentry *dentry;
};

static struct cached_fid *find_or_create_cached_dir(struct cached_fids *cfids,
						    const char *path,
						    bool lookup_only,
						    __u32 max_cached_dirs)
{
	struct cached_fid *cfid;

	list_for_each_entry(cfid, &cfids->entries, entry) {
		if (!strcmp(cfid->path, path)) {
			/*
			 * If it doesn't have a lease it is either not yet
			 * fully cached or it may be in the process of
			 * being deleted due to a lease break.
			 */
			if (!is_valid_cached_dir(cfid))
				return NULL;
			kref_get(&cfid->refcount);
			return cfid;
		}
	}
	if (lookup_only) {
		return NULL;
	}
	if (cfids->num_entries >= max_cached_dirs) {
		return NULL;
	}
	cfid = init_cached_dir(path);
	if (cfid == NULL) {
		return NULL;
	}
	cfid->cfids = cfids;
	cfids->num_entries++;
	list_add(&cfid->entry, &cfids->entries);
	cfid->on_list = true;
	kref_get(&cfid->refcount);
	/*
	 * Set @cfid->has_lease to true during construction so that the lease
	 * reference can be put in cached_dir_lease_break() due to a potential
	 * lease break right after the request is sent or while @cfid is still
	 * being cached, or if a reconnection is triggered during construction.
	 * Concurrent processes won't be to use it yet due to @cfid->time being
	 * zero.
	 */
	cfid->has_lease = true;

	return cfid;
}

static struct dentry *
path_to_dentry(struct cifs_sb_info *cifs_sb, const char *path)
{
	struct dentry *dentry;
	const char *s, *p;
	char sep;

	sep = CIFS_DIR_SEP(cifs_sb);
	dentry = dget(cifs_sb->root);
	s = path;

	do {
		struct inode *dir = d_inode(dentry);
		struct dentry *child;

		if (!S_ISDIR(dir->i_mode)) {
			dput(dentry);
			dentry = ERR_PTR(-ENOTDIR);
			break;
		}

		/* skip separators */
		while (*s == sep)
			s++;
		if (!*s)
			break;
		p = s++;
		/* next separator */
		while (*s && *s != sep)
			s++;

		child = lookup_noperm_positive_unlocked(&QSTR_LEN(p, s - p),
							dentry);
		dput(dentry);
		dentry = child;
	} while (!IS_ERR(dentry));
	return dentry;

Annotation

Implementation Notes