Skip to content

Commit

Permalink
[CIFS] Migrate from prefixpath logic
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Steve French committed May 27, 2011
1 parent 641a58d commit f87d39d
Show file tree
Hide file tree
Showing 7 changed files with 189 additions and 148 deletions.
2 changes: 0 additions & 2 deletions fs/cifs/cifs_fs_sb.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
101 changes: 98 additions & 3 deletions fs/cifs/cifsfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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:
Expand Down
75 changes: 75 additions & 0 deletions fs/cifs/cifsglob.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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

Expand Down
5 changes: 3 additions & 2 deletions fs/cifs/cifsproto.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Loading

0 comments on commit f87d39d

Please sign in to comment.