[CIFS] Migrate from prefixpath logic
Now we point superblock to a server share root and set a root dentry appropriately. This let us share superblock between mounts like //server/sharename/foo/bar and //server/sharename/foo further. Reviewed-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Pavel Shilovsky <piastry@etersoft.ru> Signed-off-by: Steve French <sfrench@us.ibm.com>
This commit is contained in:
Родитель
641a58d66d
Коммит
f87d39d951
|
@ -56,8 +56,6 @@ struct cifs_sb_info {
|
|||
mode_t mnt_file_mode;
|
||||
mode_t mnt_dir_mode;
|
||||
unsigned int mnt_cifs_flags;
|
||||
int prepathlen;
|
||||
char *prepath; /* relative path under the share to mount to */
|
||||
char *mountdata; /* options received at mount time or via DFS refs */
|
||||
struct backing_dev_info bdi;
|
||||
struct delayed_work prune_tlinks;
|
||||
|
|
101
fs/cifs/cifsfs.c
101
fs/cifs/cifsfs.c
|
@ -415,8 +415,6 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
|
|||
seq_printf(s, ",nocase");
|
||||
if (tcon->retry)
|
||||
seq_printf(s, ",hard");
|
||||
if (cifs_sb->prepath)
|
||||
seq_printf(s, ",prepath=%s", cifs_sb->prepath);
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
|
||||
seq_printf(s, ",posixpaths");
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)
|
||||
|
@ -530,6 +528,100 @@ static const struct super_operations cifs_super_ops = {
|
|||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
static struct dentry *
|
||||
cifs_do_mount(struct file_system_type *fs_type,
|
||||
int flags, const char *dev_name, void *data)
|
||||
|
@ -585,7 +677,10 @@ cifs_do_mount(struct file_system_type *fs_type,
|
|||
|
||||
sb->s_flags |= MS_ACTIVE;
|
||||
|
||||
root = dget(sb->s_root);
|
||||
root = cifs_get_root(volume_info, sb);
|
||||
if (root == NULL)
|
||||
goto out_super;
|
||||
cFYI(1, "dentry root is: %p", root);
|
||||
goto out;
|
||||
|
||||
out_super:
|
||||
|
|
|
@ -155,6 +155,61 @@ struct cifs_cred {
|
|||
*****************************************************************
|
||||
*/
|
||||
|
||||
struct smb_vol {
|
||||
char *username;
|
||||
char *password;
|
||||
char *domainname;
|
||||
char *UNC;
|
||||
char *UNCip;
|
||||
char *iocharset; /* local code page for mapping to and from Unicode */
|
||||
char source_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* clnt nb name */
|
||||
char target_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* srvr nb name */
|
||||
uid_t cred_uid;
|
||||
uid_t linux_uid;
|
||||
gid_t linux_gid;
|
||||
mode_t file_mode;
|
||||
mode_t dir_mode;
|
||||
unsigned secFlg;
|
||||
bool retry:1;
|
||||
bool intr:1;
|
||||
bool setuids:1;
|
||||
bool override_uid:1;
|
||||
bool override_gid:1;
|
||||
bool dynperm:1;
|
||||
bool noperm:1;
|
||||
bool no_psx_acl:1; /* set if posix acl support should be disabled */
|
||||
bool cifs_acl:1;
|
||||
bool no_xattr:1; /* set if xattr (EA) support should be disabled*/
|
||||
bool server_ino:1; /* use inode numbers from server ie UniqueId */
|
||||
bool direct_io:1;
|
||||
bool strict_io:1; /* strict cache behavior */
|
||||
bool remap:1; /* set to remap seven reserved chars in filenames */
|
||||
bool posix_paths:1; /* unset to not ask for posix pathnames. */
|
||||
bool no_linux_ext:1;
|
||||
bool sfu_emul:1;
|
||||
bool nullauth:1; /* attempt to authenticate with null user */
|
||||
bool nocase:1; /* request case insensitive filenames */
|
||||
bool nobrl:1; /* disable sending byte range locks to srv */
|
||||
bool mand_lock:1; /* send mandatory not posix byte range lock reqs */
|
||||
bool seal:1; /* request transport encryption on share */
|
||||
bool nodfs:1; /* Do not request DFS, even if available */
|
||||
bool local_lease:1; /* check leases only on local system, not remote */
|
||||
bool noblocksnd:1;
|
||||
bool noautotune:1;
|
||||
bool nostrictsync:1; /* do not force expensive SMBflush on every sync */
|
||||
bool fsc:1; /* enable fscache */
|
||||
bool mfsymlinks:1; /* use Minshall+French Symlinks */
|
||||
bool multiuser:1;
|
||||
unsigned int rsize;
|
||||
unsigned int wsize;
|
||||
bool sockopt_tcp_nodelay:1;
|
||||
unsigned short int port;
|
||||
unsigned long actimeo; /* attribute cache timeout (jiffies) */
|
||||
char *prepath;
|
||||
struct sockaddr_storage srcaddr; /* allow binding to a local IP */
|
||||
struct nls_table *local_nls;
|
||||
};
|
||||
|
||||
struct TCP_Server_Info {
|
||||
struct list_head tcp_ses_list;
|
||||
struct list_head smb_ses_list;
|
||||
|
@ -517,6 +572,26 @@ static inline char CIFS_DIR_SEP(const struct cifs_sb_info *cifs_sb)
|
|||
return '\\';
|
||||
}
|
||||
|
||||
static inline void
|
||||
convert_delimiter(char *path, char delim)
|
||||
{
|
||||
int i;
|
||||
char old_delim;
|
||||
|
||||
if (path == NULL)
|
||||
return;
|
||||
|
||||
if (delim == '/')
|
||||
old_delim = '\\';
|
||||
else
|
||||
old_delim = '/';
|
||||
|
||||
for (i = 0; path[i] != '\0'; i++) {
|
||||
if (path[i] == old_delim)
|
||||
path[i] = delim;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CIFS_STATS
|
||||
#define cifs_stats_inc atomic_inc
|
||||
|
||||
|
|
|
@ -57,8 +57,9 @@ extern int init_cifs_idmap(void);
|
|||
extern void exit_cifs_idmap(void);
|
||||
extern void cifs_destroy_idmaptrees(void);
|
||||
extern char *build_path_from_dentry(struct dentry *);
|
||||
extern char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb,
|
||||
struct cifsTconInfo *tcon);
|
||||
extern char *cifs_build_path_to_root(struct smb_vol *vol,
|
||||
struct cifs_sb_info *cifs_sb,
|
||||
struct cifsTconInfo *tcon);
|
||||
extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
|
||||
extern char *cifs_compose_mount_options(const char *sb_mountdata,
|
||||
const char *fullpath, const struct dfs_info3_param *ref,
|
||||
|
|
|
@ -57,61 +57,6 @@
|
|||
|
||||
extern mempool_t *cifs_req_poolp;
|
||||
|
||||
struct smb_vol {
|
||||
char *username;
|
||||
char *password;
|
||||
char *domainname;
|
||||
char *UNC;
|
||||
char *UNCip;
|
||||
char *iocharset; /* local code page for mapping to and from Unicode */
|
||||
char source_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* clnt nb name */
|
||||
char target_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* srvr nb name */
|
||||
uid_t cred_uid;
|
||||
uid_t linux_uid;
|
||||
gid_t linux_gid;
|
||||
mode_t file_mode;
|
||||
mode_t dir_mode;
|
||||
unsigned secFlg;
|
||||
bool retry:1;
|
||||
bool intr:1;
|
||||
bool setuids:1;
|
||||
bool override_uid:1;
|
||||
bool override_gid:1;
|
||||
bool dynperm:1;
|
||||
bool noperm:1;
|
||||
bool no_psx_acl:1; /* set if posix acl support should be disabled */
|
||||
bool cifs_acl:1;
|
||||
bool no_xattr:1; /* set if xattr (EA) support should be disabled*/
|
||||
bool server_ino:1; /* use inode numbers from server ie UniqueId */
|
||||
bool direct_io:1;
|
||||
bool strict_io:1; /* strict cache behavior */
|
||||
bool remap:1; /* set to remap seven reserved chars in filenames */
|
||||
bool posix_paths:1; /* unset to not ask for posix pathnames. */
|
||||
bool no_linux_ext:1;
|
||||
bool sfu_emul:1;
|
||||
bool nullauth:1; /* attempt to authenticate with null user */
|
||||
bool nocase:1; /* request case insensitive filenames */
|
||||
bool nobrl:1; /* disable sending byte range locks to srv */
|
||||
bool mand_lock:1; /* send mandatory not posix byte range lock reqs */
|
||||
bool seal:1; /* request transport encryption on share */
|
||||
bool nodfs:1; /* Do not request DFS, even if available */
|
||||
bool local_lease:1; /* check leases only on local system, not remote */
|
||||
bool noblocksnd:1;
|
||||
bool noautotune:1;
|
||||
bool nostrictsync:1; /* do not force expensive SMBflush on every sync */
|
||||
bool fsc:1; /* enable fscache */
|
||||
bool mfsymlinks:1; /* use Minshall+French Symlinks */
|
||||
bool multiuser:1;
|
||||
unsigned int rsize;
|
||||
unsigned int wsize;
|
||||
bool sockopt_tcp_nodelay:1;
|
||||
unsigned short int port;
|
||||
unsigned long actimeo; /* attribute cache timeout (jiffies) */
|
||||
char *prepath;
|
||||
struct sockaddr_storage srcaddr; /* allow binding to a local IP */
|
||||
struct nls_table *local_nls;
|
||||
};
|
||||
|
||||
/* FIXME: should these be tunable? */
|
||||
#define TLINK_ERROR_EXPIRE (1 * HZ)
|
||||
#define TLINK_IDLE_EXPIRE (600 * HZ)
|
||||
|
@ -2569,12 +2514,6 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
|
|||
CIFS_MOUNT_POSIX_PATHS;
|
||||
}
|
||||
|
||||
/* We might be setting the path sep back to a different
|
||||
form if we are reconnecting and the server switched its
|
||||
posix path capability for this share */
|
||||
if (sb && (CIFS_SB(sb)->prepathlen > 0))
|
||||
CIFS_SB(sb)->prepath[0] = CIFS_DIR_SEP(CIFS_SB(sb));
|
||||
|
||||
if (sb && (CIFS_SB(sb)->rsize > 127 * 1024)) {
|
||||
if ((cap & CIFS_UNIX_LARGE_READ_CAP) == 0) {
|
||||
CIFS_SB(sb)->rsize = 127 * 1024;
|
||||
|
@ -2619,26 +2558,6 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
convert_delimiter(char *path, char delim)
|
||||
{
|
||||
int i;
|
||||
char old_delim;
|
||||
|
||||
if (path == NULL)
|
||||
return;
|
||||
|
||||
if (delim == '/')
|
||||
old_delim = '\\';
|
||||
else
|
||||
old_delim = '/';
|
||||
|
||||
for (i = 0; path[i] != '\0'; i++) {
|
||||
if (path[i] == old_delim)
|
||||
path[i] = delim;
|
||||
}
|
||||
}
|
||||
|
||||
void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
|
||||
struct cifs_sb_info *cifs_sb)
|
||||
{
|
||||
|
@ -2659,18 +2578,6 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
|
|||
/* Windows ME may prefer this */
|
||||
cFYI(1, "readsize set to minimum: 2048");
|
||||
}
|
||||
/* calculate prepath */
|
||||
cifs_sb->prepath = pvolume_info->prepath;
|
||||
if (cifs_sb->prepath) {
|
||||
cifs_sb->prepathlen = strlen(cifs_sb->prepath);
|
||||
/* we can not convert the / to \ in the path
|
||||
separators in the prefixpath yet because we do not
|
||||
know (until reset_cifs_unix_caps is called later)
|
||||
whether POSIX PATH CAP is available. We normalize
|
||||
the / to \ after reset_cifs_unix_caps is called */
|
||||
pvolume_info->prepath = NULL;
|
||||
} else
|
||||
cifs_sb->prepathlen = 0;
|
||||
cifs_sb->mnt_uid = pvolume_info->linux_uid;
|
||||
cifs_sb->mnt_gid = pvolume_info->linux_gid;
|
||||
cifs_sb->mnt_file_mode = pvolume_info->file_mode;
|
||||
|
@ -2834,24 +2741,13 @@ build_unc_path_to_root(const struct smb_vol *volume_info,
|
|||
char *full_path;
|
||||
|
||||
int unc_len = strnlen(volume_info->UNC, MAX_TREE_SIZE + 1);
|
||||
full_path = kmalloc(unc_len + cifs_sb->prepathlen + 1, GFP_KERNEL);
|
||||
full_path = kmalloc(unc_len + 1, GFP_KERNEL);
|
||||
if (full_path == NULL)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
strncpy(full_path, volume_info->UNC, unc_len);
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
|
||||
int i;
|
||||
for (i = 0; i < unc_len; i++) {
|
||||
if (full_path[i] == '\\')
|
||||
full_path[i] = '/';
|
||||
}
|
||||
}
|
||||
|
||||
if (cifs_sb->prepathlen)
|
||||
strncpy(full_path + unc_len, cifs_sb->prepath,
|
||||
cifs_sb->prepathlen);
|
||||
|
||||
full_path[unc_len + cifs_sb->prepathlen] = 0; /* add trailing null */
|
||||
full_path[unc_len] = 0; /* add trailing null */
|
||||
convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
|
||||
return full_path;
|
||||
}
|
||||
|
||||
|
@ -3049,10 +2945,6 @@ try_mount_again:
|
|||
CIFSSMBQFSAttributeInfo(xid, tcon);
|
||||
}
|
||||
|
||||
/* convert forward to back slashes in prepath here if needed */
|
||||
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0)
|
||||
convert_delimiter(cifs_sb->prepath, CIFS_DIR_SEP(cifs_sb));
|
||||
|
||||
if ((tcon->unix_ext == 0) && (cifs_sb->rsize > (1024 * 127))) {
|
||||
cifs_sb->rsize = 1024 * 127;
|
||||
cFYI(DBG2, "no very large read support, rsize now 127K");
|
||||
|
@ -3082,10 +2974,10 @@ remote_path_check:
|
|||
}
|
||||
#endif
|
||||
|
||||
/* check if a whole path (including prepath) is not remote */
|
||||
/* check if a whole path is not remote */
|
||||
if (!rc && tcon) {
|
||||
/* build_path_to_root works only when we have a valid tcon */
|
||||
full_path = cifs_build_path_to_root(cifs_sb, tcon);
|
||||
full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon);
|
||||
if (full_path == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto mount_fail_check;
|
||||
|
@ -3111,10 +3003,6 @@ remote_path_check:
|
|||
rc = -ELOOP;
|
||||
goto mount_fail_check;
|
||||
}
|
||||
/* convert forward to back slashes in prepath here if needed */
|
||||
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0)
|
||||
convert_delimiter(cifs_sb->prepath,
|
||||
CIFS_DIR_SEP(cifs_sb));
|
||||
|
||||
rc = expand_dfs_referral(xid, pSesInfo, volume_info, cifs_sb,
|
||||
true);
|
||||
|
@ -3340,7 +3228,6 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
|
|||
struct rb_root *root = &cifs_sb->tlink_tree;
|
||||
struct rb_node *node;
|
||||
struct tcon_link *tlink;
|
||||
char *tmp;
|
||||
|
||||
cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
|
||||
|
||||
|
@ -3357,11 +3244,6 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
|
|||
}
|
||||
spin_unlock(&cifs_sb->tlink_tree_lock);
|
||||
|
||||
tmp = cifs_sb->prepath;
|
||||
cifs_sb->prepathlen = 0;
|
||||
cifs_sb->prepath = NULL;
|
||||
kfree(tmp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,6 @@ build_path_from_dentry(struct dentry *direntry)
|
|||
{
|
||||
struct dentry *temp;
|
||||
int namelen;
|
||||
int pplen;
|
||||
int dfsplen;
|
||||
char *full_path;
|
||||
char dirsep;
|
||||
|
@ -63,13 +62,12 @@ build_path_from_dentry(struct dentry *direntry)
|
|||
when the server crashed */
|
||||
|
||||
dirsep = CIFS_DIR_SEP(cifs_sb);
|
||||
pplen = cifs_sb->prepathlen;
|
||||
if (tcon->Flags & SMB_SHARE_IS_IN_DFS)
|
||||
dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
|
||||
else
|
||||
dfsplen = 0;
|
||||
cifs_bp_rename_retry:
|
||||
namelen = pplen + dfsplen;
|
||||
namelen = dfsplen;
|
||||
for (temp = direntry; !IS_ROOT(temp);) {
|
||||
namelen += (1 + temp->d_name.len);
|
||||
temp = temp->d_parent;
|
||||
|
@ -100,7 +98,7 @@ cifs_bp_rename_retry:
|
|||
return NULL;
|
||||
}
|
||||
}
|
||||
if (namelen != pplen + dfsplen) {
|
||||
if (namelen != dfsplen) {
|
||||
cERROR(1, "did not end path lookup where expected namelen is %d",
|
||||
namelen);
|
||||
/* presumably this is only possible if racing with a rename
|
||||
|
@ -126,7 +124,6 @@ cifs_bp_rename_retry:
|
|||
}
|
||||
}
|
||||
}
|
||||
strncpy(full_path + dfsplen, CIFS_SB(direntry->d_sb)->prepath, pplen);
|
||||
return full_path;
|
||||
}
|
||||
|
||||
|
|
|
@ -735,10 +735,10 @@ static const struct inode_operations cifs_ipc_inode_ops = {
|
|||
.lookup = cifs_lookup,
|
||||
};
|
||||
|
||||
char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb,
|
||||
struct cifsTconInfo *tcon)
|
||||
char *cifs_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
|
||||
struct cifsTconInfo *tcon)
|
||||
{
|
||||
int pplen = cifs_sb->prepathlen;
|
||||
int pplen = vol->prepath ? strlen(vol->prepath) : 0;
|
||||
int dfsplen;
|
||||
char *full_path = NULL;
|
||||
|
||||
|
@ -772,7 +772,7 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb,
|
|||
}
|
||||
}
|
||||
}
|
||||
strncpy(full_path + dfsplen, cifs_sb->prepath, pplen);
|
||||
strncpy(full_path + dfsplen, vol->prepath, pplen);
|
||||
full_path[dfsplen + pplen] = 0; /* add trailing null */
|
||||
return full_path;
|
||||
}
|
||||
|
@ -884,19 +884,13 @@ struct inode *cifs_root_iget(struct super_block *sb)
|
|||
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||
struct inode *inode = NULL;
|
||||
long rc;
|
||||
char *full_path;
|
||||
struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
|
||||
|
||||
full_path = cifs_build_path_to_root(cifs_sb, tcon);
|
||||
if (full_path == NULL)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
xid = GetXid();
|
||||
if (tcon->unix_ext)
|
||||
rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
|
||||
rc = cifs_get_inode_info_unix(&inode, "", sb, xid);
|
||||
else
|
||||
rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
|
||||
xid, NULL);
|
||||
rc = cifs_get_inode_info(&inode, "", NULL, sb, xid, NULL);
|
||||
|
||||
if (!inode) {
|
||||
inode = ERR_PTR(rc);
|
||||
|
@ -922,7 +916,6 @@ struct inode *cifs_root_iget(struct super_block *sb)
|
|||
}
|
||||
|
||||
out:
|
||||
kfree(full_path);
|
||||
/* can not call macro FreeXid here since in a void func
|
||||
* TODO: This is no longer true
|
||||
*/
|
||||
|
|
Загрузка…
Ссылка в новой задаче