예제 #1
0
/*
 * Get root dentry from superblock according to prefix path mount option.
 * Return dentry with refcount + 1 on success and NULL otherwise.
 */
static struct dentry *
cifs_get_root(struct smb_vol *vol, struct super_block *sb)
{
	struct dentry *dentry;
	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
	char *full_path = NULL;
	char *s, *p;
	char sep;
	int xid;

	full_path = cifs_build_path_to_root(vol, cifs_sb,
					    cifs_sb_master_tcon(cifs_sb));
	if (full_path == NULL)
		return ERR_PTR(-ENOMEM);

	cFYI(1, "Get root dentry for %s", full_path);

	xid = GetXid();
	sep = CIFS_DIR_SEP(cifs_sb);
	dentry = dget(sb->s_root);
	p = s = full_path;

	do {
		struct inode *dir = dentry->d_inode;
		struct dentry *child;

		if (!dir) {
			dput(dentry);
			dentry = ERR_PTR(-ENOENT);
			break;
		}

		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++;

		mutex_lock(&dir->i_mutex);
		child = lookup_one_len(p, dentry, s - p);
		mutex_unlock(&dir->i_mutex);
		dput(dentry);
		dentry = child;
	} while (!IS_ERR(dentry));
	_FreeXid(xid);
	kfree(full_path);
	return dentry;
}
예제 #2
0
파일: inode.c 프로젝트: piastry/etercifs
/* gets root inode */
struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
{
	int xid;
	struct cifs_sb_info *cifs_sb;
	struct inode *inode;
	long rc;

	inode = iget_locked(sb, ino);
	if (!inode)
		return ERR_PTR(-ENOMEM);
	if (!(inode->i_state & I_NEW))
		return inode;

	cifs_sb = CIFS_SB(inode->i_sb);
	xid = GetXid();

	if (cifs_sb->tcon->unix_ext)
		rc = cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid);
	else
		rc = cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid,
					 NULL);
	if (rc && cifs_sb->tcon->ipc) {
		cFYI(1, ("ipc connection - fake read inode"));
		inode->i_mode |= S_IFDIR;
		inode->i_nlink = 2;
		inode->i_op = &cifs_ipc_inode_ops;
		inode->i_fop = &simple_dir_operations;
		inode->i_uid = cifs_sb->mnt_uid;
		inode->i_gid = cifs_sb->mnt_gid;
	} else if (rc) {
		_FreeXid(xid);
		iget_failed(inode);
		return ERR_PTR(rc);
	}

	unlock_new_inode(inode);

	/* can not call macro FreeXid here since in a void func
	 * TODO: This is no longer true
	 */
	_FreeXid(xid);
	return inode;
}
예제 #3
0
/* gets root inode */
void cifs_read_inode(struct inode *inode)
{
	int xid;
	struct cifs_sb_info *cifs_sb;

	cifs_sb = CIFS_SB(inode->i_sb);
	xid = GetXid();
	if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
		cifs_get_inode_info_unix(&inode, "", inode->i_sb,xid);
	else
		cifs_get_inode_info(&inode, "", NULL, inode->i_sb,xid);
	/* can not call macro FreeXid here since in a void func */
	_FreeXid(xid);
}
예제 #4
0
/*
 * Get root dentry from superblock according to prefix path mount option.
 * Return dentry with refcount + 1 on success and NULL otherwise.
 */
static struct dentry *
cifs_get_root(struct smb_vol *vol, struct super_block *sb)
{
	int xid, rc;
	struct inode *inode;
	struct qstr name;
	struct dentry *dparent = NULL, *dchild = NULL, *alias;
	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
	unsigned int i, full_len, len;
	char *full_path = NULL, *pstart;
	char sep;

	full_path = cifs_build_path_to_root(vol, cifs_sb,
					    cifs_sb_master_tcon(cifs_sb));
	if (full_path == NULL)
		return NULL;

	cFYI(1, "Get root dentry for %s", full_path);

	xid = GetXid();
	sep = CIFS_DIR_SEP(cifs_sb);
	dparent = dget(sb->s_root);
	full_len = strlen(full_path);
	full_path[full_len] = sep;
	pstart = full_path + 1;

	for (i = 1, len = 0; i <= full_len; i++) {
		if (full_path[i] != sep || !len) {
			len++;
			continue;
		}

		full_path[i] = 0;
		cFYI(1, "get dentry for %s", pstart);

		name.name = pstart;
		name.len = len;
		name.hash = full_name_hash(pstart, len);
		dchild = d_lookup(dparent, &name);
		if (dchild == NULL) {
			cFYI(1, "not exists");
			dchild = d_alloc(dparent, &name);
			if (dchild == NULL) {
				dput(dparent);
				dparent = NULL;
				goto out;
			}
		}

		cFYI(1, "get inode");
		if (dchild->d_inode == NULL) {
			cFYI(1, "not exists");
			inode = NULL;
			if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
				rc = cifs_get_inode_info_unix(&inode, full_path,
							      sb, xid);
			else
				rc = cifs_get_inode_info(&inode, full_path,
							 NULL, sb, xid, NULL);
			if (rc) {
				dput(dchild);
				dput(dparent);
				dparent = NULL;
				goto out;
			}
			alias = d_materialise_unique(dchild, inode);
			if (alias != NULL) {
				dput(dchild);
				if (IS_ERR(alias)) {
					dput(dparent);
					dparent = NULL;
					goto out;
				}
				dchild = alias;
			}
		}
		cFYI(1, "parent %p, child %p", dparent, dchild);

		dput(dparent);
		dparent = dchild;
		len = 0;
		pstart = full_path + i + 1;
		full_path[i] = sep;
	}
out:
	_FreeXid(xid);
	kfree(full_path);
	return dparent;
}