/* * 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; }
/* 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; }
/* 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); }
/* * 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; }